<commit_before>/*
 * File:   FieldColorClassifier.cpp
 * Author: claas
 *
 * Created on 15. march 2011, 15:56
 */

#include "FieldColorClassifier.h"
#include "Tools/Debug/Stopwatch.h"
#include "Tools/Debug/DebugImageDrawings.h"

using namespace std;
// Debug

FieldColorClassifier::FieldColorClassifier()
{
  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_V", " ", false);
  //DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_V2", " ", false);
  //DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_U", " ", false);
  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_Y", " ", false);

  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_in_image", " ", false);
  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:enable_plot", " ", false);

  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:clear", " ", false);

  histY.setMaxTotalSum(120 * getColoredGrid().uniformGrid.size());
  histU.setMaxTotalSum(120 * getColoredGrid().uniformGrid.size());
  histV.setMaxTotalSum(120 * getColoredGrid().uniformGrid.size());

  histCommonY.setMaxTotalSum(1200);
  histSigmaY.setMaxTotalSum(1200);

  histCommonU.setMaxTotalSum(1200);
  histSigmaU.setMaxTotalSum(1200);

  histCommonV.setMaxTotalSum(1200);
  histSigmaV.setMaxTotalSum(1200);
}

void FieldColorClassifier::execute(CameraInfo::CameraID id)
{
  cameraID = id;
  CANVAS_PX(cameraID);

//#ifdef QVGA
  //if(cameraID == CameraInfo::Bottom)
//#endif
  {
    Pixel pixel;

    DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:clear",
      histY.clear();
      histU.clear();
      histV.clear();

      histCommonY.clear();
      histSigmaY.clear();

      histCommonU.clear();
      histSigmaU.clear();

      histCommonV.clear();
      histSigmaV.clear();
    );

    const Statistics::HistogramX& histogramY = getColorChannelHistograms().histogramY;
    double start = histogramY.min;
    double end = histogramY.max;
    double span = histogramY.spanWidth;
    double halfSpan = span / 2.0;
    double quadSpan = span / 4.0;
    double octSpan = span / 8.0;

    double common = 0.0;

    if(histY.sum != 0)
    {
       common = histCommonY.common;
       start = histY.min;
       end = histY.max;
    }

    for(int i = 0; i < getColorChannelHistograms().histogramY.size; i++)
    {
      double f = 1.0;
      if(histY.sum != 0)
      {
        double s = 0.0;
        if(i <= common)
        {
          s = fabs(common - start) / 3.0;
        }
        else if(i > common)
        {
          s = fabs(end - common) / 3.0;
        }
        f = gauss(s, common, i);
      }
      else
      {
        f =  gauss(quadSpan, start + halfSpan, i);
      }
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_Y", i, f);
      );

      int val = (int) Math::round(getColorChannelHistograms().histogramY.rawData[i] * f);
      histY.add(i, val);
    }
    histY.calculate();

    histCommonY.add(histY.common);
    histSigmaY.add((int) histY.sigma);
    for(int i = 0; i < histCommonY.size; i++)
    {
      double f = 1.0;
      if(histCommonY.sum != 0)
      {
        f = gauss(params.deviationFactorY * histY.sigma, histCommonY.common, i);
      }
      histCommonY.rawData[i] = (int) (f *  histCommonY.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_commonY", i, f);
      );

      f = 1.0;
      if(histSigmaY.sum != 0)
      {
        f = gauss(params.deviationFactorY * histSigmaY.common, histSigmaY.common, i);
      }
      histSigmaY.rawData[i] = (int) (f *  histSigmaY.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_sigmaY", i, f);
      );
    }
    histCommonY.calculate();
    histSigmaY.calculate();

    double lowBorderY = histCommonY.common - params.PostDeviationFactor * histY.sigma;
    double highBorderY = histCommonY.common + params.PostDeviationFactor * histY.sigma;

    for(unsigned int i = 0; i < getColoredGrid().uniformGrid.size(); i++)
    {
      const Vector2i& point = getColoredGrid().uniformGrid.getPoint(i);

      getImage().get(point.x, point.y, pixel);

      if(lowBorderY < pixel.y && pixel.y < highBorderY)
      {
        histV.add(pixel.v);
      }
    }//end for
    start = getColorChannelHistograms().histogramV.min;
    end = getColorChannelHistograms().histogramV.max;
    span = getColorChannelHistograms().histogramV.spanWidth;
    halfSpan = span / 2.0;
    quadSpan = span / 4.0;
    octSpan = span / 8.0;

    if(histV.sum != 0)
    {
      start = histV.min;
      end = histV.max;
    }
    for(int i = 0; i < getColorChannelHistograms().histogramV.size; i++)
    {
      double f = 1.0;
      if(histV.sum != 0)
      {
        double s = 0.0;
        if(i <= histCommonV.common)
        {
          s = histCommonV.common / 3.0;
        }
        else
        {
          s = fabs(end - histCommonV.common) / 3.0;
        }
        f = gauss(params.deviationFactorV * s, histCommonV.common, i);
      }
      else
      {
        f =  gauss(quadSpan, start, i);
      }

      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_V", i, f);
      );
      histV.rawData[i] = (int) Math::round(histV.rawData[i] * f);
    }
    histV.calculate();

    histCommonV.add(histV.common);
    histSigmaV.add((int) histV.sigma);
    for(int i = 0; i < histCommonV.size; i++)
    {
      double f = 1.0;
      if(histCommonV.sum != 0)
      {
        f = gauss(params.deviationFactorV * histV.sigma, histCommonV.common, i);
      }
      histCommonV.rawData[i] = (int) (f *  histCommonV.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_commonV", i, f);
      );

      f = 1.0;
      if(histSigmaV.sum != 0)
      {
        f = gauss(params.deviationFactorV * histSigmaV.common, histSigmaV.common, i);
      }
      histSigmaV.rawData[i] = (int) (f *  histSigmaV.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_sigmaV", i, f);
      );
    }
    histCommonV.calculate();
    histSigmaV.calculate();

    double lowBorderV = histCommonV.common - params.PostDeviationFactor * histV.sigma;
    double highBorderV = histCommonV.common + params.PostDeviationFactor * histV.sigma;

    for(unsigned int i = 0; i < getColoredGrid().uniformGrid.size(); i++)
    {
      const Vector2i& point = getColoredGrid().uniformGrid.getPoint(i);
      getImage().get(point.x, point.y, pixel);

      if
      (
        lowBorderY < pixel.y && pixel.y < highBorderY
        //&&
        //lowBorderV < pixel.v && pixel.v < highBorderV
      )
      {
        histU.add(pixel.u);
      }
    }//end for
    start = getColorChannelHistograms().histogramU.min;
    span = getColorChannelHistograms().histogramU.spanWidth;
    halfSpan = span / 2.0;
    quadSpan = span / 4.0;
    octSpan = span / 8.0;

    if(histU.sum != 0)
    {
      start = histU.min;
      end = histU.max;
    }
    for(int i = 0; i < getColorChannelHistograms().histogramU.size; i++)
    {
      double f = 1.0;
      if(histU.sum != 0)
      {
        double s = 0.0;
        if(i <= histCommonU.common)
        {
          s = histCommonU.common / 3.0;
        }
        else
        {
          s = fabs(end - histCommonU.common) / 3.0;
        }
        f = gauss(params.deviationFactorU * s, histCommonU.common, i);
      }
      else
      {
        f =  gauss(quadSpan, start, i);
      }

      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_U", i, f);
      );
      histU.rawData[i] = (int) Math::round(histU.rawData[i] * f);
    }
    histU.calculate();

    histCommonU.add(histU.common);
    histSigmaU.add((int) histU.sigma);
    for(int i = 0; i < histCommonU.size; i++)
    {
      double  f = 1.0;
      if(histCommonU.sum != 0)
      {
        f = gauss(params.deviationFactorU * histU.sigma, histCommonU.common, i);
      }
      histCommonU.rawData[i] = (int) (f *  histCommonU.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_commonU", i, f);
      );

      f = 1.0;
      if(histSigmaU.sum != 0)
      {
        f = gauss(params.deviationFactorU * histSigmaU.common, histSigmaU.common, i);
      }
      histSigmaU.rawData[i] = (int) (f *  histSigmaU.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_sigmaU", i, f);
      );
    }
    histCommonU.calculate();
    histSigmaU.calculate();
  }

  runDebugRequests();
}

void FieldColorClassifier::setPercept()
{
  int lowBorderV = (int)(histCommonV.common - params.PostDeviationFactor * histSigmaV.common);
  int highBorderV = (int)(histCommonV.common + params.PostDeviationFactor * histSigmaV.common);
  int lowBorderU = (int)(histCommonU.common - params.PostDeviationFactor * histSigmaU.common);
  int highBorderU = (int)(histCommonU.common + params.PostDeviationFactor * histSigmaU.common);
  int lowBorderY = (int)(histCommonY.common - params.deviationFactorY * histSigmaY.common);
  int highBorderY = (int)(histCommonY.common + params.deviationFactorY * histSigmaY.common);

  getFieldColorPercept().range.set(lowBorderY, lowBorderU, lowBorderV, highBorderY, highBorderU, highBorderV);
  getFieldColorPercept().lastUpdated = getFrameInfo();
  getFieldColorPerceptTop().range.set(lowBorderY, lowBorderU, lowBorderV, highBorderY, highBorderU, highBorderV);
  getFieldColorPerceptTop().lastUpdated = getFrameInfo();
}

double FieldColorClassifier::gauss(double sigma, double mean, double x)
{
  //static const double f = 1.0 / sqrt(2.0 * Math::pi);
  double exponent = -((x - mean) * (x - mean)) / (2 * sigma * sigma);
  double ret = /* f / sigma **/ exp( exponent );
  return Math::isInf(ret) || Math::isNan(ret) ? 0.0 : ret;
}

void FieldColorClassifier::runDebugRequests()
{
  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
    histY.plotNormalized("FieldColorClassifier:histY");
    histU.plotNormalized("FieldColorClassifier:histU");
    histV.plotNormalized("FieldColorClassifier:histV");

    histCommonY.plotNormalized("FieldColorClassifier:histCommonY");
    histSigmaY.plotNormalized("FieldColorClassifier:histSigmaY");

    histCommonU.plotNormalized("FieldColorClassifier:histCommonU");
    histSigmaU.plotNormalized("FieldColorClassifier:histSigmaU");

    histCommonV.plotNormalized("FieldColorClassifier:histCommonV");
    histSigmaV.plotNormalized("FieldColorClassifier:histSigmaV");
  );

  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:set_in_image",
    for(unsigned int x = 0; x < getImage().width(); x++)
    {
      for(unsigned int y = 0; y < getImage().height(); y++)
      {
        const Pixel& pixel = getImage().get(x, y);
        if(getFieldColorPercept().isFieldColor(pixel))
        {
          POINT_PX(ColorClasses::green, x, y);
        }
      }
    }
  );

  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:set_dev_V",
    double lowBorderY = histCommonY.common - params.deviationFactorY * histSigmaY.common;
    double highBorderY = histCommonY.common + params.deviationFactorY * histSigmaY.common;
    double lowBorder = histCommonV.common - params.PostDeviationFactor * histSigmaV.common;
    double highBorder = histCommonV.common + params.PostDeviationFactor * histSigmaV.common;
    for(unsigned int x = 0; x < getImage().width(); x++)
    {
      for(unsigned int y = 0; y < getImage().height(); y++)
      {
        const Pixel& pixel = getImage().get(x, y);
        if
        (
          lowBorderY < pixel.y && pixel.y < highBorderY
          &&
          lowBorder < pixel.v && pixel.v < highBorder
        )
        {
          POINT_PX(ColorClasses::red, x, y);
        }
      }
    }
  );

  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:set_dev_Y",
    double lowBorder = histCommonY.common - params.deviationFactorY * histSigmaY.common;
    double highBorder = histCommonY.common + params.deviationFactorY * histSigmaY.common;
    for(unsigned int x = 0; x < getImage().width(); x++)
    {
      for(unsigned int y = 0; y < getImage().height(); y++)
      {
        const Pixel& pixel = getImage().get(x, y);
        if(lowBorder < pixel.y && pixel.y < highBorder)
        {
          POINT_PX(ColorClasses::black, x, y);
        }
      }
    }
  );
}

<commit_msg>removed unused variable<commit_after>/*
 * File:   FieldColorClassifier.cpp
 * Author: claas
 *
 * Created on 15. march 2011, 15:56
 */

