implemented race details

This commit is contained in:
Dorian Zedler 2020-10-03 11:10:15 +02:00
parent 3c626b82da
commit c9e1f4f8ec
Signed by: dorian
GPG key ID: D3B255CB8BC7CD37
6 changed files with 67 additions and 46 deletions

View file

@ -23,6 +23,7 @@
#include "scstwrace.h" #include "scstwrace.h"
#include "scstwclient.h" #include "scstwclient.h"
#include "scstwremotetimer.h" #include "scstwremotetimer.h"
#include "scstwsoundplayer.h"
class ScStwRemoteRace : public ScStwRace class ScStwRemoteRace : public ScStwRace
{ {
@ -34,6 +35,7 @@ protected:
double currentStartTotalDelay; double currentStartTotalDelay;
double currentStartDelayStartedAt; double currentStartDelayStartedAt;
bool currentlyWaitingForClimbers; bool currentlyWaitingForClimbers;
bool isReadyForNextState;
private: private:
ScStwClient *scStwClient; ScStwClient *scStwClient;
@ -47,11 +49,13 @@ public slots:
ScStw::StatusCode reset(); ScStw::StatusCode reset();
bool addTimer(ScStwTimer *timer); bool addTimer(ScStwTimer *timer);
QVariantList getCurrentStartDelay(); QVariantList getCurrentStartDelay();
bool getIsReadyForNextState();
private slots: private slots:
void handleClientStateChanged(); void handleClientStateChanged();
void handleBaseStationSignal(ScStw::SignalKey key, QVariant data); void handleBaseStationSignal(ScStw::SignalKey key, QVariant data);
bool refreshRemoteTimers(QVariantList remoteTimers); bool refreshRemoteTimers(QVariantList remoteTimers);
void refreshDetails(QVariantMap details);
}; };

View file

@ -26,6 +26,8 @@
#include "scstwtimer.h" #include "scstwtimer.h"
#include "scstwsoundplayer.h" #include "scstwsoundplayer.h"
class ScStwRemoteRace;
/*! /*!
* \brief The ScStwRace class can be used to measure timings of climbing races with multiple lanes at once. * \brief The ScStwRace class can be used to measure timings of climbing races with multiple lanes at once.
* *
@ -52,12 +54,14 @@ class ScStwRace : public QObject
Q_PROPERTY(RaceState state READ getState NOTIFY stateChanged) Q_PROPERTY(RaceState state READ getState NOTIFY stateChanged)
Q_PROPERTY(QVariantList timers READ getTimerDetailList NOTIFY timersChanged) Q_PROPERTY(QVariantList timers READ getTimerDetailList NOTIFY timersChanged)
Q_PROPERTY(QVariantList currentStartDelay READ getCurrentStartDelay NOTIFY currentStartDelayChanged) Q_PROPERTY(QVariantList currentStartDelay READ getCurrentStartDelay NOTIFY currentStartDelayChanged)
Q_PROPERTY(bool isReadyForNextState READ isReadyForNextState NOTIFY isReadyForNextStateChanged) Q_PROPERTY(bool isReadyForNextState READ getIsReadyForNextState NOTIFY isReadyForNextStateChanged)
Q_PROPERTY(QVariantMap details READ getDetails NOTIFY detailsChanged) Q_PROPERTY(QVariantMap details READ getDetails NOTIFY detailsChanged)
public: public:
explicit ScStwRace(QObject *parent = nullptr); explicit ScStwRace(QObject *parent = nullptr);
friend class ScStwRemoteRace;
enum RaceState { IDLE, PREPAIRING, WAITING, STARTING, RUNNING, STOPPED, INCIDENT }; enum RaceState { IDLE, PREPAIRING, WAITING, STARTING, RUNNING, STOPPED, INCIDENT };
Q_ENUM(RaceState) Q_ENUM(RaceState)
@ -154,7 +158,7 @@ private slots:
void handleTimerStop(); void handleTimerStop();
bool isStarting(); bool isStarting();
bool isReadyForNextState(); virtual bool getIsReadyForNextState();
void handleTimerReadyStateChange(ScStwTimer::ReadyState readyState); void handleTimerReadyStateChange(ScStwTimer::ReadyState readyState);
signals: signals:
@ -164,11 +168,8 @@ signals:
void stateChanged(RaceState state); void stateChanged(RaceState state);
void currentStartDelayChanged(); void currentStartDelayChanged();
void timersChanged(); void timersChanged();
<<<<<<< HEAD
void isReadyForNextStateChanged(); void isReadyForNextStateChanged();
=======
void detailsChanged(); void detailsChanged();
>>>>>>> origin/master
}; };

View file

@ -110,7 +110,7 @@ public slots:
* \param volume the volume to play the false start sound at * \param volume the volume to play the false start sound at
* \return true if the playback was successfully stopped, false otherwise * \return true if the playback was successfully stopped, false otherwise
*/ */
bool cancel(double volume = 0); bool cancel();
private slots: private slots:

