<commit_before>#include <RefereeModule.hpp>
#include <framework/SystemState.hpp>

using namespace RefereeCommands;

// Distance in meters that the ball must travel for a kick to be detected
static const float KickThreshold = 0.150f;

// How many milliseconds the ball must be more than KickThreshold meters away from
// its position when the referee indicated Ready for us to detect the ball as having been kicked.
static const int KickVerifyTime_ms = 500;

RefereeModule::RefereeModule(SystemState *state):
	_mutex(QMutex::Recursive)
{
	_state = state;
	_counter = -1;
	_kickDetectState = WaitForReady;
	_blueTeam = false;
}

void RefereeModule::run()
{
	QMutexLocker locker(&_mutex);
	
	if (_state->ball.valid)
	{
		// Only run the kick detector when the ball is visible
		switch (_kickDetectState)
		{
			case WaitForReady:
				// Never kicked and not ready for a restart
				break;
				
			case CapturePosition:
				// Do this in the processing thread
				_readyBallPos = _state->ball.pos;
				_kickDetectState = WaitForKick;
				break;
				
			case WaitForKick:
				if (!_state->ball.pos.nearPoint(_readyBallPos, KickThreshold))
				{
					// The ball appears to have moved
					_kickTime = QTime::currentTime();
					_kickDetectState = VerifyKick;
				}
				break;
				
			case VerifyKick:
				if (_state->ball.pos.nearPoint(_readyBallPos, KickThreshold))
				{
					// The ball is back where it was.  There was probably a vision error.
					_kickDetectState = WaitForKick;
				} else if (_kickTime.msecsTo(QTime::currentTime()) >= KickVerifyTime_ms)
				{
					// The ball has been far enough away for enough time, so call this a kick.
					_kickDetectState = Kicked;
				}
				break;
				
			case Kicked:
				// Stay here until the referee puts us back in Ready
				break;
		}
	}
	
	if (_state->gameState.state == GameState::Ready && kicked())
	{
		_state->gameState.state = GameState::Playing;
	}
}

QString RefereeModule::lastPacketDescription()
{
	QMutexLocker locker(&_mutex);
	QString desc;
	
	if (_lastPacket.size() != 6)
	{
		return QString("%1 bytes").arg(_lastPacket.size());
	}
	char cmd = _lastPacket[0];
	switch (cmd)
	{
		case Halt:
			desc = "Halt";
			break;
		case Stop:
			desc = "Stop";
			break;
		case ForceStart:
			desc = "ForceStart";
			break;
		case Ready:
			desc = "Ready";
			break;
		case FirstHalf:
			desc = "FirstHalf";
			break;
		case Halftime:
			desc = "Halftime";
			break;
		case SecondHalf:
			desc = "SecondHalf";
			break;
		case Overtime1:
			desc = "Overtime1";
			break;
		case Overtime2:
			desc = "Overtime2";
			break;
		case PenaltyShootout:
			desc = "PenaltyShootout";
			break;
		case TimeoutYellow:
			desc = "TimeoutYellow";
			break;
		case TimeoutBlue:
			desc = "TimeoutBlue";
			break;
		case TimeoutEnd:
			desc = "TimeoutEnd";
			break;
		case TimeoutCancel:
			desc = "TimeoutCancel";
			break;
		case GoalYellow:
			desc = "GoalYellow";
			break;
		case GoalBlue:
			desc = "GoalBlue";
			break;
		case SubtractGoalYellow:
			desc = "SubtractGoalYellow";
			break;
		case SubtractGoalBlue:
			desc = "SubtractGoalBlue";
			break;
		case YellowCardYellow:
			desc = "YellowCardYellow";
			break;
		case YellowCardBlue:
			desc = "YellowCardBlue";
			break;
		case RedCardYellow:
			desc = "RedCardYellow";
			break;
		case RedCardBlue:
			desc = "RedCardBlue";
			break;
		case KickoffYellow:
			desc = "KickoffYellow";
			break;
		case KickoffBlue:
			desc = "KickoffBlue";
			break;
		case PenaltyYellow:
			desc = "PenaltyYellow";
			break;
		case PenaltyBlue:
			desc = "PenaltyBlue";
			break;
		case DirectYellow:
			desc = "DirectYellow";
			break;
		case DirectBlue:
			desc = "DirectBlue";
			break;
		case IndirectYellow:
			desc = "IndirectYellow";
			break;
		case IndirectBlue:
			desc = "IndirectBlue";
			break;
		default:
			desc = QString("'%1'").arg(cmd);
			break;
	}
	
	desc += QString(" #%1 Y%2 B%3").arg(QString::number(_lastPacket[1]), QString::number(_lastPacket[3]), QString::number(_lastPacket[2]));
	
	return desc;
}

