- re-implemented nextStartActionDelayProgress and nextStartAction
- implemented new "init" feature of command 1
This commit is contained in:
parent
8f295735da
commit
01ba412e4e
5 changed files with 84 additions and 130 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
19
qml/main.qml
19
qml/main.qml
|
@ -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: ""
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -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()}};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Reference in a new issue