#include "FieldColorClassifier.h"
#include "Tools/Debug/Stopwatch.h"
#include "Tools/Debug/DebugImageDrawings.h"

using namespace std;
// Debug

FieldColorClassifier::FieldColorClassifier()
{
  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_V", " ", false);
  //DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_V2", " ", false);
  //DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_U", " ", false);
  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_dev_Y", " ", false);

  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:set_in_image", " ", false);
  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:enable_plot", " ", false);

  DEBUG_REQUEST_REGISTER("Vision:ColorClassifiers:FieldColorClassifier:clear", " ", false);

  histY.setMaxTotalSum(120 * getColoredGrid().uniformGrid.size());
  histU.setMaxTotalSum(120 * getColoredGrid().uniformGrid.size());
  histV.setMaxTotalSum(120 * getColoredGrid().uniformGrid.size());

  histCommonY.setMaxTotalSum(1200);
  histSigmaY.setMaxTotalSum(1200);

  histCommonU.setMaxTotalSum(1200);
  histSigmaU.setMaxTotalSum(1200);

  histCommonV.setMaxTotalSum(1200);
  histSigmaV.setMaxTotalSum(1200);
}

void FieldColorClassifier::execute(CameraInfo::CameraID id)
{
  cameraID = id;
  CANVAS_PX(cameraID);

//#ifdef QVGA
  //if(cameraID == CameraInfo::Bottom)
//#endif
  {
    Pixel pixel;

    DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:clear",
      histY.clear();
      histU.clear();
      histV.clear();

      histCommonY.clear();
      histSigmaY.clear();

      histCommonU.clear();
      histSigmaU.clear();

      histCommonV.clear();
      histSigmaV.clear();
    );

    const Statistics::HistogramX& histogramY = getColorChannelHistograms().histogramY;
    double start = histogramY.min;
    double end = histogramY.max;
    double span = histogramY.spanWidth;
    double halfSpan = span / 2.0;
    double quadSpan = span / 4.0;
    double octSpan = span / 8.0;

    double common = 0.0;

    if(histY.sum != 0)
    {
       common = histCommonY.common;
       start = histY.min;
       end = histY.max;
    }

    for(int i = 0; i < getColorChannelHistograms().histogramY.size; i++)
    {
      double f = 1.0;
      if(histY.sum != 0)
      {
        double s = 0.0;
        if(i <= common)
        {
          s = fabs(common - start) / 3.0;
        }
        else if(i > common)
        {
          s = fabs(end - common) / 3.0;
        }
        f = gauss(s, common, i);
      }
      else
      {
        f =  gauss(quadSpan, start + halfSpan, i);
      }
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_Y", i, f);
      );

      int val = (int) Math::round(getColorChannelHistograms().histogramY.rawData[i] * f);
      histY.add(i, val);
    }
    histY.calculate();

    histCommonY.add(histY.common);
    histSigmaY.add((int) histY.sigma);
    for(int i = 0; i < histCommonY.size; i++)
    {
      double f = 1.0;
      if(histCommonY.sum != 0)
      {
        f = gauss(params.deviationFactorY * histY.sigma, histCommonY.common, i);
      }
      histCommonY.rawData[i] = (int) (f *  histCommonY.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_commonY", i, f);
      );

      f = 1.0;
      if(histSigmaY.sum != 0)
      {
        f = gauss(params.deviationFactorY * histSigmaY.common, histSigmaY.common, i);
      }
      histSigmaY.rawData[i] = (int) (f *  histSigmaY.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_sigmaY", i, f);
      );
    }
    histCommonY.calculate();
    histSigmaY.calculate();

    double lowBorderY = histCommonY.common - params.PostDeviationFactor * histY.sigma;
    double highBorderY = histCommonY.common + params.PostDeviationFactor * histY.sigma;

    for(unsigned int i = 0; i < getColoredGrid().uniformGrid.size(); i++)
    {
      const Vector2i& point = getColoredGrid().uniformGrid.getPoint(i);

      getImage().get(point.x, point.y, pixel);

      if(lowBorderY < pixel.y && pixel.y < highBorderY)
      {
        histV.add(pixel.v);
      }
    }//end for
    start = getColorChannelHistograms().histogramV.min;
    end = getColorChannelHistograms().histogramV.max;
    span = getColorChannelHistograms().histogramV.spanWidth;
    halfSpan = span / 2.0;
    quadSpan = span / 4.0;
    octSpan = span / 8.0;

    if(histV.sum != 0)
    {
      start = histV.min;
      end = histV.max;
    }
    for(int i = 0; i < getColorChannelHistograms().histogramV.size; i++)
    {
      double f = 1.0;
      if(histV.sum != 0)
      {
        double s = 0.0;
        if(i <= histCommonV.common)
        {
          s = histCommonV.common / 3.0;
        }
        else
        {
          s = fabs(end - histCommonV.common) / 3.0;
        }
        f = gauss(params.deviationFactorV * s, histCommonV.common, i);
      }
      else
      {
        f =  gauss(quadSpan, start, i);
      }

      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_V", i, f);
      );
      histV.rawData[i] = (int) Math::round(histV.rawData[i] * f);
    }
    histV.calculate();

    histCommonV.add(histV.common);
    histSigmaV.add((int) histV.sigma);
    for(int i = 0; i < histCommonV.size; i++)
    {
      double f = 1.0;
      if(histCommonV.sum != 0)
      {
        f = gauss(params.deviationFactorV * histV.sigma, histCommonV.common, i);
      }
      histCommonV.rawData[i] = (int) (f *  histCommonV.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_commonV", i, f);
      );

      f = 1.0;
      if(histSigmaV.sum != 0)
      {
        f = gauss(params.deviationFactorV * histSigmaV.common, histSigmaV.common, i);
      }
      histSigmaV.rawData[i] = (int) (f *  histSigmaV.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_sigmaV", i, f);
      );
    }
    histCommonV.calculate();
    histSigmaV.calculate();

    //double lowBorderV = histCommonV.common - params.PostDeviationFactor * histV.sigma;
    //double highBorderV = histCommonV.common + params.PostDeviationFactor * histV.sigma;

    for(unsigned int i = 0; i < getColoredGrid().uniformGrid.size(); i++)
    {
      const Vector2i& point = getColoredGrid().uniformGrid.getPoint(i);
      getImage().get(point.x, point.y, pixel);

      if
      (
        lowBorderY < pixel.y && pixel.y < highBorderY
        //&&
        //lowBorderV < pixel.v && pixel.v < highBorderV
      )
      {
        histU.add(pixel.u);
      }
    }//end for
    start = getColorChannelHistograms().histogramU.min;
    span = getColorChannelHistograms().histogramU.spanWidth;
    halfSpan = span / 2.0;
    quadSpan = span / 4.0;
    octSpan = span / 8.0;

    if(histU.sum != 0)
    {
      start = histU.min;
      end = histU.max;
    }
    for(int i = 0; i < getColorChannelHistograms().histogramU.size; i++)
    {
      double f = 1.0;
      if(histU.sum != 0)
      {
        double s = 0.0;
        if(i <= histCommonU.common)
        {
          s = histCommonU.common / 3.0;
        }
        else
        {
          s = fabs(end - histCommonU.common) / 3.0;
        }
        f = gauss(params.deviationFactorU * s, histCommonU.common, i);
      }
      else
      {
        f =  gauss(quadSpan, start, i);
      }

      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_U", i, f);
      );
      histU.rawData[i] = (int) Math::round(histU.rawData[i] * f);
    }
    histU.calculate();

    histCommonU.add(histU.common);
    histSigmaU.add((int) histU.sigma);
    for(int i = 0; i < histCommonU.size; i++)
    {
      double  f = 1.0;
      if(histCommonU.sum != 0)
      {
        f = gauss(params.deviationFactorU * histU.sigma, histCommonU.common, i);
      }
      histCommonU.rawData[i] = (int) (f *  histCommonU.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_commonU", i, f);
      );

      f = 1.0;
      if(histSigmaU.sum != 0)
      {
        f = gauss(params.deviationFactorU * histSigmaU.common, histSigmaU.common, i);
      }
      histSigmaU.rawData[i] = (int) (f *  histSigmaU.rawData[i]);
      DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
        PLOT_GENERIC("FieldColorClassifier:f_sigmaU", i, f);
      );
    }
    histCommonU.calculate();
    histSigmaU.calculate();
  }

  runDebugRequests();
}

void FieldColorClassifier::setPercept()
{
  int lowBorderV = (int)(histCommonV.common - params.PostDeviationFactor * histSigmaV.common);
  int highBorderV = (int)(histCommonV.common + params.PostDeviationFactor * histSigmaV.common);
  int lowBorderU = (int)(histCommonU.common - params.PostDeviationFactor * histSigmaU.common);
  int highBorderU = (int)(histCommonU.common + params.PostDeviationFactor * histSigmaU.common);
  int lowBorderY = (int)(histCommonY.common - params.deviationFactorY * histSigmaY.common);
  int highBorderY = (int)(histCommonY.common + params.deviationFactorY * histSigmaY.common);

  getFieldColorPercept().range.set(lowBorderY, lowBorderU, lowBorderV, highBorderY, highBorderU, highBorderV);
  getFieldColorPercept().lastUpdated = getFrameInfo();
  getFieldColorPerceptTop().range.set(lowBorderY, lowBorderU, lowBorderV, highBorderY, highBorderU, highBorderV);
  getFieldColorPerceptTop().lastUpdated = getFrameInfo();
}

double FieldColorClassifier::gauss(double sigma, double mean, double x)
{
  //static const double f = 1.0 / sqrt(2.0 * Math::pi);
  double exponent = -((x - mean) * (x - mean)) / (2 * sigma * sigma);
  double ret = /* f / sigma **/ exp( exponent );
  return Math::isInf(ret) || Math::isNan(ret) ? 0.0 : ret;
}

void FieldColorClassifier::runDebugRequests()
{
  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:enable_plot",
    histY.plotNormalized("FieldColorClassifier:histY");
    histU.plotNormalized("FieldColorClassifier:histU");
    histV.plotNormalized("FieldColorClassifier:histV");

    histCommonY.plotNormalized("FieldColorClassifier:histCommonY");
    histSigmaY.plotNormalized("FieldColorClassifier:histSigmaY");

    histCommonU.plotNormalized("FieldColorClassifier:histCommonU");
    histSigmaU.plotNormalized("FieldColorClassifier:histSigmaU");

    histCommonV.plotNormalized("FieldColorClassifier:histCommonV");
    histSigmaV.plotNormalized("FieldColorClassifier:histSigmaV");
  );

  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:set_in_image",
    for(unsigned int x = 0; x < getImage().width(); x++)
    {
      for(unsigned int y = 0; y < getImage().height(); y++)
      {
        const Pixel& pixel = getImage().get(x, y);
        if(getFieldColorPercept().isFieldColor(pixel))
        {
          POINT_PX(ColorClasses::green, x, y);
        }
      }
    }
  );

  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:set_dev_V",
    double lowBorderY = histCommonY.common - params.deviationFactorY * histSigmaY.common;
    double highBorderY = histCommonY.common + params.deviationFactorY * histSigmaY.common;
    double lowBorder = histCommonV.common - params.PostDeviationFactor * histSigmaV.common;
    double highBorder = histCommonV.common + params.PostDeviationFactor * histSigmaV.common;
    for(unsigned int x = 0; x < getImage().width(); x++)
    {
      for(unsigned int y = 0; y < getImage().height(); y++)
      {
        const Pixel& pixel = getImage().get(x, y);
        if
        (
          lowBorderY < pixel.y && pixel.y < highBorderY
          &&
          lowBorder < pixel.v && pixel.v < highBorder
        )
        {
          POINT_PX(ColorClasses::red, x, y);
        }
      }
    }
  );

  DEBUG_REQUEST("Vision:ColorClassifiers:FieldColorClassifier:set_dev_Y",
    double lowBorder = histCommonY.common - params.deviationFactorY * histSigmaY.common;
    double highBorder = histCommonY.common + params.deviationFactorY * histSigmaY.common;
    for(unsigned int x = 0; x < getImage().width(); x++)
    {
      for(unsigned int y = 0; y < getImage().height(); y++)
      {
        const Pixel& pixel = getImage().get(x, y);
        if(lowBorder < pixel.y && pixel.y < highBorder)
        {
          POINT_PX(ColorClasses::black, x, y);
        }
      }
    }
  );
}

