<commit_before>#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cstdlib>

//Change these values according to your image
#define IMAGE_HEIGHT 32
#define IMAGE_WIDTH  32

void decode(std::string, int*, int*);

int main()
{
	std::string line;
	std::ifstream file ("pic.txt"); //Input file

	if(!file.is_open())
	{
		std::cout << "Error opening file." << std::endl;
		exit(1);
	}

	std::string delimiter = ", ";
	size_t pos = 0;
	std::string token;
	int hex = 0x00, add = 128, counter = 0, inc = 0;
	int image_area = IMAGE_HEIGHT * IMAGE_WIDTH;
	int arr_size = image_area / 8;

	if(image_area % 8 > 0)
		arr_size += 1;

	int hexarr[arr_size];

	for(int i=0; i < IMAGE_HEIGHT; i++)
	{
		std::getline(file, line);

		while((pos = line.find(delimiter)) != std::string::npos)
		{
			token = line.substr(0, pos);
			decode(token, &hex, &add);

			line.erase(0, pos + delimiter.length());
			if(counter < 7)
			{
				counter++;
				add /= 2;
			}
			else
			{
				counter = 0;
				add = 128;
				hexarr[inc++] = hex;
				hex = 0;
			}
		}

		if(i == IMAGE_HEIGHT-1)
		{
			decode(line, &hex, &add);
			hexarr[inc] = hex;

			if(image_area % 8 > 0)
				hexarr[inc] << image_area % 8;
		}

		std::cout << "\n";
	}

	file.close();

	std::ofstream outfile ("hex.txt"); //Output file

	if(!outfile.is_open())
	{
		std::cout << "Error opening file." << std::endl;
		exit(1);
	}

	for(int i=0; i < arr_size; i++)
	{
		std::cout << std::showbase << std::internal << std::setfill('0');
		outfile << std::showbase << std::internal << std::setfill('0');
		if(hexarr[i] != 0)
		{
			std::cout << std::hex << std::setw(4) << hexarr[i] << " ";
			outfile << std::hex << std::setw(4) << hexarr[i];
		}
		else
		{
			std::cout << "0x00 ";
			outfile << "0x00";
		}
		outfile << ", ";
		if((i+1) % 12 == 0)
		{
			std::cout << "\n";
			outfile << "\n";
		}
		else if(i == arr_size - 1)
			std::cout << "\n";
	}

	outfile.close();

	return 0;
}

void decode(std::string parsed_string, int *hex, int *add)
{
	if(parsed_string == "0x00000000")
	{
		std::cout << "0";
	}
	else if (parsed_string == "0xff000000")
	{
		std::cout << "1";
		*hex += *add;
	}
}
<commit_msg>Update ArraytoHex.cpp<commit_after>#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cstdlib>

//Change these values according to your image
#define IMAGE_HEIGHT 32
#define IMAGE_WIDTH  32

void decode(std::string, int*, int*);

int main()
{
	std::string line;
	std::ifstream file ("pic.txt"); //Input file

	if(!file.is_open())
	{
		std::cout << "Error opening file." << std::endl;
		exit(1);
	}

	std::string delimiter = ", ";
	size_t pos = 0;
	std::string token;
	int hex = 0x00, add = 128, counter = 0, inc = 0;
	int image_area = IMAGE_HEIGHT * IMAGE_WIDTH;
	int arr_size = image_area / 8;

	if(image_area % 8 > 0)
		arr_size += 1;

	int hexarr[arr_size];

	for(int i=0; i < IMAGE_HEIGHT; i++)
	{
		std::getline(file, line);

		while((pos = line.find(delimiter)) != std::string::npos)
		{
			token = line.substr(0, pos);
			decode(token, &hex, &add);

			line.erase(0, pos + delimiter.length());
			if(counter < 7)
			{
				counter++;
				add /= 2;
			}
			else
			{
				counter = 0;
				add = 128;
				hexarr[inc++] = hex;
				hex = 0;
			}
		}

		if(i == IMAGE_HEIGHT-1)
		{
			decode(line, &hex, &add);
			hexarr[inc] = hex;

			if(image_area % 8 > 0)
				hexarr[inc] << image_area % 8;
		}

		std::cout << "\n";
	}

	file.close();

	std::ofstream outfile ("hex.txt"); //Output file

	if(!outfile.is_open())
	{
		std::cout << "Error opening file." << std::endl;
		exit(1);
	}

	for(int i=0; i < arr_size; i++)
	{
		std::cout << std::showbase << std::internal << std::setfill('0');
		outfile << std::showbase << std::internal << std::setfill('0');
		if(hexarr[i] != 0)
		{
			std::cout << std::hex << std::setw(4) << hexarr[i] << " ";
			outfile << std::hex << std::setw(4) << hexarr[i];
		}
		else
		{
			std::cout << "0x00 ";
			outfile << "0x00";
		}
		outfile << ", ";
		if((i+1) % 12 == 0)
		{
			std::cout << "\n";
			outfile << "\n";
		}
		else if(i == arr_size - 1)
			std::cout << "\n";
	}

	outfile.close();

	return 0;
}

