/**************************************************************************** ** 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 . ****************************************************************************/ #ifndef SCSTWTIMER_H #define SCSTWTIMER_H #include #include #include #include #include "ScStw.hpp" class ScStwRace; class ScStwRemoteRace; /*! * \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 Q_PROPERTY(QString letter READ getLetter WRITE setLetter) public: explicit ScStwTimer(QObject *parent = nullptr); /*! * \brief ScStwTimer constructor * \param parent the parent object * \param directControlEnabled Defines if protected properties (startTimer, stopTime, reactionTime and state) can be directly set from outside. * \param letter the letter of the timer (only first char will be used!) */ explicit ScStwTimer(QString letter, QObject *parent = nullptr); friend class ScStwRace; /*! * \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 to be set to either WON or LOST */ WON, /*!< Timer has won */ LOST, /*!< Timer has lost */ 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 */ }; Q_ENUM(TimerState); /*! * \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 */ ExtensionIsNotConnected, /*!< Not all extension of the timer are conneted */ ExtensionBatteryIsCritical, /*!< The battery level of one or more extension is critical or unknown */ ClimberIsNotReady /*!< The startpad of the timer is not triggered */ }; Q_ENUM(ReadyState) 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; /*! * \brief The letter (eg. "A" or "B") of the Timer (only one char) */ QString letter; /*! * \brief Defines if the timer currently wants to be disabled or not */ bool wantsToBeDisabled; 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 */ virtual 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 */ virtual 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 get the text, a timer display is supposed to show * \return The text to show */ QString getText(); /*! * \brief Function to get the letter of the timer * \return The letter of the timer or "" */ QString getLetter(); /*! * \brief Function to set the letter of the timer * \param letter the letter * \return The letter of the timer or "" */ void setLetter(QString letter); /*! * \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); /*! * \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(); bool isRunning(); bool isDisabled(); 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 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); /*! * \brief Function to set whether the timer currently wants to be disabled * \param wantsToBeDisabled true or false */ void setWantsToBeDisabled(bool wantsToBeDisabled); /*! * \brief Function to set the timer into INCIDENT state immidieately * * The current state of the timer will be ignored! It can only get out of this state by calling ScStwTimer::reset * * \see reset */ void technicalIncident(); /*! * \brief Function to set the timer into WILDCARD state * * Only works when the timer is in STARTING state. * * \return false if not in STARTING state */ bool wildcard(); signals: /*! * \brief Emitted when the state of the timer changed */ void stateChanged(TimerState state); /*! * \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 wantsToBeDisabledChanged(ScStwTimer* timer, bool wantsToBeDisabled); /*! * \brief Emitted when the ready state of the timer changes * \param readyState the new ReadyState */ void readyStateChanged(ReadyState readyState); }; #endif // SCSTWTIMER_H