/**************************************************************************** ** 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" #include "scstwsettings.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(QVariantMap currentStartDelay READ getCurrentStartDelay NOTIFY currentStartDelayChanged) Q_PROPERTY(bool isReadyForNextState READ getIsReadyForNextState NOTIFY isReadyForNextStateChanged) Q_PROPERTY(bool competitionMode READ getCompetitionMode NOTIFY competitionModeChanged) Q_PROPERTY(bool readySoundEnabled READ getReadySoundEnabled NOTIFY readySoundEnabledChanged) Q_PROPERTY(QVariantMap details READ getDetails NOTIFY detailsChanged) Q_PROPERTY(ScStwSettings* settings READ getSettings WRITE setSettings NOTIFY settingsChanged) Q_PROPERTY(bool autoRefreshTimerText READ getAutoRefreshTimerText WRITE setAutoRefreshTimerText NOTIFY autoRefreshTimerTextChanged) public: explicit ScStwRace(QObject *parent = nullptr); explicit ScStwRace(ScStwSettings *settings, QObject *parent = nullptr); friend class ScStwRemoteRace; enum RaceState { IDLE, PREPAIRING, WAITING, STARTING, RUNNING, STOPPED, INCIDENT }; Q_ENUM(RaceState) protected: QList timers; void setState(RaceState newState); private: RaceState state; QTimer *startDelayTimer; QTimer *timerTextRefreshTimer; QEventLoop *startWaitLoop; // sounds ScStwSoundPlayer * soundPlayer; // settings ScStwSettings *settings; bool competitionMode; bool autoRefreshTimerText; enum LoopExitTypes { LoopAutomaticExit = 0, LoopReadyStateChangeExit = 1, 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(); virtual ScStw::StatusCode setTimerDisabled(int id, bool disabled); Q_INVOKABLE virtual bool addTimer(ScStwTimer *timer); // getters RaceState getState(); virtual QVariantMap getCurrentStartDelay(); QList getTimers(); QVariantList getTimerDetailList(); QVariantMap getDetails(); bool getCompetitionMode(); virtual bool getReadySoundEnabled(); ScStwSettings* getSettings(); void setSettings(ScStwSettings* settings); bool getAutoRefreshTimerText(); void setAutoRefreshTimerText(bool autoRefresh); protected slots: private slots: void handleTimerStateChange(ScStwTimer::TimerState newState); /** * \brief Function to declare the winner and looser timers after a timer has been stopped */ void handleTimerStop(); void handleFalseStart(); void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled); bool playSoundsAndStartTimers(); ScStwSoundPlayer::PlayResult doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr); void technicalIncident(); ScStw::StatusCode setTimerDisabled(ScStwTimer* timer, bool disabled); virtual void refreshCompetitionMode(); double getSoundVolume(); ScStwSoundPlayer::StartSound getSoundForState(ScStwRace::RaceState state); bool getSoundEnabledSetting(ScStwSoundPlayer::StartSound sound); int getSoundDelaySetting(ScStwSoundPlayer::StartSound sound); 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(); void competitionModeChanged(); void readySoundEnabledChanged(); void settingsChanged(); void autoRefreshTimerTextChanged(); }; #endif // SCSTWRACE_H