void decode(std::string parsed_string, int *hex, int *add)
{
	if(parsed_string == "0x00000000") //Transparent
	{
		std::cout << "0";
	}
	else if (parsed_string == "0xff000000") //Black
	{
		std::cout << "1";
		*hex += *add;
	}
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2008 Jens-Michael Hoffmann <jensmh@gmx.de>

    This file is part of the KDE project

    This library is free software you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation either
    version 2 of the License, or (at your option) any later version.

    This library 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.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    aint with this library see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/
#include "osm-namefinder/NearestPlacesTagHandler.h"

#include <QtCore/QDebug>

#include "GeoDataPlacemark.h"
#include "GeoParser.h"
#include "osm-namefinder/ElementDictionary.h"

namespace Marble
{
namespace OsmNamefinder
{

static GeoTagHandlerRegistrar
s_handler( GeoTagHandler::QualifiedName( tag_nearestplaces, tag_namespace ),
           new NearestPlacesTagHandler );

GeoNode * NearestPlacesTagHandler::parse( GeoParser & parser ) const
{
    Q_ASSERT( parser.isStartElement() && parser.isValidElement( tag_nearestplaces ));
    qDebug() << "OnfNearestPlacesTagHandler";

    GeoStackItem parentItem = parser.parentElement();
    GeoDataPlacemark * named = 0;
    if ( parentItem.represents( tag_named ))
        named = parentItem.nodeAs<GeoDataPlacemark>();
    return named;
}

}
}
<commit_msg>Fix debug output.<commit_after>/*
    Copyright (C) 2008 Jens-Michael Hoffmann <jensmh@gmx.de>

    This file is part of the KDE project

    This library is free software you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation either
    version 2 of the License, or (at your option) any later version.

    This library 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.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    aint with this library see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/
#include "osm-namefinder/NearestPlacesTagHandler.h"

#include <QtCore/QDebug>

#include "GeoDataPlacemark.h"
#include "GeoParser.h"
#include "osm-namefinder/ElementDictionary.h"

namespace Marble
{
namespace OsmNamefinder
{

static GeoTagHandlerRegistrar
s_handler( GeoTagHandler::QualifiedName( tag_nearestplaces, tag_namespace ),
           new NearestPlacesTagHandler );

GeoNode * NearestPlacesTagHandler::parse( GeoParser & parser ) const
{
    Q_ASSERT( parser.isStartElement() && parser.isValidElement( tag_nearestplaces ));
    qDebug() << "NearestPlacesTagHandler";

    GeoStackItem parentItem = parser.parentElement();
    GeoDataPlacemark * named = 0;
    if ( parentItem.represents( tag_named ))
        named = parentItem.nodeAs<GeoDataPlacemark>();
    return named;
}

}
}
<|endoftext|>


<commit_before>#include "../includes/Signstate.h"
#include <iostream>

using namespace std;

Signstate::Signstate() {
  one = '0';
  two = '0';
  comment = 0;
}

Signstate::~Signstate() {
}

int Signstate::handle(char c){
  // logic of the state....

  if (comment == 1) {
    // Im Kommentar
    // cout << "in the comment " << c << "\n";
    if (c == ':' && one == '*') {
      // raus aus Kommentar
      // cout << "exit comment " << c << "\n";
      comment = 0;
      one = '0';
      two = '0';
      return 24;
    } else {
      one = '0';
      two = '0';
    }
    if (c == '*') {
      one = c;
    }
    if (c == '\n') {
      return 23;
    }
    return 22;
  }

  // einteilige Zeichen
  if (one == '0' && two == '0') {
    switch (c) {
      case '+':
        return 30;
      break;
      case '-':
        return 31;
      break;
      case '<':
        return 34;
      break;
      case '>':
        return 35;
      break;
      case '!':
        return 39;
      break;
      case ';':
        return 41;
      break;
      case '(':
        return 42;
      break;
      case ')':
        return 43;
      break;
      case '{':
        return 44;
      break;
      case '}':
        return 45;
      break;
      case '[':
        return 46;
      break;
      case ']':
        return 47;
      break;
    }
    // if (c == '+' || c == '-' || c == '<' || c == '>' || c == '(' || c == ')' ||
    //     c == '{' || c == '}' || c == '[' || c == ']' || c == '!' || c == ';') {
    //     return 20;
    // }
  }
  // mehrteilige Zeichen
    switch (c) {
      case ':':
        if (one == '0') {
          one = c;
          return 1;
        } else if(one == '='){
          two = c;
          return 1;
        } else {
          one = '0';
          two = '0';
          return 32;
        }
      case '*':
        if (one == '0') {
          one = c;
          return 1;
        } else if (one == ':') {
          // Kommentar beginnt!
          comment = 1;
          one = '0';
          two = '0';
          return 1;
        }{
          //TODO:CHECK!
          return 33;
        }
      case '=':
        if (one == '0') {
          one = c;
          return 1;
        } else if (one == ':') {
          one = '0';
          two = '0';
          return 37;
        } else if(one == '=' && two == ':'){
          one = '0';
          two = '0';
          return 38;
        } else {
          one = '0';
          two = '0';
          return 36;
        }
      case '&':
        if (one == '0') {
          one = c;
          return 1;
        } else if (one == '&') {
          one = '0';
          two = '0';
          return 40;
        } else {
          one = '0';
          two = '0';
          return 0;
        }
      default:
        one = '0';
        two = '0';
        return 0;
    }

}
<commit_msg>fix Comments at the end of a file<commit_after>#include "../includes/Signstate.h"
#include <iostream>

using namespace std;

Signstate::Signstate() {
  one = '0';
  two = '0';
  comment = 0;
}

Signstate::~Signstate() {
}

int Signstate::handle(char c){
  // logic of the state....
  if (c == '\0') {
    return -99;
  }

  if (comment == 1) {
    // Im Kommentar
    // cout << "in the comment " << c << "\n";
    if (c == ':' && one == '*') {
      // raus aus Kommentar
      // cout << "exit comment " << c << "\n";
      comment = 0;
      one = '0';
      two = '0';
      return 24;
    } else {
      one = '0';
      two = '0';
    }
    if (c == '*') {
      one = c;
    }
    if (c == '\n') {
      return 23;
    }
    return 22;
  }

  // einteilige Zeichen
  if (one == '0' && two == '0') {
    switch (c) {
      case '+':
        return 30;
      break;
      case '-':
        return 31;
      break;
      case '<':
        return 34;
      break;
      case '>':
        return 35;
      break;
      case '!':
        return 39;
      break;
      case ';':
        return 41;
      break;
      case '(':
        return 42;
      break;
      case ')':
        return 43;
      break;
      case '{':
        return 44;
      break;
      case '}':
        return 45;
      break;
      case '[':
        return 46;
      break;
      case ']':
        return 47;
      break;
    }
    // if (c == '+' || c == '-' || c == '<' || c == '>' || c == '(' || c == ')' ||
    //     c == '{' || c == '}' || c == '[' || c == ']' || c == '!' || c == ';') {
    //     return 20;
    // }
  }
  // mehrteilige Zeichen
    switch (c) {
      case ':':
        if (one == '0') {
          one = c;
          return 1;
        } else if(one == '='){
          two = c;
          return 1;
        } else {
          one = '0';
          two = '0';
          return 32;
        }
      case '*':
        if (one == '0') {
          one = c;
          return 1;
        } else if (one == ':') {
          // Kommentar beginnt!
          comment = 1;
          one = '0';
          two = '0';
          return 1;
        }{
          //TODO:CHECK!
          return 33;
        }
      case '=':
        if (one == '0') {
          one = c;
          return 1;
        } else if (one == ':') {
          one = '0';
          two = '0';
          return 37;
        } else if(one == '=' && two == ':'){
          one = '0';
          two = '0';
          return 38;
        } else {
          one = '0';
          two = '0';
          return 36;
        }
      case '&':
        if (one == '0') {
          one = c;
          return 1;
        } else if (one == '&') {
          one = '0';
          two = '0';
          return 40;
        } else {
          one = '0';
          two = '0';
          return 0;
        }
      default:
        one = '0';
        two = '0';
        return 0;
    }

}
<|endoftext|>


<commit_before>#include "RobotPosition.h"
#include "DistanceCalculator.h"

extern DistanceCalculator gDistanceCalculator;

//RobotPosition::RobotPosition() {
//	this->polarMetricCoords = cv::Point(0, 0);
//}

RobotPosition::RobotPosition(GatePosition &yellowGate, GatePosition &blueGate, cv::Point initialCoords):
yellowGate(yellowGate), blueGate(blueGate), filter(initialCoords){
	this->polarMetricCoords = cv::Point(0, 0);
	this->fieldCoords = initialCoords;
}

RobotPosition::~RobotPosition()
{
}

void RobotPosition::updateFieldCoordsNew(cv::Point orgin) {

	double d1 = blueGate.getDistance();
	double d2 = yellowGate.getDistance();
	double a1 = blueGate.getAngle();
	double a2 = yellowGate.getAngle();
	double a = a1 - a2;
	if (a < 0) a += 360;

	cv::Point pos;
	if (abs(a - 180) > 0){
		pos.x = a < 180 ? 1 : -1;
	}
	if (abs(d1 - d2) > 1){
		pos.y = d1 < d2 ? -1 : 1;
	}
	fieldCoords = cv::Point(60 * pos.x, 100 * pos.y);
	double aa = a > 180 ? a - 180: a;
	double a11 = asin(d2 * sin(abs(aa / 180 * CV_PI)) / 450) / CV_PI * 180;
	double a12 = asin(d1 * sin(abs(aa / 180 * CV_PI)) / 450) / CV_PI * 180;
	double a111 = pos.x < 0 ? a11 : 180 - a11;
	double a112 = pos.y > 0 ? a11 : 180 - a11;
	double a121 = pos.x < 0 ? a12 : 180 - a12;
	double a122 = pos.y > 0 ? a12 : 180 - a12;
	double dx1 = d1 * sin(a111 / 180 * CV_PI)*pos.x;
	double dy1 = d1 * cos(a112 / 180 * CV_PI)*pos.y;
	double dx2 = d2 * sin(a121 / 180 * CV_PI)*pos.x;
	double dy2 = d2 * cos(a122 / 180 * CV_PI)*-pos.y;

	double x1 = dx1 + blueGate.fieldCoords.x;
	double y1 = dy1 + blueGate.fieldCoords.y;
	double x2 = dx2 + yellowGate.fieldCoords.x;
	double y2 = dy2 + yellowGate.fieldCoords.y;
//	x1 = x2; y1 = y2;
//	x2 = x1; y2 = y1;
	fieldCoords.x = (x1 + x2) / 2;
	fieldCoords.y = (y1 + y2) / 2;

	// no that we know robot position, we can calculate it's angle to blue or yellow gate on the field
	double angleToBlueGate = DistanceCalculator::angleBetween(fieldCoords - blueGate.fieldCoords, { 0, 1 });
	double angleToYellowGate = DistanceCalculator::angleBetween(fieldCoords - yellowGate.fieldCoords, { 0, 1 });
	// now add real gate angle to this angle
	auto da1 = (angleToBlueGate - blueGate.getAngle());
	auto da2 = (angleToYellowGate - yellowGate.getAngle());
	// for taking average, they must have same sign
	if (abs(da1 - da2) > 180) {
		if (da1 < 0) da1 = 360 + da1;
		if (da2< 0) da2 = 360 + da2;
	}
//	if (da2 < 0) da2 += 360;
	polarMetricCoords.y = (da1 + da2) / 2;
	//polarMetricCoords.y = d1 > d2 ? da1 : da2;

	/*
	if (d1 < d2) {
		if (a < 180) {
			// top right
			fieldCoords = { 60, -100 };
		}
		else {
			//top bottom
			fieldCoords = { -60, -100 };
		}
	}
	else {
		if (a < 180 ) {
			// bottom right
			fieldCoords = { 60, 100 };
		}
		else {
			//bottom bottom
			fieldCoords = { -60, 100 };
		}

	}
	*/
	/*
	if (a < 0) a = 360 + a;
	double a1, a2 = 0;
	int axis = 0;
	double err, lastErr = INT_MAX;
	double d;
	do {
		d = sqrt(pow(d1, 2) + pow(d2, 2) - 2 * d1 * d2*cos(a/360*CV_PI));
		err = abs(d - 450);
		if (err < 10) break;

		if (err > lastErr) {
			axis = axis ^ 1;
		}
		else {
			if (axis == 0) d1 += err*0.1;
			if (axis == 1) d2 += err*0.1;
			lastErr = err;
		}
	} while (true);
	blueGate.polarMetricCoords.x = d1;
	yellowGate.polarMetricCoords.x = d2;
	*/
}
void RobotPosition::updateFieldCoords(cv::Point orgin) {

	updateFieldCoordsNew();
	return;

	auto possiblePoints = intersectionOfTwoCircles(yellowGate.fieldCoords, yellowGate.getDistance(), blueGate.fieldCoords, blueGate.getDistance());

	if (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle())){
		if (possiblePoints.first.y > 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	else {
		if (possiblePoints.first.y < 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	fieldCoords = filter.doFiltering(rawFieldCoords);
	/*double possiblePointDistance1 = cv::norm(possiblePoints.first - lastFieldCoords);
	double possiblePointDistance2 = cv::norm(possiblePoints.second - lastFieldCoords);
	if (possiblePointDistance1 < possiblePointDistance2) {
		this->fieldCoords = possiblePoints.first;
	}
	else {
		this->fieldCoords = possiblePoints.second;
	}*/

	// no that we know robot position, we can calculate it's angle to blue or yellow gate on the field
	double angleToBlueGate = DistanceCalculator::angleBetween(fieldCoords - blueGate.fieldCoords, { 0, 1 });
	double angleToYellowGate = DistanceCalculator::angleBetween(fieldCoords - yellowGate.fieldCoords, { 0, 1 });
	// now add real gate angle to this angle
	auto a1 = (angleToBlueGate - blueGate.getAngle());
	auto a2 = (angleToYellowGate - yellowGate.getAngle());
	// for taking average, they must have same sign
	if (a1 < 0) a1 += 360;
	if (a2 < 0) a2 += 360;
	//polarMetricCoords.y = (a1 + a2) / 2;
	polarMetricCoords.y = blueGate.getDistance() > yellowGate.getDistance() ? a1 : a2;

}

void RobotPosition::updatePolarCoords() {
	return;
}

std::pair<cv::Point, cv::Point> RobotPosition::intersectionOfTwoCircles(cv::Point circle1center,
																		   double circle1Rad,
																		cv::Point circle2center,
																		   double circle2Rad) {
	// distance between the centers
	double distance = cv::norm(circle1center - circle2center);

	// if two circle radiuses do not reach
	while (distance > circle1Rad + circle2Rad) {
		circle1Rad += 0.2*circle1Rad;
		circle2Rad += 0.2*circle2Rad;
	}

	// calculating area and height of trianlge formed by points
	double a = (pow(circle1Rad,2) - pow(circle2Rad, 2) + pow(distance, 2)) / (2.0*distance);
	double h = sqrt(pow(circle1Rad, 2) - pow(a, 2));

	//Calculate point p, where the line through the circle intersection points crosses the line between the circle centers.
	cv::Point p;

	p.x = (int)(circle1center.x + (a / distance) * (circle2center.x - circle1center.x));
	p.y = (int)(circle1center.y + (a / distance) * (circle2center.y - circle1center.y));

	// if has only one intersection point
	if (distance == circle1Rad + circle2Rad) {
		return std::pair<cv::Point, cv::Point>(p, p);
	}

	// if has two intersection points
	cv::Point possible1;
	cv::Point possible2;

	possible1.x = (int)(p.x + (h / distance) * (circle2center.y - circle1center.y));
	possible1.y = (int)(p.y - (h / distance) * (circle2center.x - circle1center.x));

	possible2.x = (int)(p.x - (h / distance) * (circle2center.y - circle1center.y));
	possible2.y = (int)(p.y + (h / distance) * (circle2center.x - circle1center.x));

	return std::pair<cv::Point, cv::Point>(possible1, possible2);
}

double RobotPosition::getAngle() {
	return polarMetricCoords.y;
}

bool RobotPosition::isRobotAboveCenterLine(double yellowGoalAngle, double blueGoalAngle){
	/*Calculation based on field:
	  _________________
	 |                 |
	B|]-------o-------[|Y
	 |_________________|

	*/
	double yellowToBlue = blueGoalAngle - yellowGoalAngle;
	if (yellowToBlue < 0)
		yellowToBlue += 360;
	double blueToYellow = yellowGoalAngle - blueGoalAngle;
	if (blueToYellow < 0)
		blueToYellow += 360;
	if (yellowToBlue < blueToYellow)
		return true;
	return false;
}

//bluegoal 0 degrees, yellow 180 degrees
double RobotPosition::getRobotDirection(){

	// we have triangle and two conrners are known, subtract those from full circle
	return  ((int)(yellowGate.getAngle() - blueGate.getAngle()) % 360); // <- this is not correct

	// distance between the centers
	double distance = cv::norm(yellowGate.fieldCoords - blueGate.fieldCoords);
	double yellowGoalDist = yellowGate.getDistance();
	double blueGoalDist = blueGate.getDistance();

	// if two circle radiuses do not reach
	while (distance > yellowGoalDist + blueGoalDist) {
		yellowGoalDist++;
		blueGoalDist++;
	}

	double aSqr = blueGoalDist * blueGoalDist;
	double bSqr = 500.0 * 500.0;
	double cSqr = yellowGoalDist* yellowGoalDist;
	double ab2 = 2.0*blueGoalDist*500.0;
	double gammaCos = (aSqr + bSqr - cSqr) / ab2;
	double gammaRads = acos(gammaCos);
	double gammaDegrees = gammaRads*(180 / PI);
	double dir = gammaDegrees + (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle()) ? 0 : -360);
	return blueGate.getAngle() + dir;

}<commit_msg>cleanup<commit_after>#include "RobotPosition.h"
#include "DistanceCalculator.h"

extern DistanceCalculator gDistanceCalculator;

//RobotPosition::RobotPosition() {
//	this->polarMetricCoords = cv::Point(0, 0);
//}

RobotPosition::RobotPosition(GatePosition &yellowGate, GatePosition &blueGate, cv::Point initialCoords):
yellowGate(yellowGate), blueGate(blueGate), filter(initialCoords){
	this->polarMetricCoords = cv::Point(0, 0);
	this->fieldCoords = initialCoords;
}

RobotPosition::~RobotPosition()
{
}

void RobotPosition::updateFieldCoordsNew(cv::Point orgin) {

	double d1 = blueGate.getDistance();
	double d2 = yellowGate.getDistance();
	double a1 = blueGate.getAngle();
	double a2 = yellowGate.getAngle();
	double a = a1 - a2;
	if (a < 0) a += 360;

	cv::Point pos;
	if (abs(a - 180) > 0){
		pos.x = a < 180 ? 1 : -1;
	}
	if (abs(d1 - d2) > 1){
		pos.y = d1 < d2 ? -1 : 1;
	}
	fieldCoords = cv::Point(60 * pos.x, 100 * pos.y);
	double aa = a > 180 ? a - 180: a;
	double a11 = asin(d2 * sin(abs(aa / 180 * CV_PI)) / 450) / CV_PI * 180;
	double a12 = asin(d1 * sin(abs(aa / 180 * CV_PI)) / 450) / CV_PI * 180;
	double a111 = pos.x < 0 ? a11 : 180 - a11;
	double a112 = pos.y > 0 ? a11 : 180 - a11;
	double a121 = pos.x < 0 ? a12 : 180 - a12;
	double a122 = pos.y > 0 ? a12 : 180 - a12;
	double dx1 = d1 * sin(a111 / 180 * CV_PI)*pos.x;
	double dy1 = d1 * cos(a112 / 180 * CV_PI)*pos.y;
	double dx2 = d2 * sin(a121 / 180 * CV_PI)*pos.x;
	double dy2 = d2 * cos(a122 / 180 * CV_PI)*-pos.y;

	double x1 = dx1 + blueGate.fieldCoords.x;
	double y1 = dy1 + blueGate.fieldCoords.y;
	double x2 = dx2 + yellowGate.fieldCoords.x;
	double y2 = dy2 + yellowGate.fieldCoords.y;
//	x1 = x2; y1 = y2;
//	x2 = x1; y2 = y1;
	fieldCoords.x = (x1 + x2) / 2;
	fieldCoords.y = (y1 + y2) / 2;

	// no that we know robot position, we can calculate it's angle to blue or yellow gate on the field
	double angleToBlueGate = DistanceCalculator::angleBetween(fieldCoords - blueGate.fieldCoords, { 0, 1 });
	double angleToYellowGate = DistanceCalculator::angleBetween(fieldCoords - yellowGate.fieldCoords, { 0, 1 });
	// now add real gate angle to this angle
	auto da1 = (angleToBlueGate - blueGate.getAngle());
	auto da2 = (angleToYellowGate - yellowGate.getAngle());
	// for taking average, they must have same sign
	if (abs(da1 - da2) > 180) {
		if (da1 < 0) da1 = 360 + da1;
		if (da2< 0) da2 = 360 + da2;
	}
//	if (da2 < 0) da2 += 360;
	polarMetricCoords.y = (da1 + da2) / 2;
	//polarMetricCoords.y = d1 > d2 ? da1 : da2;

}
void RobotPosition::updateFieldCoords(cv::Point orgin) {

	updateFieldCoordsNew();
	return;

	auto possiblePoints = intersectionOfTwoCircles(yellowGate.fieldCoords, yellowGate.getDistance(), blueGate.fieldCoords, blueGate.getDistance());

	if (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle())){
		if (possiblePoints.first.y > 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	else {
		if (possiblePoints.first.y < 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	fieldCoords = filter.doFiltering(rawFieldCoords);
	/*double possiblePointDistance1 = cv::norm(possiblePoints.first - lastFieldCoords);
	double possiblePointDistance2 = cv::norm(possiblePoints.second - lastFieldCoords);
	if (possiblePointDistance1 < possiblePointDistance2) {
		this->fieldCoords = possiblePoints.first;
	}
	else {
		this->fieldCoords = possiblePoints.second;
	}*/

	// no that we know robot position, we can calculate it's angle to blue or yellow gate on the field
	double angleToBlueGate = DistanceCalculator::angleBetween(fieldCoords - blueGate.fieldCoords, { 0, 1 });
	double angleToYellowGate = DistanceCalculator::angleBetween(fieldCoords - yellowGate.fieldCoords, { 0, 1 });
	// now add real gate angle to this angle
	auto a1 = (angleToBlueGate - blueGate.getAngle());
	auto a2 = (angleToYellowGate - yellowGate.getAngle());
	// for taking average, they must have same sign
	if (a1 < 0) a1 += 360;
	if (a2 < 0) a2 += 360;
	//polarMetricCoords.y = (a1 + a2) / 2;
	polarMetricCoords.y = blueGate.getDistance() > yellowGate.getDistance() ? a1 : a2;

}

void RobotPosition::updatePolarCoords() {
	return;
}

std::pair<cv::Point, cv::Point> RobotPosition::intersectionOfTwoCircles(cv::Point circle1center,
																		   double circle1Rad,
																		cv::Point circle2center,
																		   double circle2Rad) {
	// distance between the centers
	double distance = cv::norm(circle1center - circle2center);

	// if two circle radiuses do not reach
	while (distance > circle1Rad + circle2Rad) {
		circle1Rad += 0.2*circle1Rad;
		circle2Rad += 0.2*circle2Rad;
	}

	// calculating area and height of trianlge formed by points
	double a = (pow(circle1Rad,2) - pow(circle2Rad, 2) + pow(distance, 2)) / (2.0*distance);
	double h = sqrt(pow(circle1Rad, 2) - pow(a, 2));

	//Calculate point p, where the line through the circle intersection points crosses the line between the circle centers.
	cv::Point p;

	p.x = (int)(circle1center.x + (a / distance) * (circle2center.x - circle1center.x));
	p.y = (int)(circle1center.y + (a / distance) * (circle2center.y - circle1center.y));

	// if has only one intersection point
	if (distance == circle1Rad + circle2Rad) {
		return std::pair<cv::Point, cv::Point>(p, p);
	}

	// if has two intersection points
	cv::Point possible1;
	cv::Point possible2;

	possible1.x = (int)(p.x + (h / distance) * (circle2center.y - circle1center.y));
	possible1.y = (int)(p.y - (h / distance) * (circle2center.x - circle1center.x));

	possible2.x = (int)(p.x - (h / distance) * (circle2center.y - circle1center.y));
	possible2.y = (int)(p.y + (h / distance) * (circle2center.x - circle1center.x));

	return std::pair<cv::Point, cv::Point>(possible1, possible2);
}

double RobotPosition::getAngle() {
	return polarMetricCoords.y;
}

bool RobotPosition::isRobotAboveCenterLine(double yellowGoalAngle, double blueGoalAngle){
	/*Calculation based on field:
	  _________________
	 |                 |
	B|]-------o-------[|Y
	 |_________________|

	*/
	double yellowToBlue = blueGoalAngle - yellowGoalAngle;
	if (yellowToBlue < 0)
		yellowToBlue += 360;
	double blueToYellow = yellowGoalAngle - blueGoalAngle;
	if (blueToYellow < 0)
		blueToYellow += 360;
	if (yellowToBlue < blueToYellow)
		return true;
	return false;
}

//bluegoal 0 degrees, yellow 180 degrees
double RobotPosition::getRobotDirection(){

	// we have triangle and two conrners are known, subtract those from full circle
	return  ((int)(yellowGate.getAngle() - blueGate.getAngle()) % 360); // <- this is not correct

	// distance between the centers
	double distance = cv::norm(yellowGate.fieldCoords - blueGate.fieldCoords);
	double yellowGoalDist = yellowGate.getDistance();
	double blueGoalDist = blueGate.getDistance();

	// if two circle radiuses do not reach
	while (distance > yellowGoalDist + blueGoalDist) {
		yellowGoalDist++;
		blueGoalDist++;
	}

	double aSqr = blueGoalDist * blueGoalDist;
	double bSqr = 500.0 * 500.0;
	double cSqr = yellowGoalDist* yellowGoalDist;
	double ab2 = 2.0*blueGoalDist*500.0;
	double gammaCos = (aSqr + bSqr - cSqr) / ab2;
	double gammaRads = acos(gammaCos);
	double gammaDegrees = gammaRads*(180 / PI);
	double dir = gammaDegrees + (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle()) ? 0 : -360);
	return blueGate.getAngle() + dir;

}<|endoftext|>


<commit_before>#include "RobotPosition.h"

//RobotPosition::RobotPosition() {
//	this->polarMetricCoords = cv::Point(0, 0);
//}

RobotPosition::RobotPosition(GatePosition &yellowGate, GatePosition &blueGate, cv::Point initialCoords):
yellowGate(yellowGate), blueGate(blueGate), filter(initialCoords){
	this->polarMetricCoords = cv::Point(0, 0);
	this->fieldCoords = initialCoords;
}

RobotPosition::~RobotPosition()
{
}

void RobotPosition::updateFieldCoords(cv::Point orgin) {

	//we konw all angles of triangle and length of one side, use cosinus theorem to find
	const int distanceBetweenGates = 450;
	// we have two equations
	// distanceBetweenGates^2 = distanceToBlueGate^2 + distanceToYellowGate^2 - 2*distanceToBlueGate*distanceToYellowGate*cos(robotAngle)
	double diff = INT_MAX;
	double w = 1;
	double a = 0.0001;//learning rate
	double d1 = blueGate.getDistance();
	double d2 = yellowGate.getDistance();
	double g = abs(blueGate.getAngle() - yellowGate.getAngle());
	if (true || abs(g - 180) > 15) { // do not use this for wery acute triangles, floating point errors are big
		while (d1 > 0 && d2 > 0 && diff > 1) {
			diff = distanceBetweenGates - sqrt(pow(w*d1, 2) + pow(w*d2, 2) - 2 * w*d1*d2*cos(g));
			w += diff*a;
		}
	}
	w = 1;
	auto possiblePoints = intersectionOfTwoCircles(yellowGate.fieldCoords, w*d2, blueGate.fieldCoords,  w*d1);

	if (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle())){
		if (possiblePoints.first.y > 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	else {
		if (possiblePoints.first.y < 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	fieldCoords = filter.doFiltering(rawFieldCoords);
	/*double possiblePointDistance1 = cv::norm(possiblePoints.first - lastFieldCoords);
	double possiblePointDistance2 = cv::norm(possiblePoints.second - lastFieldCoords);
	if (possiblePointDistance1 < possiblePointDistance2) {
		this->fieldCoords = possiblePoints.first;
	}
	else {
		this->fieldCoords = possiblePoints.second;
	}*/

	// no that we know robot position, we can calculate it's angle to blue or yellow gate on the field
	double angleToBlueGate = angleBetween(fieldCoords - blueGate.fieldCoords, { 0, 1 });
	double angleToYellowGate = angleBetween(fieldCoords - yellowGate.fieldCoords, { 0, 1 });
	// now add real gate angle to this angle
	auto a1 = (angleToBlueGate - blueGate.getAngle());
	auto a2 = (angleToYellowGate - yellowGate.getAngle());
	// for taking average, they must have same sign
	if (a1 < 0) a1 += 360;
	if (a2 < 0) a2 += 360;
	polarMetricCoords.y = (a1 + a2) / 2;

}

void RobotPosition::updatePolarCoords() {
	return;
}

std::pair<cv::Point, cv::Point> RobotPosition::intersectionOfTwoCircles(cv::Point circle1center,
																		   double circle1Rad,
																		cv::Point circle2center,
																		   double circle2Rad) {
	// distance between the centers
	double distance = cv::norm(circle1center - circle2center);

	// if two circle radiuses do not reach
	while (distance > circle1Rad + circle2Rad) {
		circle1Rad++;
		circle2Rad++;
	}

	// calculating area and height of trianlge formed by points
	double a = (pow(circle1Rad,2) - pow(circle2Rad, 2) + pow(distance, 2)) / (2.0*distance);
	double h = sqrt(pow(circle1Rad, 2) - pow(a, 2));

	//Calculate point p, where the line through the circle intersection points crosses the line between the circle centers.
	cv::Point p;

	p.x = (int)(circle1center.x + (a / distance) * (circle2center.x - circle1center.x));
	p.y = (int)(circle1center.y + (a / distance) * (circle2center.y - circle1center.y));

	// if has only one intersection point
	if (distance == circle1Rad + circle2Rad) {
		return std::pair<cv::Point, cv::Point>(p, p);
	}

	// if has two intersection points
	cv::Point possible1;
	cv::Point possible2;

	possible1.x = (int)(p.x + (h / distance) * (circle2center.y - circle1center.y));
	possible1.y = (int)(p.y - (h / distance) * (circle2center.x - circle1center.x));

	possible2.x = (int)(p.x - (h / distance) * (circle2center.y - circle1center.y));
	possible2.y = (int)(p.y + (h / distance) * (circle2center.x - circle1center.x));

	return std::pair<cv::Point, cv::Point>(possible1, possible2);
}

double RobotPosition::getAngle() {
	return polarMetricCoords.y;
}

bool RobotPosition::isRobotAboveCenterLine(double yellowGoalAngle, double blueGoalAngle){
	/*Calculation based on field:
	  _________________
	 |                 |
	B|]-------o-------[|Y
	 |_________________|

	*/
	double yellowToBlue = blueGoalAngle - yellowGoalAngle;
	if (yellowToBlue < 0)
		yellowToBlue += 360;
	double blueToYellow = yellowGoalAngle - blueGoalAngle;
	if (blueToYellow < 0)
		blueToYellow += 360;
	if (yellowToBlue < blueToYellow)
		return true;
	return false;
}

//bluegoal 0 degrees, yellow 180 degrees
double RobotPosition::getRobotDirection(){

	// we have triangle and two conrners are known, subtract those from full circle
	return  ((int)(yellowGate.getAngle() - blueGate.getAngle()) % 360); // <- this is not correct

	// distance between the centers
	double distance = cv::norm(yellowGate.fieldCoords - blueGate.fieldCoords);
	double yellowGoalDist = yellowGate.getDistance();
	double blueGoalDist = blueGate.getDistance();

	// if two circle radiuses do not reach
	while (distance > yellowGoalDist + blueGoalDist) {
		yellowGoalDist++;
		blueGoalDist++;
	}

	double aSqr = blueGoalDist * blueGoalDist;
	double bSqr = 500.0 * 500.0;
	double cSqr = yellowGoalDist* yellowGoalDist;
	double ab2 = 2.0*blueGoalDist*500.0;
	double gammaCos = (aSqr + bSqr - cSqr) / ab2;
	double gammaRads = acos(gammaCos);
	double gammaDegrees = gammaRads*(180 / PI);
	double dir = gammaDegrees + (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle()) ? 0 : -360);
	return blueGate.getAngle() + dir;

}<commit_msg>minor improvements<commit_after>#include "RobotPosition.h"

//RobotPosition::RobotPosition() {
//	this->polarMetricCoords = cv::Point(0, 0);
//}

RobotPosition::RobotPosition(GatePosition &yellowGate, GatePosition &blueGate, cv::Point initialCoords):
yellowGate(yellowGate), blueGate(blueGate), filter(initialCoords){
	this->polarMetricCoords = cv::Point(0, 0);
	this->fieldCoords = initialCoords;
}

RobotPosition::~RobotPosition()
{
}

void RobotPosition::updateFieldCoords(cv::Point orgin) {

	//we konw all angles of triangle and length of one side, use cosinus theorem to find
	const int distanceBetweenGates = 450;
	// we have two equations
	// distanceBetweenGates^2 = distanceToBlueGate^2 + distanceToYellowGate^2 - 2*distanceToBlueGate*distanceToYellowGate*cos(robotAngle)
	double diff = INT_MAX;
	double w = 1;
	double a = 0.0001;//learning rate
	double d1 = blueGate.getDistance();
	double d2 = yellowGate.getDistance();
	double g = abs(blueGate.getAngle() - yellowGate.getAngle());
	if (true || abs(g - 180) > 15) { // do not use this for wery acute triangles, floating point errors are big
		while (d1 > 0 && d2 > 0 && abs(diff) > 1) {
			diff = distanceBetweenGates - sqrt(pow(w*d1, 2) + pow(w*d2, 2) - 2 * w*w*d1*d2*cos(g));
			w += diff*a;
		}
	}
	//w = 1;
	auto possiblePoints = intersectionOfTwoCircles(yellowGate.fieldCoords, w*d2, blueGate.fieldCoords,  w*d1);

	if (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle())){
		if (possiblePoints.first.y > 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	else {
		if (possiblePoints.first.y < 155){
			this->rawFieldCoords = possiblePoints.first;
		}else
			this->rawFieldCoords = possiblePoints.second;
	}
	fieldCoords = filter.doFiltering(rawFieldCoords);
	/*double possiblePointDistance1 = cv::norm(possiblePoints.first - lastFieldCoords);
	double possiblePointDistance2 = cv::norm(possiblePoints.second - lastFieldCoords);
	if (possiblePointDistance1 < possiblePointDistance2) {
		this->fieldCoords = possiblePoints.first;
	}
	else {
		this->fieldCoords = possiblePoints.second;
	}*/

	// no that we know robot position, we can calculate it's angle to blue or yellow gate on the field
	double angleToBlueGate = angleBetween(fieldCoords - blueGate.fieldCoords, { 0, 1 });
	double angleToYellowGate = angleBetween(fieldCoords - yellowGate.fieldCoords, { 0, 1 });
	// now add real gate angle to this angle
	auto a1 = (angleToBlueGate - blueGate.getAngle());
	auto a2 = (angleToYellowGate - yellowGate.getAngle());
	// for taking average, they must have same sign
	if (a1 < 0) a1 += 360;
	if (a2 < 0) a2 += 360;
	//polarMetricCoords.y = (a1 + a2) / 2;
	polarMetricCoords.y = blueGate.getDistance() > yellowGate.getDistance() ? a1 : a2;

}

void RobotPosition::updatePolarCoords() {
	return;
}

std::pair<cv::Point, cv::Point> RobotPosition::intersectionOfTwoCircles(cv::Point circle1center,
																		   double circle1Rad,
																		cv::Point circle2center,
																		   double circle2Rad) {
	// distance between the centers
	double distance = cv::norm(circle1center - circle2center);

	// if two circle radiuses do not reach
	while (distance > circle1Rad + circle2Rad) {
		circle1Rad++;
		circle2Rad++;
	}

	// calculating area and height of trianlge formed by points
	double a = (pow(circle1Rad,2) - pow(circle2Rad, 2) + pow(distance, 2)) / (2.0*distance);
	double h = sqrt(pow(circle1Rad, 2) - pow(a, 2));

	//Calculate point p, where the line through the circle intersection points crosses the line between the circle centers.
	cv::Point p;

	p.x = (int)(circle1center.x + (a / distance) * (circle2center.x - circle1center.x));
	p.y = (int)(circle1center.y + (a / distance) * (circle2center.y - circle1center.y));

	// if has only one intersection point
	if (distance == circle1Rad + circle2Rad) {
		return std::pair<cv::Point, cv::Point>(p, p);
	}

	// if has two intersection points
	cv::Point possible1;
	cv::Point possible2;

	possible1.x = (int)(p.x + (h / distance) * (circle2center.y - circle1center.y));
	possible1.y = (int)(p.y - (h / distance) * (circle2center.x - circle1center.x));

	possible2.x = (int)(p.x - (h / distance) * (circle2center.y - circle1center.y));
	possible2.y = (int)(p.y + (h / distance) * (circle2center.x - circle1center.x));

	return std::pair<cv::Point, cv::Point>(possible1, possible2);
}

double RobotPosition::getAngle() {
	return polarMetricCoords.y;
}

bool RobotPosition::isRobotAboveCenterLine(double yellowGoalAngle, double blueGoalAngle){
	/*Calculation based on field:
	  _________________
	 |                 |
	B|]-------o-------[|Y
	 |_________________|

	*/
	double yellowToBlue = blueGoalAngle - yellowGoalAngle;
	if (yellowToBlue < 0)
		yellowToBlue += 360;
	double blueToYellow = yellowGoalAngle - blueGoalAngle;
	if (blueToYellow < 0)
		blueToYellow += 360;
	if (yellowToBlue < blueToYellow)
		return true;
	return false;
}

//bluegoal 0 degrees, yellow 180 degrees
double RobotPosition::getRobotDirection(){

	// we have triangle and two conrners are known, subtract those from full circle
	return  ((int)(yellowGate.getAngle() - blueGate.getAngle()) % 360); // <- this is not correct

	// distance between the centers
	double distance = cv::norm(yellowGate.fieldCoords - blueGate.fieldCoords);
	double yellowGoalDist = yellowGate.getDistance();
	double blueGoalDist = blueGate.getDistance();

	// if two circle radiuses do not reach
	while (distance > yellowGoalDist + blueGoalDist) {
		yellowGoalDist++;
		blueGoalDist++;
	}

	double aSqr = blueGoalDist * blueGoalDist;
	double bSqr = 500.0 * 500.0;
	double cSqr = yellowGoalDist* yellowGoalDist;
	double ab2 = 2.0*blueGoalDist*500.0;
	double gammaCos = (aSqr + bSqr - cSqr) / ab2;
	double gammaRads = acos(gammaCos);
	double gammaDegrees = gammaRads*(180 / PI);
	double dir = gammaDegrees + (isRobotAboveCenterLine(yellowGate.getAngle(), blueGate.getAngle()) ? 0 : -360);
	return blueGate.getAngle() + dir;

}<|endoftext|>


<commit_before>#include <stdio.h>
#include "./LFC/LFC.h"
#include "./Tests/Tests.h"

int main(int argc, char **argv)
{
	lfc_init(); // lfc initialization

	StdOut::PrintLine("hello world");

	if (TestText::PerformAnsi() != 0) {
		printf("PerformAnsi error!\r\n");
		return -1;
	}
	StdOut::PrintLine();

	if (TestText::PerformWide() != 0) {
		printf("PerformWide error!\r\n");
		return -1;
	}
	StdOut::PrintLine();

	if (TestDirectory::Perform() != 0) {
		printf("TestDirectory::Perform error!\r\n");
		return -1;
	}
	StdOut::PrintLine();

	if (TestDateTime::Perform() != 0) {
		printf("TestDateTime::Perform error!\r\n");
		return -1;
	}
	StdOut::PrintLine();

	if (TestAdministration::Perform() != 0) {
		StdOut::PrintLine("TestAdministration::Perform error!!!");
		return -1;
	}
	StdOut::PrintLine();

	if (TestFile::Perform() != 0) {
		StdOut::PrintLine("TestFile::Perform error!!!");
		return -1;
	}

	return 0;
}
<commit_msg>Code cleaning<commit_after>#include <stdio.h>
#include "./LFC/LFC.h"
#include "./Tests/Tests.h"

int main(int argc, char **argv)
{
	lfc_init(); // lfc initialization

	StdOut::PrintLine("hello world");

	if (TestText::PerformAnsi() != 0) {
		StdOut::PrintLine("PerformAnsi error!");
		return -1;
	}
	StdOut::PrintLine();

	if (TestText::PerformWide() != 0) {
		StdOut::PrintLine("PerformWide error!");
		return -1;
	}
	StdOut::PrintLine();

	if (TestDirectory::Perform() != 0) {
		StdOut::PrintLine("TestDirectory::Perform error!");
		return -1;
	}
	StdOut::PrintLine();

	if (TestDateTime::Perform() != 0) {
		StdOut::PrintLine("TestDateTime::Perform error!");
		return -1;
	}
	StdOut::PrintLine();

	if (TestAdministration::Perform() != 0) {
		StdOut::PrintLine("TestAdministration::Perform error!!!");
		return -1;
	}
	StdOut::PrintLine();

	if (TestFile::Perform() != 0) {
		StdOut::PrintLine("TestFile::Perform error!!!");
		return -1;
	}

	return 0;
}
<|endoftext|>


<commit_before>#include "pxt.h"
#include "Adafruit_SSD1306.h"

using namespace pxt;

namespace OLED {
	#define SSD1306_ADDRESS 0x78
	#undef printf

	// maintain compatibility with pre-unicode versions of microbit
	#ifndef PXT_STRING_DATA
	#define PXT_STRING_DATA(str) str->data
	#endif

	MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
	Adafruit_SSD1306_I2c *oled;

	void init(int height, int width){
		if (oled != NULL) delete oled;
		oled = new Adafruit_SSD1306_I2c(i2c, SSD1306_ADDRESS, height, width);
		oled->splash();
		oled->display();
	}

	//%
	void init_terminal(int height, int width){
		if (oled != NULL) delete oled;
		oled = new Adafruit_SSD1306_I2c(i2c, SSD1306_ADDRESS, height, width);
		oled->clearDisplay();
		oled->display();
		oled->setTextCursor(0, 0);
	}

	//%
    void showStringNoNewLine(String text) {
		oled->printf("%s", PXT_STRING_DATA(text));
		oled->display();
    }

	//%
    void showStringWithNewLine(String text) {
		oled->printf("%s\n", PXT_STRING_DATA(text));
		oled->display();
    }

    //%
    void showNumberWithoutNewLine (int number) {
		oled->printf("%d", number);
		oled->display();
	}

	//%
    void showNumberWithNewLine (int number) {
		oled->printf("%d\n", number);
		oled->display();
	}

    //%
    void NextLine () {
		oled->printf("\n");
		oled->display();
	}

	//%
	void clearDisplay(){
		oled->setTextCursor(0, 0);
		oled->clearDisplay();
		oled->display();
	}

	//%
	void drawCircle(int x, int y, int r){
		oled->drawCircle(x, y, r, 1);
		oled->display();
	}

	//%
	void fillCircle(int x, int y, int r){
		oled->fillCircle(x, y, r, 1);
		oled->display();
	}

	//%
	void drawLine(int x0, int y0, int x1, int y1){
		oled->drawLine(x0, y0, x1, y1, 1);
		oled->display();
	}

	//%
	void fillRect(int x, int y, int w, int h){
		oled->fillRect(x, y, w, h, 1);
		oled->display();
	}

	//%
    void drawRect(int x, int y, int w, int h){
    	oled->drawRect(x, y, w, h, 1);
		oled->display();
    }

    //%
	void fillRoundRect(int x, int y, int w, int h, int r){
		oled->fillRoundRect(x, y, w, h, r, 1);
		oled->display();
	}

	//%
    void drawRoundRect(int x, int y, int w, int h, int r){
    	oled->drawRoundRect(x, y, w, h, r, 1);
		oled->display();
    }

    //%
    void drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2){
    	oled->drawTriangle(x0, y0, x1, y1, x2, y2, 1);
		oled->display();
    }

    //%
    void fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2){
    	oled->fillTriangle(x0, y0, x1, y1, x2, y2, 1);
		oled->display();
    }

	//%
	void LoadingScreen() {
		int x,y = 0;
		int w = 21;
		int h = 64;
		for (int i = 0; i < 6;i++){
			fillRect(x, y, w, h);
			x = x + 21;
			oled->display();
		}

	}

	//%
	void showProgress(int progress) {
		oled->clearDisplay();
		drawRect(0,21,128,21);
		fillRect(0,21,progress*128/100,21);
	}
    #define printf(...) uBit.serial.printf(__VA_ARGS__)

}
<commit_msg>remove accidental extra line<commit_after>#include "pxt.h"
#include "Adafruit_SSD1306.h"

using namespace pxt;

namespace OLED {
	#define SSD1306_ADDRESS 0x78
	#undef printf

	// maintain compatibility with pre-unicode versions of microbit
	#ifndef PXT_STRING_DATA
	#define PXT_STRING_DATA(str) str->data
	#endif

	MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
	Adafruit_SSD1306_I2c *oled;

	void init(int height, int width){
		if (oled != NULL) delete oled;
		oled = new Adafruit_SSD1306_I2c(i2c, SSD1306_ADDRESS, height, width);
		oled->splash();
		oled->display();
	}

	//%
	void init_terminal(int height, int width){
		if (oled != NULL) delete oled;
		oled = new Adafruit_SSD1306_I2c(i2c, SSD1306_ADDRESS, height, width);
		oled->clearDisplay();
		oled->display();
		oled->setTextCursor(0, 0);
	}

	//%
    void showStringNoNewLine(String text) {
		oled->printf("%s", PXT_STRING_DATA(text));
		oled->display();
    }

	//%
    void showStringWithNewLine(String text) {
		oled->printf("%s\n", PXT_STRING_DATA(text));
		oled->display();
    }

    //%
    void showNumberWithoutNewLine (int number) {
		oled->printf("%d", number);
		oled->display();
	}

	//%
    void showNumberWithNewLine (int number) {
		oled->printf("%d\n", number);
		oled->display();
	}

    //%
    void NextLine () {
		oled->printf("\n");
		oled->display();
	}

	//%
	void clearDisplay(){
		oled->setTextCursor(0, 0);
		oled->clearDisplay();
		oled->display();
	}

	//%
	void drawCircle(int x, int y, int r){
		oled->drawCircle(x, y, r, 1);
		oled->display();
	}

	//%
	void fillCircle(int x, int y, int r){
		oled->fillCircle(x, y, r, 1);
		oled->display();
	}

	//%
	void drawLine(int x0, int y0, int x1, int y1){
		oled->drawLine(x0, y0, x1, y1, 1);
		oled->display();
	}

	//%
	void fillRect(int x, int y, int w, int h){
		oled->fillRect(x, y, w, h, 1);
		oled->display();
	}

	//%
    void drawRect(int x, int y, int w, int h){
    	oled->drawRect(x, y, w, h, 1);
		oled->display();
    }

    //%
	void fillRoundRect(int x, int y, int w, int h, int r){
		oled->fillRoundRect(x, y, w, h, r, 1);
		oled->display();
	}

	//%
    void drawRoundRect(int x, int y, int w, int h, int r){
    	oled->drawRoundRect(x, y, w, h, r, 1);
		oled->display();
    }

    //%
    void drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2){
    	oled->drawTriangle(x0, y0, x1, y1, x2, y2, 1);
		oled->display();
    }

    //%
    void fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2){
    	oled->fillTriangle(x0, y0, x1, y1, x2, y2, 1);
		oled->display();
    }

	//%
	void LoadingScreen() {
		int x,y = 0;
		int w = 21;
		int h = 64;
		for (int i = 0; i < 6;i++){
			fillRect(x, y, w, h);
			x = x + 21;
			oled->display();
		}

	}

	//%
	void showProgress(int progress) {
		oled->clearDisplay();
		drawRect(0,21,128,21);
		fillRect(0,21,progress*128/100,21);
	}
    #define printf(...) uBit.serial.printf(__VA_ARGS__)

}
<|endoftext|>


<commit_before>//
// Defines main() function and command-line arguments used by ccons.
//
// Part of ccons, the interactive console for the C programming language.
//
// Copyright (c) 2009 Alexei Svitkine. This file is distributed under the
// terms of MIT Open Source License. See file LICENSE for details.
//

#include <iostream>
#include <fstream>
#include <sstream>

#include <llvm/ADT/OwningPtr.h>
#include <llvm/ADT/StringExtras.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Signals.h>
#include <llvm/Target/TargetSelect.h>

#include "Console.h"
#include "EditLineReader.h"
#include "InternalCommands.h"
#include "RemoteConsole.h"

using std::string;
using ccons::Console;
using ccons::IConsole;
using ccons::RemoteConsole;
using ccons::SerializedOutputConsole;
using ccons::LineReader;
using ccons::EditLineReader;
using ccons::StdInLineReader;

static llvm::cl::opt<bool>
	DebugMode("ccons-debug",
			llvm::cl::desc("Print debugging information"));
static llvm::cl::opt<bool>
	UseStdIo("ccons-use-std-io",
			llvm::cl::desc("Use standard IO for input and output"));
static llvm::cl::opt<bool>
	SerializedOutput("ccons-serialized-output",
			llvm::cl::desc("Output will be serialized"));
static llvm::cl::opt<bool>
	MultiProcess("ccons-multi-process",
			llvm::cl::desc("Run in multi-process mode"));

static IConsole * createConsole()
{
	if (MultiProcess)
		return new RemoteConsole(DebugMode);
	else if (SerializedOutput)
		return new SerializedOutputConsole(DebugMode);
	else
		return new Console(DebugMode);
}

static LineReader * createReader()
{
	if (UseStdIo)
		return new StdInLineReader;
	else
		return new EditLineReader;
}

extern "C" void LLVMInitializeX86TargetMC();

int main(const int argc, char **argv)
{
	llvm::cl::SetVersionPrinter(ccons::PrintVersionInformation);
	llvm::cl::ParseCommandLineOptions(argc, argv, "ccons Interactive C Console\n",
	                                  false/*, "ccons-"*/);

	if (DebugMode && !SerializedOutput) {
		std::cerr << "NOTE: Debugging information will be displayed.\n";
		llvm::sys::PrintStackTraceOnErrorSignal();
	}

	llvm::InitializeNativeTarget();

	// FIXME: This shouldn't be needed - it should have been done by llvm::InitializeNativeTarget().
	LLVMInitializeX86TargetMC();

	llvm::OwningPtr<IConsole> console(createConsole());
	llvm::OwningPtr<LineReader> reader(createReader());

	const char *line = reader->readLine(console->prompt(), console->input());
	while (line) {
		console->process(line);
		line = reader->readLine(console->prompt(), console->input());
	}

	return 0;
}

<commit_msg>add a TODO<commit_after>//
// Defines main() function and command-line arguments used by ccons.
//
// Part of ccons, the interactive console for the C programming language.
//
// Copyright (c) 2009 Alexei Svitkine. This file is distributed under the
// terms of MIT Open Source License. See file LICENSE for details.
//

#include <iostream>
#include <fstream>
#include <sstream>

#include <llvm/ADT/OwningPtr.h>
#include <llvm/ADT/StringExtras.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Signals.h>
#include <llvm/Target/TargetSelect.h>

#include "Console.h"
#include "EditLineReader.h"
#include "InternalCommands.h"
#include "RemoteConsole.h"

using std::string;
using ccons::Console;
using ccons::IConsole;
using ccons::RemoteConsole;
using ccons::SerializedOutputConsole;
using ccons::LineReader;
using ccons::EditLineReader;
using ccons::StdInLineReader;

static llvm::cl::opt<bool>
	DebugMode("ccons-debug",
			llvm::cl::desc("Print debugging information"));
static llvm::cl::opt<bool>
	UseStdIo("ccons-use-std-io",
			llvm::cl::desc("Use standard IO for input and output"));
static llvm::cl::opt<bool>
	SerializedOutput("ccons-serialized-output",
			llvm::cl::desc("Output will be serialized"));
static llvm::cl::opt<bool>
	MultiProcess("ccons-multi-process",
			llvm::cl::desc("Run in multi-process mode"));

static IConsole * createConsole()
{
	if (MultiProcess)
		return new RemoteConsole(DebugMode);
	else if (SerializedOutput)
		return new SerializedOutputConsole(DebugMode);
	else
		return new Console(DebugMode);
}

static LineReader * createReader()
{
	if (UseStdIo)
		return new StdInLineReader;
	else
		return new EditLineReader;
}

extern "C" void LLVMInitializeX86TargetMC();

int main(const int argc, char **argv)
{
	llvm::cl::SetVersionPrinter(ccons::PrintVersionInformation);
	llvm::cl::ParseCommandLineOptions(argc, argv, "ccons Interactive C Console\n",
	                                  false/*, "ccons-"*/);

	if (DebugMode && !SerializedOutput) {
		std::cerr << "NOTE: Debugging information will be displayed.\n";
		llvm::sys::PrintStackTraceOnErrorSignal();
	}

	llvm::InitializeNativeTarget();

	// FIXME: This shouldn't be needed - it should have been done by llvm::InitializeNativeTarget().
	// TODO: Bisect builds and report a bug to LLVM if this doesn't disappear soon. I noticed the breakage at r139193 of LLVM.
	LLVMInitializeX86TargetMC();

	llvm::OwningPtr<IConsole> console(createConsole());
	llvm::OwningPtr<LineReader> reader(createReader());

	const char *line = reader->readLine(console->prompt(), console->input());
	while (line) {
		console->process(line);
		line = reader->readLine(console->prompt(), console->input());
	}

	return 0;
}

<|endoftext|>


<commit_before><commit_msg>Update AliAnalysisTaskCaloHFEpp.cxx<commit_after><|endoftext|>


<commit_before><commit_msg>changed cuts on the associated tracks<commit_after><|endoftext|>


<commit_before>// $Id: options.C,v 1.6 2000/02/06 19:54:07 oliver Exp $

#include <BALL/DATATYPE/options.h>

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <math.h>

#include <fstream>
#include <list>
#include <algorithm>

using namespace std;

namespace BALL
{

	Options::Options()
		:	StringHashMap<String>(),
			name_("")
	{
	}

	Options::Options(const Options& options, bool deep)
		:	StringHashMap<String>(options, deep),
			name_(options.name_)
	{
	}

	Options::~Options()
	{
	}

	bool Options::isReal(const String& key) const
	{
		errno = 0;
		char*	endptr;
		String value(get(key));

		// an empty String is no real number
		if (value =="")
		{
			return false;
		}

		// try to convert it to a number
		strtod(value.c_str(), &endptr);

		// return and tell whether it happend to work
		return (errno == 0) && (endptr != value.c_str());
	}

	bool Options::isVector(const String& key) const
	{
		float	dummy;

		if (!has(key))
			return false;

		if (sscanf(get(key).c_str(), "(%f %f %f)", &dummy, &dummy, &dummy) == 3)
			return true;

		return false;
	}

	bool Options::isBool(const String& key) const
	{
		String s = get(key);
		if (s == "")
			return false;

		s.toLower();
		return (s.compare("true") == 0 || s.compare("false") == 0);
	}

	bool Options::isSet(const String& key) const
	{
		return (StringHashMap<String>::find(key) != StringHashMap<String>::end());
	}

	bool Options::isInteger(const String& key) const
	{
		double double_value;
		long long_value;

		// if it cannot be read as a floating point number
		// it cannot be an integer
		if (!isReal(key))
			return false;

		// check wheter it is an integer
		long_value = atol(get(key).c_str());
		double_value = atof(get(key).c_str());

		// check if it is an integer (cutoff is 1e-7)
		if (fabs(double_value - ((double)long_value)) <= 1e-7)
			return true;

		// it is a floating point number, but no integer
		return false;
	}

	double Options::getReal(const String& key) const
	{
		double value;

		errno = 0;
		value = atof((*find(key)).second.c_str());

		if (errno == 0){
			return value;
		} else {
			return 0.0;
		}
	}

	Vector3	Options::getVector(const String& key) const
	{
		Vector3	h(0,0,0);

		if (!has(key))
		{
			return h;
		}

		sscanf(get(key).c_str(), "(%f %f %f)", &(h.x), &(h.y), &(h.z));

		return h;
	}

	bool Options::getBool(const String& key) const
	{
		ConstIterator it = find(key);
		if ((it != end()) && (it->second == "true"))
		{
			return true;
		} else {
			return false;
		}
	}

	long Options::getInteger(const String& key) const
	{
		long value;

		errno = 0;
		ConstIterator it = find(key);
		if (it == end())
			return 0;

		value = atol((*it).second.c_str());

		if (errno == 0)
		{
			return value;
		} else {
			errno = 0;
			return 0;
		}
	}

	void Options::set(const String& key, const String& value)
	{
		(*this)[key] = value;
	}

	void Options::setInteger(const String& key, const long value)
	{
		static char buffer[MaxEntryLength + 1];

		sprintf(buffer, "%ld", value);

		set(key, &(buffer[0]));
	}

	void Options::setReal(const String& key, const double value)
	{
		char buffer[MaxEntryLength + 1];

		sprintf(buffer, "%f", value);

		set(key, buffer);
	}

	void Options::setVector(const String& key, const Vector3& value)
	{
		char buffer[MaxEntryLength + 1];

		sprintf(buffer, "(%f %f %f)", value.x, value.y, value.z);

		set(key, buffer);
	}

	void Options::setBool(const String& key, const bool value)
	{
		if (value)
		{
			set(key, "true");
		} else {
			set(key, "false");
		}
	}

	String Options::setDefault(const String& key, const String& value)
	{
		if (!has(key))
		{
			set(key, value);
			return key;
		} else {
			return get(key);
		}
	}

	double Options::setDefaultReal(const String& key, const double value)
	{
		if (!has(key) || !isReal(key))
		{
			setReal(key, value);
			return value;
		} else {
			return getReal(key);
		}
	}

	bool Options::setDefaultBool(const String& key, const bool value)
	{
		if (!has(key) || !isBool(key))
		{
			setBool(key, value);
			return value;
		} else {
			return getBool(key);
		}
	}

	long Options::setDefaultInteger(const String& key, const long value)
	{
		if (!has(key) || !isInteger(key))
		{
			setInteger(key, value);
			return value;
		} else {
			return getInteger(key);
		}
	}

	void Options::setName(const String& name)
	{
		name_ = name;
	}

	const String& Options::getName() const
	{
		return name_;
	}

	String Options::get(const String& key) const
	{
		ConstIterator it = find(key);

		if (it == end())
		{
			return "";
		} else {
			return (*it).second;
		}
	}

	bool Options::readOptionFile(const String& filename)
	{
		ifstream		infile;

		infile.open(filename.c_str(), ios::in);
		if (!infile)
			return false;

		char		buffer[MaxEntryLength + 1];
		String	s, key;
		while (infile.getline(buffer, MaxEntryLength))
		{
			if ((buffer[0] != '#') && (buffer[0] != '!') && (buffer[0] != ';'))
			{
				s = buffer;
				key = s.getField(0, " ");
				s = s.after(" ");
				set(key, s);
			}
		}

		infile.close();

		return true;
	}

	void Options::dump (ostream& stream, Size /* depth */) const
	{
		std::list<String>		entry_list;
		String							entry;

		stream << "[OptionsTable: " << getName() << " (" << size() << " entries)]" << endl;

		StringHashMap<String>::ConstIterator	it(begin());
		for(; !(it == end()); ++it)
		{
			entry = (*it).first + ' ' + (*it).second;
			entry_list.push_back(entry);
		}

		entry_list.sort();

		std::list<String>::iterator	list_it = entry_list.begin();
		for (; list_it != entry_list.end(); ++list_it)
		{
	  	stream << *list_it << endl;
		}

		stream << "-----------------------------------" << endl;

		entry_list.clear();
	}

} // namespace BALL
<commit_msg>fixed: options now supports both single and double precision vectors (depending on the   current definition of Vector3)<commit_after>// $Id: options.C,v 1.7 2000/03/17 11:23:26 oliver Exp $

#include <BALL/DATATYPE/options.h>

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <math.h>

#include <fstream>
#include <list>
#include <algorithm>

using namespace std;

namespace BALL
{

	Options::Options()
		:	StringHashMap<String>(),
			name_("")
	{
	}

	Options::Options(const Options& options, bool deep)
		:	StringHashMap<String>(options, deep),
			name_(options.name_)
	{
	}

	Options::~Options()
	{
	}

	bool Options::isReal(const String& key) const
	{
		errno = 0;
		char*	endptr;
		String value(get(key));

		// an empty String is no real number
		if (value =="")
		{
			return false;
		}

		// try to convert it to a number
		strtod(value.c_str(), &endptr);

		// return and tell whether it happend to work
		return (errno == 0) && (endptr != value.c_str());
	}

	bool Options::isVector(const String& key) const
	{
		// if the key does not exist - then the nonexistent value
		// cannot contain a vector
		if (!has(key))
		{
			return false;
		}

		// try to interpret the string as three double values
		double dummy;
		if (sscanf(get(key).c_str(), "(%lf %lf %lf)", &dummy, &dummy, &dummy) == 3)
		{
			return true;
		}

		return false;
	}

	bool Options::isBool(const String& key) const
	{
		String s = get(key);
		if (s == "")
			return false;

		s.toLower();
		return (s.compare("true") == 0 || s.compare("false") == 0);
	}

	bool Options::isSet(const String& key) const
	{
		return (StringHashMap<String>::find(key) != StringHashMap<String>::end());
	}

	bool Options::isInteger(const String& key) const
	{
		double double_value;
		long long_value;

		// if it cannot be read as a floating point number
		// it cannot be an integer
		if (!isReal(key))
			return false;

		// check wheter it is an integer
		long_value = atol(get(key).c_str());
		double_value = atof(get(key).c_str());

		// check if it is an integer (cutoff is 1e-7)
		if (fabs(double_value - ((double)long_value)) <= 1e-7)
			return true;

		// it is a floating point number, but no integer
		return false;
	}

	double Options::getReal(const String& key) const
	{
		double value;

		errno = 0;
		value = atof((*find(key)).second.c_str());

		if (errno == 0){
			return value;
		} else {
			return 0.0;
		}
	}

	Vector3	Options::getVector(const String& key) const
	{
		Vector3	h(0,0,0);

		if (!has(key))
		{
			return h;
		}

		// use temporary variables of double precision
		// this avoids trouble if the definition of
		// Vector3 is changed between TVector3<float> and TVector3<double>
		double x, y, z;

		// try to interpret the option as a vector
		sscanf(get(key).c_str(), "(%lf %lf %lf)", &(h.x), &(h.y), &(h.z));
		h.x = x;
		h.y = y;
		h.z = z;

		return h;
	}

	bool Options::getBool(const String& key) const
	{
		ConstIterator it = find(key);
		if ((it != end()) && (it->second == "true"))
		{
			return true;
		} else {
			return false;
		}
	}

	long Options::getInteger(const String& key) const
	{
		long value;

		errno = 0;
		ConstIterator it = find(key);
		if (it == end())
			return 0;

		value = atol((*it).second.c_str());

		if (errno == 0)
		{
			return value;
		} else {
			errno = 0;
			return 0;
		}
	}

	void Options::set(const String& key, const String& value)
	{
		(*this)[key] = value;
	}

	void Options::setInteger(const String& key, const long value)
	{
		static char buffer[MaxEntryLength + 1];

		sprintf(buffer, "%ld", value);

		set(key, &(buffer[0]));
	}

	void Options::setReal(const String& key, const double value)
	{
		char buffer[MaxEntryLength + 1];

		sprintf(buffer, "%f", value);

		set(key, buffer);
	}

	void Options::setVector(const String& key, const Vector3& value)
	{
		char buffer[MaxEntryLength + 1];

		sprintf(buffer, "(%f %f %f)", value.x, value.y, value.z);

		set(key, buffer);
	}

	void Options::setBool(const String& key, const bool value)
	{
		if (value)
		{
			set(key, "true");
		} else {
			set(key, "false");
		}
	}

	String Options::setDefault(const String& key, const String& value)
	{
		if (!has(key))
		{
			set(key, value);
			return key;
		} else {
			return get(key);
		}
	}

	double Options::setDefaultReal(const String& key, const double value)
	{
		if (!has(key) || !isReal(key))
		{
			setReal(key, value);
			return value;
		} else {
			return getReal(key);
		}
	}

	bool Options::setDefaultBool(const String& key, const bool value)
	{
		if (!has(key) || !isBool(key))
		{
			setBool(key, value);
			return value;
		} else {
			return getBool(key);
		}
	}

	long Options::setDefaultInteger(const String& key, const long value)
	{
		if (!has(key) || !isInteger(key))
		{
			setInteger(key, value);
			return value;
		} else {
			return getInteger(key);
		}
	}

	void Options::setName(const String& name)
	{
		name_ = name;
	}

	const String& Options::getName() const
	{
		return name_;
	}

	String Options::get(const String& key) const
	{
		ConstIterator it = find(key);

		if (it == end())
		{
			return "";
		} else {
			return (*it).second;
		}
	}

	bool Options::readOptionFile(const String& filename)
	{
		ifstream		infile;

		infile.open(filename.c_str(), ios::in);
		if (!infile)
			return false;

		char		buffer[MaxEntryLength + 1];
		String	s, key;
		while (infile.getline(buffer, MaxEntryLength))
		{
			if ((buffer[0] != '#') && (buffer[0] != '!') && (buffer[0] != ';'))
			{
				s = buffer;
				key = s.getField(0, " ");
				s = s.after(" ");
				set(key, s);
			}
		}

		infile.close();

		return true;
	}

	void Options::dump (ostream& stream, Size /* depth */) const
	{
		std::list<String>		entry_list;
		String							entry;

		stream << "[OptionsTable: " << getName() << " (" << size() << " entries)]" << endl;

		StringHashMap<String>::ConstIterator	it(begin());
		for(; !(it == end()); ++it)
		{
			entry = (*it).first + ' ' + (*it).second;
			entry_list.push_back(entry);
		}

		entry_list.sort();

		std::list<String>::iterator	list_it = entry_list.begin();
		for (; list_it != entry_list.end(); ++list_it)
		{
	  	stream << *list_it << endl;
		}

		stream << "-----------------------------------" << endl;

		entry_list.clear();
	}

} // namespace BALL
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <list>

#include "Type.hpp"
#include "FunctionContext.hpp"
#include "GlobalContext.hpp"
#include "Variable.hpp"

#include "mtac/DeadCodeElimination.hpp"
#include "mtac/GlobalOptimizations.hpp"
#include "mtac/LiveVariableAnalysisProblem.hpp"
#include "mtac/Utils.hpp"
#include "mtac/Offset.hpp"
#include "mtac/Statement.hpp"

#include "ltac/Statement.hpp"

using namespace eddic;

bool mtac::dead_code_elimination::operator()(mtac::Function& function){
    bool optimized = false;

    mtac::LiveVariableAnalysisProblem problem;
    auto results = mtac::data_flow(function, problem);

    for(auto& block : function){
        auto it = iterate(block->statements);

        while(it.has_next()){
            auto statement = *it;

            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                if(mtac::erase_result((*ptr)->op)){
                    if(results->OUT_S[statement].values().find((*ptr)->result) == results->OUT_S[statement].values().end()){
                        it.erase();
                        optimized=true;
                        continue;
                    }
                }
            }

            ++it;
        }
    }

    std::unordered_set<Offset, mtac::OffsetHash> used_offsets;

    for(auto& block : function){
        for(auto& statement : block->statements){
            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                auto quadruple = *ptr;

                if(quadruple->op == mtac::Operator::DOT || quadruple->op == mtac::Operator::FDOT || quadruple->op == mtac::Operator::PDOT){
                    if(auto* var_ptr = boost::get<std::shared_ptr<Variable>>(&*quadruple->arg1)){
                        if(auto* offset_ptr = boost::get<int>(&*quadruple->arg2)){
                            mtac::Offset offset(*var_ptr, *offset_ptr);
                            used_offsets.insert(offset);
                        }
                    }
                }
            }
        }
    }

    for(auto& block : function){
        auto it = block->statements.begin();
        auto end = block->statements.end();

        while(it != end){
            auto statement = *it;

            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                auto quadruple = *ptr;

                if(quadruple->op == mtac::Operator::DOT_ASSIGN || quadruple->op == mtac::Operator::DOT_FASSIGN || quadruple->op == mtac::Operator::DOT_PASSIGN){
                    //Arrays are a problem because they are not considered as escaped after being passed in parameters
                    if(!quadruple->result->type()->is_pointer() && !quadruple->result->type()->is_array()){
                        if(auto* offset_ptr = boost::get<int>(&*quadruple->arg1)){
                            if(quadruple->result->type()->is_custom_type() || quadruple->result->type()->is_template_type()){
                                auto struct_type = function.context->global()->get_struct(quadruple->result->type()->mangle());
                                auto member_type = function.context->global()->member_type(struct_type, *offset_ptr);

                                if(member_type->is_pointer()){
                                    ++it;
                                    continue;
                                }
                            }

                            mtac::Offset offset(quadruple->result, *offset_ptr);

                            if(problem.pointer_escaped->find(quadruple->result) == problem.pointer_escaped->end() && used_offsets.find(offset) == used_offsets.end()){
                                it = block->statements.erase(it);
                                end = block->statements.end();
                                optimized=true;
                                continue;
                            }
                        }
                    }
                }
            }

            ++it;
        }
    }

    return optimized;
}
<commit_msg>Fix DCE<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <list>

