<commit_before>// kate: indent-mode cstyle; indent-width 4; tab-width 4; space-indent false;
// vim:ai ts=4 et

//FIXME - The rules allow for changing the goalie only in certain circumstances.  Make sure we do this right.

#include "Goalie.hpp"

#include <gameplay/Play.hpp>
#include <gameplay/Window.hpp>
#include <Geometry2d/util.h>

#include <boost/foreach.hpp>

#include <Constants.hpp>

#include <iostream>

using namespace std;
using namespace Geometry2d;

static const float MaxX = Field_GoalWidth / 2.0f;
static const float margin = /*Ball_Radius * 4*/ 0;

void Gameplay::Behaviors::Goalie::createConfiguration(Configuration *cfg) {

}

Gameplay::Behaviors::Goalie::Goalie(GameplayModule *gameplay) :
		SingleRobotBehavior(gameplay), _kick(gameplay) {
	_win = new WindowEvaluator(_gameplay->state());
	_win->debug = true;

	_state = Defend;
	robot = 0;
	_index = 0;

}

Gameplay::Behaviors::Goalie::~Goalie() {
	delete _win;
}

/** Checks whether or not the given ball is in the defense area. */
bool ballIsInGoalieBox(Ball ball) {
	if (abs(ball.pos.x) < Field_GoalFlat / 2.0f) // Ball is in center (rectangular) portion of defensive bubble
	{
		if (ball.pos.y > 0 && ball.pos.y < Field_ArcRadius) {
			return true;
		} else {
			return false;
		}
	} else if (abs(ball.pos.x) < (Field_ArcRadius + Field_GoalFlat / 2.0f)) // Ball is in one of the side (arc) portions of defensive bubble
	{
		double adjusted_x = abs(ball.pos.x) - (Field_GoalFlat / 2.0f);
		double max_y = sqrt( (Field_ArcRadius * Field_ArcRadius) - (adjusted_x * adjusted_x));
		if (ball.pos.y > 0 && ball.pos.y <= max_y) {
			return true;
		} else {
			return false;
		}
	}
	return false;
}

void Gameplay::Behaviors::Goalie::assign(set<OurRobot *> &available) {
	if (!robot) {
		// Take the robot nearest the goal
		assignNearest(robot, available, Geometry2d::Point());
		if (robot) {
			printf("Goalie: no robot, took %d\n", robot->shell());
		} else {
// 			printf("Goalie: not assigned\n");
		}
	/*	} else if (robot && !robot->visible)
		{
		 //FIXME - Goalie replacement
		 available.erase(robot);*/
	} else {
		// Keep the current goalie, and prevent it from being used in a play
		available.erase(robot);
	}
}

bool Gameplay::Behaviors::Goalie::opponentsHavePossession() {
	if(opponentWithBall())
		return true;
	else
		return false;
}

float angleBetweenThreePoints(Point a, Point b, Point vertex)
{
	float VA = sqrt(powf(vertex.x-a.x,2) + powf(vertex.y-a.y,2));//Segment(vertex, a).length();
	float VB = sqrt(powf(vertex.x-b.x,2) + powf(vertex.y-b.y,2));//Segment(vertex, b).length();
	float AB = sqrt(powf(a.x-b.x,2) + powf(a.y-b.y,2));//Segment(a, b).length();
	std::cout  << (VA*VA + VB*VB + AB*AB)/(2*VA*VB) << std::endl;
	//std::cout << acosf((VA*VA + VB*VB + AB*AB)/(2*VA*VB));
	return acosf((VA*VA + VB*VB + AB*AB)/(2*VA*VB));
}

Robot* Gameplay::Behaviors::Goalie::opponentWithBall()
{
	Robot* closest = 0;
	float bestDist = 0;
	BOOST_FOREACH(Robot *r, state()->opp){
		float dist = r->pos.distTo(ball().pos);
		if (!closest || dist < bestDist)
		{
			closest = r;
			bestDist = dist;
		}
	}
	float angle = 3.14 * (closest->angle / 180);
	float theta = angleBetweenThreePoints(Point(closest->pos.x + cos(angle), closest->pos.y + sin(angle)),ball().pos,closest->pos);
	float maxRadius = Robot_Diameter + Robot_Diameter*cos(theta);
	//std::cout << theta << std::endl;
	if(closest && closest->pos.nearPoint(ball().pos, maxRadius))
		return closest;
	else
		return 0;
}

