diff --git a/ScStwLibraries/headers/scstwrace.h b/ScStwLibraries/headers/scstwrace.h index f4d8718..17213b1 100644 --- a/ScStwLibraries/headers/scstwrace.h +++ b/ScStwLibraries/headers/scstwrace.h @@ -57,6 +57,7 @@ public: explicit ScStwRace(QObject *parent = nullptr); enum RaceState { IDLE, STARTING, WAITING, RUNNING, STOPPED }; + // will become IDLE, PREPAIRING, WAITING, STARTING, RUNNING, STOPPED later Q_ENUM(RaceState) enum StartAction { None = -1, AtYourMarks = 0, Ready = 1, Start = 2 }; @@ -77,17 +78,16 @@ protected: private: RaceState state; - QList timerEnableQueque; - QTimer *nextActionTimer; QEventLoop *nextActionLoop; // sounds ScStwSoundPlayer * soundPlayer; - // some settings double soundVolume; + bool allowAutomaticTimerDisable; + bool allowAutomaticTimerDisableChanged; /*! * \brief stores the start action settings @@ -125,6 +125,7 @@ public slots: bool writeStartActionSetting(StartAction action, bool enabled, int delay); bool setSoundVolume(double volume); virtual bool addTimer(ScStwTimer *timer); + void setAllowAutomaticTimerDisable(bool allow); // getters RaceState getState(); @@ -138,10 +139,10 @@ protected slots: private slots: void refreshTimerStates(); - void handleTimerEnable(ScStwTimer* timer); + void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled); int handleFalseStart(); bool playSoundsAndStartTimers(StartAction thisAction); - + void enableAllTimers(); /** * \brief Function to declare the winner and looser timers after a timer has been stopped diff --git a/ScStwLibraries/headers/scstwtimer.h b/ScStwLibraries/headers/scstwtimer.h index e1aac72..ee82a10 100644 --- a/ScStwLibraries/headers/scstwtimer.h +++ b/ScStwLibraries/headers/scstwtimer.h @@ -82,6 +82,7 @@ public: LOST, /*!< Timer has lost */ FAILED, /*!< A false start occured */ CANCELLED, /*!< Timer was cancelled */ +// INCIDENT, /*!< There was a technical incident */ DISABLED /*!< Timer is disabled */ }; Q_ENUM(TimerState); @@ -90,10 +91,22 @@ public: * \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) */ + 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) + */ + enum ReadyState { + IsReady = 0, /*!< Timer is ready for start */ + NotInIdleState, /*!< Timer is not in IDLE state */ + IsDisabled, /*!< Timer is disabled */ + NotAllExtensionsConnected, /*!< Not all extension of the timer are conneted */ + NotAllClimbersReady /*!< The startpad of the timer is not triggered */ }; protected: @@ -127,6 +140,11 @@ protected: */ QString letter; + /*! + * \brief Defines if the timer currently wants to be disabled or not + */ + bool wantsToBeDisabled; + public slots: /*! @@ -294,6 +312,18 @@ public slots: */ bool setLetter(QString newLetter); + /*! + * \brief Function to check if the timer currently wants to be disabled + * \return true or false + */ + bool getWantsToBeDisabled(); + + /*! + * \brief Function to get the current ready status of a timer + * \return The current ready status + */ + virtual ScStwTimer::ReadyState getReadyState(); + protected slots: /*! @@ -338,6 +368,12 @@ protected slots: */ void setState(TimerState newState); + /*! + * \brief Function to set whether the timer currently wants to be disabled + * \param wantsToBeDisabled true or false + */ + void setWantsToBeDisabled(bool wantsToBeDisabled); + signals: /*! @@ -354,7 +390,13 @@ signals: * \brief Emitted when the timer wants its state to be changed by the external handler * \param timer the timer object */ - void requestEnableChange(ScStwTimer* timer); + void wantsToBeDisabledChanged(ScStwTimer* timer, bool wantsToBeDisabled); + + /*! + * \brief Emitted when the ready state of the timer changes + * \param readyState the new ReadyState + */ + void readyStateChanged(ReadyState readyState); }; diff --git a/ScStwLibraries/sources/scstwrace.cpp b/ScStwLibraries/sources/scstwrace.cpp index 4c4adb1..12961cb 100644 --- a/ScStwLibraries/sources/scstwrace.cpp +++ b/ScStwLibraries/sources/scstwrace.cpp @@ -1,4 +1,4 @@ -/**************************************************************************** + /**************************************************************************** ** ScStw Libraries ** Copyright (C) 2020 Itsblue development ** @@ -39,6 +39,7 @@ ScStwRace::ScStwRace(QObject *parent) : QObject(parent) this->writeStartActionSetting(AtYourMarks, false, 0); this->writeStartActionSetting(Ready, false, 0); this->setSoundVolume(1.0); + this->allowAutomaticTimerDisable = false; } // -------------------------- @@ -256,12 +257,18 @@ void ScStwRace::setState(RaceState newState) { emit this->stateChanged(newState); if(this->state == IDLE) { - // if we changed to IDLE -> enable timers - foreach(ScStwTimer* timer, this->timerEnableQueque) { - this->handleTimerEnable(timer); + // if we changed to IDLE -> handle timer enable / disable + if(this->allowAutomaticTimerDisableChanged && !this->allowAutomaticTimerDisable) { + this->enableAllTimers(); + this->allowAutomaticTimerDisableChanged = false; } - this->timerEnableQueque.clear(); + if(this->allowAutomaticTimerDisable) { + foreach(ScStwTimer* timer, this->timers) { + if(timer->getWantsToBeDisabled() && timer->getState() != ScStwTimer::DISABLED) + this->handleTimerWantsToBeDisabledChange(timer, timer->getWantsToBeDisabled()); + } + } } } } @@ -299,17 +306,38 @@ void ScStwRace::refreshTimerStates() { * @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 */ -void ScStwRace::handleTimerEnable(ScStwTimer* timer) { +void ScStwRace::handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled) { + if(!this->allowAutomaticTimerDisable) + return; + if(this->state == IDLE) { - if(timer->getState() == ScStwTimer::DISABLED) { - timer->setDisabled(false); - } - else { - timer->setDisabled(true); - } + timer->setDisabled(wantsToBeDisabled); } - else { - this->timerEnableQueque.append(timer); +} + + +void ScStwRace::setAllowAutomaticTimerDisable(bool allow) { + if(this->allowAutomaticTimerDisable == allow) + return; + + qDebug() << "Setting allow automatic timer disable to " << allow; + + this->allowAutomaticTimerDisable = allow; + + if(this->state != IDLE) + this->allowAutomaticTimerDisableChanged = true; + else if(!this->allowAutomaticTimerDisable) + this->enableAllTimers(); +} + +void ScStwRace::enableAllTimers() { + if(this->state != IDLE) + return; + + qDebug() << "ENABLING ALL TIMERS"; + + foreach (ScStwTimer *timer, this->timers) { + timer->setDisabled(false); } } @@ -370,10 +398,13 @@ bool ScStwRace::addTimer(ScStwTimer *timer) { this->timers.append(timer); connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::refreshTimerStates); - connect(timer, &ScStwTimer::requestEnableChange, this, &ScStwRace::handleTimerEnable); + connect(timer, &ScStwTimer::wantsToBeDisabledChanged, this, &ScStwRace::handleTimerWantsToBeDisabledChange); connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged); connect(timer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged); + if(!this->allowAutomaticTimerDisable && timer->getState() == ScStwTimer::DISABLED) + timer->setDisabled(false); + return true; } diff --git a/ScStwLibraries/sources/scstwtimer.cpp b/ScStwLibraries/sources/scstwtimer.cpp index 11950e5..6a69f52 100644 --- a/ScStwLibraries/sources/scstwtimer.cpp +++ b/ScStwLibraries/sources/scstwtimer.cpp @@ -157,6 +157,10 @@ bool ScStwTimer::reset(){ return true; } +ScStwTimer::ReadyState ScStwTimer::getReadyState() { + return this->state == IDLE ? ScStwTimer::IsReady : ScStwTimer::NotInIdleState; +} + // ------------------------ // --- helper functions --- // ------------------------ @@ -283,3 +287,16 @@ void ScStwTimer::setDisabled(bool disabled) { else this->setState(IDLE); } + +void ScStwTimer::setWantsToBeDisabled(bool wantsToBeDisabled) { + if(this->wantsToBeDisabled == wantsToBeDisabled) + return; + + this->wantsToBeDisabled = wantsToBeDisabled; + + emit this->wantsToBeDisabledChanged(this, wantsToBeDisabled); +} + +bool ScStwTimer::getWantsToBeDisabled() { + return this->wantsToBeDisabled; +}