#include "Type.hpp"
#include "FunctionContext.hpp"
#include "GlobalContext.hpp"
#include "Variable.hpp"

#include "mtac/DeadCodeElimination.hpp"
#include "mtac/GlobalOptimizations.hpp"
#include "mtac/LiveVariableAnalysisProblem.hpp"
#include "mtac/Utils.hpp"
#include "mtac/Offset.hpp"
#include "mtac/Statement.hpp"

#include "ltac/Statement.hpp"

using namespace eddic;

bool mtac::dead_code_elimination::operator()(mtac::Function& function){
    bool optimized = false;

    mtac::LiveVariableAnalysisProblem problem;
    auto results = mtac::data_flow(function, problem);

    for(auto& block : function){
        auto it = iterate(block->statements);

        while(it.has_next()){
            auto statement = *it;

            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                if(mtac::erase_result((*ptr)->op)){
                    if(results->OUT_S[statement].top() || results->OUT_S[statement].values().find((*ptr)->result) == results->OUT_S[statement].values().end()){
                        it.erase();
                        optimized=true;
                        continue;
                    }
                }
            }

            ++it;
        }
    }

    std::unordered_set<Offset, mtac::OffsetHash> used_offsets;

    for(auto& block : function){
        for(auto& statement : block->statements){
            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                auto quadruple = *ptr;

                if(quadruple->op == mtac::Operator::DOT || quadruple->op == mtac::Operator::FDOT || quadruple->op == mtac::Operator::PDOT){
                    if(auto* var_ptr = boost::get<std::shared_ptr<Variable>>(&*quadruple->arg1)){
                        if(auto* offset_ptr = boost::get<int>(&*quadruple->arg2)){
                            mtac::Offset offset(*var_ptr, *offset_ptr);
                            used_offsets.insert(offset);
                        }
                    }
                }
            }
        }
    }

    for(auto& block : function){
        auto it = block->statements.begin();
        auto end = block->statements.end();

        while(it != end){
            auto statement = *it;

            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                auto quadruple = *ptr;

                if(quadruple->op == mtac::Operator::DOT_ASSIGN || quadruple->op == mtac::Operator::DOT_FASSIGN || quadruple->op == mtac::Operator::DOT_PASSIGN){
                    //Arrays are a problem because they are not considered as escaped after being passed in parameters
                    if(!quadruple->result->type()->is_pointer() && !quadruple->result->type()->is_array()){
                        if(auto* offset_ptr = boost::get<int>(&*quadruple->arg1)){
                            if(quadruple->result->type()->is_custom_type() || quadruple->result->type()->is_template_type()){
                                auto struct_type = function.context->global()->get_struct(quadruple->result->type()->mangle());
                                auto member_type = function.context->global()->member_type(struct_type, *offset_ptr);

                                if(member_type->is_pointer()){
                                    ++it;
                                    continue;
                                }
                            }

                            mtac::Offset offset(quadruple->result, *offset_ptr);

                            if(problem.pointer_escaped->find(quadruple->result) == problem.pointer_escaped->end() && used_offsets.find(offset) == used_offsets.end()){
                                it = block->statements.erase(it);
                                end = block->statements.end();
                                optimized=true;
                                continue;
                            }
                        }
                    }
                }
            }

            ++it;
        }
    }

    return optimized;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/conformance/rpcclient/GTestHarnessRPCClient.h>

