317 lines
8.4 KiB
C++
317 lines
8.4 KiB
C++
/****************************************************************************
|
|
** ScStw Libraries
|
|
** Copyright (C) 2020 Itsblue development
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
****************************************************************************/
|
|
|
|
#include "../headers/scstwtimer.h"
|
|
|
|
ScStwTimer::ScStwTimer(QObject* parent) : ScStwTimer("", parent)
|
|
{
|
|
}
|
|
|
|
ScStwTimer::ScStwTimer(QString letter, QObject *parent) : QObject(parent)
|
|
{
|
|
if(letter.length() > 1)
|
|
this->letter = letter[0];
|
|
else
|
|
this->letter = letter;
|
|
|
|
qDebug() << "Timer created with letter: " << letter;
|
|
|
|
this->startTime = 0;
|
|
this->stopTime = 0;
|
|
this->reactionTime = 0;
|
|
this->wantsToBeDisabled = false;
|
|
|
|
this->state = IDLE;
|
|
}
|
|
|
|
bool ScStwTimer::start() {
|
|
return this->start(QDateTime::currentMSecsSinceEpoch());
|
|
}
|
|
|
|
bool ScStwTimer::start(double timeOfStart) {
|
|
switch (this->state) {
|
|
case IDLE: {
|
|
// in case of IDLE, start the race!
|
|
|
|
this->startTime = timeOfStart;
|
|
this->stopTime = 0;
|
|
|
|
if(timeOfStart - QDateTime::currentMSecsSinceEpoch() > 0) {
|
|
this->setState(STARTING);
|
|
QTimer::singleShot(timeOfStart - QDateTime::currentMSecsSinceEpoch(), [=]() {
|
|
if(this->state == STARTING)
|
|
this->setState(RUNNING);
|
|
});
|
|
}
|
|
else
|
|
this->setState(RUNNING);
|
|
return true;
|
|
}
|
|
default: {
|
|
// otherwise the timer is not supposed to be started!
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScStwTimer::technicalIncident() {
|
|
qDebug() << "[INFO][TIMER] Timer got a technical incident";
|
|
|
|
this->setState(INCIDENT);
|
|
}
|
|
|
|
bool ScStwTimer::wildcard() {
|
|
if(this->state != STARTING)
|
|
return false;
|
|
|
|
this->setState(WILDCARD);
|
|
return true;
|
|
}
|
|
|
|
void ScStwTimer::handleClimberStart(double timeOfStart) {
|
|
this->reactionTime = timeOfStart - this->startTime;
|
|
qDebug() << "+ [INFO][TIMER] reaction time: " << this->reactionTime;
|
|
|
|
if(this->reactionTime <= 100 && this->reactionTime) {
|
|
qDebug() << "[INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime;
|
|
this->setState(FAILING);
|
|
}
|
|
|
|
emit this->reactionTimeChanged();
|
|
}
|
|
|
|
bool ScStwTimer::cancel() {
|
|
if(!(this->state == IDLE || this->state == STARTING || this->state == RUNNING))
|
|
return false;
|
|
|
|
qDebug() << "[INFO][TIMER] Timer was cancelled";
|
|
this->reactionTime = 0;
|
|
this->startTime = 0;
|
|
this->stopTime = 0;
|
|
|
|
this->setState(CANCELLED);
|
|
return true;
|
|
}
|
|
|
|
bool ScStwTimer::stop() {
|
|
return this->stop(QDateTime::currentMSecsSinceEpoch());
|
|
}
|
|
|
|
bool ScStwTimer::stop(double timeOfStop) {
|
|
if(this->state != RUNNING)
|
|
return false;
|
|
|
|
this->stopTime = timeOfStop;
|
|
|
|
// trigger an external state refresh to set the state to either WON or LOST depending on the other timers values (see ScStwRace::refreshTimerStates())
|
|
this->setState(WAITING);
|
|
|
|
qDebug() << "[INFO][TIMER] Stopped: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << this->getCurrentTime() << " reactionTime: " << reactionTime;
|
|
return true;
|
|
}
|
|
|
|
bool ScStwTimer::setResult(TimerState result) {
|
|
|
|
QList<ScStwTimer::TimerState> allowedStates = {
|
|
STARTING,
|
|
RUNNING,
|
|
WAITING,
|
|
WON,
|
|
FAILING,
|
|
FAILED
|
|
};
|
|
|
|
if(!allowedStates.contains(this->state))
|
|
return false;
|
|
|
|
/* The reasons why it has to accept all these states:
|
|
*
|
|
* STARTING: To set a timer to WILDCARD when its opponent has done a false start
|
|
* RUNNING: To set a timer to WILDCARD when its opponent has done a false start that was received with a delay
|
|
* WAITING: To set a timer to either WON or LOST
|
|
* WON: To set a timer to LOST when its opponent has won the race but their trigger was delayed
|
|
* FAILING: To set a timer to either FAILED or WILDCARD
|
|
* FAILED: To set a timer to WILDCARD when its opponent did an earlier false start but their tirgger was delayed
|
|
*/
|
|
|
|
switch (result) {
|
|
case LOST:
|
|
case WON:
|
|
if(this->state == WAITING || this->state == WON) {
|
|
this->setState(result);
|
|
return true;
|
|
}
|
|
break;
|
|
case WILDCARD:
|
|
case FAILED:
|
|
if(this->state == STARTING || this->state == RUNNING || this->state == FAILED || this->state == FAILING) {
|
|
this->setState(result);
|
|
return true;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ScStwTimer::reset() {
|
|
if( this->state < WON || this->state == DISABLED ) {
|
|
return false;
|
|
}
|
|
|
|
this->startTime = 0;
|
|
this->stopTime = 0;
|
|
this->reactionTime = 0;
|
|
|
|
this->setState(IDLE);
|
|
return true;
|
|
}
|
|
|
|
ScStwTimer::ReadyState ScStwTimer::getReadyState() {
|
|
return this->state == IDLE ? ScStwTimer::IsReady : ScStwTimer::NotInIdleState;
|
|
}
|
|
|
|
// ------------------------
|
|
// --- helper functions ---
|
|
// ------------------------
|
|
|
|
void ScStwTimer::setState(TimerState newState) {
|
|
if(this->state == DISABLED && newState != IDLE)
|
|
return;
|
|
|
|
if(this->state == INCIDENT && newState != IDLE)
|
|
return;
|
|
|
|
if(this->state != newState) {
|
|
this->state = newState;
|
|
qDebug() << "[INFO][TIMER] timer state changed: " << newState;
|
|
emit this->stateChanged(newState);
|
|
}
|
|
}
|
|
|
|
ScStwTimer::TimerState ScStwTimer::getState() {
|
|
return this->state;
|
|
}
|
|
|
|
double ScStwTimer::getCurrentTime() {
|
|
switch (this->state) {
|
|
case RUNNING:
|
|
return QDateTime::currentMSecsSinceEpoch() - this->startTime;
|
|
default: {
|
|
if(this->state == WAITING || this->state == WON || this->state == LOST)
|
|
return abs(this->stopTime - this->startTime);
|
|
else
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
double ScStwTimer::getReactionTime() {
|
|
return this->reactionTime;
|
|
}
|
|
|
|
QString ScStwTimer::getLetter() {
|
|
return this->letter;
|
|
}
|
|
|
|
QString ScStwTimer::getText() {
|
|
QString newText = "";
|
|
int newTime = 0;
|
|
switch (this->state) {
|
|
case ScStwTimer::IDLE:
|
|
newTime = 0;
|
|
break;
|
|
case ScStwTimer::STARTING:
|
|
newTime = 0;
|
|
break;
|
|
case ScStwTimer::RUNNING:
|
|
newTime = this->getCurrentTime();
|
|
break;
|
|
case ScStwTimer::WAITING:
|
|
newText = "please wait...";
|
|
break;
|
|
case ScStwTimer::WON:
|
|
newTime = this->getCurrentTime();
|
|
break;
|
|
case ScStwTimer::LOST:
|
|
newTime = this->getCurrentTime();
|
|
break;
|
|
case ScStwTimer::FAILING:
|
|
newText = "please wait...";
|
|
break;
|
|
case ScStwTimer::FAILED:
|
|
newText = "false start";
|
|
break;
|
|
case ScStwTimer::WILDCARD:
|
|
newText = "wildcard";
|
|
break;
|
|
case ScStwTimer::CANCELLED:
|
|
newText = "cancelled";
|
|
break;
|
|
case ScStwTimer::INCIDENT:
|
|
newText = "Technical incident!";
|
|
break;
|
|
case ScStwTimer::DISABLED:
|
|
newText = "---";
|
|
break;
|
|
}
|
|
|
|
if(newText == "")
|
|
newText = QString::number( newTime / 1000.0, 'f', 3 ).rightJustified(6, '0');
|
|
|
|
return newText;
|
|
}
|
|
|
|
void ScStwTimer::setDisabled(bool disabled) {
|
|
if(this->isDisabled() == disabled)
|
|
return;
|
|
|
|
if(disabled)
|
|
this->setState(DISABLED);
|
|
else
|
|
this->setState(IDLE);
|
|
|
|
emit this->readyStateChanged(this->getReadyState());
|
|
|
|
}
|
|
|
|
void ScStwTimer::setWantsToBeDisabled(bool wantsToBeDisabled) {
|
|
if(this->wantsToBeDisabled == wantsToBeDisabled)
|
|
return;
|
|
|
|
qDebug() << "Wants to be disabled changed: " << wantsToBeDisabled;
|
|
|
|
this->wantsToBeDisabled = wantsToBeDisabled;
|
|
|
|
emit this->wantsToBeDisabledChanged(this, wantsToBeDisabled);
|
|
}
|
|
|
|
bool ScStwTimer::getWantsToBeDisabled() {
|
|
return this->wantsToBeDisabled;
|
|
}
|
|
|
|
bool ScStwTimer::isRunning() {
|
|
return this->state == RUNNING;
|
|
}
|
|
|
|
bool ScStwTimer::isDisabled() {
|
|
return this->state == DISABLED;
|
|
}
|