<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgrePrerequisites.h"
#include "OgreCommon.h"
#include "OgreString.h"
#include "OgreLogManager.h"

namespace Ogre
{
    int findCommandLineOpts(int numargs, char** argv, UnaryOptionList& unaryOptList,
        BinaryOptionList& binOptList)
    {
        int startIndex = 1;
        for (int i = 1; i < numargs; ++i)
        {
            String tmp(argv[i]);
            if (StringUtil::startsWith(tmp, "-"))
            {
                UnaryOptionList::iterator ui = unaryOptList.find(argv[i]);
                if(ui != unaryOptList.end())
                {
                    ui->second = true;
                    ++startIndex;
                    continue;
                }
                BinaryOptionList::iterator bi = binOptList.find(argv[i]);
                if(bi != binOptList.end())
                {
                    bi->second = argv[i+1];
                    startIndex += 2;
                    ++i;
                    continue;
                }

                // Invalid option
                LogManager::getSingleton().logMessage("Invalid option " + tmp);

            }
        }
        return startIndex;
    }

	/** General hash function, derived from here
	http://www.azillionmonkeys.com/qed/hash.html
	Original by Paul Hsieh
	*/
#define OGRE_GET16BITS(d) (*((const uint16 *) (d)))
	uint32 _OgreExport FastHash (const char * data, int len, uint32 hashSoFar)
	{
		uint32 hash;
		uint32 tmp;
		int rem;

		if (hashSoFar)
			hash = hashSoFar;
		else
			hash = len;

		if (len <= 0 || data == NULL) return 0;

		rem = len & 3;
		len >>= 2;

		/* Main loop */
		for (;len > 0; len--) {
			hash  += OGRE_GET16BITS (data);
			tmp    = (OGRE_GET16BITS (data+2) << 11) ^ hash;
			hash   = (hash << 16) ^ tmp;
			data  += 2*sizeof (uint16);
			hash  += hash >> 11;
		}

		/* Handle end cases */
		switch (rem) {
		case 3: hash += OGRE_GET16BITS (data);
			hash ^= hash << 16;
			hash ^= data[sizeof (uint16)] << 18;
			hash += hash >> 11;
			break;
		case 2: hash += OGRE_GET16BITS (data);
			hash ^= hash << 11;
			hash += hash >> 17;
			break;
		case 1: hash += *data;
			hash ^= hash << 10;
			hash += hash >> 1;
		}

		/* Force "avalanching" of final 127 bits */
		hash ^= hash << 3;
		hash += hash >> 5;
		hash ^= hash << 4;
		hash += hash >> 17;
		hash ^= hash << 25;
		hash += hash >> 6;

		return hash;
	}

}
<commit_msg>Endian fix for FastHash - casting to uint16 is non-portable NOTE: this will break checksums if you're on a big-endian machine using files generated before this change.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgrePrerequisites.h"
#include "OgreCommon.h"
#include "OgreString.h"
#include "OgreLogManager.h"

namespace Ogre
{
    int findCommandLineOpts(int numargs, char** argv, UnaryOptionList& unaryOptList,
        BinaryOptionList& binOptList)
    {
        int startIndex = 1;
        for (int i = 1; i < numargs; ++i)
        {
            String tmp(argv[i]);
            if (StringUtil::startsWith(tmp, "-"))
            {
                UnaryOptionList::iterator ui = unaryOptList.find(argv[i]);
                if(ui != unaryOptList.end())
                {
                    ui->second = true;
                    ++startIndex;
                    continue;
                }
                BinaryOptionList::iterator bi = binOptList.find(argv[i]);
                if(bi != binOptList.end())
                {
                    bi->second = argv[i+1];
                    startIndex += 2;
                    ++i;
                    continue;
                }

                // Invalid option
                LogManager::getSingleton().logMessage("Invalid option " + tmp);

            }
        }
        return startIndex;
    }

	/** General hash function, derived from here
	http://www.azillionmonkeys.com/qed/hash.html
	Original by Paul Hsieh
	*/
#if OGRE_ENDIAN == OGRE_ENDIAN_LITTLE
#  define OGRE_GET16BITS(d) (*((const uint16 *) (d)))
#else
	// Cast to uint16 in little endian means first byte is least significant
	// replicate that here
#  define OGRE_GET16BITS(d) (*((const uint8 *) (d)) + (*((const uint8 *) (d+1))<<8))
#endif
	uint32 _OgreExport FastHash (const char * data, int len, uint32 hashSoFar)
	{
		uint32 hash;
		uint32 tmp;
		int rem;

		if (hashSoFar)
			hash = hashSoFar;
		else
			hash = len;

		if (len <= 0 || data == NULL) return 0;

		rem = len & 3;
		len >>= 2;

		/* Main loop */
		for (;len > 0; len--) {
			hash  += OGRE_GET16BITS (data);
			tmp    = (OGRE_GET16BITS (data+2) << 11) ^ hash;
			hash   = (hash << 16) ^ tmp;
			data  += 2*sizeof (uint16);
			hash  += hash >> 11;
		}

		/* Handle end cases */
		switch (rem) {
		case 3: hash += OGRE_GET16BITS (data);
			hash ^= hash << 16;
			hash ^= data[sizeof (uint16)] << 18;
			hash += hash >> 11;
			break;
		case 2: hash += OGRE_GET16BITS (data);
			hash ^= hash << 11;
			hash += hash >> 17;
			break;
		case 1: hash += *data;
			hash ^= hash << 10;
			hash += hash >> 1;
		}

		/* Force "avalanching" of final 127 bits */
		hash ^= hash << 3;
		hash += hash >> 5;
		hash ^= hash << 4;
		hash += hash >> 17;
		hash ^= hash << 25;
		hash += hash >> 6;

		return hash;
	}

}
<|endoftext|>


<commit_before>/**
* @file Main.cpp
*/
#include <GL/glew.h>
#include <GLFW\glfw3.h>
#include <iostream>

/**
* GLFW̃G[񍐂.
*
* @param error G[ԍ.
* @param desc  G[̓e.
*/
void ErrorCallback(int error, const char* desc)
{
  std::cerr << "ERROR: " << desc << std::endl;
}

/// Gg[|Cg.
int main()
{
  // GLFW̏.
  glfwSetErrorCallback(ErrorCallback);
  if (glfwInit() != GL_TRUE) {
    return 1;
  }
  GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Tutorial", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return 1;
  }
  glfwMakeContextCurrent(window);

  // GLEW̏.
  if (glewInit() != GLEW_OK) {
    std::cerr << "ERROR: GLEW̏Ɏs܂." << std::endl;
    glfwTerminate();
    return 1;
  }

  // C[v.
  while (!glfwWindowShouldClose(window)) {
    glClearColor(0.1f, 0.3f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glfwPollEvents();
    glfwSwapBuffers(window);
  }

  // GLFW̏I.
  glfwTerminate();

  return 0;
}<commit_msg>第01回9章を実装.<commit_after>/**
* @file Main.cpp
*/
#include <GL/glew.h>
#include <GLFW\glfw3.h>
#include <iostream>

/**
* GLFW̃G[񍐂.
*
* @param error G[ԍ.
* @param desc  G[̓e.
*/
void ErrorCallback(int error, const char* desc)
{
  std::cerr << "ERROR: " << desc << std::endl;
}

/// Gg[|Cg.
int main()
{
  // GLFW̏.
  glfwSetErrorCallback(ErrorCallback);
  if (glfwInit() != GL_TRUE) {
    return 1;
  }
  GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Tutorial", nullptr, nullptr);
  if (!window) {
    glfwTerminate();
    return 1;
  }
  glfwMakeContextCurrent(window);

  // GLEW̏.
  if (glewInit() != GLEW_OK) {
    std::cerr << "ERROR: GLEW̏Ɏs܂." << std::endl;
    glfwTerminate();
    return 1;
  }

  // OpenGL̏o͂.
  const GLubyte* renderer = glGetString(GL_RENDERER);
  std::cout << "Renderer: " << renderer << std::endl;
  const GLubyte* version = glGetString(GL_VERSION);
  std::cout << "Version: " << version << std::endl;

  // C[v.
  while (!glfwWindowShouldClose(window)) {
    glClearColor(0.1f, 0.3f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glfwPollEvents();
    glfwSwapBuffers(window);
  }

  // GLFW̏I.
  glfwTerminate();

  return 0;
}<|endoftext|>


<commit_before>// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
//----------------------------------------------------------------------------------
#include "stdafx.h"

#include <psapi.h>
#include <tlhelp32.h>
//----------------------------------------------------------------------------------
string GetMemStorageText(const uint &storage)
{
	switch (storage)
	{
		case MEM_FREE:
			return "Free";
		case MEM_RESERVE:
			return "Reserve";
		case MEM_IMAGE:
			return "Image";
		case MEM_MAPPED:
			return "Mapped";
		case MEM_PRIVATE:
			return "Private";
		default:
			break;
	}

	return "Unknown";
}
//----------------------------------------------------------------------------------
inline BOOL ModuleFind(const HANDLE &snapshot, PVOID pvBaseAddr, PMODULEENTRY32 pme)
{
	for (BOOL ok = Module32First(snapshot, pme); ok; ok = Module32Next(snapshot, pme))
	{
		if (pme->modBaseAddr == pvBaseAddr)
			return TRUE;
	}

	return FALSE;
}
//----------------------------------------------------------------------------------
void DumpRegionInfo(const HANDLE &snapshot, HANDLE hProcess, VMQUERY &vmq)
{
	if (vmq.dwRgnStorage == MEM_FREE)
		return;

	string filePath = "";

	if (vmq.pvRgnBaseAddress != NULL)
	{
		MODULEENTRY32 me = { sizeof(me) };
		if (ModuleFind(snapshot, vmq.pvRgnBaseAddress, &me))
			filePath = ToString(me.szExePath);
		else
		{
			wchar_t filename[MAX_PATH + 1];
			DWORD d = GetMappedFileName(hProcess, vmq.pvRgnBaseAddress, filename, MAX_PATH);

			if (d)
				filePath = ToString(filename);
		}
	}

	if (vmq.fRgnIsAStack)
		filePath = "Thread Stack";

	CRASHLOG("Address: 0x%08X => 0x%08X Storage: '%s' size: %i blocks: %i path: %s\n", vmq.pvBlkBaseAddress, (puchar)vmq.pvBlkBaseAddress + vmq.RgnSize, GetMemStorageText(vmq.dwBlkStorage).c_str(), vmq.RgnSize, vmq.dwRgnBlocks, filePath.c_str());
}
//----------------------------------------------------------------------------------
void DumpLibraryInformation()
{
#if USE_WISP_DEBUG_FUNCTION_NAMES == 1
	CRASHLOG("trace functions:\n");
	for (const string &str : g_WispDebugFunStack)
		CRASHLOG("%s\n", str.c_str());
#elif USE_WISP_DEBUG_FUNCTION_NAMES == 2
	if (g_WispCurrentFunctionName != NULL)
	{
		CRASHLOG("trace function: %s\n", g_WispCurrentFunctionName);
	}
#endif

	static bool libraryInfoPrinted = false;

	if (!libraryInfoPrinted)
	{
		libraryInfoPrinted = true;

		CRASHLOG("Library information:\n");

		DWORD processId = 0;
		GetWindowThreadProcessId(g_OrionWindow.Handle, &processId);

		HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);

		if (process == NULL)
		{
			CRASHLOG("::OpenProcess failed!\n");
			return;
		}

		HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, processId);

		if (snapshot == NULL)
		{
			CRASHLOG("::CreateToolhelp32Snapshot failed!\n");
			CloseHandle(process);
			return;
		}

		PVOID address = NULL;

		while (true)
		{
			VMQUERY vmq = { 0 };

			if (!VMQuery(process, address, &vmq))
				break;

			DumpRegionInfo(snapshot, process, vmq);

			address = ((puchar)vmq.pvRgnBaseAddress + vmq.RgnSize);
		}

		CloseHandle(snapshot);
		CloseHandle(process);
	}
}
//----------------------------------------------------------------------------------
void DumpCurrentRegistersInformation(CONTEXT* CR)
{
#if defined(_WIN64)
	CRASHLOG("EAX=0x%016LX, EBX=0x%016LX, ECX=0x%016LX, EDX=0x%016LX\n", CR->Rax, CR->Rbx, CR->Rcx, CR->Rdx);
	CRASHLOG("ESI=0x%016LX, EDI=0x%016LX, ESP=0x%016LX, EBP=0x%016LX\n", CR->Rsi, CR->Rdi, CR->Rsp, CR->Rbp);
	CRASHLOG("EIP=0x%016LX, EFLAGS=0x%016LX\n\n", CR->Rip, CR->EFlags);

	CRASHLOG("Bytes at EIP:\n");
	CRASHLOG_DUMP((puchar)CR->Rip, 16);

	CRASHLOG("Bytes at ESP:\n");
	CRASHLOG_DUMP((puchar)CR->Rsp, 64);
#else
	CRASHLOG("EAX=0x%08X, EBX=0x%08X, ECX=0x%08X, EDX=0x%08X\n", CR->Eax, CR->Ebx, CR->Ecx, CR->Edx);
	CRASHLOG("ESI=0x%08X, EDI=0x%08X, ESP=0x%08X, EBP=0x%08X\n", CR->Esi, CR->Edi, CR->Esp, CR->Ebp);
	CRASHLOG("EIP=0x%08X, EFLAGS=0x%08X\n\n", CR->Eip, CR->EFlags);

	CRASHLOG("Bytes at EIP:\n");
	CRASHLOG_DUMP((puchar)CR->Eip, 16);

	CRASHLOG("Bytes at ESP:\n");
	CRASHLOG_DUMP((puchar)CR->Esp, 64);
#endif
}
//----------------------------------------------------------------------------------
LONG __stdcall OrionUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionInfo)
{
	static int errorCount = 0;
	static uint lastErrorTime = 0;

	uint ticks = GetTickCount();

	errorCount++;

	if (exceptionInfo->ExceptionRecord)
	{
#if defined(_WIN64)
		CRASHLOG("Unhandled exception #%i: 0x%016LX at %016LX\n", errorCount, exceptionInfo->ExceptionRecord->ExceptionCode, exceptionInfo->ExceptionRecord->ExceptionAddress);
#else
		CRASHLOG("Unhandled exception #%i: 0x%08X at %08X\n", errorCount, exceptionInfo->ExceptionRecord->ExceptionCode, exceptionInfo->ExceptionRecord->ExceptionAddress);
#endif

		if (errorCount > 10 && (ticks - lastErrorTime) < 5000)
		{
			OrionStackWalker sw;
			sw.ShowCallstack(GetCurrentThread(), exceptionInfo->ContextRecord);

			DumpLibraryInformation();

			DumpCurrentRegistersInformation(exceptionInfo->ContextRecord);

			WISP_FILE::CMappedFile file;

			wchar_t fileName[MAX_PATH] = { 0 };
			GetModuleFileName(0, fileName, MAX_PATH);
			bool crashlog = false;
			if (file.Load(fileName))
			{
				UCHAR_LIST pattern;
#if defined(_WIN64)
				puchar eipBytes = (puchar)exceptionInfo->ContextRecord->Rip;
#else
				puchar eipBytes = (puchar)exceptionInfo->ContextRecord->Eip;
#endif

				IFOR(i, 0, 16)
					pattern.push_back(eipBytes[i]);

				UINT_LIST list = COrion::FindPattern(file.Start, (int)file.Size, pattern);

				for (const int &item : list)
					CRASHLOG("Address in exe (by EIP): 0x%08X\n", item);

				file.Unload();

				if (g_PacketManager.m_PacketsStack.empty())
					CRASHLOG("\nPackets stack is empty.\n");
				else
				{
					CRASHLOG("\nPackets in stack:\n");

					for (deque<UCHAR_LIST>::iterator i = g_PacketManager.m_PacketsStack.begin(); i != g_PacketManager.m_PacketsStack.end(); ++i)
					{
						CRASHLOG("Packet data:\n");
						CRASHLOG_DUMP((puchar)i->data(), i->size());
					}
				}
				crashlog = true;
			}

			string reporterPath = g_App.ExeFilePath("Reporter.dll");
			string functionName = "SendCrashReport";
			HMODULE dll = LoadLibraryA(reporterPath.c_str());
			bool reportSent = false;
			if (dll != NULL)
			{
				typedef void __cdecl dllFunc();

				dllFunc *initFunc = reinterpret_cast<dllFunc*>(GetProcAddress(dll, functionName.c_str()));
				if (initFunc != NULL)
				{
					initFunc();
					reportSent = true;
				}
			}

			g_Orion.Uninstall();

			if (!reportSent)
			{
				string msg = "Orion client performed an unrecoverable operation.";
				if (crashlog)
					msg += "\nCrashlog has been created in crashlogs folder.";
				msg += "\nTerminating...";

				MessageBoxA(0, msg.c_str(), 0, MB_ICONSTOP | MB_OK);
			}

			ExitProcess(1);
		}

		if (ticks - lastErrorTime > 5000)
		{
			errorCount = 0;
			lastErrorTime = ticks;
		}

		if (errorCount == 1)
			DumpCurrentRegistersInformation(exceptionInfo->ContextRecord);
	}

	//	return EXCEPTION_CONTINUE_SEARCH;
	return EXCEPTION_CONTINUE_EXECUTION;
}
//----------------------------------------------------------------------------------
<commit_msg>Replaced Reporter.dll with OrionCrashReporter.exe, init on crash and passing path to crashlog as args<commit_after>// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
//----------------------------------------------------------------------------------
#include "stdafx.h"

