/****************************************************************************
** 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"
/*!
* \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
* \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(QObject *parent = nullptr, bool directControlEnabled = false, QString letter = "" );
/*!
* \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 */
};
Q_ENUM(TimerState);
/*!
* \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;
/*!
* \brief Defines if protected properties (startTimer, stopTime, reactionTime and state) can be directly set from outside.
*/
bool directControlEnabled;
/*!
* \brief The letter (eg. "A" or "B") of the Timer (only one char)
*/
QString letter;
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 change the state of the timer
*
* Only works when directControlEnabled is set to true!
* Doing this will emit the ScStwTimer::stateChanged() signal (only if the new state differs from the current one)
*
* \param newState The new state
* \param force whether to force the state change (just to distinguish between protected and public function)
* \return false when directControlEnabled or force is set to false and the startTime was therefore not modified, true otherwise
*/
bool setState(TimerState newState, bool force);
/*!
* \brief Function to dircetly change the start time
*
* Only works when directControlEnabled is set to true!
*
* \param startTime the time to change to
* \return false when directControlEnabled is set to false and the startTime was therefore not modified, true otherwise
*/
bool setStartTime(double startTime);
/*!
* \brief Function to dircetly change the stop time
*
* Only works when directControlEnabled is set to true!
*
* \param stopTime the time to change to
* \return false when directControlEnabled is set to false and the stopTime was therefore not modified, true otherwise
*/
bool setStopTime(double stopTime);
/*!
* \brief Function to dircetly change the rection time
*
* Only works when directControlEnabled is set to true!
*
* \param reactionTime the time to change to
* \return false when directControlEnabled is set to false and the reactionTime was therefore not modified, true otherwise
*/
bool setReactionTime(double rectionTime);
/*!
* \brief Function to dircetly change the letter
*
* Only works when directControlEnabled is set to true!
*
* \param newLetter the letter to change to
* \return false when directControlEnabled is set to false and the letter was therefore not modified, true otherwise
*/
bool setLetter(QString newLetter);
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
*/
virtual 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);
/*!
* \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 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