void RefereeModule::packet(const std::string &packet)
{
	QMutexLocker locker(&_mutex);
	
	_lastPacket = packet;
	_lastPacketTime = QTime::currentTime();
	
	int cmd = packet[0];
	uint8_t newCounter = packet[1];
	
	// Update scores and time
	int scoreBlue = packet[2];<commit_msg>Time since last ref packet<commit_after>#include <RefereeModule.hpp>
#include <framework/SystemState.hpp>

using namespace RefereeCommands;

// Distance in meters that the ball must travel for a kick to be detected
static const float KickThreshold = 0.150f;

// How many milliseconds the ball must be more than KickThreshold meters away from
// its position when the referee indicated Ready for us to detect the ball as having been kicked.
static const int KickVerifyTime_ms = 500;

RefereeModule::RefereeModule(SystemState *state):
	_mutex(QMutex::Recursive)
{
	_state = state;
	_counter = -1;
	_kickDetectState = WaitForReady;
	_blueTeam = false;
}

void RefereeModule::run()
{
	QMutexLocker locker(&_mutex);
	
	if (_state->ball.valid)
	{
		// Only run the kick detector when the ball is visible
		switch (_kickDetectState)
		{
			case WaitForReady:
				// Never kicked and not ready for a restart
				break;
				
			case CapturePosition:
				// Do this in the processing thread
				_readyBallPos = _state->ball.pos;
				_kickDetectState = WaitForKick;
				break;
				
			case WaitForKick:
				if (!_state->ball.pos.nearPoint(_readyBallPos, KickThreshold))
				{
					// The ball appears to have moved
					_kickTime = QTime::currentTime();
					_kickDetectState = VerifyKick;
				}
				break;
				
			case VerifyKick:
				if (_state->ball.pos.nearPoint(_readyBallPos, KickThreshold))
				{
					// The ball is back where it was.  There was probably a vision error.
					_kickDetectState = WaitForKick;
				} else if (_kickTime.msecsTo(QTime::currentTime()) >= KickVerifyTime_ms)
				{
					// The ball has been far enough away for enough time, so call this a kick.
					_kickDetectState = Kicked;
				}
				break;
				
			case Kicked:
				// Stay here until the referee puts us back in Ready
				break;
		}
	}
	
	if (_state->gameState.state == GameState::Ready && kicked())
	{
		_state->gameState.state = GameState::Playing;
	}
}

QString RefereeModule::lastPacketDescription()
{
	QMutexLocker locker(&_mutex);
	QString desc;
	
	if (_lastPacket.size() != 6)
	{
		return QString("%1 bytes").arg(_lastPacket.size());
	}
	char cmd = _lastPacket[0];
	switch (cmd)
	{
		case Halt:
			desc = "Halt";
			break;
		case Stop:
			desc = "Stop";
			break;
		case ForceStart:
			desc = "ForceStart";
			break;
		case Ready:
			desc = "Ready";
			break;
		case FirstHalf:
			desc = "FirstHalf";
			break;
		case Halftime:
			desc = "Halftime";
			break;
		case SecondHalf:
			desc = "SecondHalf";
			break;
		case Overtime1:
			desc = "Overtime1";
			break;
		case Overtime2:
			desc = "Overtime2";
			break;
		case PenaltyShootout:
			desc = "PenaltyShootout";
			break;
		case TimeoutYellow:
			desc = "TimeoutYellow";
			break;
		case TimeoutBlue:
			desc = "TimeoutBlue";
			break;
		case TimeoutEnd:
			desc = "TimeoutEnd";
			break;
		case TimeoutCancel:
			desc = "TimeoutCancel";
			break;
		case GoalYellow:
			desc = "GoalYellow";
			break;
		case GoalBlue:
			desc = "GoalBlue";
			break;
		case SubtractGoalYellow:
			desc = "SubtractGoalYellow";
			break;
		case SubtractGoalBlue:
			desc = "SubtractGoalBlue";
			break;
		case YellowCardYellow:
			desc = "YellowCardYellow";
			break;
		case YellowCardBlue:
			desc = "YellowCardBlue";
			break;
		case RedCardYellow:
			desc = "RedCardYellow";
			break;
		case RedCardBlue:
			desc = "RedCardBlue";
			break;
		case KickoffYellow:
			desc = "KickoffYellow";
			break;
		case KickoffBlue:
			desc = "KickoffBlue";
			break;
		case PenaltyYellow:
			desc = "PenaltyYellow";
			break;
		case PenaltyBlue:
			desc = "PenaltyBlue";
			break;
		case DirectYellow:
			desc = "DirectYellow";
			break;
		case DirectBlue:
			desc = "DirectBlue";
			break;
		case IndirectYellow:
			desc = "IndirectYellow";
			break;
		case IndirectBlue:
			desc = "IndirectBlue";
			break;
		default:
			desc = QString("'%1'").arg(cmd);
			break;
	}
	
	desc += QString(" #%1 Y%2 B%3 (%4s)").arg(QString::number(_lastPacket[1]), QString::number(_lastPacket[3]), QString::number(_lastPacket[2]), QString::number(_lastPacketTime.msecsTo(QTime::currentTime()) / 1000.0, 'f', 1));
	
	return desc;
}

void RefereeModule::packet(const std::string &packet)
{
	QMutexLocker locker(&_mutex);
	
	_lastPacket = packet;
	_lastPacketTime = QTime::currentTime();
	
	int cmd = packet[0];
	uint8_t newCounter = packet[1];
	
	// Update scores and time
	int scoreBlue = packet[2];
{'fraction_non_alphanumeric': 0.11184058972586962, 'fraction_numerical': 0.006795669200645013, 'mean_word_length': 3.3589357429718874, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, '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': '7116220', 'n_tokens_mistral': 3597, 'n_tokens_neox': 2955, 'n_words': 796}