View file

@ -21,12 +21,11 @@
ScStwRemoteRace::ScStwRemoteRace(ScStwClient *monitorClient, QObject *parent) : ScStwRace(parent) ScStwRemoteRace::ScStwRemoteRace(ScStwClient *monitorClient, QObject *parent) : ScStwRace(parent)
{ {
this->currentlyWaitingForClimbers = false; this->currentlyWaitingForClimbers = false;
this->isReadyForNextState = true;
this->scStwClient = monitorClient; this->scStwClient = monitorClient;
this->scStwClient->addSignalSubscription(ScStw::RaceStateChanged); this->scStwClient->addSignalSubscription(ScStw::RaceDetailsChanged);
this->scStwClient->addSignalSubscription(ScStw::TimersChanged);
this->scStwClient->addSignalSubscription(ScStw::CurrentStartDelayChanged);
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ScStwRemoteRace::handleClientStateChanged); connect(this->scStwClient, &ScStwClient::stateChanged, this, &ScStwRemoteRace::handleClientStateChanged);
connect(this->scStwClient, &ScStwClient::gotSignal, this, &ScStwRemoteRace::handleBaseStationSignal); connect(this->scStwClient, &ScStwClient::gotSignal, this, &ScStwRemoteRace::handleBaseStationSignal);
@ -112,39 +111,48 @@ void ScStwRemoteRace::handleClientStateChanged() {
void ScStwRemoteRace::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) { void ScStwRemoteRace::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {
//qDebug() << "got signal: " << data; //qDebug() << "got signal: " << data;
switch (key) { switch (key) {
case ScStw::RaceStateChanged: case ScStw::RaceDetailsChanged:
{ {
// the remote race state has changed this->refreshDetails(data.toMap());
this->setState( ScStwRace::RaceState( data.toInt() ) );
break; break;
} }
case ScStw::TimersChanged:
{
// the remote timers have changed
this->refreshRemoteTimers(data.toList());
break;
}
case ScStw::CurrentStartDelayChanged:
{
// the next start action has changed
this->currentStartTotalDelay = data.toList()[ScStwRace::CurrentStartStateTotalDelay].toInt();
this->currentStartDelayStartedAt = QDateTime::currentMSecsSinceEpoch() - (this->currentStartTotalDelay * data.toList()[ScStwRace::CurrentStartStateDelayProgress].toDouble());
this->currentlyWaitingForClimbers = data.toList()[ScStwRace::CurrentStartStateDelayProgress].toDouble() == 0 && this->currentStartTotalDelay == -1;
emit this->currentStartDelayChanged();
qDebug() << "Current start delay changed: total:" << this->currentStartTotalDelay << " progress: " << data.toList()[ScStwRace::CurrentStartStateDelayProgress].toDouble();
break;
}
case ScStw::InvalidSignal:
return;
default: default:
return; return;
} }
} }
void ScStwRemoteRace::refreshDetails(QVariantMap details) {
// the details of the race have changed:
// state
this->setState(ScStwRace::RaceState(details["state"].toInt()));
// competition mode
this->competitionMode = details["competitionMode"].toBool();
// ready sound enabled
this->writeStartSoundSetting(ScStwSoundPlayer::Ready, details["readySoundEnabled"].toBool(), 0);
// current start delay
this->currentStartTotalDelay = details["currentStartDelay"].toList()[ScStwRace::CurrentStartStateTotalDelay].toInt();
this->currentStartDelayStartedAt = QDateTime::currentMSecsSinceEpoch() - (this->currentStartTotalDelay * details["currentStartDelay"].toList()[ScStwRace::CurrentStartStateDelayProgress].toDouble());
this->currentlyWaitingForClimbers = details["currentStartDelay"].toList()[ScStwRace::CurrentStartStateDelayProgress].toDouble() == 0 && this->currentStartTotalDelay == -1;
emit this->currentStartDelayChanged();
// timers
this->refreshRemoteTimers(details["timers"].toList());
// isReady
if(this->state == WAITING) {
this->isReadyForNextState = details["isReadyForNextState"].toBool();
emit this->isReadyForNextStateChanged();
}
emit this->detailsChanged();
}
bool ScStwRemoteRace::refreshRemoteTimers(QVariantList remoteTimers) { bool ScStwRemoteRace::refreshRemoteTimers(QVariantList remoteTimers) {
if(remoteTimers.length() != this->timers.length()){ if(remoteTimers.length() != this->timers.length()){
@ -218,3 +226,7 @@ QVariantList ScStwRemoteRace::getCurrentStartDelay() {
nextActionDelayProg nextActionDelayProg
}; };
} }
bool ScStwRemoteRace::getIsReadyForNextState() {
return this->isReadyForNextState;
}

View file

@ -34,6 +34,7 @@ ScStwRace::ScStwRace(QObject *parent) : QObject(parent)
connect(this, &ScStwRace::currentStartDelayChanged, this, &ScStwRace::detailsChanged); connect(this, &ScStwRace::currentStartDelayChanged, this, &ScStwRace::detailsChanged);
connect(this, &ScStwRace::timersChanged, this, &ScStwRace::detailsChanged); connect(this, &ScStwRace::timersChanged, this, &ScStwRace::detailsChanged);
connect(this, &ScStwRace::stateChanged, this, &ScStwRace::detailsChanged);
// write default settings // write default settings
this->startSoundSettings.insert(ScStwSoundPlayer::Start, {{"Enabled", true}, {"Delay", 1}}); this->startSoundSettings.insert(ScStwSoundPlayer::Start, {{"Enabled", true}, {"Delay", 1}});
@ -49,7 +50,7 @@ ScStwRace::ScStwRace(QObject *parent) : QObject(parent)
ScStw::StatusCode ScStwRace::start(bool asyncronous) { ScStw::StatusCode ScStwRace::start(bool asyncronous) {
if(this->state == WAITING) { if(this->state == WAITING) {
if(this->isReadyForNextState()) { if(this->getIsReadyForNextState()) {
this->startWaitLoop->exit(LoopManualExit); this->startWaitLoop->exit(LoopManualExit);
return ScStw::Success; return ScStw::Success;
} }
@ -61,7 +62,7 @@ ScStw::StatusCode ScStwRace::start(bool asyncronous) {
return ScStw::CurrentStateNotVaildForOperationError; return ScStw::CurrentStateNotVaildForOperationError;
} }
if(!this->isReadyForNextState()) if(!this->getIsReadyForNextState())
return ScStw::TimersNotReadyError; return ScStw::TimersNotReadyError;
this->setState(PREPAIRING); this->setState(PREPAIRING);
@ -181,7 +182,7 @@ ScStw::StatusCode ScStwRace::cancel() {
this->setState(STOPPED); this->setState(STOPPED);
this->startWaitLoop->exit(LoopCancelExit); this->startWaitLoop->exit(LoopCancelExit);
this->soundPlayer->cancel(this->soundVolume); this->soundPlayer->cancel();
this->startDelayTimer->stop(); this->startDelayTimer->stop();
emit this->currentStartDelayChanged(); emit this->currentStartDelayChanged();
@ -246,7 +247,7 @@ bool ScStwRace::playSoundsAndStartTimers() {
bool timerTriggered = true; bool timerTriggered = true;
do { do {
if(!this->isReadyForNextState()) { if(!this->getIsReadyForNextState()) {
this->startDelayTimer->stop(); this->startDelayTimer->stop();
timerTriggered = false; timerTriggered = false;
} }
@ -276,7 +277,7 @@ bool ScStwRace::playSoundsAndStartTimers() {
//qDebug() << "At end of loop: remaining time: " << this->startDelayTimer->remainingTime() << " timer triggered: " << timerTriggered << " ready for next state: " << this->isReadyForNextState(); //qDebug() << "At end of loop: remaining time: " << this->startDelayTimer->remainingTime() << " timer triggered: " << timerTriggered << " ready for next state: " << this->isReadyForNextState();
} while(this->startDelayTimer->remainingTime() > 0 || !timerTriggered || !this->isReadyForNextState()); } while(this->startDelayTimer->remainingTime() > 0 || !timerTriggered || !this->getIsReadyForNextState());
qDebug() << "[RACE][DEBUG] Wait finished, starting now!"; qDebug() << "[RACE][DEBUG] Wait finished, starting now!";
@ -296,7 +297,7 @@ bool ScStwRace::playSoundsAndStartTimers() {
if(loopExitCode == LoopCancelExit) if(loopExitCode == LoopCancelExit)
return false; return false;
} while(loopExitCode != LoopManualExit || !this->isReadyForNextState()); } while(loopExitCode != LoopManualExit || !this->getIsReadyForNextState());
} }
else { else {
qDebug() << "now playing ready sound"; qDebug() << "now playing ready sound";
@ -449,7 +450,7 @@ void ScStwRace::refreshTimerStates() {
// --- helper functions --- // --- helper functions ---
// ------------------------ // ------------------------
bool ScStwRace::isReadyForNextState() { bool ScStwRace::getIsReadyForNextState() {
if(!this->competitionMode) { if(!this->competitionMode) {
return true; return true;
} }
@ -542,7 +543,7 @@ QVariantList ScStwRace::getCurrentStartDelay() {
int nextActionDelay = -1; int nextActionDelay = -1;
double nextActionDelayProg = -1; double nextActionDelayProg = -1;
if(this->state == WAITING && !this->isReadyForNextState()) { if(this->state == WAITING && !this->getIsReadyForNextState()) {
// indicate that we are waiting for climbers and the progress shall be zero // indicate that we are waiting for climbers and the progress shall be zero
nextActionDelayProg = 0; nextActionDelayProg = 0;
} }
@ -645,13 +646,14 @@ QVariantList ScStwRace::getTimerDetailList() {
QVariantMap ScStwRace::getDetails() { QVariantMap ScStwRace::getDetails() {
QVariantMap tmpDetails; QVariantMap tmpDetails;
tmpDetails.insert("timers", this->getTimerDetailList()); tmpDetails.insert("state", this->getState());
tmpDetails.insert("currentStartDelay", this->getCurrentStartDelay());
tmpDetails.insert("competitionMode", this->competitionMode); tmpDetails.insert("competitionMode", this->competitionMode);
tmpDetails.insert("readySoundEnabled", this->startSoundSettings[ScStwSoundPlayer::Ready]["Enabled"].toBool()); tmpDetails.insert("readySoundEnabled", this->startSoundSettings[ScStwSoundPlayer::Ready]["Enabled"].toBool());
tmpDetails.insert("currentStartDelay", this->getCurrentStartDelay());
tmpDetails.insert("timers", this->getTimerDetailList());
if(this->state == WAITING) if(this->state == WAITING)
tmpDetails.insert("isReady", this->isReadyForNextState()); tmpDetails.insert("isReadyForNextState", this->getIsReadyForNextState());
return tmpDetails; return tmpDetails;
} }

View file

@ -79,13 +79,15 @@ bool ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, d
return true; return true;
} }
bool ScStwSoundPlayer::cancel(double volume) { bool ScStwSoundPlayer::cancel() {
if(!this->soundEffect->isPlaying() ) if(!this->soundEffect->isPlaying() )
return false; return false;
// stop playback // stop playback
this->soundEffect->stop(); this->soundEffect->stop();
this->waitLoop->quit(); this->waitLoop->quit();
return true;
} }
bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) { bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {