/**************************************************************************** ** 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 SCSTWRACE_H #define SCSTWRACE_H #include #include #include #include #include "scstwtimer.h" #include "scstwsoundplayer.h" class ScStwRemoteRace; /*! * \brief The ScStwRace class can be used to measure timings of climbing races with multiple lanes at once. * * The ScStwRace is a container to manage multiple timers at a time and introduces a propper start sequence * with start commands ('At your Marks' and 'Ready') and the official IFSC start signal. * * ## Basic usage: * * \code * ScStwRace race; * * // add two timers * race.addTimer(new ScStwTimer()); * race.addTimer(new ScStwTimer()); * * // start a race * race.start(); * \endcode * */ class ScStwRace : public QObject { Q_OBJECT Q_PROPERTY(RaceState state READ getState NOTIFY stateChanged) Q_PROPERTY(QVariantList timers READ getTimerDetailList NOTIFY timersChanged) Q_PROPERTY(QVariantList currentStartDelay READ getCurrentStartDelay NOTIFY currentStartDelayChanged) Q_PROPERTY(bool isReadyForNextState READ getIsReadyForNextState NOTIFY isReadyForNextStateChanged) Q_PROPERTY(QVariantMap details READ getDetails NOTIFY detailsChanged) public: explicit ScStwRace(QObject *parent = nullptr); friend class ScStwRemoteRace; enum RaceState { IDLE, PREPAIRING, WAITING, STARTING, RUNNING, STOPPED, INCIDENT }; Q_ENUM(RaceState) enum CurrentStartDetailAttributes { CurrentStartStateTotalDelay = 0, CurrentStartStateDelayProgress = 1 }; Q_ENUM(CurrentStartDetailAttributes); protected: QList timers; void setState(RaceState newState); private: RaceState state; QTimer *startDelayTimer; QEventLoop *startWaitLoop; // sounds ScStwSoundPlayer * soundPlayer; // some settings double soundVolume; bool competitionMode; bool competitionModeChanged; /*! * \brief stores the start action settings * * \details Stores the settings for the action ScStwRace::AtYourMarks and ScStwRace::Ready. The settings keys are: "Enabled" and "Delay" */ QMap startSoundSettings; enum LoopExitTypes { LoopAutomaticExit = 0, LoopManualExit = 2, LoopCancelExit = 3 }; public slots: /*! * \brief Function to start the race * * \param asyncronous if the function should just start the start sequence and then quit (true) * or if if should wait until the start sequence is over and quit after that (false) * \return 200: OK; 904: state not matching */ virtual ScStw::StatusCode start(bool asyncronous = true); /*! * \brief Function to stop the currently running race * * \return 200: OK; 904: state not matching */ virtual ScStw::StatusCode stop(); /*! * \brief Function to reset a stopped race * \return */ virtual ScStw::StatusCode reset(); virtual ScStw::StatusCode cancel(); // setters bool writeStartSoundSetting(ScStwSoundPlayer::StartSound sound, bool enabled, int delay); bool setSoundVolume(double volume); virtual bool addTimer(ScStwTimer *timer); void setCompetitionMode(bool competitionMode); // getters RaceState getState(); virtual QVariantList getCurrentStartDelay(); QList getTimers(); QVariantList getTimerDetailList(); QVariantMap getDetails(); protected slots: private slots: void refreshTimerStates(); void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled); int handleFalseStart(); bool playSoundsAndStartTimers(); bool doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr); void enableAllTimers(); /** * \brief Function to declare the winner and looser timers after a timer has been stopped */ void handleTimerStop(); bool isStarting(); virtual bool getIsReadyForNextState(); void handleTimerReadyStateChange(ScStwTimer::ReadyState readyState); signals: void startTimers(); void stopTimers(int type); void resetTimers(); void stateChanged(RaceState state); void currentStartDelayChanged(); void timersChanged(); void isReadyForNextStateChanged(); void detailsChanged(); }; #endif // SCSTWRACE_H