#include <chrono>
#include <memory>
#include <stdexcept>

#include <fmt/core.h>
#include <folly/Subprocess.h>
#include <folly/experimental/coro/AsyncGenerator.h>
#include <folly/experimental/coro/BlockingWait.h>
#include <folly/experimental/coro/Sleep.h>
#include <folly/futures/Future.h>
#include <thrift/conformance/RpcStructComparator.h>
#include <thrift/conformance/Utils.h>
#include <thrift/conformance/if/gen-cpp2/RPCConformanceService.h>
#include <thrift/lib/cpp2/async/Sink.h>
#include <thrift/lib/cpp2/server/BaseThriftServer.h>
#include <thrift/lib/cpp2/util/ScopedServerInterfaceThread.h>

namespace apache::thrift::conformance {

class ConformanceVerificationServer
    : public apache::thrift::ServiceHandler<RPCConformanceService> {
 public:
  explicit ConformanceVerificationServer(const RpcTestCase& testCase)
      : testCase_(testCase) {}

  void getTestCase(RpcTestCase& testCase) override {
    testCase = testCase_;
    getTestReceivedPromise_.setValue();
  }

  void sendTestResult(std::unique_ptr<ClientTestResult> result) override {
    clientResultPromise_.setValue(*result);
  }

  // =================== Request-Response ===================
  void requestResponseBasic(
      Response& res, std::unique_ptr<Request> req) override {
    res =
        *testCase_.serverInstruction()->requestResponseBasic_ref()->response();
    serverResult_.requestResponseBasic_ref().emplace().request() = *req;
  }

  void requestResponseDeclaredException(std::unique_ptr<Request> req) override {
    serverResult_.requestResponseDeclaredException_ref().emplace().request() =
        *req;
    throw can_throw(*testCase_.serverInstruction()
                         ->requestResponseDeclaredException_ref()
                         ->userException());
  }

  void requestResponseUndeclaredException(
      std::unique_ptr<Request> req) override {
    serverResult_.requestResponseUndeclaredException_ref().emplace().request() =
        *req;
    throw std::runtime_error(*testCase_.serverInstruction()
                                  ->requestResponseUndeclaredException_ref()
                                  ->exceptionMessage());
  }

  void requestResponseNoArgVoidResponse() override {
    serverResult_.requestResponseNoArgVoidResponse_ref().emplace();
  }

  void requestResponseTimeout(
      Response&, std::unique_ptr<Request> req) override {
    serverResult_.requestResponseTimeout_ref().emplace().request() = *req;
    folly::coro::blockingWait([&]() -> folly::coro::Task<void> {
      co_await folly::coro::sleep(
          std::chrono::milliseconds(*testCase_.serverInstruction()
                                         ->requestResponseTimeout_ref()
                                         ->timeoutMs()));
    }());
  }

  // =================== Stream ===================
  apache::thrift::ServerStream<Response> streamBasic(
      std::unique_ptr<Request> req) override {
    serverResult_.streamBasic_ref().emplace().request() = *req;
    for (auto payload :
         *testCase_.serverInstruction()->streamBasic_ref()->streamPayloads()) {
      co_yield std::move(payload);
    }
  }

  apache::thrift::ServerStream<Response> streamChunkTimeout(
      std::unique_ptr<Request> req) override {
    serverResult_.streamChunkTimeout_ref().emplace().request() = *req;
    for (auto payload : *testCase_.serverInstruction()
                             ->streamChunkTimeout_ref()
                             ->streamPayloads()) {
      co_yield std::move(payload);
    }
    co_await folly::coro::sleep(
        std::chrono::milliseconds(*testCase_.serverInstruction()
                                       ->streamChunkTimeout_ref()
                                       ->chunkTimeoutMs()));
  }

  apache::thrift::ResponseAndServerStream<Response, Response>
  streamInitialResponse(std::unique_ptr<Request> req) override {
    serverResult_.streamInitialResponse_ref().emplace().request() = *req;
    auto stream = folly::coro::co_invoke(
        [&]() -> folly::coro::AsyncGenerator<Response&&> {
          for (auto payload : *testCase_.serverInstruction()
                                   ->streamInitialResponse_ref()
                                   ->streamPayloads()) {
            co_yield std::move(payload);
          }
        });

    return {
        *testCase_.serverInstruction()
             ->streamInitialResponse_ref()
             ->initialResponse(),
        std::move(stream)};
  }

  apache::thrift::ServerStream<Response> streamCreditTimeout(
      std::unique_ptr<Request> req) override {
    serverResult_.streamCreditTimeout_ref().emplace().request() = *req;
    for (auto payload : *testCase_.serverInstruction()
                             ->streamCreditTimeout_ref()
                             ->streamPayloads()) {
      co_yield std::move(payload);
    }
  }

  // =================== Sink ===================
  apache::thrift::SinkConsumer<Request, Response> sinkBasic(
      std::unique_ptr<Request> req) override {
    serverResult_.sinkBasic_ref().emplace().request() = *req;
    return apache::thrift::SinkConsumer<Request, Response>{
        [&](folly::coro::AsyncGenerator<Request&&> gen)
            -> folly::coro::Task<Response> {
          while (auto item = co_await gen.next()) {
            serverResult_.sinkBasic_ref()->sinkPayloads()->push_back(
                std::move(*item));
          }
          co_return *testCase_.serverInstruction()
              ->sinkBasic_ref()
              ->finalResponse();
        },
        static_cast<uint64_t>(
            *testCase_.serverInstruction()->sinkBasic_ref()->bufferSize())};
  }

  folly::SemiFuture<folly::Unit> getTestReceived() {
    return getTestReceivedPromise_.getSemiFuture();
  }

  folly::SemiFuture<ClientTestResult> clientResult() {
    return clientResultPromise_.getSemiFuture();
  }

  const ServerTestResult& serverResult() { return serverResult_; }

 private:
  const RpcTestCase& testCase_;
  folly::Promise<folly::Unit> getTestReceivedPromise_;
  folly::Promise<ClientTestResult> clientResultPromise_;
  ServerTestResult serverResult_;
};

class RPCClientConformanceTest : public testing::Test {
 public:
  RPCClientConformanceTest(
      std::string_view clientCmd, const TestCase* testCase, bool conforming)
      : testCase_(*testCase),
        conforming_(conforming),
        handler_(std::make_shared<ConformanceVerificationServer>(
            *testCase_.rpc_ref())),
        server_(handler_) {
    clientProcess_ = folly::Subprocess(std::vector<std::string>{
        std::string(clientCmd),
        "--port",
        folly::to<std::string>(server_.getPort())});
    if (testCase_.rpc_ref()->serverInstruction()->streamCreditTimeout_ref()) {
      server_.getThriftServer().setStreamExpireTime(
          std::chrono::milliseconds{*testCase_.rpc_ref()
                                         ->serverInstruction()
                                         ->streamCreditTimeout_ref()
                                         ->streamExpireTime()});
    }
  }