bool Gameplay::Behaviors::Goalie::ballIsMovingTowardsGoal()
{
	if(ball().vel.y < 0)
		return true;
	else<commit_msg>Fixed the math! Goalie can now accurately determine possession (according to our possession formula).<commit_after>// kate: indent-mode cstyle; indent-width 4; tab-width 4; space-indent false;
// vim:ai ts=4 et

//FIXME - The rules allow for changing the goalie only in certain circumstances.  Make sure we do this right.

#include "Goalie.hpp"

#include <gameplay/Play.hpp>
#include <gameplay/Window.hpp>
#include <Geometry2d/util.h>

#include <boost/foreach.hpp>

#include <Constants.hpp>

#include <iostream>

using namespace std;
using namespace Geometry2d;

static const float MaxX = Field_GoalWidth / 2.0f;
static const float margin = /*Ball_Radius * 4*/ 0;

void Gameplay::Behaviors::Goalie::createConfiguration(Configuration *cfg) {

}

Gameplay::Behaviors::Goalie::Goalie(GameplayModule *gameplay) :
		SingleRobotBehavior(gameplay), _kick(gameplay) {
	_win = new WindowEvaluator(_gameplay->state());
	_win->debug = true;

	_state = Defend;
	robot = 0;
	_index = 0;

}

Gameplay::Behaviors::Goalie::~Goalie() {
	delete _win;
}

/** Checks whether or not the given ball is in the defense area. */
bool ballIsInGoalieBox(Ball ball) {
	if (abs(ball.pos.x) < Field_GoalFlat / 2.0f) // Ball is in center (rectangular) portion of defensive bubble
	{
		if (ball.pos.y > 0 && ball.pos.y < Field_ArcRadius) {
			return true;
		} else {
			return false;
		}
	} else if (abs(ball.pos.x) < (Field_ArcRadius + Field_GoalFlat / 2.0f)) // Ball is in one of the side (arc) portions of defensive bubble
	{
		double adjusted_x = abs(ball.pos.x) - (Field_GoalFlat / 2.0f);
		double max_y = sqrt( (Field_ArcRadius * Field_ArcRadius) - (adjusted_x * adjusted_x));
		if (ball.pos.y > 0 && ball.pos.y <= max_y) {
			return true;
		} else {
			return false;
		}
	}
	return false;
}

void Gameplay::Behaviors::Goalie::assign(set<OurRobot *> &available) {
	if (!robot) {
		// Take the robot nearest the goal
		assignNearest(robot, available, Geometry2d::Point());
		if (robot) {
			printf("Goalie: no robot, took %d\n", robot->shell());
		} else {
// 			printf("Goalie: not assigned\n");
		}
	/*	} else if (robot && !robot->visible)
		{
		 //FIXME - Goalie replacement
		 available.erase(robot);*/
	} else {
		// Keep the current goalie, and prevent it from being used in a play
		available.erase(robot);
	}
}

bool Gameplay::Behaviors::Goalie::opponentsHavePossession() {
	if(opponentWithBall())
		return true;
	else
		return false;
}

float angleBetweenThreePoints(Point a, Point b, Point vertex)
{
	float VA = sqrt(powf(vertex.x-a.x,2) + powf(vertex.y-a.y,2));
	float VB = sqrt(powf(vertex.x-b.x,2) + powf(vertex.y-b.y,2));
	float AB = sqrt(powf(a.x-b.x,2) + powf(a.y-b.y,2));
	return acosf((VA*VA + VB*VB - AB*AB)/(2*VA*VB));
}

Robot* Gameplay::Behaviors::Goalie::opponentWithBall()
{
	Robot* closest = 0;
	float bestDist = 0;
	BOOST_FOREACH(Robot *r, state()->opp){
		float dist = r->pos.distTo(ball().pos);
		if (!closest || dist < bestDist)
		{
			closest = r;
			bestDist = dist;
		}
	}
	float angle = 3.14 * (closest->angle / 180);
	float theta = angleBetweenThreePoints(Point(closest->pos.x + cos(angle), closest->pos.y + sin(angle)),ball().pos,closest->pos);
	float maxRadius = Robot_Diameter + Robot_Diameter*cos(theta);
	//std::cout << theta << std::endl;
	if(closest && closest->pos.nearPoint(ball().pos, maxRadius))
		return closest;
	else
		return 0;
}

bool Gameplay::Behaviors::Goalie::ballIsMovingTowardsGoal()
{
	if(ball().vel.y < 0)
		return true;
	else
{'fraction_non_alphanumeric': 0.16168941979522183, 'fraction_numerical': 0.01080773606370876, 'mean_word_length': 4.12983223924143, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '969891', 'n_tokens_mistral': 2814, 'n_tokens_neox': 2659, 'n_words': 624}