#include <psapi.h>
#include <tlhelp32.h>
//----------------------------------------------------------------------------------
string GetMemStorageText(const uint &storage)
{
	switch (storage)
	{
		case MEM_FREE:
			return "Free";
		case MEM_RESERVE:
			return "Reserve";
		case MEM_IMAGE:
			return "Image";
		case MEM_MAPPED:
			return "Mapped";
		case MEM_PRIVATE:
			return "Private";
		default:
			break;
	}

	return "Unknown";
}
//----------------------------------------------------------------------------------
inline BOOL ModuleFind(const HANDLE &snapshot, PVOID pvBaseAddr, PMODULEENTRY32 pme)
{
	for (BOOL ok = Module32First(snapshot, pme); ok; ok = Module32Next(snapshot, pme))
	{
		if (pme->modBaseAddr == pvBaseAddr)
			return TRUE;
	}

	return FALSE;
}
//----------------------------------------------------------------------------------
void DumpRegionInfo(const HANDLE &snapshot, HANDLE hProcess, VMQUERY &vmq)
{
	if (vmq.dwRgnStorage == MEM_FREE)
		return;

	string filePath = "";

	if (vmq.pvRgnBaseAddress != NULL)
	{
		MODULEENTRY32 me = { sizeof(me) };
		if (ModuleFind(snapshot, vmq.pvRgnBaseAddress, &me))
			filePath = ToString(me.szExePath);
		else
		{
			wchar_t filename[MAX_PATH + 1];
			DWORD d = GetMappedFileName(hProcess, vmq.pvRgnBaseAddress, filename, MAX_PATH);

			if (d)
				filePath = ToString(filename);
		}
	}

	if (vmq.fRgnIsAStack)
		filePath = "Thread Stack";

	CRASHLOG("Address: 0x%08X => 0x%08X Storage: '%s' size: %i blocks: %i path: %s\n", vmq.pvBlkBaseAddress, (puchar)vmq.pvBlkBaseAddress + vmq.RgnSize, GetMemStorageText(vmq.dwBlkStorage).c_str(), vmq.RgnSize, vmq.dwRgnBlocks, filePath.c_str());
}
//----------------------------------------------------------------------------------
void DumpLibraryInformation()
{
#if USE_WISP_DEBUG_FUNCTION_NAMES == 1
	CRASHLOG("trace functions:\n");
	for (const string &str : g_WispDebugFunStack)
		CRASHLOG("%s\n", str.c_str());
#elif USE_WISP_DEBUG_FUNCTION_NAMES == 2
	if (g_WispCurrentFunctionName != NULL)
	{
		CRASHLOG("trace function: %s\n", g_WispCurrentFunctionName);
	}
#endif

	static bool libraryInfoPrinted = false;

	if (!libraryInfoPrinted)
	{
		libraryInfoPrinted = true;

		CRASHLOG("Library information:\n");

		DWORD processId = 0;
		GetWindowThreadProcessId(g_OrionWindow.Handle, &processId);

		HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);

		if (process == NULL)
		{
			CRASHLOG("::OpenProcess failed!\n");
			return;
		}

		HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, processId);

		if (snapshot == NULL)
		{
			CRASHLOG("::CreateToolhelp32Snapshot failed!\n");
			CloseHandle(process);
			return;
		}

		PVOID address = NULL;

		while (true)
		{
			VMQUERY vmq = { 0 };

			if (!VMQuery(process, address, &vmq))
				break;

			DumpRegionInfo(snapshot, process, vmq);

			address = ((puchar)vmq.pvRgnBaseAddress + vmq.RgnSize);
		}

		CloseHandle(snapshot);
		CloseHandle(process);
	}
}
//----------------------------------------------------------------------------------
void DumpCurrentRegistersInformation(CONTEXT* CR)
{
#if defined(_WIN64)
	CRASHLOG("EAX=0x%016LX, EBX=0x%016LX, ECX=0x%016LX, EDX=0x%016LX\n", CR->Rax, CR->Rbx, CR->Rcx, CR->Rdx);
	CRASHLOG("ESI=0x%016LX, EDI=0x%016LX, ESP=0x%016LX, EBP=0x%016LX\n", CR->Rsi, CR->Rdi, CR->Rsp, CR->Rbp);
	CRASHLOG("EIP=0x%016LX, EFLAGS=0x%016LX\n\n", CR->Rip, CR->EFlags);

	CRASHLOG("Bytes at EIP:\n");
	CRASHLOG_DUMP((puchar)CR->Rip, 16);

	CRASHLOG("Bytes at ESP:\n");
	CRASHLOG_DUMP((puchar)CR->Rsp, 64);
#else
	CRASHLOG("EAX=0x%08X, EBX=0x%08X, ECX=0x%08X, EDX=0x%08X\n", CR->Eax, CR->Ebx, CR->Ecx, CR->Edx);
	CRASHLOG("ESI=0x%08X, EDI=0x%08X, ESP=0x%08X, EBP=0x%08X\n", CR->Esi, CR->Edi, CR->Esp, CR->Ebp);
	CRASHLOG("EIP=0x%08X, EFLAGS=0x%08X\n\n", CR->Eip, CR->EFlags);

	CRASHLOG("Bytes at EIP:\n");
	CRASHLOG_DUMP((puchar)CR->Eip, 16);

	CRASHLOG("Bytes at ESP:\n");
	CRASHLOG_DUMP((puchar)CR->Esp, 64);
#endif
}
//----------------------------------------------------------------------------------
LONG __stdcall OrionUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionInfo)
{
	static int errorCount = 0;
	static uint lastErrorTime = 0;

	uint ticks = GetTickCount();

	errorCount++;

	if (exceptionInfo->ExceptionRecord)
	{
#if defined(_WIN64)
		CRASHLOG("Unhandled exception #%i: 0x%016LX at %016LX\n", errorCount, exceptionInfo->ExceptionRecord->ExceptionCode, exceptionInfo->ExceptionRecord->ExceptionAddress);
#else
		CRASHLOG("Unhandled exception #%i: 0x%08X at %08X\n", errorCount, exceptionInfo->ExceptionRecord->ExceptionCode, exceptionInfo->ExceptionRecord->ExceptionAddress);
#endif

		if (errorCount > 10 && (ticks - lastErrorTime) < 5000)
		{
			OrionStackWalker sw;
			sw.ShowCallstack(GetCurrentThread(), exceptionInfo->ContextRecord);

			DumpLibraryInformation();

			DumpCurrentRegistersInformation(exceptionInfo->ContextRecord);

			WISP_FILE::CMappedFile file;

			wchar_t fileName[MAX_PATH] = { 0 };
			GetModuleFileName(0, fileName, MAX_PATH);
			bool crashlog = false;
			if (file.Load(fileName))
			{
				UCHAR_LIST pattern;
#if defined(_WIN64)
				puchar eipBytes = (puchar)exceptionInfo->ContextRecord->Rip;
#else
				puchar eipBytes = (puchar)exceptionInfo->ContextRecord->Eip;
#endif

				IFOR(i, 0, 16)
					pattern.push_back(eipBytes[i]);

				UINT_LIST list = COrion::FindPattern(file.Start, (int)file.Size, pattern);

				for (const int &item : list)
					CRASHLOG("Address in exe (by EIP): 0x%08X\n", item);

				file.Unload();

				if (g_PacketManager.m_PacketsStack.empty())
					CRASHLOG("\nPackets stack is empty.\n");
				else
				{
					CRASHLOG("\nPackets in stack:\n");

					for (deque<UCHAR_LIST>::iterator i = g_PacketManager.m_PacketsStack.begin(); i != g_PacketManager.m_PacketsStack.end(); ++i)
					{
						CRASHLOG("Packet data:\n");
						CRASHLOG_DUMP((puchar)i->data(), i->size());
					}
				}
				crashlog = true;
			}

			Wisp::g_WispCrashLogger.Close();
			string crashlogPath = g_App.ExeFilePath("OrionCrashReporter.exe ") + Wisp::g_WispCrashLogger.GetFileName();
			STARTUPINFOA si;
			PROCESS_INFORMATION pi;
			ZeroMemory(&si, sizeof(si));
			si.cb = sizeof(si);
			ZeroMemory(&pi, sizeof(pi));
			bool reportSent = CreateProcessA(NULL,   // No module name (use command line)
				&crashlogPath[0],        // Command line
				NULL,           // Process handle not inheritable
				NULL,           // Thread handle not inheritable
				FALSE,          // Set handle inheritance to FALSE
				0,              // No creation flags
				NULL,           // Use parent's environment block
				NULL,           // Use parent's starting directory
				&si,            // Pointer to STARTUPINFO structure
				&pi);

			g_Orion.Uninstall();

			if (!reportSent)
			{
				string msg = "Orion client performed an unrecoverable operation.";
				if (crashlog)
					msg += "\nCrashlog has been created in crashlogs folder.";
				msg += "\nTerminating...";

				MessageBoxA(0, msg.c_str(), 0, MB_ICONSTOP | MB_OK);
			}

			ExitProcess(1);
		}

		if (ticks - lastErrorTime > 5000)
		{
			errorCount = 0;
			lastErrorTime = ticks;
		}

		if (errorCount == 1)
			DumpCurrentRegistersInformation(exceptionInfo->ContextRecord);
	}

	//	return EXCEPTION_CONTINUE_SEARCH;
	return EXCEPTION_CONTINUE_EXECUTION;
}
//----------------------------------------------------------------------------------
<|endoftext|>


