- re-implemented nextStartActionDelayProgress and nextStartAction

- implemented new "init" feature of command 1
This commit is contained in:
dorian 2019-10-13 16:42:38 +02:00
parent 8f295735da
commit 01ba412e4e
5 changed files with 84 additions and 130 deletions

View file

@ -15,7 +15,7 @@
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
--> -->
<manifest package="com.itsblue.speedclimbing_stopwatchtest" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.04" android:versionCode="4" android:installLocation="auto"> <manifest package="com.itsblue.speedclimbing_stopwatchtest" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="10" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="speedclimbing stw" android:icon="@drawable/icon"> <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="speedclimbing stw" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="com.itsblue.speedclimbing_stopwatch.MainActivity" android:label="speedclimbing stw" android:screenOrientation="unspecified" android:launchMode="singleTop"> <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="com.itsblue.speedclimbing_stopwatch.MainActivity" android:label="speedclimbing stw" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter> <intent-filter>
@ -82,7 +82,7 @@
</application> </application>
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="26"/> <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="28"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.

View file

@ -19,6 +19,7 @@ class ClimbingRace : public QObject
Q_PROPERTY(QString baseStationState READ getBaseStationState NOTIFY baseStationStateChanged) Q_PROPERTY(QString baseStationState READ getBaseStationState NOTIFY baseStationStateChanged)
Q_PROPERTY(QVariant baseStationConnections READ getBaseStationConnections NOTIFY baseStationConnectionsChanged) Q_PROPERTY(QVariant baseStationConnections READ getBaseStationConnections NOTIFY baseStationConnectionsChanged)
Q_PROPERTY(double nextStartActionDelayProgress READ getNextStartActionDelayProgress NOTIFY nextStartActionDelayProgressChanged) Q_PROPERTY(double nextStartActionDelayProgress READ getNextStartActionDelayProgress NOTIFY nextStartActionDelayProgressChanged)
Q_PROPERTY(int nextStartAction READ getNextStartAction NOTIFY nextStartActionChanged)
public: public:
explicit ClimbingRace(QObject *parent = nullptr); explicit ClimbingRace(QObject *parent = nullptr);
@ -29,13 +30,14 @@ public:
enum raceMode { LOCAL, REMOTE }; enum raceMode { LOCAL, REMOTE };
raceMode mode; raceMode mode;
enum NextStartAction { AtYourMarks, Ready, Start, None };
private: private:
AppSettings * appSettings; AppSettings * appSettings;
BaseConn * baseConn; BaseConn * baseConn;
QMediaPlayer * player; QMediaPlayer * player;
QTimer * baseStationSyncTimer;
QTimer * timerTextRefreshTimer; QTimer * timerTextRefreshTimer;
QTimer * nextStartActionTimer; QTimer * nextStartActionTimer;
@ -43,12 +45,12 @@ private:
QList<SpeedTimer *> speedTimers; QList<SpeedTimer *> speedTimers;
int nextStartAction; NextStartAction nextStartAction;
// 0 : 'at your marks'
// 1 : 'ready'
// 2 : 'start'
double nextStartActionDelayProgress; double nextStartActionDelayProgress;
// only used in remote mode:
double nextStartActionDelayStartedAt;
double nextStartActionTotalDelay;
// helper vars // helper vars
QVariantList qmlTimers; QVariantList qmlTimers;
@ -66,7 +68,7 @@ private slots:
bool refreshRemoteTimers(QVariantList timers); bool refreshRemoteTimers(QVariantList timers);
signals: signals:
void nextStartActionChanged(int nextStartAction); void nextStartActionChanged();
void nextStartActionDelayProgressChanged(); void nextStartActionDelayProgressChanged();
void stateChanged(int state); void stateChanged(int state);
@ -81,7 +83,6 @@ public slots:
Q_INVOKABLE int resetRace(); Q_INVOKABLE int resetRace();
// base station sync // base station sync
void syncWithBaseStation();
void handleBaseStationUpdate(QVariant data); void handleBaseStationUpdate(QVariant data);
// functions for qml // functions for qml
@ -89,6 +90,7 @@ public slots:
Q_INVOKABLE int getMode(); Q_INVOKABLE int getMode();
Q_INVOKABLE QVariant getTimerTextList(); Q_INVOKABLE QVariant getTimerTextList();
Q_INVOKABLE double getNextStartActionDelayProgress(); Q_INVOKABLE double getNextStartActionDelayProgress();
Q_INVOKABLE int getNextStartAction();
Q_INVOKABLE void writeSetting(QString key, QVariant value); Q_INVOKABLE void writeSetting(QString key, QVariant value);
Q_INVOKABLE QString readSetting(QString key); Q_INVOKABLE QString readSetting(QString key);

