From fcd12b127ea6c745f06fd5bde73f4581cd350aea Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Sun, 4 Oct 2020 16:31:49 +0200 Subject: [PATCH 1/2] finished implementing wildcard and failing state --- ScStwLibraries/headers/scstwrace.h | 14 +++++----- ScStwLibraries/headers/scstwtimer.h | 2 +- ScStwLibraries/sources/scstwrace.cpp | 39 +++++++++++++-------------- ScStwLibraries/sources/scstwtimer.cpp | 11 +++----- 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/ScStwLibraries/headers/scstwrace.h b/ScStwLibraries/headers/scstwrace.h index 48150bf..9b513dc 100644 --- a/ScStwLibraries/headers/scstwrace.h +++ b/ScStwLibraries/headers/scstwrace.h @@ -131,17 +131,19 @@ public slots: protected slots: private slots: - void handleTimerStateChange(); - void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled); - void handleFalseStart(); - bool playSoundsAndStartTimers(); - ScStwSoundPlayer::PlayResult doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr); - void technicalIncident(); + void handleTimerStateChange(ScStwTimer::TimerState newState); /** * \brief Function to declare the winner and looser timers after a timer has been stopped */ void handleTimerStop(); + void handleFalseStart(); + + + void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled); + bool playSoundsAndStartTimers(); + ScStwSoundPlayer::PlayResult doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr); + void technicalIncident(); virtual void refreshCompetitionMode(); diff --git a/ScStwLibraries/headers/scstwtimer.h b/ScStwLibraries/headers/scstwtimer.h index f2682c3..5ad69cf 100644 --- a/ScStwLibraries/headers/scstwtimer.h +++ b/ScStwLibraries/headers/scstwtimer.h @@ -348,7 +348,7 @@ signals: /*! * \brief Emitted when the state of the timer changed */ - void stateChanged(); + void stateChanged(TimerState state); /*! * \brief Emitted when the reaction time changed diff --git a/ScStwLibraries/sources/scstwrace.cpp b/ScStwLibraries/sources/scstwrace.cpp index 9deaa31..91bed70 100644 --- a/ScStwLibraries/sources/scstwrace.cpp +++ b/ScStwLibraries/sources/scstwrace.cpp @@ -405,7 +405,15 @@ void ScStwRace::setState(RaceState newState) { } } -void ScStwRace::handleTimerStateChange() { +void ScStwRace::handleTimerStateChange(ScStwTimer::TimerState newState) { + if( + newState == ScStwTimer::WON || + newState == ScStwTimer::LOST || + newState == ScStwTimer::WILDCARD || + newState == ScStwTimer::FAILED + ) + return; + qDebug() << "[INFO][MAIN] handling timer state change"; // check if the race is over @@ -438,7 +446,7 @@ void ScStwRace::handleTimerStop() { // iterate through all timers and find the lowest time that was stopped foreach(ScStwTimer * timer, this->timers) { - if(timer->getCurrentTime() > 0 && (timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0)) { + if(timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0) { // this is the timer with the lowest stopped time lowestStoppedTime = timer->getCurrentTime(); } @@ -446,26 +454,11 @@ void ScStwRace::handleTimerStop() { // append the timer(s) with the lowest stopped time to the winner list foreach(ScStwTimer * timer, this->timers) { - if(timer->getCurrentTime() > 0 - && (timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0) - && timer->getState() != ScStwTimer::RUNNING - ) { + if(timer->getCurrentTime() <= lowestStoppedTime) // this is the timer with the lowest stopped time - timersWhichHaveWon.append(timer); - } - } - - // update the states of all timers - foreach(ScStwTimer * timer, this->timers) { - if(timer->getState() == ScStwTimer::RUNNING) - continue; - - if(timersWhichHaveWon.contains(timer)) { timer->setResult(ScStwTimer::WON); - } - else { + else timer->setResult(ScStwTimer::LOST); - } } } @@ -476,7 +469,7 @@ void ScStwRace::handleFalseStart() { qDebug() << "[INFO][RACE] Got a FALSE START"; // set lowest to a value that is impossible to reach (start tone is only 3100ms long) - int lowestReactionTime = -4000; + double lowestReactionTime = -4000; // iterate through all timers and find the lowest reactiontime that was stopped foreach(ScStwTimer *timer, this->timers) { @@ -496,15 +489,19 @@ void ScStwRace::handleFalseStart() { // no timer has failed return; + qDebug() << "LOWEST reaction time is: " << lowestReactionTime; + // find out which timer(s) have lost and which get a wildcard foreach(ScStwTimer * timer, this->timers) { + qDebug() << "THIS TIMERS reaction time is: " << lowestReactionTime; if( timer->getState() >= ScStwTimer::FAILING && timer->getState() <= ScStwTimer::FAILED && - timer->getCurrentTime() <= lowestReactionTime + timer->getReactionTime() == lowestReactionTime ) { // this is the timer with the lowest stopped time timer->setResult(ScStwTimer::FAILED); + qDebug() << "FOUND BAD TIMER"; } else { timer->setResult(ScStwTimer::WILDCARD); diff --git a/ScStwLibraries/sources/scstwtimer.cpp b/ScStwLibraries/sources/scstwtimer.cpp index 0a5eff3..644e9b7 100644 --- a/ScStwLibraries/sources/scstwtimer.cpp +++ b/ScStwLibraries/sources/scstwtimer.cpp @@ -84,8 +84,8 @@ void ScStwTimer::handleClimberStart(double timeOfStart) { qDebug() << "+ [INFO][TIMER] reaction time: " << this->reactionTime; if(this->reactionTime <= 0 && this->reactionTime > -3100){ - this->stop(FailStop); - return; + qDebug() << "[INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime; + this->setState(FAILING); } emit this->reactionTimeChanged(); @@ -134,11 +134,6 @@ bool ScStwTimer::stop(StopReason reason, double timeOfStop) { } break; } - case FailStop: { - qDebug() << "[INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime; - this->setState(FAILED); - break; - } default: { return false; } @@ -209,7 +204,7 @@ void ScStwTimer::setState(TimerState newState){ if(this->state != newState) { this->state = newState; qDebug() << "[INFO][TIMER] timer state changed: " << newState; - emit this->stateChanged(); + emit this->stateChanged(newState); } } From 80aae3b22a0fc15e156feca9cb25e70845c31910 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Sun, 4 Oct 2020 17:25:30 +0200 Subject: [PATCH 2/2] fixes issues with delayed triggers. --- ScStwLibraries/headers/scstwtimer.h | 38 ---------------- ScStwLibraries/sources/scstwrace.cpp | 2 + ScStwLibraries/sources/scstwtimer.cpp | 62 +++++++++++++-------------- 3 files changed, 32 insertions(+), 70 deletions(-) diff --git a/ScStwLibraries/headers/scstwtimer.h b/ScStwLibraries/headers/scstwtimer.h index 5ad69cf..5b52247 100644 --- a/ScStwLibraries/headers/scstwtimer.h +++ b/ScStwLibraries/headers/scstwtimer.h @@ -94,17 +94,6 @@ public: }; Q_ENUM(TimerState); - /*! - * \brief The StopReason enum contains all possible reasons for a stop - */ - enum StopReason { - ManualStop, /*!< Timer was stopped manually */ - CancelStop, /*!< Timer was cancelled */ - FailStop, /*!< A false start occured */ - TopPadStop, /*!< Timer was stopped by a physical trigger (eg. a ScStwExtension) */ - TechnicalIncidentStop /*!< The timer was stopped due to a technical incident */ - }; - /*! * \brief The ReadyStatus enum contains all possible reasons for a timer not to be ready (>0) and the case that it is ready (0) */ @@ -283,33 +272,6 @@ protected slots: */ void handleClimberStart(double timeOfStart); - /*! - * \brief Function to stop the timer at a given point in time (past or future) - * - * To do this, the timer has to be in ScStwTimer::RUNNING state! - * - * \param reason reason for the timer stop - * \param timeOfStop the point in time (msecs since epoch) when the timer is supposted to be stopped - * - * \return false if the timer was not in the required state and therefore not stopped, true otherwise - * - * \see ScStwTimer::StopReason - */ - virtual bool stop(StopReason reason, double timeOfStop); - - /*! - * \brief Function to stop the timer - * - * To do this, the timer has to be in ScStwTimer::RUNNING state! - * - * \param reason reason for the timer stop - * - * \return false if the timer was not in the required state and therefore not stopped, true otherwise - * - * \see ScStwTimer::StopReason - */ - bool stop(StopReason reason); - /*! * \brief Function to change the state of the timer * diff --git a/ScStwLibraries/sources/scstwrace.cpp b/ScStwLibraries/sources/scstwrace.cpp index 91bed70..4b3c97c 100644 --- a/ScStwLibraries/sources/scstwrace.cpp +++ b/ScStwLibraries/sources/scstwrace.cpp @@ -440,6 +440,8 @@ void ScStwRace::handleTimerStop() { if(this->state != RUNNING) return; + qDebug() << "[INFO][RACE] Got a TIMER STOP"; + // find out which timer has won double lowestStoppedTime = -1; QList timersWhichHaveWon; diff --git a/ScStwLibraries/sources/scstwtimer.cpp b/ScStwLibraries/sources/scstwtimer.cpp index 644e9b7..c853ae3 100644 --- a/ScStwLibraries/sources/scstwtimer.cpp +++ b/ScStwLibraries/sources/scstwtimer.cpp @@ -83,7 +83,7 @@ void ScStwTimer::handleClimberStart(double timeOfStart) { this->reactionTime = timeOfStart - this->startTime; qDebug() << "+ [INFO][TIMER] reaction time: " << this->reactionTime; - if(this->reactionTime <= 0 && this->reactionTime > -3100){ + if(this->reactionTime <= 0 && this->reactionTime){ qDebug() << "[INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime; this->setState(FAILING); } @@ -109,58 +109,56 @@ bool ScStwTimer::stop() { } bool ScStwTimer::stop(double timeOfStop) { - return this->stop(ManualStop, timeOfStop); -} - -bool ScStwTimer::stop(StopReason reason) { - return this->stop(reason, QDateTime::currentMSecsSinceEpoch()); -} - -bool ScStwTimer::stop(StopReason reason, double timeOfStop) { - if(this->state != STARTING && this->state != WILDCARD && this->state != RUNNING && this->state != WAITING){ + if(this->state != RUNNING) return false; - } - switch (reason) { - case ManualStop: { - if(this->state == STARTING){ - this->setState(CANCELLED); - } - else { - this->stopTime = timeOfStop; + 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); - } - break; - } - default: { - return false; - } - } + // 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) { - if(this->state != FAILING && this->state != WAITING && this->state != STARTING) + + QList 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 WON: case LOST: - if(this->state == WAITING) { + case WON: + if(this->state == WAITING || this->state == WON) { this->setState(result); return true; } break; case WILDCARD: - if(this->state == STARTING) { + case FAILED: + if(this->state == STARTING || this->state == RUNNING || this->state == FAILED) { this->setState(WILDCARD); return true; } - case FAILED: if(this->state == FAILING) { this->setState(result); return true;