#ifndef SCSTWTIMER_H #define SCSTWTIMER_H #include #include #include #include #include "ScStw.hpp" /*! * \brief The ScStwTimer class is used for advanced time measurement. * * It does not work on its own though. * It is recommended to use it in combination with the ScStwRace class. * * ## When using standalone: * \code{.cpp} * ScStwTimer timer; * // start the timer * timer.start(); * // stop the timer * timer.stop(); * \endcode * * The timer will now go into ScStw::WAITING state. * That indicates that the timer has stopped and the final result has to be assigned by an external handler. * * \code{.cpp} * // assign result 'won' * timer.setResult(ScStwTimer::WON); * \endcode * * The timer is now in ScStwTimer::WON state. * * \code{.cpp} * // reset the timer * timer.reset(); * \endcode * * The timer is not in ScStwTimer::IDLE state again. */ class ScStwTimer : public QObject { Q_OBJECT public: /*! * \brief ScStwTimer constructor * \param parent the parent object */ explicit ScStwTimer(QObject *parent = nullptr); /*! * \brief The TimerState enum contains all state the timer can be in */ enum TimerState { 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 */ WON, /*!< Timer has won */ LOST, /*!< Timer has lost */ FAILED, /*!< A false start occured */ CANCELLED, /*!< Timer was cancelled */ DISABLED /*!< Timer is disabled */ }; /*! * \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) */ }; protected: /*! * \brief The current state of the timer */ TimerState state; /*! * \brief The time the timer was started at */ double startTime; /*! * \brief The time the timer was stopped at */ double stopTime; /*! * \brief the reaction time of the climber */ double reactionTime; public slots: /*! * \brief Function to start the timer * * To do this, the timer has to be in ScStwTimer::STARTING state! * * \return false if the timer was not in the required state and therefore not started, true otherwise */ bool start(); /*! * \brief Function to start the timer at a given point in time (present or future) * * To do this, the timer has to be in ScStwTimer::STARTING state! * * \param timeOfStart the point in time (msecs since epoch) when the timer is supposted to be started * \return false if the timer was not in the required state and therefore not started, true otherwise */ bool start(double timeOfStart); /*! * \brief Function to cancel the timer * * To do this, the timer has to be in ScStwTimer::IDLE, ScStwTimer::STARTING or ScStwTimer::RUNNING state! * * \return false if the timer was not in the required state and therefore not cancelled, true otherwise */ bool cancel(); /*! * \brief Function to stop the timer * * To do this, the timer has to be in ScStwTimer::RUNNING state! * * \return false if the timer was not in the required state and therefore not stopped, true otherwise */ bool stop(); /*! * \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 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 */ bool stop(double timeOfStop); /*! * \brief Function to assing the result of the race to the timer * * To do this, the timer has to be in ScStwTimer::WAITING state! * * \return false if the timer was not in the required state and the result therefore not set, true otherwise */ bool setResult(TimerState); /*! * \brief Function to reset the timer * * To do this, the timer has to be in ScStwTimer::WON or ScSTw::LOST state! * * \return false if the timer was not in the required state and therefore not reset, true otherwise */ bool reset(); // -- helper functions -- /*! * \brief Function to get the current state of the timer * \return current state of the timer * \see ScStwTimer::TimerState */ TimerState getState(); /*! * \brief Function to get the current time of the timer * * To do this, the timer has to be in ScStwTimer::RUNNING, ScStwTimer::WAITING, ScStwTimer::WON or ScSTw::LOST state! * * \return The current / final time of the timer or -1 if it is not in the required state */ double getCurrentTime(); /*! * \brief Function to get the reaction time of the climber. * \return The climbers reaction time */ double getReactionTime(); /*! * \brief Function to set if the timer is supposed to be disabled * * !!! CAUTION use this function with care, it immidiately changes the state of the timer !!! * It is recommended to only use this function to change the timers state after the * ScStwTimer::requestTimerEnableChange() signal was called, during the race, * the timer is used in, is in IDLE state. * * \param disabled if the timer is supposed to be diabled */ void setDisabled(bool disabled); protected slots: /*! * \brief slot to call when the climber has started * \param timeOfStart time (msecs since epoch) when the climber started */ 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 */ 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); // --- helper functions --- /*! * \brief Function to change the state of the timer * * Doing this will emit the ScStwTimer::stateChanged() signal (only if the new state differs from the current one) * * \param newState The new state */ void setState(TimerState newState); signals: /*! * \brief Emitted when the state of the timer changed */ void stateChanged(); /*! * \brief Emitted when the start was canceled * \param falseStart Wheter a false start occured */ void startCanceled(bool falseStart); /*! * \brief Emitted when the reaction time changed */ void reactionTimeChanged(); /*! * \brief Emitted when the timer wants its state to be changed by the external handler * \param timer the timer object */ void requestEnableChange(ScStwTimer* timer); }; #endif // SCSTWTIMER_H