 protected:
  void TestBody() override {
    // Wait for client to fetch test case
    bool getTestReceived =
        handler_->getTestReceived().wait(std::chrono::seconds(5));
    EXPECT_EQ(conforming_, getTestReceived);

    // End test if client was unable to fetch test case
    if (!getTestReceived) {
      return;
    }

    // Wait for result from client
    folly::Try<ClientTestResult> actualClientResult =
        handler_->clientResult().within(std::chrono::seconds(5)).getTry();

    // End test if result was not received
    if (actualClientResult.hasException()) {
      EXPECT_FALSE(conforming_);
      return;
    }

    auto& expectedClientResult = *testCase_.rpc_ref()->clientTestResult();
    if (!equal(*actualClientResult, expectedClientResult)) {
      EXPECT_FALSE(conforming_);
    }

    auto& actualServerResult = handler_->serverResult();
    auto& expectedServerResult = *testCase_.rpc_ref()->serverTestResult();
    if (actualServerResult != expectedServerResult) {
      EXPECT_FALSE(conforming_);
    }

    EXPECT_TRUE(conforming_);
  }

  void TearDown() override {
    clientProcess_.sendSignal(SIGINT);
    clientProcess_.waitOrTerminateOrKill(
        std::chrono::seconds(5), std::chrono::seconds(5));
  }

