diff --git a/ScStwLibraries/headers/scstwrace.h b/ScStwLibraries/headers/scstwrace.h index 3df605b..48150bf 100644 --- a/ScStwLibraries/headers/scstwrace.h +++ b/ScStwLibraries/headers/scstwrace.h @@ -131,9 +131,9 @@ public slots: protected slots: private slots: - void handleTimersStateChange(); + void handleTimerStateChange(); void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled); - int handleFalseStart(); + void handleFalseStart(); bool playSoundsAndStartTimers(); ScStwSoundPlayer::PlayResult doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr); void technicalIncident(); diff --git a/ScStwLibraries/headers/scstwtimer.h b/ScStwLibraries/headers/scstwtimer.h index af782b8..f2682c3 100644 --- a/ScStwLibraries/headers/scstwtimer.h +++ b/ScStwLibraries/headers/scstwtimer.h @@ -82,11 +82,12 @@ public: IDLE, /*!< Timer is waiting to be started */ STARTING, /*!< Timer is starting and will react with a false start if the climber starts */ RUNNING, /*!< Timer is running */ - WAITING, /*!< Timer was stopped and is waiting for the result */ + WAITING, /*!< Timer was stopped and is waiting to be set to either WON or LOST */ WON, /*!< Timer has won */ LOST, /*!< Timer has lost */ - FAILED, /*!< A false start occured */ + FAILING, /*!< Timer encountered a false start and is waiting to be set to either FAILED or WILDCARD */ WILDCARD, /*!< The opponent has done a false start */ + FAILED, /*!< A false start occured */ CANCELLED, /*!< Timer was cancelled */ INCIDENT, /*!< There was a technical incident (most likely a disconnected extension) */ DISABLED /*!< Timer is disabled */ diff --git a/ScStwLibraries/sources/scstwrace.cpp b/ScStwLibraries/sources/scstwrace.cpp index a9adecc..9deaa31 100644 --- a/ScStwLibraries/sources/scstwrace.cpp +++ b/ScStwLibraries/sources/scstwrace.cpp @@ -103,46 +103,6 @@ ScStw::StatusCode ScStwRace::stop() { return returnCode; } -void ScStwRace::handleTimerStop() { - if(this->state == RUNNING) { - // find out which timer has won - double lowestStoppedTime = -1; - QList timersWhichHaveWonIds; - - // iterate through all timers and find the lowest time taht was stopped - foreach(ScStwTimer * timer, this->timers) { - if(timer->getCurrentTime() > 0 && (timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0)) { - // this is the timer with the lowest stopped time - lowestStoppedTime = timer->getCurrentTime(); - } - } - - // 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 - ) { - // this is the timer with the lowest stopped time - timersWhichHaveWonIds.append(timer); - } - } - - // update the states of all timers - foreach(ScStwTimer * timer, this->timers) { - if(timer->getState() == ScStwTimer::RUNNING) - continue; - - if(timersWhichHaveWonIds.contains(timer)) { - timer->setResult(ScStwTimer::WON); - } - else { - timer->setResult(ScStwTimer::LOST); - } - } - } -} - ScStw::StatusCode ScStwRace::reset() { if(this->state != STOPPED && this->state != INCIDENT) { return ScStw::CurrentStateNotVaildForOperationError; @@ -240,28 +200,6 @@ void ScStwRace::handleTimerReadyStateChange(ScStwTimer::ReadyState readyState) { } } -int ScStwRace::handleFalseStart() { - if(this->state != STARTING && this->state != RUNNING) - return ScStw::CurrentStateNotVaildForOperationError; - - qDebug() << "[INFO][RACE] Got a FALSE START"; - - int returnCode = ScStw::Success; - - // set all running timers to wildcard - foreach(ScStwTimer *timer, this->timers) { - if(timer->getState() != ScStwTimer::FAILED && timer->getState() != ScStwTimer::DISABLED) - if(!timer->wildcard()) - returnCode = ScStw::InternalErrorTimerOperationFailed; - } - - this->setState(STOPPED); - this->soundPlayer->cancel(); - this->soundPlayer->play(ScStwSoundPlayer::FalseStart, this->getSoundVolume()); - - return returnCode; -} - bool ScStwRace::playSoundsAndStartTimers() { if(this->state != PREPAIRING) return true; @@ -467,20 +405,20 @@ void ScStwRace::setState(RaceState newState) { } } -void ScStwRace::handleTimersStateChange() { +void ScStwRace::handleTimerStateChange() { qDebug() << "[INFO][MAIN] handling timer state change"; // check if the race is over bool raceIsOver = true; foreach(ScStwTimer * timer, this->timers){ - if(timer->getState() < ScStwTimer::WON && timer->getState() != ScStwTimer::WAITING){ + if(timer->getState() < ScStwTimer::WAITING){ // if the timer is not in stoped state raceIsOver = false; } else if(timer->getState() == ScStwTimer::WAITING) this->handleTimerStop(); - else if (timer->getState() == ScStwTimer::FAILED) + else if (timer->getState() == ScStwTimer::FAILING) this->handleFalseStart(); else if (timer->getState() == ScStwTimer::INCIDENT) return; @@ -490,6 +428,94 @@ void ScStwRace::handleTimersStateChange() { this->setState(STOPPED); } +void ScStwRace::handleTimerStop() { + if(this->state != RUNNING) + return; + + // find out which timer has won + double lowestStoppedTime = -1; + QList timersWhichHaveWon; + + // 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)) { + // this is the timer with the lowest stopped time + lowestStoppedTime = timer->getCurrentTime(); + } + } + + // 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 + ) { + // 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 { + timer->setResult(ScStwTimer::LOST); + } + } +} + +void ScStwRace::handleFalseStart() { + if(this->state != STARTING && this->state != RUNNING && this->state != STOPPED) + return; + + 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; + + // iterate through all timers and find the lowest reactiontime that was stopped + foreach(ScStwTimer *timer, this->timers) { + if( + timer->getState() >= ScStwTimer::FAILING && + timer->getState() <= ScStwTimer::FAILED && + ( + timer->getReactionTime() < lowestReactionTime || + lowestReactionTime == -4000 + ) + ) { + lowestReactionTime = timer->getReactionTime(); + } + } + + if(lowestReactionTime == -4000) + // no timer has failed + return; + + // find out which timer(s) have lost and which get a wildcard + foreach(ScStwTimer * timer, this->timers) { + if( + timer->getState() >= ScStwTimer::FAILING && + timer->getState() <= ScStwTimer::FAILED && + timer->getCurrentTime() <= lowestReactionTime + ) { + // this is the timer with the lowest stopped time + timer->setResult(ScStwTimer::FAILED); + } + else { + timer->setResult(ScStwTimer::WILDCARD); + } + } + + this->setState(STOPPED); + this->soundPlayer->cancel(); + this->soundPlayer->play(ScStwSoundPlayer::FalseStart, this->getSoundVolume()); +} + // ------------------------ // --- helper functions --- // ------------------------ @@ -631,7 +657,7 @@ bool ScStwRace::addTimer(ScStwTimer *timer) { this->timers.append(timer); - connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::handleTimersStateChange); + connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::handleTimerStateChange); connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged); connect(timer, &ScStwTimer::wantsToBeDisabledChanged, this, &ScStwRace::handleTimerWantsToBeDisabledChange); connect(timer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged); diff --git a/ScStwLibraries/sources/scstwtimer.cpp b/ScStwLibraries/sources/scstwtimer.cpp index b0e01e5..f6cd71d 100644 --- a/ScStwLibraries/sources/scstwtimer.cpp +++ b/ScStwLibraries/sources/scstwtimer.cpp @@ -76,7 +76,6 @@ bool ScStwTimer::wildcard() { return false; this->setState(WILDCARD); - return true; } @@ -84,7 +83,7 @@ void ScStwTimer::handleClimberStart(double timeOfStart) { this->reactionTime = timeOfStart - this->startTime; qDebug() << "+ [INFO][TIMER] reaction time: " << this->reactionTime; - if(this->reactionTime <= 0){ + if(this->reactionTime <= 0 && this->reactionTime > -3100){ this->stop(FailStop); return; } @@ -150,19 +149,33 @@ bool ScStwTimer::stop(StopReason reason, double timeOfStop) { } bool ScStwTimer::setResult(TimerState result) { - if(this->state != WAITING) + if(this->state != FAILING && this->state != WAITING && this->state != STARTING) return false; switch (result) { case WON: - this->setState(WON); - return true; case LOST: - this->setState(LOST); - return true; + if(this->state == WAITING) { + this->setState(result); + return true; + } + break; + case WILDCARD: + if(this->state == STARTING) { + this->setState(WILDCARD); + return true; + } + case FAILED: + if(this->state == FAILING) { + this->setState(result); + return true; + } + break; default: - return false; + break; } + + return false; } bool ScStwTimer::reset(){ @@ -195,7 +208,7 @@ void ScStwTimer::setState(TimerState newState){ if(this->state != newState) { this->state = newState; - qDebug() << "+ [INFO][TIMER] timer state changed: " << newState; + qDebug() << "[INFO][TIMER] timer state changed: " << newState; emit this->stateChanged(); } }