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

View file

@ -131,13 +131,16 @@ Window {
Text {
id: topLa
property string implicitText: ""
anchors.centerIn: parent
opacity: ( speedBackend.state < 3 ) ? 1:0
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
@ -189,8 +192,8 @@ Window {
elide: "ElideRight"
color: ["WON"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.successColor :
["LOST", "FAILED"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.errorColor:
appTheme.style.textColor
["LOST", "FAILED"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.errorColor:
appTheme.style.textColor
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 {
target: topLa
text: "click start to start"
implicitText: "click start to start"
}
},
@ -742,7 +745,7 @@ Window {
PropertyChanges { target: menu_container; }
PropertyChanges {
target: topLa
text: "please wait..."
implicitText: "please wait..."
}
},
State {
@ -756,7 +759,7 @@ Window {
PropertyChanges { target: menu_container; }
PropertyChanges {
target: topLa
text: "starting..."
implicitText: "NEXT_START_ACTION"
}
},
@ -770,7 +773,7 @@ Window {
}
PropertyChanges {
target: topLa
text: ""
implicitText: ""
}
},

View file

@ -50,8 +50,8 @@ bool BaseConn::init() {
this->setState("connected");
// init remote session
QJsonArray updateSubs = {"onRaceStateChanged", "onTimersChanged", "onExtensionConnectionsChanged"};
QJsonObject sessionParams = {{"updateSubs", updateSubs}};
QJsonArray updateSubs = {"onRaceStateChanged", "onTimersChanged", "onExtensionConnectionsChanged", "onNextStartActionChanged"};
QJsonObject sessionParams = {{"updateSubs", updateSubs}, {"init", true}};
if(this->sendCommand(1, sessionParams)["status"] != 200) {
return false;
@ -207,7 +207,6 @@ QVariantMap BaseConn::sendCommand(int header, QJsonValue data){
}
delete timer;
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);
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->setInterval(1);
this->timerTextRefreshTimer->setSingleShot(true);
@ -65,7 +59,7 @@ int ClimbingRace::startRace() {
this->setState(STARTING);
this->nextStartAction = -1;
this->nextStartAction = None;
this->playSoundsAndStartRace();
returnCode = 200;
@ -115,7 +109,7 @@ int ClimbingRace::stopRace(int type) {
if(type == 1){
this->nextStartActionTimer->stop();
this->player->stop();
this->nextStartAction = -1;
this->nextStartAction = None;
}
returnCode = this->speedTimers[0]->stop(type) ? 200:904;
@ -190,76 +184,6 @@ int ClimbingRace::resetRace() {
// --- 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
*
@ -269,7 +193,7 @@ void ClimbingRace::syncWithBaseStation() {
* @param data
*/
void ClimbingRace::handleBaseStationUpdate(QVariant data) {
qDebug() << "got update: " << data;
//qDebug() << "got update: " << data;
int header = data.toMap()["header"].toInt();
switch (header) {
case 9000:
@ -290,6 +214,15 @@ void ClimbingRace::handleBaseStationUpdate(QVariant data) {
this->baseConn->setConnections(data.toMap()["data"].toList());
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()));
switch (this->nextStartAction) {
case 0:
case AtYourMarks:
{
if(!playSound("qrc:/sounds/at_marks_1.wav")){
return;
}
if(appSettings->loadSetting("ready_en") == "true"){
nextStartAction = 1;
nextStartAction = Ready;
nextStartActionTimer->setInterval(appSettings->loadSetting("ready_delay").toInt() <= 0 ? 1:appSettings->loadSetting("ready_delay").toInt());
}
else{
nextStartAction = 2;
nextStartAction = Start;
nextStartActionTimer->setInterval(1);
}
break;
}
case 1:
case Ready:
{
if(!playSound("qrc:/sounds/ready_1.wav")){
return;
}
nextStartAction = 2;
nextStartAction = Start;
nextStartActionTimer->setInterval(1);
break;
}
case 2:
case Start:
{
if(!playSound("qrc:/sounds/IFSC_STARTSIGNAL_SINE.wav")){
return;
}
nextStartAction = -1;
nextStartAction = None;
nextStartActionTimer->disconnect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
this->setState(RUNNING);
speedTimers[0]->start();
emit this->nextStartActionChanged();
return;
}
default:
case None:
{
this->speedTimers[0]->setState(SpeedTimer::STARTING);
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());
}
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());
}
else{
nextStartAction = 2;
nextStartAction = Start;
nextStartActionTimer->setInterval(1);
}
@ -394,6 +329,8 @@ void ClimbingRace::playSoundsAndStartRace() {
}
}
emit this->nextStartActionChanged();
nextStartActionTimer->connect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
nextStartActionTimer->start();
}
@ -488,34 +425,47 @@ void ClimbingRace::refreshTimerText() {
}
// --- refresh next start action delay progress ---
double nextStartActionRemainingDelay = 0;
if(this->mode == LOCAL){
QString totalStr;
switch (this->mode) {
case LOCAL: {
// get remaining and total next start action delay time
if(nextStartAction == 0){
totalStr = appSettings->loadSetting("at_marks_delay");
this->nextStartActionTotalDelay = appSettings->loadSetting("at_marks_delay").toDouble();
}
else if (nextStartAction == 1) {
totalStr = appSettings->loadSetting("ready_delay");
this->nextStartActionTotalDelay = appSettings->loadSetting("ready_delay").toDouble();
}
double remaining = this->nextStartActionTimer->remainingTime();
double total = totalStr.toDouble();
//qDebug() << "DELAY_PROG: " << "total: " << total << " remaining: " << remaining << " prog: " << remaining / total;
if(remaining > 0){
this->nextStartActionDelayProgress = remaining / total;
emit this->nextStartActionDelayProgressChanged();
}
else {
this->nextStartActionDelayProgress = 0;
emit this->nextStartActionDelayProgressChanged();
}
nextStartActionRemainingDelay = this->nextStartActionTimer->remainingTime();
break;
}
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;
emit this->nextStartActionDelayProgressChanged();
}
/*if (this->mode == REMOTE && this->state == IDLE) {
this->nextStartActionDelayProgress = 0;
emit this->nextStartActionDelayProgressChanged();
}*/
this->timerTextRefreshTimer->start();
}
@ -614,16 +564,16 @@ int ClimbingRace::getMode() {
QVariant ClimbingRace::getTimerTextList() {
return this->qmlTimers;
// QVariantList test;
// QVariantMap test2 = {{"text", "1234"}, {"reacttime", 2.0}};
// test.append(test2);
// return test;
}
double ClimbingRace::getNextStartActionDelayProgress() {
return this->nextStartActionDelayProgress;
}
int ClimbingRace::getNextStartAction() {
return this->nextStartAction;
}
void ClimbingRace::writeSetting(QString key, QVariant value) {
this->refreshMode();