2020-09-29 12:53:40 +02:00
/****************************************************************************
2020-06-07 14:43:47 +02:00
* * 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/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-04-11 23:41:34 +02:00
# include "../headers/scstwrace.h"
ScStwRace : : ScStwRace ( QObject * parent ) : QObject ( parent )
{
this - > state = IDLE ;
// configure the loop that waits for the sound effect to finish
this - > soundPlayer = new ScStwSoundPlayer ( ) ;
// configure timer that handles the delay between the start commands
2020-10-02 14:16:24 +02:00
this - > startDelayTimer = new QTimer ( this ) ;
startDelayTimer - > setSingleShot ( true ) ;
this - > startWaitLoop = new QEventLoop ( this ) ;
2020-04-11 23:41:34 +02:00
2020-10-02 14:16:24 +02:00
connect ( this - > startDelayTimer , & QTimer : : timeout , this - > startWaitLoop , & QEventLoop : : quit ) ;
2020-04-11 23:41:34 +02:00
// write default settings
2020-10-02 14:16:24 +02:00
this - > startSoundSettings . insert ( ScStwSoundPlayer : : Start , { { " Enabled " , true } , { " Delay " , 1 } } ) ;
this - > writeStartSoundSetting ( ScStwSoundPlayer : : AtYourMarks , false , 0 ) ;
this - > writeStartSoundSetting ( ScStwSoundPlayer : : Ready , false , 0 ) ;
2020-04-11 23:41:34 +02:00
this - > setSoundVolume ( 1.0 ) ;
2020-10-02 14:16:24 +02:00
this - > competitionMode = false ;
2020-04-11 23:41:34 +02:00
}
// --------------------------
// --- Main Functionality ---
// --------------------------
2020-04-19 13:09:24 +02:00
int ScStwRace : : start ( bool asyncronous ) {
2020-10-02 14:16:24 +02:00
if ( this - > state = = WAITING ) {
if ( this - > isReadyForNextState ( ) ) {
this - > startWaitLoop - > exit ( LoopManualExit ) ;
return ScStw : : Success ;
}
else {
return ScStw : : TimersNotReadyError ;
}
}
else if ( this - > state ! = IDLE ) {
2020-05-10 17:39:16 +02:00
return ScStw : : CurrentStateNotVaildForOperationError ;
2020-04-11 23:41:34 +02:00
}
2020-09-29 12:53:40 +02:00
qDebug ( ) < < " [INFO][RACE] checking timers " ;
2020-10-02 14:16:24 +02:00
if ( ! this - > isReadyForNextState ( ) )
return ScStw : : TimersNotReadyError ;
2020-09-29 12:53:40 +02:00
qDebug ( ) < < " [INFO][RACE] starting race " ;
this - > setState ( PREPAIRING ) ;
2020-04-11 23:41:34 +02:00
2020-04-19 13:09:24 +02:00
if ( asyncronous ) {
2020-09-29 12:53:40 +02:00
QTimer : : singleShot ( 1 , [ = ] ( ) { this - > playSoundsAndStartTimers ( ) ; } ) ;
2020-04-19 13:09:24 +02:00
}
else
2020-09-29 12:53:40 +02:00
this - > playSoundsAndStartTimers ( ) ;
2020-04-11 23:41:34 +02:00
2020-04-19 22:39:33 +02:00
return ScStw : : Success ;
2020-04-11 23:41:34 +02:00
}
int ScStwRace : : stop ( ) {
if ( this - > state ! = RUNNING & & this - > state ! = STARTING ) {
2020-05-10 17:39:16 +02:00
return ScStw : : CurrentStateNotVaildForOperationError ;
2020-04-11 23:41:34 +02:00
}
qDebug ( ) < < " + [INFO] stopping race " ;
2020-04-15 19:21:32 +02:00
double timeOfStop = QDateTime : : currentMSecsSinceEpoch ( ) ;
2020-04-19 22:39:33 +02:00
int returnCode = ScStw : : Success ;
2020-04-11 23:41:34 +02:00
foreach ( ScStwTimer * speedTimer , this - > timers ) {
2020-04-15 19:21:32 +02:00
if ( ! speedTimer - > stop ( timeOfStop ) & & speedTimer - > getState ( ) ! = ScStwTimer : : DISABLED ) {
2020-04-19 22:39:33 +02:00
returnCode = ScStw : : InternalErrorTimerOperationFailed ;
2020-04-11 23:41:34 +02:00
}
}
2020-04-19 22:39:33 +02:00
if ( returnCode = = ScStw : : Success ) {
2020-04-11 23:41:34 +02:00
this - > setState ( STOPPED ) ;
}
return returnCode ;
}
void ScStwRace : : handleTimerStop ( ) {
if ( this - > state = = RUNNING ) {
// find out which timer has won
double lowestStoppedTime = - 1 ;
2020-04-15 19:21:32 +02:00
QList < ScStwTimer * > timersWhichHaveWonIds ;
2020-04-11 23:41:34 +02:00
// iterate through all timers and find the lowest time taht was stopped
2020-04-15 19:21:32 +02:00
foreach ( ScStwTimer * timer , this - > timers ) {
2020-04-11 23:41:34 +02:00
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
2020-04-15 19:21:32 +02:00
foreach ( ScStwTimer * timer , this - > timers ) {
if ( timer - > getCurrentTime ( ) > 0
& & ( timer - > getCurrentTime ( ) < = lowestStoppedTime | | lowestStoppedTime < 0 )
& & timer - > getState ( ) ! = ScStwTimer : : RUNNING
) {
2020-04-11 23:41:34 +02:00
// this is the timer with the lowest stopped time
2020-04-15 19:21:32 +02:00
timersWhichHaveWonIds . append ( timer ) ;
2020-04-11 23:41:34 +02:00
}
}
// update the states of all timers
2020-04-15 19:21:32 +02:00
foreach ( ScStwTimer * timer , this - > timers ) {
if ( timer - > getState ( ) = = ScStwTimer : : RUNNING )
continue ;
2020-04-11 23:41:34 +02:00
2020-04-15 19:21:32 +02:00
if ( timersWhichHaveWonIds . contains ( timer ) ) {
timer - > setResult ( ScStwTimer : : WON ) ;
2020-04-11 23:41:34 +02:00
}
2020-04-15 19:21:32 +02:00
else {
timer - > setResult ( ScStwTimer : : LOST ) ;
2020-04-11 23:41:34 +02:00
}
}
}
}
int ScStwRace : : reset ( ) {
2020-09-29 15:21:00 +02:00
if ( this - > state ! = STOPPED & & this - > state ! = INCIDENT ) {
2020-05-10 17:39:16 +02:00
return ScStw : : CurrentStateNotVaildForOperationError ;
2020-04-11 23:41:34 +02:00
}
qDebug ( ) < < " + [INFO] resetting race " ;
2020-04-19 22:39:33 +02:00
int returnCode = ScStw : : Success ;
2020-04-11 23:41:34 +02:00
foreach ( ScStwTimer * speedTimer , this - > timers ) {
if ( ! speedTimer - > reset ( ) & & speedTimer - > getState ( ) ! = ScStwTimer : : DISABLED ) {
2020-04-19 22:39:33 +02:00
returnCode = ScStw : : InternalErrorTimerOperationFailed ;
2020-04-11 23:41:34 +02:00
}
}
2020-10-01 01:54:39 +02:00
if ( returnCode = = ScStw : : Success )
2020-04-11 23:41:34 +02:00
this - > setState ( IDLE ) ;
return returnCode ;
}
2020-04-19 22:39:33 +02:00
int ScStwRace : : cancel ( ) {
2020-09-29 15:21:00 +02:00
if ( this - > state ! = PREPAIRING & & this - > state ! = WAITING & & this - > state ! = STARTING & & this - > state ! = RUNNING )
2020-05-10 17:39:16 +02:00
return ScStw : : CurrentStateNotVaildForOperationError ;
2020-04-11 23:41:34 +02:00
2020-04-19 22:39:33 +02:00
qDebug ( ) < < " [INFO][RACE] cancelling race " ;
2020-04-11 23:41:34 +02:00
2020-04-19 22:39:33 +02:00
int returnCode = ScStw : : Success ;
2020-04-11 23:41:34 +02:00
2020-04-19 22:39:33 +02:00
foreach ( ScStwTimer * timer , this - > timers ) {
if ( ! timer - > cancel ( ) & & timer - > getState ( ) ! = ScStwTimer : : DISABLED )
returnCode = ScStw : : InternalErrorTimerOperationFailed ;
2020-04-11 23:41:34 +02:00
}
2020-10-01 01:54:39 +02:00
if ( returnCode ! = ScStw : : Success )
return returnCode ;
this - > setState ( STOPPED ) ;
2020-10-02 14:16:24 +02:00
this - > startWaitLoop - > exit ( LoopCancelExit ) ;
2020-10-01 01:54:39 +02:00
this - > soundPlayer - > cancel ( this - > soundVolume ) ;
2020-10-02 14:16:24 +02:00
this - > startDelayTimer - > stop ( ) ;
2020-10-01 01:54:39 +02:00
2020-04-19 22:39:33 +02:00
return returnCode ;
}
int ScStwRace : : handleFalseStart ( ) {
if ( this - > getState ( ) ! = STARTING & & this - > getState ( ) ! = RUNNING )
2020-05-10 17:39:16 +02:00
return ScStw : : CurrentStateNotVaildForOperationError ;
2020-04-19 22:39:33 +02:00
int returnCode = ScStw : : Success ;
// cancel all running timers
foreach ( ScStwTimer * timer , this - > timers ) {
if ( ! timer - > cancel ( ) & & timer - > getState ( ) ! = ScStwTimer : : DISABLED & & timer - > getState ( ) ! = ScStwTimer : : FAILED )
returnCode = ScStw : : InternalErrorTimerOperationFailed ;
2020-04-11 23:41:34 +02:00
}
2020-04-19 22:39:33 +02:00
this - > setState ( STOPPED ) ;
this - > soundPlayer - > cancel ( this - > soundVolume ) ;
return returnCode ;
2020-04-11 23:41:34 +02:00
}
2020-09-29 12:53:40 +02:00
bool ScStwRace : : playSoundsAndStartTimers ( ) {
if ( this - > state ! = PREPAIRING )
2020-04-11 23:41:34 +02:00
return true ;
2020-09-29 12:53:40 +02:00
// The check if all timers are ready has already happened at this point
2020-10-02 15:20:11 +02:00
qDebug ( ) < < " now playing at marks sound " ;
2020-10-02 14:16:24 +02:00
if ( ! this - > doDelayAndSoundOfCurrentStartState ( ) )
2020-09-29 12:53:40 +02:00
return false ;
2020-04-11 23:41:34 +02:00
2020-09-29 15:21:00 +02:00
// check if the start was cancelled
2020-10-01 01:54:39 +02:00
if ( ! this - > isStarting ( ) )
2020-09-29 15:21:00 +02:00
return false ;
2020-10-02 15:20:11 +02:00
qDebug ( ) < < " Now in waiting state " ;
2020-09-29 12:53:40 +02:00
this - > setState ( WAITING ) ;
2020-04-11 23:41:34 +02:00
2020-09-29 12:53:40 +02:00
// do climber readiness tests
2020-10-02 14:16:24 +02:00
// wait until both climbers are ready
2020-09-29 12:53:40 +02:00
// if the automatic ready tone is enabled, wait for the climbers to become ready
2020-10-02 15:20:11 +02:00
if ( this - > competitionMode & & this - > startSoundSettings . contains ( ScStwSoundPlayer : : Ready ) & & this - > startSoundSettings [ ScStwSoundPlayer : : Ready ] [ " Enabled " ] . toBool ( ) ) {
2020-09-29 12:53:40 +02:00
2020-09-29 15:21:00 +02:00
qDebug ( ) < < " [RACE][INFO] Now waiting for climbers " ;
2020-04-11 23:41:34 +02:00
2020-09-29 15:21:00 +02:00
// get delay
int minimumReadyDelay = 1000 ;
2020-10-02 14:16:24 +02:00
if ( this - > startSoundSettings [ ScStwSoundPlayer : : Ready ] [ " Delay " ] . toInt ( ) > 1000 )
minimumReadyDelay = this - > startSoundSettings [ ScStwSoundPlayer : : Ready ] [ " Delay " ] . toInt ( ) ;
this - > startDelayTimer - > setInterval ( minimumReadyDelay ) ;
2020-09-29 12:53:40 +02:00
2020-09-29 15:21:00 +02:00
// wait for climbers to become ready initially
2020-10-02 14:16:24 +02:00
bool timerTriggered = true ;
do {
if ( ! this - > isReadyForNextState ( ) ) {
this - > startDelayTimer - > stop ( ) ;
timerTriggered = false ;
}
else if ( this - > startDelayTimer - > isActive ( ) ) {
timerTriggered = true ;
}
else {
this - > startDelayTimer - > stop ( ) ;
this - > startDelayTimer - > start ( ) ;
2020-10-02 15:20:11 +02:00
timerTriggered = true ;
2020-09-29 15:21:00 +02:00
}
2020-09-29 12:53:40 +02:00
2020-10-02 14:16:24 +02:00
emit this - > currentStartDelayChanged ( ) ;
2020-09-29 12:53:40 +02:00
2020-10-02 15:20:11 +02:00
qDebug ( ) < < " entering wait loop... " ;
2020-10-02 14:16:24 +02:00
int loopExitCode = this - > startWaitLoop - > exec ( ) ;
2020-10-02 15:20:11 +02:00
qDebug ( ) < < " wait loop exited with code " < < loopExitCode ;
2020-10-02 14:16:24 +02:00
switch ( loopExitCode ) {
case LoopAutomaticExit :
break ;
case LoopManualExit :
// prevent manual stop
timerTriggered = false ;
break ;
case LoopCancelExit :
2020-09-29 15:21:00 +02:00
return false ;
2020-10-02 14:16:24 +02:00
}
2020-10-02 15:20:11 +02:00
qDebug ( ) < < " At end of loop: remaining time: " < < this - > startDelayTimer - > remainingTime ( ) < < " timer triggered: " < < timerTriggered < < " ready for next state: " < < this - > isReadyForNextState ( ) ;
2020-10-02 14:16:24 +02:00
} while ( this - > startDelayTimer - > remainingTime ( ) > 0 | | ! timerTriggered | | ! this - > isReadyForNextState ( ) ) ;
2020-09-29 12:53:40 +02:00
2020-09-29 15:21:00 +02:00
qDebug ( ) < < " [RACE][DEBUG] Initial wait finished " ;
2020-09-29 12:53:40 +02:00
2020-09-29 15:21:00 +02:00
// wait for all climbers to be ready for the ReadyActionDelay, but at least one second continuosly
// the climber ready wait loop will also quit, if the climber steps of the pad
// -> wait for both climbers to stand on the pad for at least one second
qDebug ( ) < < " [RACE][DEBUG] Wait finished, starting now! " ;
// play ready tone
2020-10-02 14:16:24 +02:00
if ( ! this - > soundPlayer - > play ( ScStwSoundPlayer : : Ready , this - > soundVolume ) )
2020-09-29 15:21:00 +02:00
return false ;
2020-04-11 23:41:34 +02:00
}
2020-10-02 15:20:11 +02:00
else if ( this - > competitionMode ) {
2020-10-02 14:16:24 +02:00
// wait for climbers and manual start
int loopExitCode ;
do {
loopExitCode = this - > startWaitLoop - > exec ( ) ;
if ( loopExitCode = = LoopCancelExit )
return false ;
} while ( loopExitCode ! = LoopManualExit | | ! this - > isReadyForNextState ( ) ) ;
}
2020-10-02 15:20:11 +02:00
else {
qDebug ( ) < < " now playing ready sound " ;
if ( ! this - > doDelayAndSoundOfCurrentStartState ( ) )
return false ;
}
qDebug ( ) < < " now in starting state " ;
2020-04-11 23:41:34 +02:00
2020-09-29 12:53:40 +02:00
// enter starting state
this - > setState ( STARTING ) ;
// play start tone
2020-10-02 15:20:11 +02:00
qDebug ( ) < < " now playing start sound " ;
2020-09-29 12:53:40 +02:00
double timeOfSoundPlaybackStart ;
2020-10-02 14:16:24 +02:00
this - > doDelayAndSoundOfCurrentStartState ( & timeOfSoundPlaybackStart ) ;
2020-09-29 12:53:40 +02:00
2020-04-11 23:41:34 +02:00
// perform start
// start all timers
bool startOk = true ;
foreach ( ScStwTimer * timer , this - > timers ) {
if ( ! timer - > start ( timeOfSoundPlaybackStart + 3100 ) & & timer - > getState ( ) ! = ScStwTimer : : DISABLED ) {
startOk = false ;
}
}
if ( ! startOk ) {
qDebug ( ) < < " [ERROR][START] error staring all timers " ;
return false ;
}
if ( ! this - > soundPlayer - > waitForSoundFinish ( ) ) {
qDebug ( ) < < " [ERROR][START] start sound wait error " ;
return false ;
}
// check if a false start occured
2020-10-01 01:54:39 +02:00
if ( ! this - > isStarting ( ) )
2020-04-11 23:41:34 +02:00
return true ;
this - > setState ( RUNNING ) ;
return true ;
}
2020-10-02 14:16:24 +02:00
bool ScStwRace : : doDelayAndSoundOfCurrentStartState ( double * timeOfSoundPlaybackStart ) {
ScStwSoundPlayer : : StartSound sound ;
switch ( this - > state ) {
case PREPAIRING :
sound = ScStwSoundPlayer : : AtYourMarks ;
break ;
case WAITING :
sound = ScStwSoundPlayer : : Ready ;
break ;
case STARTING :
sound = ScStwSoundPlayer : : Start ;
break ;
default :
2020-10-01 01:54:39 +02:00
return false ;
2020-10-02 14:16:24 +02:00
}
2020-10-01 01:54:39 +02:00
2020-10-02 14:16:24 +02:00
if ( this - > startSoundSettings . contains ( sound ) & & this - > startSoundSettings [ sound ] [ " Enabled " ] . toBool ( ) ) {
if ( sound ! = ScStwSoundPlayer : : Start & & this - > startSoundSettings [ sound ] [ " Delay " ] . toInt ( ) > 0 ) {
2020-09-29 12:53:40 +02:00
// perform the delay before the start
// get delay
2020-10-02 14:16:24 +02:00
int thisSoundDelay = this - > startSoundSettings [ sound ] [ " Delay " ] . toInt ( ) ;
2020-09-29 12:53:40 +02:00
// perform next action
2020-10-02 14:16:24 +02:00
if ( thisSoundDelay > 0 ) {
this - > startDelayTimer - > setInterval ( thisSoundDelay ) ;
this - > startDelayTimer - > start ( ) ;
emit this - > currentStartDelayChanged ( ) ;
if ( this - > startWaitLoop - > exec ( ) = = LoopCancelExit )
return false ;
2020-09-29 12:53:40 +02:00
}
}
2020-10-01 01:54:39 +02:00
if ( ! this - > isStarting ( ) )
return false ;
2020-10-02 14:16:24 +02:00
if ( ! this - > soundPlayer - > play ( sound , this - > soundVolume , timeOfSoundPlaybackStart ) )
2020-09-29 12:53:40 +02:00
return false ;
}
return true ;
}
2020-04-11 23:41:34 +02:00
void ScStwRace : : setState ( RaceState newState ) {
if ( newState ! = this - > state ) {
2020-04-19 13:09:24 +02:00
qDebug ( ) < < " [INFO][RACE] state changed: " < < newState ;
2020-04-11 23:41:34 +02:00
this - > state = newState ;
emit this - > stateChanged ( newState ) ;
if ( this - > state = = IDLE ) {
2020-08-09 13:29:37 +02:00
// if we changed to IDLE -> handle timer enable / disable
2020-10-02 14:16:24 +02:00
if ( this - > competitionModeChanged & & this - > competitionMode ) {
2020-08-09 13:29:37 +02:00
this - > enableAllTimers ( ) ;
2020-10-02 14:16:24 +02:00
this - > competitionModeChanged = false ;
2020-04-11 23:41:34 +02:00
}
2020-10-02 14:16:24 +02:00
if ( ! this - > competitionMode ) {
2020-08-09 13:29:37 +02:00
foreach ( ScStwTimer * timer , this - > timers ) {
if ( timer - > getWantsToBeDisabled ( ) & & timer - > getState ( ) ! = ScStwTimer : : DISABLED )
this - > handleTimerWantsToBeDisabledChange ( timer , timer - > getWantsToBeDisabled ( ) ) ;
}
}
2020-04-11 23:41:34 +02:00
}
}
}
void ScStwRace : : refreshTimerStates ( ) {
qDebug ( ) < < " [INFO][MAIN] refreshing timer states " ;
// check if the race is over
2020-04-15 19:21:32 +02:00
bool raceIsOver = true ;
2020-04-11 23:41:34 +02:00
foreach ( ScStwTimer * timer , this - > timers ) {
2020-04-17 19:57:00 +02:00
if ( timer - > getState ( ) < ScStwTimer : : WON & & timer - > getState ( ) ! = ScStwTimer : : WAITING ) {
2020-04-11 23:41:34 +02:00
// if the timer is not in stoped state
2020-04-15 19:21:32 +02:00
raceIsOver = false ;
2020-04-11 23:41:34 +02:00
break ;
}
2020-04-15 19:21:32 +02:00
else if ( timer - > getState ( ) = = ScStwTimer : : WAITING ) {
this - > handleTimerStop ( ) ;
2020-04-11 23:41:34 +02:00
}
2020-04-19 22:39:33 +02:00
else if ( timer - > getState ( ) = = ScStwTimer : : FAILED ) {
this - > handleFalseStart ( ) ;
}
2020-04-11 23:41:34 +02:00
}
2020-04-19 22:39:33 +02:00
if ( raceIsOver )
2020-04-11 23:41:34 +02:00
this - > setState ( STOPPED ) ;
}
// ------------------------
// --- helper functions ---
// ------------------------
2020-10-02 14:16:24 +02:00
bool ScStwRace : : isReadyForNextState ( ) {
2020-10-02 15:20:11 +02:00
if ( ! this - > competitionMode ) {
return true ;
}
2020-10-02 14:16:24 +02:00
switch ( this - > state ) {
case IDLE : {
foreach ( ScStwTimer * timer , this - > timers ) {
if ( timer - > getState ( ) = = ScStwTimer : : DISABLED )
continue ;
if ( timer - > getReadyState ( ) = = ScStwTimer : : ExtensionIsNotConnected | | timer - > getReadyState ( ) = = ScStwTimer : : ExtensionBatteryNotFine ) {
qDebug ( ) < < " Timer ready state is: " < < timer - > getReadyState ( ) ;
timer - > technicalIncident ( ) ;
foreach ( ScStwTimer * subTimer , this - > timers ) {
if ( timer ! = subTimer & & ( timer - > getReadyState ( ) = = ScStwTimer : : ExtensionIsNotConnected | | timer - > getReadyState ( ) = = ScStwTimer : : ExtensionBatteryNotFine ) )
subTimer - > technicalIncident ( ) ;
else if ( timer ! = subTimer )
subTimer - > setState ( ScStwTimer : : CANCELLED ) ;
}
this - > setState ( INCIDENT ) ;
qDebug ( ) < < " [ERROR][RACE] Could not start due to not-ready timers " ;
return false ;
}
}
break ;
case WAITING : {
foreach ( ScStwTimer * timer , this - > timers ) {
if ( timer - > getReadyState ( ) ! = ScStwTimer : : IsReady )
return false ;
}
break ;
}
default :
break ; ;
}
}
return true ;
}
2020-04-11 23:41:34 +02:00
/**
* @ brief ScStwRace : : handleTimerEnable function to enable timers at the right moment to prevent them from bricking the state machine
* @ param { ScStwExtensionControlledTimer * } timer timer to be enabled
*/
2020-08-09 13:29:37 +02:00
void ScStwRace : : handleTimerWantsToBeDisabledChange ( ScStwTimer * timer , bool wantsToBeDisabled ) {
2020-10-02 14:16:24 +02:00
if ( this - > competitionMode )
2020-08-09 13:29:37 +02:00
return ;
2020-04-11 23:41:34 +02:00
if ( this - > state = = IDLE ) {
2020-08-09 13:29:37 +02:00
timer - > setDisabled ( wantsToBeDisabled ) ;
2020-04-11 23:41:34 +02:00
}
2020-08-09 13:29:37 +02:00
}
2020-10-02 14:16:24 +02:00
void ScStwRace : : setCompetitionMode ( bool competitionMode ) {
if ( this - > competitionMode = = competitionMode )
2020-08-09 13:29:37 +02:00
return ;
2020-10-02 14:16:24 +02:00
qDebug ( ) < < " Setting competition mode to " < < competitionMode ;
2020-08-09 13:29:37 +02:00
2020-10-02 14:16:24 +02:00
this - > competitionMode = competitionMode ;
2020-08-09 13:29:37 +02:00
if ( this - > state ! = IDLE )
2020-10-02 14:16:24 +02:00
this - > competitionModeChanged = true ;
else if ( this - > competitionMode )
2020-08-09 13:29:37 +02:00
this - > enableAllTimers ( ) ;
}
void ScStwRace : : enableAllTimers ( ) {
if ( this - > state ! = IDLE )
return ;
qDebug ( ) < < " ENABLING ALL TIMERS " ;
foreach ( ScStwTimer * timer , this - > timers ) {
timer - > setDisabled ( false ) ;
2020-04-11 23:41:34 +02:00
}
}
2020-10-02 14:16:24 +02:00
QVariantList ScStwRace : : getCurrentStartDelay ( ) {
2020-04-11 23:41:34 +02:00
int nextActionDelay = 0 ;
2020-04-17 19:57:00 +02:00
double nextActionDelayProg = - 1 ;
2020-04-11 23:41:34 +02:00
2020-10-02 14:16:24 +02:00
if ( this - > state = = PREPAIRING | | this - > state = = WAITING ) {
2020-04-11 23:41:34 +02:00
// get the total delay and the delay progress of the next action timer
2020-10-02 14:16:24 +02:00
double remaining = this - > startDelayTimer - > remainingTime ( ) ;
nextActionDelay = this - > startDelayTimer - > interval ( ) ; ;
2020-04-11 23:41:34 +02:00
if ( remaining < 0 ) {
remaining = nextActionDelay ;
}
nextActionDelayProg = 1 - ( remaining / nextActionDelay ) ;
}
2020-04-17 19:57:00 +02:00
return {
2020-04-19 22:39:33 +02:00
nextActionDelay ,
nextActionDelayProg
2020-04-17 19:57:00 +02:00
} ;
2020-04-11 23:41:34 +02:00
}
2020-10-02 14:16:24 +02:00
bool ScStwRace : : writeStartSoundSetting ( ScStwSoundPlayer : : StartSound sound , bool enabled , int delay ) {
if ( sound ! = ScStwSoundPlayer : : AtYourMarks & & sound ! = ScStwSoundPlayer : : Ready )
2020-04-11 23:41:34 +02:00
return false ;
QVariantMap setting = { { " Enabled " , enabled } , { " Delay " , delay } } ;
2020-10-02 14:16:24 +02:00
if ( ! this - > startSoundSettings . contains ( sound ) )
this - > startSoundSettings . insert ( sound , setting ) ;
2020-04-11 23:41:34 +02:00
else
2020-10-02 14:16:24 +02:00
this - > startSoundSettings [ sound ] = setting ;
2020-04-11 23:41:34 +02:00
return true ;
}
bool ScStwRace : : setSoundVolume ( double volume ) {
if ( volume > = 0 & & volume < = 1 ) {
this - > soundVolume = volume ;
return true ;
}
else {
return false ;
}
}
bool ScStwRace : : addTimer ( ScStwTimer * timer ) {
if ( this - > state ! = IDLE )
return false ;
foreach ( ScStwTimer * existingTimer , this - > timers ) {
if ( existingTimer = = timer )
return true ;
}
this - > timers . append ( timer ) ;
connect ( timer , & ScStwTimer : : stateChanged , this , & ScStwRace : : refreshTimerStates ) ;
2020-08-09 13:29:37 +02:00
connect ( timer , & ScStwTimer : : wantsToBeDisabledChanged , this , & ScStwRace : : handleTimerWantsToBeDisabledChange ) ;
2020-04-17 19:57:00 +02:00
connect ( timer , & ScStwTimer : : stateChanged , this , & ScStwRace : : timersChanged ) ;
connect ( timer , & ScStwTimer : : reactionTimeChanged , this , & ScStwRace : : timersChanged ) ;
2020-10-02 14:16:24 +02:00
connect ( timer , & ScStwTimer : : readyStateChanged , this - > startWaitLoop , & QEventLoop : : quit ) ;
2020-04-11 23:41:34 +02:00
2020-10-02 14:16:24 +02:00
if ( this - > competitionMode & & timer - > getState ( ) = = ScStwTimer : : DISABLED )
2020-08-09 13:29:37 +02:00
timer - > setDisabled ( false ) ;
2020-04-11 23:41:34 +02:00
return true ;
}
ScStwRace : : RaceState ScStwRace : : getState ( ) {
return this - > state ;
}
2020-07-29 17:56:32 +02:00
QList < ScStwTimer * > ScStwRace : : getTimers ( ) {
return this - > timers ;
}
2020-04-11 23:41:34 +02:00
QVariantList ScStwRace : : getTimerDetailList ( ) {
QVariantList tmpTimers ;
foreach ( ScStwTimer * timer , this - > timers ) {
QVariantMap tmpTimer ;
tmpTimer . insert ( " id " , this - > timers . indexOf ( timer ) ) ;
tmpTimer . insert ( " state " , timer - > getState ( ) ) ;
tmpTimer . insert ( " currentTime " , timer - > getCurrentTime ( ) ) ;
tmpTimer . insert ( " reactionTime " , timer - > getReactionTime ( ) ) ;
2020-04-17 19:57:00 +02:00
tmpTimer . insert ( " text " , timer - > getText ( ) ) ;
2020-06-13 12:38:24 +02:00
tmpTimer . insert ( " letter " , timer - > getLetter ( ) ) ;
2020-04-11 23:41:34 +02:00
tmpTimers . append ( tmpTimer ) ;
}
return tmpTimers ;
}
2020-10-01 01:54:39 +02:00
bool ScStwRace : : isStarting ( ) {
return this - > state = = PREPAIRING | | this - > state = = WAITING | | this - > state = = STARTING ;
}