<commit_before>/**************************************************************************
*
* Copyright 2016 by Matthew McGowan.
* Copyright 2014 by Petr Gargulak. eGUI Community.
* Copyright 2009-2013 by Petr Gargulak. Freescale Semiconductor, Inc.
*
***************************************************************************
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License Version 3
* or later (the "LGPL").
*
* As a special exception, the copyright holders of the eGUI project give you
* permission to link the eGUI sources with independent modules to produce an
* executable, regardless of the license terms of these independent modules,
* and to copy and distribute the resulting executable under terms of your
* choice, provided that you also meet, for each linked independent module,
* the terms and conditions of the license of that module.
* An independent module is a module which is not derived from or based
* on this library.
* If you modify the eGUI sources, you may extend this exception
* to your version of the eGUI sources, but you are not obligated
* to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*
*/

extern "C" {
#include "d4d.h"            // include of all public items (types, function etc) of D4D driver
#include "common_files/d4d_lldapi.h"     // include non public low level driver interface header file (types, function prototypes, enums etc. )
#include "common_files/d4d_private.h"    // include the private header file that contains perprocessor macros as D4D_MK_STR
}
#include "application.h"
#include "WebSocketsServer.h"
#include <vector>

/******************************************************************************
* D4D LCD HW Driver setting  constants
*
*//*! @addtogroup doxd4d_lcdhwfb_const
* @{
*******************************************************************************/

/*! @brief  Identification string of driver - must be same as name D4DLCDHWFB_FUNCTIONS structure + "_ID"
 it is used for enable the code for compilation   */
#define d4dlcdhw_websocket_server_fb_ID 1

 /*! @} End of doxd4d_lcdhwfb_const                                           */

// compilation enable preprocessor condition
// the string d4dtch_websocket_server_fb_ID must be replaced by define created one line up
#if (D4D_MK_STR(D4D_LLD_LCD_HW) == d4dlcdhw_websocket_server_fb_ID)

  // include of low level driver heaser file
  // it will be included into wole project only in case that this driver is selected in main D4D configuration file
  #include "low_level_drivers/LCD/lcd_hw_interface/websocket_server_fb/d4dlcdhw_websocket_server_fb.h"
  /******************************************************************************
  * Macros
  ******************************************************************************/

  /******************************************************************************
  * Internal function prototypes
  ******************************************************************************/

  static unsigned char D4DLCDHW_Init_WebsocketServerFb(void);
  static unsigned char D4DLCDHW_DeInit_WebsocketServerFb(void);
  static void D4DLCDHW_WriteData_WebsocketServerFb(unsigned long addr, D4D_COLOR value);
  static D4D_COLOR D4DLCDHW_ReadData_WebsocketServerFb(unsigned long addr);
  static D4DLCD_FRAMEBUFF_DESC* D4DLCDHW_GetFbDescriptor_WebsocketServerFb(void);
  static unsigned char D4DLCDHW_PinCtl_WebsocketServerFb(D4DLCDHW_PINS pinId, D4DHW_PIN_STATE setState);
  static void D4DLCD_FlushBuffer_WebsocketServerFb(D4DLCD_FLUSH_MODE mode);

  /**************************************************************//*!
  *
  * Global variables
  *
  ******************************************************************/

  // the main structure that contains low level driver api functions
  // the name fo this structure is used for recognizing of configured low level driver of whole D4D
  // so this name has to be used in main configuration header file of D4D driver to enable this driver
  extern "C" const D4DLCDHWFB_FUNCTIONS d4dlcdhw_websocket_server_fb __attribute__((used)) =
  {
    D4DLCDHW_Init_WebsocketServerFb,
    D4DLCDHW_WriteData_WebsocketServerFb,
    D4DLCDHW_ReadData_WebsocketServerFb,
	D4DLCDHW_GetFbDescriptor_WebsocketServerFb,
    D4DLCDHW_PinCtl_WebsocketServerFb,
    D4DLCD_FlushBuffer_WebsocketServerFb,
    D4DLCDHW_DeInit_WebsocketServerFb
  };
  /**************************************************************//*!
  *
  * Local variables
  *
  ******************************************************************/

  /**************************************************************//*!
  *
  * Functions bodies
  *
  ******************************************************************/

static void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length);

struct __attribute__((packed)) Pixel
{
	uint32_t address_;
	uint32_t color_;

	Pixel() = default;
	~Pixel() = default;

	Pixel(uint32_t address, uint32_t color)
	: address_(address), color_(color)
	{
	}
};

extern "C" void websocket_touch(uint16_t x, uint16_t y);

class DisplayServer;
class DisplayBuffer
{
	static const uint32_t count = D4D_SCREEN_SIZE_LONGER_SIDE*D4D_SCREEN_SIZE_SHORTER_SIDE;
	D4D_COLOR pixels[count];
public:

	inline void set_pixel(uint32_t offset, D4D_COLOR color)
	{
		// addresses are given as offsets
		if (offset<count)
			pixels[offset] = color;
	}

	void push(DisplayServer& server);
};

static_assert(sizeof(D4D_COLOR)==2, "expected D4D_COLOR to be 16-bit");

class NoOpDisplayBuffer
{
	inline void set_pixel(uint32_t offset, D4D_COLOR color) {

	}

	void push(DisplayServer& server) {}
};

#if PLATFORM_ID==3
typedef DisplayBuffer DisplayBufferImpl;
#else
typedef NoOpDisplayBuffer DisplayBufferImpl;
#endif

class DisplayServer
{
	WebSocketsServer server;

	const static int pixel_count = D4D_SCREEN_SIZE_LONGER_SIDE;
	std::vector<Pixel> pixels;
	DisplayBufferImpl buffer;

public:
	DisplayServer(uint16_t port, const String& origin) : server(port, origin) {
		pixels.reserve(pixel_count);
	}

	bool start()
	{
		server.begin();
		server.onEvent(webSocketEvent);
		INFO("started DisplayServer");
		return true;
	}

	void loop()
	{
		server.loop();
	}

	bool stop()
	{
		return true;
	}

	void process_command(const uint8_t* data, size_t length)
	{
		if (length>=1) {
			int cmd = data[0];
			DEBUG("command %d, %d", cmd, length);
			switch (cmd) {
			case 1:
				if (length>=5) {
					uint16_t x = *((uint16_t*)(data+1));
					uint16_t y = *((uint16_t*)(data+3));
					websocket_touch(x, y);
					DEBUG("touch %d, %d", x, y);
				}
				break;
			}
		}
	}

	void handleEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
	{
		switch (type) {
		case WStype_CONNECTED:
			{
				buffer.push(*this);

				D4D_SCREEN* screen = D4D_GetActiveScreen();
				// invalidate the new screen (global complete redraw, not individual objects)
				// D4D_InvalidateScreen(D4D_GetActiveScreen(), D4D_TRUE);
				if (screen) {
					D4D_InvalidateScreen(screen, D4D_TRUE);
					D4D_RedrawScreen(screen);
				}
			}
			break;
		case WStype_BIN:
			process_command(payload, length);
			break;
		default:
			break;
		}
	}

	void flush()
	{
		uint32_t size = pixels.size();
		if (size) {
			Pixel* data = pixels.data();
			server.broadcastBIN((const uint8_t*)data, sizeof(Pixel)*size);
			pixels.clear();
		}
	}

	void add_pixel(uint32_t offset, D4D_COLOR color)
	{
		if (pixels.size()==pixels.capacity())
			flush();
		pixels.push_back(Pixel(offset, color));
		buffer.set_pixel(offset, color);
	}
};

void DisplayBuffer::push(DisplayServer& server)
{
	for (uint32_t i=0; i<count; i++)
		server.add_pixel(i, pixels[i]);
	server.flush();
}

DisplayServer server(0x1cd0, "*"); // 7376

extern "C" void loop_ws_display() {
	server.loop();
}

static void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
	server.handleEvent(num, type, payload, length);
}

  /**************************************************************************/ /*!
  * @brief   The function is used for initialization of this low level driver
  * @return  result: 1 - Success; 0 - Failed
  * @note    This should initilize all neccessary things to run template lcd hardware frame buffer interface driver.
  *******************************************************************************/
  static unsigned char D4DLCDHW_Init_WebsocketServerFb(void)
  {
	  return server.start();
  }

  /**************************************************************************/ /*!
  * @brief   The function is used for deinitialization of this low level driver
  * @return  result: 1 - Success; 0 - Failed
  * @note    This should deinitilize all neccessary things to run template lcd hardware frame buffer interface driver.
  *******************************************************************************/
  static unsigned char D4DLCDHW_DeInit_WebsocketServerFb(void)
  {
	  return server.stop();
  }

  /**************************************************************************/ /*!
  * @brief   The function send the one pixel variable into frame buffer
  * @param   addr - the absolute address to frame buffer
  * @param   value - the pixel value
  * @return  none
  * @note    This function writes one pixel on specified address to frame buffer
  *******************************************************************************/
  static void D4DLCDHW_WriteData_WebsocketServerFb(unsigned long addr, D4D_COLOR value)
  {
	  server.add_pixel(uint32_t(addr>>1), value);
  }

