- cleanup
- implemented new state ('WAITING') - multiple timers are now supported at the frontend
This commit is contained in:
parent
ecd141515f
commit
0957a913f8
7 changed files with 173 additions and 55 deletions
Binary file not shown.
Binary file not shown.
|
@ -23,7 +23,7 @@ class ClimbingRace : public QObject
|
||||||
public:
|
public:
|
||||||
explicit ClimbingRace(QObject *parent = nullptr);
|
explicit ClimbingRace(QObject *parent = nullptr);
|
||||||
|
|
||||||
enum raceState { IDLE, STARTING, RUNNING, STOPPED };
|
enum raceState { IDLE, STARTING, WAITING, RUNNING, STOPPED };
|
||||||
raceState state;
|
raceState state;
|
||||||
|
|
||||||
enum raceMode { LOCAL, REMOTE };
|
enum raceMode { LOCAL, REMOTE };
|
||||||
|
@ -63,6 +63,8 @@ private slots:
|
||||||
void refreshMode();
|
void refreshMode();
|
||||||
void refreshTimerText();
|
void refreshTimerText();
|
||||||
|
|
||||||
|
bool refreshRemoteTimers();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void nextStartActionChanged(int nextStartAction);
|
void nextStartActionChanged(int nextStartAction);
|
||||||
void nextStartActionDelayProgressChanged();
|
void nextStartActionDelayProgressChanged();
|
||||||
|
|
|
@ -13,7 +13,7 @@ class SpeedTimer : public QObject
|
||||||
public:
|
public:
|
||||||
explicit SpeedTimer(QObject *parent = nullptr);
|
explicit SpeedTimer(QObject *parent = nullptr);
|
||||||
|
|
||||||
enum timerState { IDLE, STARTING, RUNNING, STOPPED, FAILED, CANCELLED };
|
enum timerState { IDLE, STARTING, WAITING, RUNNING, STOPPED, FAILED, CANCELLED };
|
||||||
timerState state;
|
timerState state;
|
||||||
|
|
||||||
// variables for capturing the time
|
// variables for capturing the time
|
||||||
|
|
165
qml/main.qml
165
qml/main.qml
|
@ -67,10 +67,14 @@ Window {
|
||||||
settingsDialog.close()
|
settingsDialog.close()
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
stateString = "RUNNING"
|
stateString = "WAITING"
|
||||||
settingsDialog.close()
|
settingsDialog.close()
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
stateString = "RUNNING"
|
||||||
|
settingsDialog.close()
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
stateString = "STOPPED"
|
stateString = "STOPPED"
|
||||||
settingsDialog.close()
|
settingsDialog.close()
|
||||||
}
|
}
|
||||||
|
@ -91,12 +95,13 @@ Window {
|
||||||
spread: 0.02
|
spread: 0.02
|
||||||
color: "black"
|
color: "black"
|
||||||
opacity: 0.18
|
opacity: 0.18
|
||||||
anchors.fill: time_container
|
anchors.fill: topContainerItm
|
||||||
scale: 1
|
scale: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: time_container
|
id: topContainerItm
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
top: parent.top
|
top: parent.top
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
@ -117,34 +122,124 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Text {
|
||||||
id: timer_1
|
id: topLa
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
opacity: ( speedBackend.state < 3 ) ? 1:0
|
||||||
|
|
||||||
|
width: parent.width * 0.8
|
||||||
|
|
||||||
|
text: ""
|
||||||
|
|
||||||
|
color: appTheme.style.textColor
|
||||||
|
|
||||||
|
fontSizeMode: Text.Fit
|
||||||
|
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|
||||||
|
font.pixelSize: root.landscape() ? parent.width * 0.15 : parent.height * 0.4
|
||||||
|
|
||||||
|
minimumPixelSize: 0
|
||||||
|
|
||||||
|
Behavior on text {
|
||||||
|
FadeAnimation{
|
||||||
|
target: topLa
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: timerCol
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
opacity: ( speedBackend.state < 3 ) ? 0:1
|
||||||
|
|
||||||
|
spacing: height * 0.05
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: timerRep
|
||||||
|
|
||||||
|
model: speedBackend.timers.length
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
id: timerDel
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
height: timerRep.model > 1 ? ( timerCol.height * 0.9 ) / timerRep.model:timerCol.height
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: timerTextLa
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
width: ( parent.width * 0.8 )
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
elide: "ElideRight"
|
elide: "ElideRight"
|
||||||
color: appTheme.style.textColor
|
color: appTheme.style.textColor
|
||||||
|
|
||||||
font.pixelSize: 100
|
text: speedBackend.timers[index]["text"]
|
||||||
|
|
||||||
text: speedBackend.timers[0]["text"]
|
fontSizeMode: Text.Fit
|
||||||
|
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|
||||||
|
font.pixelSize: root.landscape() ? parent.width * 0.15 : parent.height * 0.4
|
||||||
|
|
||||||
|
minimumPixelSize: 0
|
||||||
|
|
||||||
Behavior on text {
|
Behavior on text {
|
||||||
enabled: root.state !== "RUNNING"
|
enabled: root.state !== "RUNNING"
|
||||||
FadeAnimation {
|
FadeAnimation {
|
||||||
target: timer_1
|
target: timerTextLa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: react_time
|
id: react_time
|
||||||
property int rtime: speedBackend.timers[0]["reacttime"]
|
|
||||||
text: qsTr("reaction time (ms): ") + Math.round(rtime)
|
property int rtime: speedBackend.timers[index]["reacttime"]
|
||||||
opacity: (root.state === "RUNNING" || root.state === "STOPPED") && rtime !== 0 ? 1:0
|
|
||||||
color: appTheme.style.textColor
|
|
||||||
anchors {
|
anchors {
|
||||||
horizontalCenter: parent.horizontalCenter
|
centerIn: parent
|
||||||
top: timer_1.bottom
|
verticalCenterOffset: parent.height * 0.25
|
||||||
topMargin: parent.height * 0.1
|
}
|
||||||
|
|
||||||
|
width: ( parent.width * 0.6 )
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
fontSizeMode: Text.Fit
|
||||||
|
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|
||||||
|
text: qsTr("reaction time (ms): ") + Math.round(rtime)
|
||||||
|
|
||||||
|
opacity: (root.state === "RUNNING" || root.state === "STOPPED") && rtime !== 0 ? 1:0
|
||||||
|
|
||||||
|
color: appTheme.style.textColor
|
||||||
|
|
||||||
|
font.pixelSize: timerTextLa.font.pixelSize * 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 200
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,8 +334,8 @@ Window {
|
||||||
width: root.landscape() ? 1:parent.width
|
width: root.landscape() ? 1:parent.width
|
||||||
height: root.landscape() ? parent.height:1
|
height: root.landscape() ? parent.height:1
|
||||||
color: appTheme.style.lineColor
|
color: appTheme.style.lineColor
|
||||||
anchors.left: root.landscape() ? time_container.right:parent.left
|
anchors.left: root.landscape() ? topContainerItm.right:parent.left
|
||||||
anchors.top: root.landscape() ? parent.top:time_container.bottom
|
anchors.top: root.landscape() ? parent.top:topContainerItm.bottom
|
||||||
anchors.bottom: root.landscape() ? parent.bottom:undefined
|
anchors.bottom: root.landscape() ? parent.bottom:undefined
|
||||||
visible: false
|
visible: false
|
||||||
}
|
}
|
||||||
|
@ -524,9 +619,8 @@ Window {
|
||||||
State {
|
State {
|
||||||
name: "IDLE"
|
name: "IDLE"
|
||||||
//state for the start page
|
//state for the start page
|
||||||
PropertyChanges { target: timer_1; font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3; scale: 1 }
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: time_container;
|
target: topContainerItm;
|
||||||
anchors.bottomMargin: root.landscape() ? undefined:parent.height * 0.1;
|
anchors.bottomMargin: root.landscape() ? undefined:parent.height * 0.1;
|
||||||
anchors.rightMargin: root.landscape() ? parent.height * 0.05:0
|
anchors.rightMargin: root.landscape() ? parent.height * 0.05:0
|
||||||
}
|
}
|
||||||
|
@ -537,8 +631,27 @@ Window {
|
||||||
anchors.bottomMargin: parent.height * 0.5 - startButt.height * 0.5
|
anchors.bottomMargin: parent.height * 0.5 - startButt.height * 0.5
|
||||||
anchors.rightMargin: parent.width * 0.5 - startButt.width * 0.5
|
anchors.rightMargin: parent.width * 0.5 - startButt.width * 0.5
|
||||||
}
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: topLa
|
||||||
|
text: qsTr("Click Start to start")
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
State {
|
||||||
|
name: "WAITING"
|
||||||
|
//state when a false start occured and waiting for time calculation
|
||||||
|
PropertyChanges {
|
||||||
|
target: startButt; enabled: false; text: qsTr("waiting...");
|
||||||
|
anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
|
||||||
|
anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
|
||||||
|
}
|
||||||
|
PropertyChanges { target: cancelButt; scale: 0; enabled: false}
|
||||||
|
PropertyChanges { target: menu_container; }
|
||||||
|
PropertyChanges {
|
||||||
|
target: topLa
|
||||||
|
text: qsTr("please wait...")
|
||||||
|
}
|
||||||
|
},
|
||||||
State {
|
State {
|
||||||
name: "STARTING"
|
name: "STARTING"
|
||||||
//state for the start sequence
|
//state for the start sequence
|
||||||
|
@ -546,14 +659,17 @@ Window {
|
||||||
anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
|
anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
|
||||||
anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
|
anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
|
||||||
}
|
}
|
||||||
PropertyChanges { target: timer_1; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
|
|
||||||
PropertyChanges { target: cancelButt; scale: 1}
|
PropertyChanges { target: cancelButt; scale: 1}
|
||||||
PropertyChanges { target: menu_container; }
|
PropertyChanges { target: menu_container; }
|
||||||
|
PropertyChanges {
|
||||||
|
target: topLa
|
||||||
|
text: qsTr("starting...")
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
name: "RUNNING"
|
name: "RUNNING"
|
||||||
//state when the timer is running
|
//state when the timer is running
|
||||||
PropertyChanges { target: timer_1; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
|
|
||||||
PropertyChanges { target: startButt; enabled: true;
|
PropertyChanges { target: startButt; enabled: true;
|
||||||
text: "stop"
|
text: "stop"
|
||||||
anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
|
anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
|
||||||
|
@ -565,11 +681,6 @@ Window {
|
||||||
State {
|
State {
|
||||||
name: "STOPPED"
|
name: "STOPPED"
|
||||||
//state when the meassuring is over
|
//state when the meassuring is over
|
||||||
PropertyChanges {
|
|
||||||
target: timer_1;
|
|
||||||
font.pixelSize: root.landscape() ? parent.width * 0.15:parent.height * 0.1;
|
|
||||||
scale: 1
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: startButt;
|
target: startButt;
|
||||||
enabled: true; text: qsTr("reset");
|
enabled: true; text: qsTr("reset");
|
||||||
|
@ -578,7 +689,7 @@ Window {
|
||||||
anchors.rightMargin: root.landscape() ? parent.height * 0.2 - startButt.height * 0.5:parent.width * 0.5 - startButt.width * 0.5
|
anchors.rightMargin: root.landscape() ? parent.height * 0.2 - startButt.height * 0.5:parent.width * 0.5 - startButt.width * 0.5
|
||||||
}
|
}
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: time_container;
|
target: topContainerItm;
|
||||||
anchors.rightMargin: root.landscape() ? 0-startButt.width/2:undefined
|
anchors.rightMargin: root.landscape() ? 0-startButt.width/2:undefined
|
||||||
anchors.bottomMargin: root.landscape() ? undefined:0-startButt.height/2
|
anchors.bottomMargin: root.landscape() ? undefined:0-startButt.height/2
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,9 +226,7 @@ void ClimbingRace::syncWithBaseStation() {
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
// case STARTING
|
// case STARTING
|
||||||
if(speedTimers[0]->state != 1){
|
this->refreshRemoteTimers();
|
||||||
speedTimers[0]->setState(SpeedTimer::STARTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpReply = this->baseConn->sendCommand(2005);
|
tmpReply = this->baseConn->sendCommand(2005);
|
||||||
if(tmpReply["status"] != 200){
|
if(tmpReply["status"] != 200){
|
||||||
|
@ -247,23 +245,7 @@ void ClimbingRace::syncWithBaseStation() {
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
|
||||||
// get current time
|
this->refreshRemoteTimers();
|
||||||
tmpReply = this->baseConn->sendCommand(2007);
|
|
||||||
if(tmpReply["status"] != 200){
|
|
||||||
//handle error!!
|
|
||||||
qDebug() << "+ --- getting timers from basestation failed";
|
|
||||||
this->baseStationSyncTimer->start();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QVariantList timers = tmpReply["data"].toList();
|
|
||||||
|
|
||||||
speedTimers[0]->startTime = this->date->currentMSecsSinceEpoch() - timers[0].toMap()["currTime"].toDouble();
|
|
||||||
speedTimers[0]->stoppedTime = timers[0].toMap()["currTime"].toDouble();
|
|
||||||
speedTimers[0]->reactionTime = timers[0].toMap()["reactTime"].toDouble();
|
|
||||||
|
|
||||||
speedTimers[0]->setState(SpeedTimer::timerState(timers[0].toMap()["state"].toInt()));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -443,6 +425,26 @@ void ClimbingRace::refreshTimerText() {
|
||||||
this->timerTextRefreshTimer->start();
|
this->timerTextRefreshTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClimbingRace::refreshRemoteTimers() {
|
||||||
|
// get current time
|
||||||
|
QVariantMap tmpReply = this->baseConn->sendCommand(2007);
|
||||||
|
if(tmpReply["status"] != 200){
|
||||||
|
//handle error!!
|
||||||
|
qDebug() << "+ --- getting timers from basestation failed";
|
||||||
|
this->baseStationSyncTimer->start();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QVariantList timers = tmpReply["data"].toList();
|
||||||
|
|
||||||
|
speedTimers[0]->startTime = this->date->currentMSecsSinceEpoch() - timers[0].toMap()["currTime"].toDouble();
|
||||||
|
speedTimers[0]->stoppedTime = timers[0].toMap()["currTime"].toDouble();
|
||||||
|
speedTimers[0]->reactionTime = timers[0].toMap()["reactTime"].toDouble();
|
||||||
|
|
||||||
|
speedTimers[0]->setState(SpeedTimer::timerState(timers[0].toMap()["state"].toInt()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
// --- functions for qml ---
|
// --- functions for qml ---
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
|
@ -132,6 +132,9 @@ QString SpeedTimer::getText() {
|
||||||
case SpeedTimer::STARTING:
|
case SpeedTimer::STARTING:
|
||||||
newText = "0.000 sec";
|
newText = "0.000 sec";
|
||||||
break;
|
break;
|
||||||
|
case SpeedTimer::WAITING:
|
||||||
|
newText = tr("Please wait...");
|
||||||
|
break;
|
||||||
case SpeedTimer::RUNNING:
|
case SpeedTimer::RUNNING:
|
||||||
newText = QString::number( this->getCurrTime() / 1000.0, 'f', 3 ) + " sec";
|
newText = QString::number( this->getCurrTime() / 1000.0, 'f', 3 ) + " sec";
|
||||||
break;
|
break;
|
||||||
|
|
Reference in a new issue