View file

@ -131,13 +131,16 @@ Window {
Text { Text {
id: topLa id: topLa
property string implicitText: ""
anchors.centerIn: parent anchors.centerIn: parent
opacity: ( speedBackend.state < 3 ) ? 1:0 opacity: ( speedBackend.state < 3 ) ? 1:0
width: parent.width * 0.7 width: parent.width * 0.7
height: parent.height * 0.7
text: "click start to start" text: implicitText === "NEXT_START_ACTION" ? ["at your \nmarks", "ready", "starting..."][speedBackend.nextStartAction]:implicitText
color: appTheme.style.textColor color: appTheme.style.textColor
@ -189,8 +192,8 @@ Window {
elide: "ElideRight" elide: "ElideRight"
color: ["WON"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.successColor : color: ["WON"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.successColor :
["LOST", "FAILED"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.errorColor: ["LOST", "FAILED"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.errorColor:
appTheme.style.textColor appTheme.style.textColor
enabled: speedBackend.timers[index]["state"] !== "DISABLED" enabled: speedBackend.timers[index]["state"] !== "DISABLED"
@ -489,7 +492,7 @@ Window {
} }
} }
animationDuration: speedBackend.mode === 1 ? 150:0 animationDuration: 0
} }
/*---------------------- /*----------------------
@ -726,7 +729,7 @@ Window {
} }
PropertyChanges { PropertyChanges {
target: topLa target: topLa
text: "click start to start" implicitText: "click start to start"
} }
}, },
@ -742,7 +745,7 @@ Window {
PropertyChanges { target: menu_container; } PropertyChanges { target: menu_container; }
PropertyChanges { PropertyChanges {
target: topLa target: topLa
text: "please wait..." implicitText: "please wait..."
} }
}, },
State { State {
@ -756,7 +759,7 @@ Window {
PropertyChanges { target: menu_container; } PropertyChanges { target: menu_container; }
PropertyChanges { PropertyChanges {
target: topLa target: topLa
text: "starting..." implicitText: "NEXT_START_ACTION"
} }
}, },
@ -770,7 +773,7 @@ Window {
} }
PropertyChanges { PropertyChanges {
target: topLa target: topLa
text: "" implicitText: ""
} }
}, },

View file

@ -50,8 +50,8 @@ bool BaseConn::init() {
this->setState("connected"); this->setState("connected");
// init remote session // init remote session
QJsonArray updateSubs = {"onRaceStateChanged", "onTimersChanged", "onExtensionConnectionsChanged"}; QJsonArray updateSubs = {"onRaceStateChanged", "onTimersChanged", "onExtensionConnectionsChanged", "onNextStartActionChanged"};
QJsonObject sessionParams = {{"updateSubs", updateSubs}}; QJsonObject sessionParams = {{"updateSubs", updateSubs}, {"init", true}};
if(this->sendCommand(1, sessionParams)["status"] != 200) { if(this->sendCommand(1, sessionParams)["status"] != 200) {
return false; return false;
@ -207,7 +207,6 @@ QVariantMap BaseConn::sendCommand(int header, QJsonValue data){
} }
delete timer; delete timer;
return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}}; return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}};
} }

View file

@ -32,12 +32,6 @@ ClimbingRace::ClimbingRace(QObject *parent) : QObject(parent)
this->nextStartActionTimer = new QTimer(this); this->nextStartActionTimer = new QTimer(this);
nextStartActionTimer->setSingleShot(true); nextStartActionTimer->setSingleShot(true);
this->baseStationSyncTimer = new QTimer(this);
this->baseStationSyncTimer->setInterval(1000);
this->baseStationSyncTimer->setSingleShot(true);
this->baseStationSyncTimer->connect(this->baseStationSyncTimer, &QTimer::timeout, this, &ClimbingRace::syncWithBaseStation);
//this->baseStationSyncTimer->start();
this->timerTextRefreshTimer = new QTimer(this); this->timerTextRefreshTimer = new QTimer(this);
this->timerTextRefreshTimer->setInterval(1); this->timerTextRefreshTimer->setInterval(1);
this->timerTextRefreshTimer->setSingleShot(true); this->timerTextRefreshTimer->setSingleShot(true);
@ -65,7 +59,7 @@ int ClimbingRace::startRace() {
this->setState(STARTING); this->setState(STARTING);
this->nextStartAction = -1; this->nextStartAction = None;
this->playSoundsAndStartRace(); this->playSoundsAndStartRace();
returnCode = 200; returnCode = 200;
@ -115,7 +109,7 @@ int ClimbingRace::stopRace(int type) {
if(type == 1){ if(type == 1){
this->nextStartActionTimer->stop(); this->nextStartActionTimer->stop();
this->player->stop(); this->player->stop();
this->nextStartAction = -1; this->nextStartAction = None;
} }
returnCode = this->speedTimers[0]->stop(type) ? 200:904; returnCode = this->speedTimers[0]->stop(type) ? 200:904;
@ -190,76 +184,6 @@ int ClimbingRace::resetRace() {
// --- Base Station sync --- // --- Base Station sync ---
// ------------------------- // -------------------------
void ClimbingRace::syncWithBaseStation() {
this->refreshMode();
if(this->mode != REMOTE){
this->baseStationSyncTimer->start();
return;
}
this->baseConn->refreshConnections();
// sync race state
QVariantMap tmpReply = this->baseConn->sendCommand(2000);
if(tmpReply["status"] != 200){
this->baseStationSyncTimer->start();
return;
}
this->setState( raceState( tmpReply["data"].toInt() ) );
switch (this->state) {
case 1:
{
// case STARTING
// refresh remote timers
tmpReply = this->baseConn->sendCommand(2007);
if(tmpReply["status"].toInt() != 200){
//handle error!!
qDebug() << "+ --- getting timers from basestation failed";
}
else {
this->refreshRemoteTimers(tmpReply["data"].toList());
}
tmpReply = this->baseConn->sendCommand(2005);
if(tmpReply["status"] != 200){
//handle error!!
qDebug() << "+ --- getting next start action progress from basestation failed";
this->baseStationSyncTimer->start();
return;
}
else {
this->nextStartActionDelayProgress = tmpReply["data"].toDouble() > 0 ? tmpReply["data"].toDouble():0;
this->nextStartActionDelayProgressChanged();
}
break;
}
default:
{
tmpReply = this->baseConn->sendCommand(2007);
if(tmpReply["status"].toInt() != 200){
//handle error!!
qDebug() << "+ --- getting timers from basestation failed";
}
else {
this->refreshRemoteTimers(tmpReply["data"].toList());
}
break;
}
}
this->baseStationSyncTimer->start();
}
/** /**
* @brief ClimbingRace::handleBaseStationUpdate * @brief ClimbingRace::handleBaseStationUpdate
* *
@ -269,7 +193,7 @@ void ClimbingRace::syncWithBaseStation() {
* @param data * @param data
*/ */
void ClimbingRace::handleBaseStationUpdate(QVariant data) { void ClimbingRace::handleBaseStationUpdate(QVariant data) {
qDebug() << "got update: " << data; //qDebug() << "got update: " << data;
int header = data.toMap()["header"].toInt(); int header = data.toMap()["header"].toInt();
switch (header) { switch (header) {
case 9000: case 9000:
@ -290,6 +214,15 @@ void ClimbingRace::handleBaseStationUpdate(QVariant data) {
this->baseConn->setConnections(data.toMap()["data"].toList()); this->baseConn->setConnections(data.toMap()["data"].toList());
break; break;
} }
case 9003:
{
// the next start action has changed
this->nextStartActionTotalDelay = data.toMap()["data"].toMap()["nextActionDelay"].toDouble();
this->nextStartActionDelayStartedAt = this->date->currentMSecsSinceEpoch() - (this->nextStartActionTotalDelay * data.toMap()["data"].toMap()["nextActionDelayProg"].toDouble());
this->nextStartAction = NextStartAction( data.toMap()["data"].toMap()["nextAction"].toInt() );
emit this->nextStartActionChanged();
}
} }
} }
@ -335,58 +268,60 @@ void ClimbingRace::playSoundsAndStartRace() {
nextStartActionTimer->disconnect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace())); nextStartActionTimer->disconnect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
switch (this->nextStartAction) { switch (this->nextStartAction) {
case 0: case AtYourMarks:
{ {
if(!playSound("qrc:/sounds/at_marks_1.wav")){ if(!playSound("qrc:/sounds/at_marks_1.wav")){
return; return;
} }
if(appSettings->loadSetting("ready_en") == "true"){ if(appSettings->loadSetting("ready_en") == "true"){
nextStartAction = 1; nextStartAction = Ready;
nextStartActionTimer->setInterval(appSettings->loadSetting("ready_delay").toInt() <= 0 ? 1:appSettings->loadSetting("ready_delay").toInt()); nextStartActionTimer->setInterval(appSettings->loadSetting("ready_delay").toInt() <= 0 ? 1:appSettings->loadSetting("ready_delay").toInt());
} }
else{ else{
nextStartAction = 2; nextStartAction = Start;
nextStartActionTimer->setInterval(1); nextStartActionTimer->setInterval(1);
} }
break; break;
} }
case 1: case Ready:
{ {
if(!playSound("qrc:/sounds/ready_1.wav")){ if(!playSound("qrc:/sounds/ready_1.wav")){
return; return;
} }
nextStartAction = 2; nextStartAction = Start;
nextStartActionTimer->setInterval(1); nextStartActionTimer->setInterval(1);
break; break;
} }
case 2: case Start:
{ {
if(!playSound("qrc:/sounds/IFSC_STARTSIGNAL_SINE.wav")){ if(!playSound("qrc:/sounds/IFSC_STARTSIGNAL_SINE.wav")){
return; return;
} }
nextStartAction = -1; nextStartAction = None;
nextStartActionTimer->disconnect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace())); nextStartActionTimer->disconnect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
this->setState(RUNNING); this->setState(RUNNING);
speedTimers[0]->start(); speedTimers[0]->start();
emit this->nextStartActionChanged();
return; return;
} }
default: case None:
{ {
this->speedTimers[0]->setState(SpeedTimer::STARTING); this->speedTimers[0]->setState(SpeedTimer::STARTING);
if(appSettings->loadSetting("at_marks_en") == "true"){ if(appSettings->loadSetting("at_marks_en") == "true"){
nextStartAction = 0; nextStartAction = AtYourMarks;
nextStartActionTimer->setInterval(appSettings->loadSetting("at_marks_delay").toInt() <= 0 ? 1:appSettings->loadSetting("at_marks_delay").toInt()); nextStartActionTimer->setInterval(appSettings->loadSetting("at_marks_delay").toInt() <= 0 ? 1:appSettings->loadSetting("at_marks_delay").toInt());
} }
else if(appSettings->loadSetting("ready_en") == "true"){ else if(appSettings->loadSetting("ready_en") == "true"){
nextStartAction = 1; nextStartAction = Ready;
nextStartActionTimer->setInterval(appSettings->loadSetting("ready_delay").toInt() <= 0 ? 1:appSettings->loadSetting("ready_delay").toInt()); nextStartActionTimer->setInterval(appSettings->loadSetting("ready_delay").toInt() <= 0 ? 1:appSettings->loadSetting("ready_delay").toInt());
} }
else{ else{
nextStartAction = 2; nextStartAction = Start;
nextStartActionTimer->setInterval(1); nextStartActionTimer->setInterval(1);
} }
@ -394,6 +329,8 @@ void ClimbingRace::playSoundsAndStartRace() {
} }
} }
emit this->nextStartActionChanged();
nextStartActionTimer->connect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace())); nextStartActionTimer->connect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
nextStartActionTimer->start(); nextStartActionTimer->start();
} }
@ -488,34 +425,47 @@ void ClimbingRace::refreshTimerText() {
} }
// --- refresh next start action delay progress --- // --- refresh next start action delay progress ---
double nextStartActionRemainingDelay = 0;
if(this->mode == LOCAL){ switch (this->mode) {
QString totalStr; case LOCAL: {
// get remaining and total next start action delay time
if(nextStartAction == 0){ if(nextStartAction == 0){
totalStr = appSettings->loadSetting("at_marks_delay"); this->nextStartActionTotalDelay = appSettings->loadSetting("at_marks_delay").toDouble();
} }
else if (nextStartAction == 1) { else if (nextStartAction == 1) {
totalStr = appSettings->loadSetting("ready_delay"); this->nextStartActionTotalDelay = appSettings->loadSetting("ready_delay").toDouble();
} }
double remaining = this->nextStartActionTimer->remainingTime(); nextStartActionRemainingDelay = this->nextStartActionTimer->remainingTime();
double total = totalStr.toDouble();
//qDebug() << "DELAY_PROG: " << "total: " << total << " remaining: " << remaining << " prog: " << remaining / total; break;
if(remaining > 0){
this->nextStartActionDelayProgress = remaining / total;
emit this->nextStartActionDelayProgressChanged();
}
else {
this->nextStartActionDelayProgress = 0;
emit this->nextStartActionDelayProgressChanged();
}
} }
else if (this->mode == REMOTE && this->state == IDLE) { case REMOTE: {
// calculate remaining next start action delay time
nextStartActionRemainingDelay = this->nextStartActionTotalDelay - ( this->date->currentMSecsSinceEpoch() - this->nextStartActionDelayStartedAt );
break;
}
}
// calculate next start action delay progress
if(nextStartActionRemainingDelay > 0){
this->nextStartActionDelayProgress = nextStartActionRemainingDelay / this->nextStartActionTotalDelay;
emit this->nextStartActionDelayProgressChanged();
}
else {
this->nextStartActionDelayProgress = 0; this->nextStartActionDelayProgress = 0;
emit this->nextStartActionDelayProgressChanged(); emit this->nextStartActionDelayProgressChanged();
} }
/*if (this->mode == REMOTE && this->state == IDLE) {
this->nextStartActionDelayProgress = 0;
emit this->nextStartActionDelayProgressChanged();
}*/
this->timerTextRefreshTimer->start(); this->timerTextRefreshTimer->start();
} }
@ -614,16 +564,16 @@ int ClimbingRace::getMode() {
QVariant ClimbingRace::getTimerTextList() { QVariant ClimbingRace::getTimerTextList() {
return this->qmlTimers; return this->qmlTimers;
// QVariantList test;
// QVariantMap test2 = {{"text", "1234"}, {"reacttime", 2.0}};
// test.append(test2);
// return test;
} }
double ClimbingRace::getNextStartActionDelayProgress() { double ClimbingRace::getNextStartActionDelayProgress() {
return this->nextStartActionDelayProgress; return this->nextStartActionDelayProgress;
} }
int ClimbingRace::getNextStartAction() {
return this->nextStartAction;
}
void ClimbingRace::writeSetting(QString key, QVariant value) { void ClimbingRace::writeSetting(QString key, QVariant value) {
this->refreshMode(); this->refreshMode();