//  D4D_COLOR buffer[D4D_SCREEN_SIZE_LONGER_SIDE*D4D_SCREEN_SIZE_SHORTER_SIDE];

  /**************************************************************************/ /*!
  * @brief   The function reads the one pixel variable from frame buffer
  * @param   addr - the absolute address to frame buffer
  * @return  the pixel value
  * @note    This function reads one pixel from specified address in frame buffer
  *******************************************************************************/
  static D4D_COLOR D4DLCDHW_ReadData_WebsocketServerFb(unsigned long addr)
  {
	  return 0;
  }

  /**************************************************************************/ /*!
  * @brief   The function return the pointer on filled frame buffer descriptor
  * @return  pointer to frame buffer descriptor
  * @note    Just to handle pointer to frame buffer descriptor
  *******************************************************************************/
  static D4DLCD_FRAMEBUFF_DESC* D4DLCDHW_GetFbDescriptor_WebsocketServerFb(void)
  {
	  static_assert(sizeof(void*)<=sizeof(D4DLCD_FRAMEBUFF_DESC::fb_start_addr), "cannot cast to a long");
	  static D4DLCD_FRAMEBUFF_DESC desc;
	  desc.fb_start_addr = 0; // (unsigned long)&buffer;
	  desc.lcd_x_max = D4D_SCREEN_SIZE_LONGER_SIDE;
	  desc.lcd_y_max = D4D_SCREEN_SIZE_SHORTER_SIDE;
	  desc.bpp_byte = sizeof(D4D_COLOR);
	  static_assert(sizeof(D4D_COLOR)==2, "expected 16-bits per pixel");
	  return &desc;
  }

  /**************************************************************************/ /*!
  * @brief   The function allows control GPIO pins for LCD conrol purposes
  * @param   pinId - the pin definition
  * @param   setState - the pin action/state definition
  * @return  for Get action retuns the pin value
  * @note    This function controls the additional control pins
  *******************************************************************************/
  static unsigned char D4DLCDHW_PinCtl_WebsocketServerFb(D4DLCDHW_PINS pinId, D4DHW_PIN_STATE setState)
  {
	  return 0;
  }

  /**************************************************************************/ /*!
  * @brief   For buffered low level interfaces is used to inform
  *            driver the complete object is drawed and pending pixels should be flushed
  * @param   mode - mode of Flush
  * @return  none
  * @note    This function just notify the driver that eGUI finish drawing element/object/screen to allow driver handle any kind of caching memmory.
  *******************************************************************************/
  static void D4DLCD_FlushBuffer_WebsocketServerFb(D4DLCD_FLUSH_MODE mode)
  {
	  server.flush();
	  if (mode == D4DLCD_FLSH_FORCE) {
		  server.loop();
	  }
  }

  /*! @} End of doxd4d_tch_func                                               */

#endif //(D4D_MK_STR(D4D_LLD_LCD_HW) == d4dlcdhw_template_fb_ID)
<commit_msg>remove unused assertion.<commit_after>/**************************************************************************
*
* Copyright 2016 by Matthew McGowan.
* Copyright 2014 by Petr Gargulak. eGUI Community.
* Copyright 2009-2013 by Petr Gargulak. Freescale Semiconductor, Inc.
*
***************************************************************************
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License Version 3
* or later (the "LGPL").
*
* As a special exception, the copyright holders of the eGUI project give you
* permission to link the eGUI sources with independent modules to produce an
* executable, regardless of the license terms of these independent modules,
* and to copy and distribute the resulting executable under terms of your
* choice, provided that you also meet, for each linked independent module,
* the terms and conditions of the license of that module.
* An independent module is a module which is not derived from or based
* on this library.
* If you modify the eGUI sources, you may extend this exception
* to your version of the eGUI sources, but you are not obligated
* to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*
*/

extern "C" {
#include "d4d.h"            // include of all public items (types, function etc) of D4D driver
#include "common_files/d4d_lldapi.h"     // include non public low level driver interface header file (types, function prototypes, enums etc. )
#include "common_files/d4d_private.h"    // include the private header file that contains perprocessor macros as D4D_MK_STR
}
#include "application.h"
#include "WebSocketsServer.h"
#include <vector>

/******************************************************************************
* D4D LCD HW Driver setting  constants
*
*//*! @addtogroup doxd4d_lcdhwfb_const
* @{
*******************************************************************************/

/*! @brief  Identification string of driver - must be same as name D4DLCDHWFB_FUNCTIONS structure + "_ID"
 it is used for enable the code for compilation   */
#define d4dlcdhw_websocket_server_fb_ID 1

 /*! @} End of doxd4d_lcdhwfb_const                                           */

// compilation enable preprocessor condition
// the string d4dtch_websocket_server_fb_ID must be replaced by define created one line up
#if (D4D_MK_STR(D4D_LLD_LCD_HW) == d4dlcdhw_websocket_server_fb_ID)

  // include of low level driver heaser file
  // it will be included into wole project only in case that this driver is selected in main D4D configuration file
  #include "low_level_drivers/LCD/lcd_hw_interface/websocket_server_fb/d4dlcdhw_websocket_server_fb.h"
  /******************************************************************************
  * Macros
  ******************************************************************************/

  /******************************************************************************
  * Internal function prototypes
  ******************************************************************************/

  static unsigned char D4DLCDHW_Init_WebsocketServerFb(void);
  static unsigned char D4DLCDHW_DeInit_WebsocketServerFb(void);
  static void D4DLCDHW_WriteData_WebsocketServerFb(unsigned long addr, D4D_COLOR value);
  static D4D_COLOR D4DLCDHW_ReadData_WebsocketServerFb(unsigned long addr);
  static D4DLCD_FRAMEBUFF_DESC* D4DLCDHW_GetFbDescriptor_WebsocketServerFb(void);
  static unsigned char D4DLCDHW_PinCtl_WebsocketServerFb(D4DLCDHW_PINS pinId, D4DHW_PIN_STATE setState);
  static void D4DLCD_FlushBuffer_WebsocketServerFb(D4DLCD_FLUSH_MODE mode);

  /**************************************************************//*!
  *
  * Global variables
  *
  ******************************************************************/

  // the main structure that contains low level driver api functions
  // the name fo this structure is used for recognizing of configured low level driver of whole D4D
  // so this name has to be used in main configuration header file of D4D driver to enable this driver
  extern "C" const D4DLCDHWFB_FUNCTIONS d4dlcdhw_websocket_server_fb __attribute__((used)) =
  {
    D4DLCDHW_Init_WebsocketServerFb,
    D4DLCDHW_WriteData_WebsocketServerFb,
    D4DLCDHW_ReadData_WebsocketServerFb,
	D4DLCDHW_GetFbDescriptor_WebsocketServerFb,
    D4DLCDHW_PinCtl_WebsocketServerFb,
    D4DLCD_FlushBuffer_WebsocketServerFb,
    D4DLCDHW_DeInit_WebsocketServerFb
  };
  /**************************************************************//*!
  *
  * Local variables
  *
  ******************************************************************/

  /**************************************************************//*!
  *
  * Functions bodies
  *
  ******************************************************************/

static void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length);

struct __attribute__((packed)) Pixel
{
	uint32_t address_;
	uint32_t color_;

	Pixel() = default;
	~Pixel() = default;

	Pixel(uint32_t address, uint32_t color)
	: address_(address), color_(color)
	{
	}
};

extern "C" void websocket_touch(uint16_t x, uint16_t y);

class DisplayServer;
class DisplayBuffer
{
	static const uint32_t count = D4D_SCREEN_SIZE_LONGER_SIDE*D4D_SCREEN_SIZE_SHORTER_SIDE;
	D4D_COLOR pixels[count];
public:

	inline void set_pixel(uint32_t offset, D4D_COLOR color)
	{
		// addresses are given as offsets
		if (offset<count)
			pixels[offset] = color;
	}

	void push(DisplayServer& server);
};

static_assert(sizeof(D4D_COLOR)==2, "expected D4D_COLOR to be 16-bit");

class NoOpDisplayBuffer
{
	inline void set_pixel(uint32_t offset, D4D_COLOR color) {

	}

	void push(DisplayServer& server) {}
};

#if PLATFORM_ID==3
typedef DisplayBuffer DisplayBufferImpl;
#else
typedef NoOpDisplayBuffer DisplayBufferImpl;
#endif

class DisplayServer
{
	WebSocketsServer server;

	const static int pixel_count = D4D_SCREEN_SIZE_LONGER_SIDE;
	std::vector<Pixel> pixels;
	DisplayBufferImpl buffer;

public:
	DisplayServer(uint16_t port, const String& origin) : server(port, origin) {
		pixels.reserve(pixel_count);
	}

	bool start()
	{
		server.begin();
		server.onEvent(webSocketEvent);
		INFO("started DisplayServer");
		return true;
	}

	void loop()
	{
		server.loop();
	}

	bool stop()
	{
		return true;
	}

	void process_command(const uint8_t* data, size_t length)
	{
		if (length>=1) {
			int cmd = data[0];
			DEBUG("command %d, %d", cmd, length);
			switch (cmd) {
			case 1:
				if (length>=5) {
					uint16_t x = *((uint16_t*)(data+1));
					uint16_t y = *((uint16_t*)(data+3));
					websocket_touch(x, y);
					DEBUG("touch %d, %d", x, y);
				}
				break;
			}
		}
	}

	void handleEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
	{
		switch (type) {
		case WStype_CONNECTED:
			{
				buffer.push(*this);

				D4D_SCREEN* screen = D4D_GetActiveScreen();
				// invalidate the new screen (global complete redraw, not individual objects)
				// D4D_InvalidateScreen(D4D_GetActiveScreen(), D4D_TRUE);
				if (screen) {
					D4D_InvalidateScreen(screen, D4D_TRUE);
					D4D_RedrawScreen(screen);
				}
			}
			break;
		case WStype_BIN:
			process_command(payload, length);
			break;
		default:
			break;
		}
	}

	void flush()
	{
		uint32_t size = pixels.size();
		if (size) {
			Pixel* data = pixels.data();
			server.broadcastBIN((const uint8_t*)data, sizeof(Pixel)*size);
			pixels.clear();
		}
	}

	void add_pixel(uint32_t offset, D4D_COLOR color)
	{
		if (pixels.size()==pixels.capacity())
			flush();
		pixels.push_back(Pixel(offset, color));
		buffer.set_pixel(offset, color);
	}
};

void DisplayBuffer::push(DisplayServer& server)
{
	for (uint32_t i=0; i<count; i++)
		server.add_pixel(i, pixels[i]);
	server.flush();
}

DisplayServer server(0x1cd0, "*"); // 7376

extern "C" void loop_ws_display() {
	server.loop();
}

static void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
	server.handleEvent(num, type, payload, length);
}

  /**************************************************************************/ /*!
  * @brief   The function is used for initialization of this low level driver
  * @return  result: 1 - Success; 0 - Failed
  * @note    This should initilize all neccessary things to run template lcd hardware frame buffer interface driver.
  *******************************************************************************/
  static unsigned char D4DLCDHW_Init_WebsocketServerFb(void)
  {
	  return server.start();
  }

  /**************************************************************************/ /*!
  * @brief   The function is used for deinitialization of this low level driver
  * @return  result: 1 - Success; 0 - Failed
  * @note    This should deinitilize all neccessary things to run template lcd hardware frame buffer interface driver.
  *******************************************************************************/
  static unsigned char D4DLCDHW_DeInit_WebsocketServerFb(void)
  {
	  return server.stop();
  }

  /**************************************************************************/ /*!
  * @brief   The function send the one pixel variable into frame buffer
  * @param   addr - the absolute address to frame buffer
  * @param   value - the pixel value
  * @return  none
  * @note    This function writes one pixel on specified address to frame buffer
  *******************************************************************************/
  static void D4DLCDHW_WriteData_WebsocketServerFb(unsigned long addr, D4D_COLOR value)
  {
	  server.add_pixel(uint32_t(addr>>1), value);
  }

//  D4D_COLOR buffer[D4D_SCREEN_SIZE_LONGER_SIDE*D4D_SCREEN_SIZE_SHORTER_SIDE];

  /**************************************************************************/ /*!
  * @brief   The function reads the one pixel variable from frame buffer
  * @param   addr - the absolute address to frame buffer
  * @return  the pixel value
  * @note    This function reads one pixel from specified address in frame buffer
  *******************************************************************************/
  static D4D_COLOR D4DLCDHW_ReadData_WebsocketServerFb(unsigned long addr)
  {
	  return 0;
  }

  /**************************************************************************/ /*!
  * @brief   The function return the pointer on filled frame buffer descriptor
  * @return  pointer to frame buffer descriptor
  * @note    Just to handle pointer to frame buffer descriptor
  *******************************************************************************/
  static D4DLCD_FRAMEBUFF_DESC* D4DLCDHW_GetFbDescriptor_WebsocketServerFb(void)
  {
	  static D4DLCD_FRAMEBUFF_DESC desc;
	  desc.fb_start_addr = 0;
	  desc.lcd_x_max = D4D_SCREEN_SIZE_LONGER_SIDE;
	  desc.lcd_y_max = D4D_SCREEN_SIZE_SHORTER_SIDE;
	  desc.bpp_byte = sizeof(D4D_COLOR);
	  static_assert(sizeof(D4D_COLOR)==2, "expected 16-bits per pixel");
	  return &desc;
  }

  /**************************************************************************/ /*!
  * @brief   The function allows control GPIO pins for LCD conrol purposes
  * @param   pinId - the pin definition
  * @param   setState - the pin action/state definition
  * @return  for Get action retuns the pin value
  * @note    This function controls the additional control pins
  *******************************************************************************/
  static unsigned char D4DLCDHW_PinCtl_WebsocketServerFb(D4DLCDHW_PINS pinId, D4DHW_PIN_STATE setState)
  {
	  return 0;
  }

  /**************************************************************************/ /*!
  * @brief   For buffered low level interfaces is used to inform
  *            driver the complete object is drawed and pending pixels should be flushed
  * @param   mode - mode of Flush
  * @return  none
  * @note    This function just notify the driver that eGUI finish drawing element/object/screen to allow driver handle any kind of caching memmory.
  *******************************************************************************/
  static void D4DLCD_FlushBuffer_WebsocketServerFb(D4DLCD_FLUSH_MODE mode)
  {
	  server.flush();
	  if (mode == D4DLCD_FLSH_FORCE) {
		  server.loop();
	  }
  }

  /*! @} End of doxd4d_tch_func                                               */

#endif //(D4D_MK_STR(D4D_LLD_LCD_HW) == d4dlcdhw_template_fb_ID)
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <math.h>

#include "ev3api.h"
#include "Point.h"
#include "FieldMap.h"
#include "InOutManager.h"
#include "ParticleFilter.h"

// 正規分布でsigmaに指定した範囲内の値を取り出す
double Particle::NormalDistribution(double sigma) {
	double alpha = (double)rand()/RAND_MAX;
    double beta = (double)rand()/RAND_MAX * M_PI * 2;
    double tmp = sin(beta);
    return sigma * sqrt(-2 * log(alpha)) * tmp;
}

// 座標を更新して、尤度を再計算する
void Particle::Update(int8_t leftMotorCount, int8_t rightMotorCount)
{
	// 車輪直径(mm)
	double TireDiameter = 81.6;

	// 左右車輪間の距離(mm)
	double d = 128;

	// 左車輪の移動距離
	double Tl = TireDiameter * M_PI * leftMotorCount / 360.0;

	// 右車輪の移動距離
	double Tr = TireDiameter * M_PI * rightMotorCount / 360.0;

	// モータエンコーダ値の変化量
	double D = (Tl + Tr) / 2.0;

	// 角度の変化量
	double theta = (Tr - Tl) / d;

	// ラジアンに変換した前回の角度
	double theta0 = RobotAngle * M_PI / 180.0;

	// 0 - 360度の範囲に変更
	if(RobotAngle + (theta / M_PI * 180.0) > 360) {
		RobotAngle = RobotAngle + (theta / M_PI * 180.0) - 360;
	}else if(RobotAngle + (theta / M_PI * 180.0) < 0) {
		RobotAngle = 360 + RobotAngle +(theta / M_PI * 180.0);
	}else {
		RobotAngle += (theta / M_PI * 180.0);
	}

	// 変化量を、正規分布の値を加味して算出
	double sinc_theta = fabs(theta)<1.0e-10 ? 1.0 : sin(theta)/theta;
	double deltaX = D * cos(theta0 + (theta / 2.0)) * sinc_theta;
	double deltaY = D * sin(theta0 + (theta / 2.0)) * sinc_theta;

	RobotPoint.X += deltaX;
	RobotPoint.Y -= deltaY;

	// 地図上の色情報を取得
	HSLColor mapColor = FieldMap::GetInstance()->GetHSLColor(RobotPoint.X, RobotPoint.Y);

	// センサから得た色情報を元に、尤度を定義
	Likelihood = ColorDecision::GetLikelihoodLuminosity(mapColor.Luminosity, InOutManager::GetInstance()->HSLValue.Luminosity);
}

// 指定した座標で粒子を撒きなおす
void Particle::Reset(Point* newPoint, double newAngle, double pointSigma, double angleSigma)
{
	// 正規分布の値を加味する
	RobotPoint.X = newPoint->X + NormalDistribution(pointSigma);
	RobotPoint.Y = newPoint->Y + NormalDistribution(pointSigma);
	RobotAngle = newAngle + NormalDistribution(angleSigma);

	Likelihood = 0;
}

// 中心値を指定して、パーティクルを散布する
void ParticleFilter::Resampling(Point* newPoint, double newAngle, double pointSigma, double angleSigma)
{
	// 全ての粒子に対しt、中心座標を指定した再散布を行う
	for(Particle* p: ParticleArray) {
		p->Reset(newPoint, newAngle, pointSigma, angleSigma);
	}
}

// パーティクルに対して、座標のアップデートを行う
void ParticleFilter::UpdateParticle(int8_t leftMotorCount, int8_t rightMotorCount)
{
	// すべての粒子に対して状態遷移を実施する
	for(Particle*  p: ParticleArray) {
		p->Update(leftMotorCount,  rightMotorCount);
	}

}

// パーティクルのうち、尤度の高い物の平均値を元に、
// 自身の状態を更新する
void ParticleFilter::Localize()
{
	// 尤度が閾値より高い粒子は、すべて平均化の対象とする。
	const double min = 0.1;

	std::vector<Particle*> pVector;

	for(Particle* p : ParticleArray) {
		if(p->Likelihood > min) pVector.push_back(p);
	}

	double x = 0, y = 0, angleX = 0, angleY = 0, angle = 0;

	// 尤度の高い粒子が存在しない場合には、すべての粒子を平均化
	if(pVector.size() == 0)	{
		for(Particle* p  : ParticleArray) {
			angleX += cos(p->RobotAngle * M_PI / 180);
			angleY += sin(p->RobotAngle * M_PI / 180);
			x += p->RobotPoint.X;
			y += p->RobotPoint.Y;
		}

		x /= PARTICLE_COUNT;
		y /= PARTICLE_COUNT;

		angle = atan2(angleY / PARTICLE_COUNT, angleX / PARTICLE_COUNT) * 180 / M_PI;

	} else {
		// 閾値以上の粒子を平均化
		for(Particle* p : pVector) {
			angleX += cos(p->RobotAngle * M_PI / 180);
			angleY += sin(p->RobotAngle * M_PI / 180);
			x += p->RobotPoint.X;
			y += p->RobotPoint.Y;
		}

		x/=pVector.size();
		y/=pVector.size();

		angle = atan2(angleY / pVector.size() ,angleX / pVector.size()) * 180 / M_PI;
	}

	// atan2の出力範囲が-pi ~ piのため、0-360の範囲に修正
	if(angle < 0) {
		angle = 360 + angle;
	}

	// 算出した平均値でフィールドを更新
	RobotPoint.X = x;
	RobotPoint.Y = y;
	RobotAngle = angle;
}
<commit_msg>sinc関数の式が間違っていたので修正<commit_after>#include <stdlib.h>
#include <math.h>

#include "ev3api.h"
#include "Point.h"
#include "FieldMap.h"
#include "InOutManager.h"
#include "ParticleFilter.h"

// 正規分布でsigmaに指定した範囲内の値を取り出す
double Particle::NormalDistribution(double sigma) {
	double alpha = (double)rand()/RAND_MAX;
    double beta = (double)rand()/RAND_MAX * M_PI * 2;
    double tmp = sin(beta);
    return sigma * sqrt(-2 * log(alpha)) * tmp;
}

// 座標を更新して、尤度を再計算する
void Particle::Update(int8_t leftMotorCount, int8_t rightMotorCount)
{
	// 車輪直径(mm)
	double TireDiameter = 81.6;

	// 左右車輪間の距離(mm)
	double d = 128;

	// 左車輪の移動距離
	double Tl = TireDiameter * M_PI * leftMotorCount / 360.0;

	// 右車輪の移動距離
	double Tr = TireDiameter * M_PI * rightMotorCount / 360.0;

	// モータエンコーダ値の変化量
	double D = (Tl + Tr) / 2.0;

	// 角度の変化量
	double theta = (Tr - Tl) / d;

	// ラジアンに変換した前回の角度
	double theta0 = RobotAngle * M_PI / 180.0;

	// 0 - 360度の範囲に変更
	if(RobotAngle + (theta / M_PI * 180.0) > 360) {
		RobotAngle = RobotAngle + (theta / M_PI * 180.0) - 360;
	}else if(RobotAngle + (theta / M_PI * 180.0) < 0) {
		RobotAngle = 360 + RobotAngle +(theta / M_PI * 180.0);
	}else {
		RobotAngle += (theta / M_PI * 180.0);
	}

	// 変化量を、正規分布の値を加味して算出
	double sinc_theta = fabs(theta/2.0)<1.0e-10 ? 1.0 : sin(theta/2.0)/(theta/2.0);
	double deltaX = D * cos(theta0 + (theta / 2.0)) * sinc_theta;
	double deltaY = D * sin(theta0 + (theta / 2.0)) * sinc_theta;

	RobotPoint.X += deltaX;
	RobotPoint.Y -= deltaY;

	// 地図上の色情報を取得
	HSLColor mapColor = FieldMap::GetInstance()->GetHSLColor(RobotPoint.X, RobotPoint.Y);

	// センサから得た色情報を元に、尤度を定義
	Likelihood = ColorDecision::GetLikelihoodLuminosity(mapColor.Luminosity, InOutManager::GetInstance()->HSLValue.Luminosity);
}

// 指定した座標で粒子を撒きなおす
void Particle::Reset(Point* newPoint, double newAngle, double pointSigma, double angleSigma)
{
	// 正規分布の値を加味する
	RobotPoint.X = newPoint->X + NormalDistribution(pointSigma);
	RobotPoint.Y = newPoint->Y + NormalDistribution(pointSigma);
	RobotAngle = newAngle + NormalDistribution(angleSigma);

	Likelihood = 0;
}

// 中心値を指定して、パーティクルを散布する
void ParticleFilter::Resampling(Point* newPoint, double newAngle, double pointSigma, double angleSigma)
{
	// 全ての粒子に対しt、中心座標を指定した再散布を行う
	for(Particle* p: ParticleArray) {
		p->Reset(newPoint, newAngle, pointSigma, angleSigma);
	}
}

// パーティクルに対して、座標のアップデートを行う
void ParticleFilter::UpdateParticle(int8_t leftMotorCount, int8_t rightMotorCount)
{
	// すべての粒子に対して状態遷移を実施する
	for(Particle*  p: ParticleArray) {
		p->Update(leftMotorCount,  rightMotorCount);
	}

}

// パーティクルのうち、尤度の高い物の平均値を元に、
// 自身の状態を更新する
void ParticleFilter::Localize()
{
	// 尤度が閾値より高い粒子は、すべて平均化の対象とする。
	const double min = 0.1;

	std::vector<Particle*> pVector;

	for(Particle* p : ParticleArray) {
		if(p->Likelihood > min) pVector.push_back(p);
	}

	double x = 0, y = 0, angleX = 0, angleY = 0, angle = 0;

	// 尤度の高い粒子が存在しない場合には、すべての粒子を平均化
	if(pVector.size() == 0)	{
		for(Particle* p  : ParticleArray) {
			angleX += cos(p->RobotAngle * M_PI / 180);
			angleY += sin(p->RobotAngle * M_PI / 180);
			x += p->RobotPoint.X;
			y += p->RobotPoint.Y;
		}

		x /= PARTICLE_COUNT;
		y /= PARTICLE_COUNT;

		angle = atan2(angleY / PARTICLE_COUNT, angleX / PARTICLE_COUNT) * 180 / M_PI;

	} else {
		// 閾値以上の粒子を平均化
		for(Particle* p : pVector) {
			angleX += cos(p->RobotAngle * M_PI / 180);
			angleY += sin(p->RobotAngle * M_PI / 180);
			x += p->RobotPoint.X;
			y += p->RobotPoint.Y;
		}

		x/=pVector.size();
		y/=pVector.size();

		angle = atan2(angleY / pVector.size() ,angleX / pVector.size()) * 180 / M_PI;
	}

	// atan2の出力範囲が-pi ~ piのため、0-360の範囲に修正
	if(angle < 0) {
		angle = 360 + angle;
	}

	// 算出した平均値でフィールドを更新
	RobotPoint.X = x;
	RobotPoint.Y = y;
	RobotAngle = angle;
}
<|endoftext|>


<commit_before><commit_msg>Fix mad poly generation and freezing bug<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <hspp/Actions/Draw.hpp>
#include <hspp/Actions/Generic.hpp>
#include <hspp/Cards/Cards.hpp>
#include <hspp/Games/Game.hpp>
#include <hspp/Games/GameManager.hpp>

#include <effolkronium/random.hpp>

#include <algorithm>

using Random = effolkronium::random_static;