 private:
  const TestCase& testCase_;
  bool conforming_;
  std::shared_ptr<ConformanceVerificationServer> handler_;
  apache::thrift::ScopedServerInterfaceThread server_;
  folly::Subprocess clientProcess_;
};

void registerTests(
    std::string_view category,
    const TestSuite* suite,
    const std::set<std::string>& nonconforming,
    std::string_view clientCmd,
    const char* file,
    int line) {
  for (const auto& test : *suite->tests()) {
    for (const auto& testCase : *test.testCases()) {
      std::string suiteName =
          fmt::format("{}/{}/{}", category, *suite->name(), *testCase.name());
      std::string fullName = fmt::format("{}.{}", suiteName, *test.name());
      bool conforming = nonconforming.find(fullName) == nonconforming.end();
      registerTest(
          suiteName.c_str(),
          test.name()->c_str(),
          nullptr,
          conforming ? nullptr : "nonconforming",
          file,
          line,
          [&testCase, clientCmd, conforming]() {
            return new RPCClientConformanceTest(
                clientCmd, &testCase, conforming);
          });
    }
  }
}

} // namespace apache::thrift::conformance
<commit_msg>Respect nonconforming in rpcclient test<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thrift/conformance/rpcclient/GTestHarnessRPCClient.h>

#include <chrono>
#include <memory>
#include <stdexcept>

#include <fmt/core.h>
#include <folly/Subprocess.h>
#include <folly/experimental/coro/AsyncGenerator.h>
#include <folly/experimental/coro/BlockingWait.h>
#include <folly/experimental/coro/Sleep.h>
#include <folly/futures/Future.h>
#include <thrift/conformance/RpcStructComparator.h>
#include <thrift/conformance/Utils.h>
#include <thrift/conformance/if/gen-cpp2/RPCConformanceService.h>
#include <thrift/lib/cpp2/async/Sink.h>
#include <thrift/lib/cpp2/server/BaseThriftServer.h>
#include <thrift/lib/cpp2/util/ScopedServerInterfaceThread.h>

namespace apache::thrift::conformance {

class ConformanceVerificationServer
    : public apache::thrift::ServiceHandler<RPCConformanceService> {
 public:
  explicit ConformanceVerificationServer(const RpcTestCase& testCase)
      : testCase_(testCase) {}

  void getTestCase(RpcTestCase& testCase) override {
    testCase = testCase_;
    getTestReceivedPromise_.setValue();
  }

  void sendTestResult(std::unique_ptr<ClientTestResult> result) override {
    clientResultPromise_.setValue(*result);
  }

  // =================== Request-Response ===================
  void requestResponseBasic(
      Response& res, std::unique_ptr<Request> req) override {
    res =
        *testCase_.serverInstruction()->requestResponseBasic_ref()->response();
    serverResult_.requestResponseBasic_ref().emplace().request() = *req;
  }

  void requestResponseDeclaredException(std::unique_ptr<Request> req) override {
    serverResult_.requestResponseDeclaredException_ref().emplace().request() =
        *req;
    throw can_throw(*testCase_.serverInstruction()
                         ->requestResponseDeclaredException_ref()
                         ->userException());
  }

  void requestResponseUndeclaredException(
      std::unique_ptr<Request> req) override {
    serverResult_.requestResponseUndeclaredException_ref().emplace().request() =
        *req;
    throw std::runtime_error(*testCase_.serverInstruction()
                                  ->requestResponseUndeclaredException_ref()
                                  ->exceptionMessage());
  }

  void requestResponseNoArgVoidResponse() override {
    serverResult_.requestResponseNoArgVoidResponse_ref().emplace();
  }

  void requestResponseTimeout(
      Response&, std::unique_ptr<Request> req) override {
    serverResult_.requestResponseTimeout_ref().emplace().request() = *req;
    folly::coro::blockingWait([&]() -> folly::coro::Task<void> {
      co_await folly::coro::sleep(
          std::chrono::milliseconds(*testCase_.serverInstruction()
                                         ->requestResponseTimeout_ref()
                                         ->timeoutMs()));
    }());
  }

  // =================== Stream ===================
  apache::thrift::ServerStream<Response> streamBasic(
      std::unique_ptr<Request> req) override {
    serverResult_.streamBasic_ref().emplace().request() = *req;
    for (auto payload :
         *testCase_.serverInstruction()->streamBasic_ref()->streamPayloads()) {
      co_yield std::move(payload);
    }
  }

  apache::thrift::ServerStream<Response> streamChunkTimeout(
      std::unique_ptr<Request> req) override {
    serverResult_.streamChunkTimeout_ref().emplace().request() = *req;
    for (auto payload : *testCase_.serverInstruction()
                             ->streamChunkTimeout_ref()
                             ->streamPayloads()) {
      co_yield std::move(payload);
    }
    co_await folly::coro::sleep(
        std::chrono::milliseconds(*testCase_.serverInstruction()
                                       ->streamChunkTimeout_ref()
                                       ->chunkTimeoutMs()));
  }

  apache::thrift::ResponseAndServerStream<Response, Response>
  streamInitialResponse(std::unique_ptr<Request> req) override {
    serverResult_.streamInitialResponse_ref().emplace().request() = *req;
    auto stream = folly::coro::co_invoke(
        [&]() -> folly::coro::AsyncGenerator<Response&&> {
          for (auto payload : *testCase_.serverInstruction()
                                   ->streamInitialResponse_ref()
                                   ->streamPayloads()) {
            co_yield std::move(payload);
          }
        });

    return {
        *testCase_.serverInstruction()
             ->streamInitialResponse_ref()
             ->initialResponse(),
        std::move(stream)};
  }

  apache::thrift::ServerStream<Response> streamCreditTimeout(
      std::unique_ptr<Request> req) override {
    serverResult_.streamCreditTimeout_ref().emplace().request() = *req;
    for (auto payload : *testCase_.serverInstruction()
                             ->streamCreditTimeout_ref()
                             ->streamPayloads()) {
      co_yield std::move(payload);
    }
  }

  // =================== Sink ===================
  apache::thrift::SinkConsumer<Request, Response> sinkBasic(
      std::unique_ptr<Request> req) override {
    serverResult_.sinkBasic_ref().emplace().request() = *req;
    return apache::thrift::SinkConsumer<Request, Response>{
        [&](folly::coro::AsyncGenerator<Request&&> gen)
            -> folly::coro::Task<Response> {
          while (auto item = co_await gen.next()) {
            serverResult_.sinkBasic_ref()->sinkPayloads()->push_back(
                std::move(*item));
          }
          co_return *testCase_.serverInstruction()
              ->sinkBasic_ref()
              ->finalResponse();
        },
        static_cast<uint64_t>(
            *testCase_.serverInstruction()->sinkBasic_ref()->bufferSize())};
  }

  folly::SemiFuture<folly::Unit> getTestReceived() {
    return getTestReceivedPromise_.getSemiFuture();
  }

  folly::SemiFuture<ClientTestResult> clientResult() {
    return clientResultPromise_.getSemiFuture();
  }

  const ServerTestResult& serverResult() { return serverResult_; }

 private:
  const RpcTestCase& testCase_;
  folly::Promise<folly::Unit> getTestReceivedPromise_;
  folly::Promise<ClientTestResult> clientResultPromise_;
  ServerTestResult serverResult_;
};

class RPCClientConformanceTest : public testing::Test {
 public:
  RPCClientConformanceTest(
      std::string_view clientCmd, const TestCase* testCase, bool conforming)
      : testCase_(*testCase),
        conforming_(conforming),
        handler_(std::make_shared<ConformanceVerificationServer>(
            *testCase_.rpc_ref())),
        server_(handler_) {
    clientProcess_ = folly::Subprocess(std::vector<std::string>{
        std::string(clientCmd),
        "--port",
        folly::to<std::string>(server_.getPort())});
    if (testCase_.rpc_ref()->serverInstruction()->streamCreditTimeout_ref()) {
      server_.getThriftServer().setStreamExpireTime(
          std::chrono::milliseconds{*testCase_.rpc_ref()
                                         ->serverInstruction()
                                         ->streamCreditTimeout_ref()
                                         ->streamExpireTime()});
    }
  }

