/****************************************************************************
** 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
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 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