namespace Hearthstonepp
{
Game::Game(GameConfig& gameConfig) : m_gameConfig(gameConfig)
{
    // Add hero and hero power
    GetPlayer1().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player1Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player1Class));
    GetPlayer2().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player2Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player2Class));

    // Set opponent player
    GetPlayer1().SetOpponent(&GetPlayer2());
    GetPlayer2().SetOpponent(&GetPlayer1());
}

Player& Game::GetPlayer1()
{
    return m_players[0];
}

Player& Game::GetPlayer2()
{
    return m_players[1];
}

Player& Game::GetCurrentPlayer()
{
    return *m_currentPlayer;
}

Player& Game::GetOpponentPlayer()
{
    return m_currentPlayer->GetOpponent();
}

void Game::BeginFirst()
{
    // Set next step
    nextStep = Step::BEGIN_SHUFFLE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginShuffle()
{
    // Shuffle cards in deck
    if (m_gameConfig.doShuffle)
    {
        GetPlayer1().GetDeck().Shuffle();
        GetPlayer2().GetDeck().Shuffle();
    }

    // Set next step
    nextStep = Step::BEGIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginDraw()
{
    for (auto& p : m_players)
    {
        // Draw 3 cards
        Generic::Draw(p);
        Generic::Draw(p);
        Generic::Draw(p);

        if (&p != m_firstPlayer)
        {
            // Draw 4th card for second player
            Generic::Draw(p);

            // Give "The Coin" card to second player
            Card coin = Cards::GetInstance().FindCardByID("GAME_005");
            p.GetHand().AddCard(*Entity::GetFromCard(p, std::move(coin)));
        }
    }

    // Set next step
    nextStep =
        m_gameConfig.skipMulligan ? Step::MAIN_BEGIN : Step::BEGIN_MULLIGAN;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginMulligan()
{
    // Do nothing
}

void Game::MainBegin()
{
    // Set next step
    nextStep = Step::MAIN_READY;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainReady()
{
    // Reset the number of attacked
    for (auto& p : m_players)
    {
        // Hero
        p.GetHero()->numAttacked = 0;
        // Field
        for (auto& m : p.GetField().GetAllMinions())
        {
            m->numAttacked = 0;
        }
    }

    // Reset exhaust for current player
    auto& curPlayer = GetCurrentPlayer();
    // Hero
    curPlayer.GetHero()->SetGameTag(GameTag::EXHAUSTED, 0);
    // Weapon
    if (curPlayer.GetHero()->weapon != nullptr)
    {
        curPlayer.GetHero()->weapon->SetGameTag(GameTag::EXHAUSTED, 0);
    }
    // Hero power
    curPlayer.GetHero()->heroPower->SetGameTag(GameTag::EXHAUSTED, 0);
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        m->SetGameTag(GameTag::EXHAUSTED, 0);
    }

    // Set next step
    nextStep = Step::MAIN_START_TRIGGERS;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStartTriggers()
{
    // Set next step
    nextStep = Step::MAIN_RESOURCE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainResource()
{
    auto& curPlayer = GetCurrentPlayer();

    // Add mana crystal to current player
    Generic::ChangeManaCrystal(curPlayer, 1, false);

    // Reset current mana
    curPlayer.currentMana = curPlayer.maximumMana;

    // Set next step
    nextStep = Step::MAIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainDraw()
{
    // Draw a card for current player
    Generic::Draw(GetCurrentPlayer());

    // Set next step
    nextStep = Step::MAIN_START;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStart()
{
    // Set next step
    nextStep = Step::MAIN_ACTION;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainEnd()
{
    // Set next step
    nextStep = Step::MAIN_CLEANUP;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainCleanUp()
{
    auto& curPlayer = GetCurrentPlayer();

    // Unfreeze all characters they control that are Frozen, don't have
    // summoning sickness (or do have Charge) and have not attacked that turn
    // Hero
    if (curPlayer.GetHero()->GetGameTag(GameTag::FROZEN) == 1 &&
        curPlayer.GetHero()->numAttacked == 0)
    {
        curPlayer.GetHero()->SetGameTag(GameTag::FROZEN, 0);
    }
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        if (m->GetGameTag(GameTag::FROZEN) == 1 && m->numAttacked == 0 &&
            m->GetGameTag(GameTag::EXHAUSTED) == 0)
        {
            m->SetGameTag(GameTag::FROZEN, 0);
        }
    }
}

void Game::MainNext()
{
    // Do nothing
}

void Game::FinalWrapUp()
{
    // Do nothing
}

void Game::FinalGameOver()
{
    // Do nothing
}

void Game::StartGame()
{
    // Reverse card order in deck
    if (!m_gameConfig.doShuffle)
    {
        std::reverse(m_gameConfig.player1Deck.begin(),
                     m_gameConfig.player1Deck.end());
        std::reverse(m_gameConfig.player2Deck.begin(),
                     m_gameConfig.player2Deck.end());
    }

    // Set up decks
    for (auto& card : m_gameConfig.player1Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer1(), std::move(card));
        GetPlayer1().GetDeck().AddCard(*entity);
    }
    for (auto& card : m_gameConfig.player2Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer2(), std::move(card));
        GetPlayer2().GetDeck().AddCard(*entity);
    }

    // Determine first player
    switch (m_gameConfig.startPlayer)
    {
        case PlayerType::RANDOM:
        {
            auto val = Random::get(0, 1);
            m_firstPlayer = &m_players[val];
            break;
        }
        case PlayerType::PLAYER1:
            m_firstPlayer = &m_players[0];
            break;
        case PlayerType::PLAYER2:
            m_firstPlayer = &m_players[1];
            break;
    }
    m_currentPlayer = m_firstPlayer;

    // Set first turn
    m_turn = 1;

    // Set next step
    nextStep = Step::BEGIN_FIRST;
    GameManager::ProcessNextStep(*this, nextStep);
}
}  // namespace Hearthstonepp<commit_msg>[ci skip] feat(game-state): Add code to set next step<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <hspp/Actions/Draw.hpp>
#include <hspp/Actions/Generic.hpp>
#include <hspp/Cards/Cards.hpp>
#include <hspp/Games/Game.hpp>
#include <hspp/Games/GameManager.hpp>

#include <effolkronium/random.hpp>

#include <algorithm>

using Random = effolkronium::random_static;

namespace Hearthstonepp
{
Game::Game(GameConfig& gameConfig) : m_gameConfig(gameConfig)
{
    // Add hero and hero power
    GetPlayer1().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player1Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player1Class));
    GetPlayer2().AddHeroAndPower(
        Cards::GetInstance().GetHeroCard(gameConfig.player2Class),
        Cards::GetInstance().GetDefaultHeroPower(gameConfig.player2Class));

    // Set opponent player
    GetPlayer1().SetOpponent(&GetPlayer2());
    GetPlayer2().SetOpponent(&GetPlayer1());
}

Player& Game::GetPlayer1()
{
    return m_players[0];
}

Player& Game::GetPlayer2()
{
    return m_players[1];
}

Player& Game::GetCurrentPlayer()
{
    return *m_currentPlayer;
}

Player& Game::GetOpponentPlayer()
{
    return m_currentPlayer->GetOpponent();
}

void Game::BeginFirst()
{
    // Set next step
    nextStep = Step::BEGIN_SHUFFLE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginShuffle()
{
    // Shuffle cards in deck
    if (m_gameConfig.doShuffle)
    {
        GetPlayer1().GetDeck().Shuffle();
        GetPlayer2().GetDeck().Shuffle();
    }

    // Set next step
    nextStep = Step::BEGIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginDraw()
{
    for (auto& p : m_players)
    {
        // Draw 3 cards
        Generic::Draw(p);
        Generic::Draw(p);
        Generic::Draw(p);

        if (&p != m_firstPlayer)
        {
            // Draw 4th card for second player
            Generic::Draw(p);

            // Give "The Coin" card to second player
            Card coin = Cards::GetInstance().FindCardByID("GAME_005");
            p.GetHand().AddCard(*Entity::GetFromCard(p, std::move(coin)));
        }
    }

    // Set next step
    nextStep =
        m_gameConfig.skipMulligan ? Step::MAIN_BEGIN : Step::BEGIN_MULLIGAN;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::BeginMulligan()
{
    // Do nothing
}

void Game::MainBegin()
{
    // Set next step
    nextStep = Step::MAIN_READY;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainReady()
{
    // Reset the number of attacked
    for (auto& p : m_players)
    {
        // Hero
        p.GetHero()->numAttacked = 0;
        // Field
        for (auto& m : p.GetField().GetAllMinions())
        {
            m->numAttacked = 0;
        }
    }

    // Reset exhaust for current player
    auto& curPlayer = GetCurrentPlayer();
    // Hero
    curPlayer.GetHero()->SetGameTag(GameTag::EXHAUSTED, 0);
    // Weapon
    if (curPlayer.GetHero()->weapon != nullptr)
    {
        curPlayer.GetHero()->weapon->SetGameTag(GameTag::EXHAUSTED, 0);
    }
    // Hero power
    curPlayer.GetHero()->heroPower->SetGameTag(GameTag::EXHAUSTED, 0);
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        m->SetGameTag(GameTag::EXHAUSTED, 0);
    }

    // Set next step
    nextStep = Step::MAIN_START_TRIGGERS;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStartTriggers()
{
    // Set next step
    nextStep = Step::MAIN_RESOURCE;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainResource()
{
    auto& curPlayer = GetCurrentPlayer();

    // Add mana crystal to current player
    Generic::ChangeManaCrystal(curPlayer, 1, false);

    // Reset current mana
    curPlayer.currentMana = curPlayer.maximumMana;

    // Set next step
    nextStep = Step::MAIN_DRAW;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainDraw()
{
    // Draw a card for current player
    Generic::Draw(GetCurrentPlayer());

    // Set next step
    nextStep = Step::MAIN_START;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainStart()
{
    // Set next step
    nextStep = Step::MAIN_ACTION;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainEnd()
{
    // Set next step
    nextStep = Step::MAIN_CLEANUP;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainCleanUp()
{
    auto& curPlayer = GetCurrentPlayer();

    // Unfreeze all characters they control that are Frozen, don't have
    // summoning sickness (or do have Charge) and have not attacked that turn
    // Hero
    if (curPlayer.GetHero()->GetGameTag(GameTag::FROZEN) == 1 &&
        curPlayer.GetHero()->numAttacked == 0)
    {
        curPlayer.GetHero()->SetGameTag(GameTag::FROZEN, 0);
    }
    // Field
    for (auto& m : curPlayer.GetField().GetAllMinions())
    {
        if (m->GetGameTag(GameTag::FROZEN) == 1 && m->numAttacked == 0 &&
            m->GetGameTag(GameTag::EXHAUSTED) == 0)
        {
            m->SetGameTag(GameTag::FROZEN, 0);
        }
    }

    // Set next step
    nextStep = Step::MAIN_NEXT;
    GameManager::ProcessNextStep(*this, nextStep);
}

void Game::MainNext()
{
    // Do nothing
}

void Game::FinalWrapUp()
{
    // Do nothing
}

void Game::FinalGameOver()
{
    // Do nothing
}

void Game::StartGame()
{
    // Reverse card order in deck
    if (!m_gameConfig.doShuffle)
    {
        std::reverse(m_gameConfig.player1Deck.begin(),
                     m_gameConfig.player1Deck.end());
        std::reverse(m_gameConfig.player2Deck.begin(),
                     m_gameConfig.player2Deck.end());
    }

    // Set up decks
    for (auto& card : m_gameConfig.player1Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer1(), std::move(card));
        GetPlayer1().GetDeck().AddCard(*entity);
    }
    for (auto& card : m_gameConfig.player2Deck)
    {
        Entity* entity = Entity::GetFromCard(GetPlayer2(), std::move(card));
        GetPlayer2().GetDeck().AddCard(*entity);
    }

    // Determine first player
    switch (m_gameConfig.startPlayer)
    {
        case PlayerType::RANDOM:
        {
            auto val = Random::get(0, 1);
            m_firstPlayer = &m_players[val];
            break;
        }
        case PlayerType::PLAYER1:
            m_firstPlayer = &m_players[0];
            break;
        case PlayerType::PLAYER2:
            m_firstPlayer = &m_players[1];
            break;
    }
    m_currentPlayer = m_firstPlayer;

    // Set first turn
    m_turn = 1;

    // Set next step
    nextStep = Step::BEGIN_FIRST;
    GameManager::ProcessNextStep(*this, nextStep);
}
}  // namespace Hearthstonepp<|endoftext|>