 protected:
  void TestBody() override {
    // Wait for client to fetch test case
    bool getTestReceived =
        handler_->getTestReceived().wait(std::chrono::seconds(5));

    // End test if client was unable to fetch test case
    if (!getTestReceived) {
      EXPECT_FALSE(conforming_);
      return;
    }

    // Wait for result from client
    folly::Try<ClientTestResult> actualClientResult =
        handler_->clientResult().within(std::chrono::seconds(5)).getTry();

    // End test if result was not received
    if (actualClientResult.hasException()) {
      EXPECT_FALSE(conforming_);
      return;
    }

    auto& expectedClientResult = *testCase_.rpc_ref()->clientTestResult();
    if (!equal(*actualClientResult, expectedClientResult)) {
      EXPECT_FALSE(conforming_);
    }

    auto& actualServerResult = handler_->serverResult();
    auto& expectedServerResult = *testCase_.rpc_ref()->serverTestResult();
    if (actualServerResult != expectedServerResult) {
      EXPECT_FALSE(conforming_);
    }

    EXPECT_TRUE(conforming_);
  }

  void TearDown() override {
    clientProcess_.sendSignal(SIGINT);
    clientProcess_.waitOrTerminateOrKill(
        std::chrono::seconds(5), std::chrono::seconds(5));
  }

 private:
  const TestCase& testCase_;
  bool conforming_;
  std::shared_ptr<ConformanceVerificationServer> handler_;
  apache::thrift::ScopedServerInterfaceThread server_;
  folly::Subprocess clientProcess_;
};

void registerTests(
    std::string_view category,
    const TestSuite* suite,
    const std::set<std::string>& nonconforming,
    std::string_view clientCmd,
    const char* file,
    int line) {
  for (const auto& test : *suite->tests()) {
    for (const auto& testCase : *test.testCases()) {
      std::string suiteName =
          fmt::format("{}/{}/{}", category, *suite->name(), *testCase.name());
      std::string fullName = fmt::format("{}.{}", suiteName, *test.name());
      bool conforming = nonconforming.find(fullName) == nonconforming.end();
      registerTest(
          suiteName.c_str(),
          test.name()->c_str(),
          nullptr,
          conforming ? nullptr : "nonconforming",
          file,
          line,
          [&testCase, clientCmd, conforming]() {
            return new RPCClientConformanceTest(
                clientCmd, &testCase, conforming);
          });
    }
  }
}

} // namespace apache::thrift::conformance
<|endoftext|>