Feat: show both results in speed quali

This commit is contained in:
Dorian Zedler 2023-07-05 16:27:15 +02:00
parent 12185337b9
commit cd0500c40b
Signed by: dorian
GPG key ID: 989DE36109AFA354
10 changed files with 459 additions and 355 deletions

View file

@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
# [0.8.0] - 2023-06-05
### Added
- Show both results in speed quali
# [0.7.3] - 2023-05-02
### Removed
- Im-App purchase on android

View file

@ -1,7 +1,7 @@
QT += quick qml quickcontrols2
CONFIG += c++11
VERSION = 0.7.4
VERSION = 0.8.0
TARGET = blueROCK
# The following define makes your compiler emit warnings if you use

2
qzxing

@ -1 +1 @@
Subproject commit cfc728583b867e157bd27e8b7c239c05a081e562
Subproject commit 6ea2b31e26db9d43db027ba207f5c73dc9d759fc

View file

@ -0,0 +1,262 @@
import QtQuick 2.10
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
Row {
id: multiResRow
property bool active: parseInt(widgetData[ "route_order" ]) > -1 && boulderResRep.model > 0
height: parent.height
width: active ? parent.width * 0.75:0
enabled: parseInt(widgetData[ "route_order" ]) > -1 && boulderResRep.model > 0
Repeater {
id: boulderResRep
model: parseInt(widgetData[ "route_num_problems" ])
function getDataForIcon(index){
// TODO: clean
var resultString = widgetData[ "participants" ][partDel.thisIndex]["boulder"+(index+1)]
var numTrys = widgetData[ "participants" ][partDel.thisIndex]["try"+(index+1)]
var resultList = []
if (resultString !== undefined) {
resultString = resultString.replace("t", "")
resultString = resultString.replace("z", "")
resultString = resultString.replace("b", "")
resultList = resultString.split(" ")
while (resultList.length < 2){
resultList.unshift(0)
}
}
else {
resultList = [-1,-1]
}
if (numTrys !== undefined) {
resultList.push(numTrys)
}
else {
resultList.push(-1)
}
return resultList
}
delegate: Item {
id: boulderResItm
anchors.verticalCenter: parent.verticalCenter
width: parent.width / ( boulderResRep.model )
height: parent.height
Canvas {
id: boulderResCv
property var resultData: boulderResRep.getDataForIcon(index)
onResultDataChanged: {
boulderResCv.requestPaint()
}
anchors.centerIn: parent
height: parent.height > parent.width ? parent.width * 0.9:parent.height * 0.9
width: height
onPaint: {
var width = 24//boulderResCv.width * 0.9
var height = width
var radius = width * 0.3
var offsetX = width * 0.05
var offsetY = height * 0.05
//console.log("drawing result rect with width: " + width + " and height: " + height)
var context = getContext("2d");
// clear all remainings from other routes
context.clearRect(0, 0, width, height);
context.beginPath();
context.moveTo(0 + offsetX + radius, 0 + offsetY);
// top line
context.lineTo(width - radius + offsetX, 0 + offsetY);
// top right corner
context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 0);
// right line
context.lineTo(width + offsetX, height - radius + offsetY);
// bottom right corner
context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI);
// bottom line
context.lineTo(0 + radius + offsetX, height + offsetY);
// bottom left corner
context.arc(radius + offsetY, height - radius + offsetY, radius, 0.5 * Math.PI, Math.PI);
// left line
context.lineTo(0 + offsetX, radius + offsetY);
// top left corner
context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI);
// fill
if(resultData[0] !== -1 || resultData[2] !== -1) {
// if there is a result available -> draw background
context.fillStyle = "#b7b7b7";
}
else {
context.fillStyle = "transparent";
}
context.fill();
// outline
context.lineWidth = 1;
context.strokeStyle = Material.primaryTextColor;
context.stroke();
if(resultData[1] > 0){
// the first triangle
context.beginPath();
// top right corner
context.arc(width-radius + offsetX, radius + offsetY, radius, 1.75 * Math.PI, 0);
// right line
context.lineTo(width + offsetX, height - radius + offsetY);
// bottom right corner
context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI);
// bottom line
context.lineTo(0 + radius + offsetX, height + offsetY);
// bottom left corner
context.arc(radius + offsetX, height - radius + offsetY, radius, 0.5 * Math.PI, 0.75 * Math.PI);
context.closePath();
context.fillStyle = "#44ed38";
context.fill();
// outline
context.lineWidth = 1;
context.strokeStyle = Material.primaryTextColor;
context.stroke();
if(resultData[0] > 0){
// the second triangle
context.beginPath();
// bottom left corner
context.arc(radius + offsetX, height - radius + offsetY, radius, 0.75 * Math.PI, 1 * Math.PI);
// left line
context.lineTo(0 + offsetX, radius + offsetY);
// top left corner
context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI);
// top line
context.lineTo(width - radius + offsetX, 0 + offsetY);
// top right corner
context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 1.75 * Math.PI);
context.closePath();
context.fillStyle = "#44ed38";
context.fill();
// outline
context.lineWidth = 1;
context.strokeStyle = Material.primaryTextColor;
context.stroke();
}
}
}
Label {
id: boulderResTrysLa
anchors.centerIn: parent
height: parent.height / 2
width: parent.width / 2
visible: !boulderResZoneLa.visible && boulderResCv.resultData[2] > 0
fontSizeMode: Text.Fit
font.pixelSize: height
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#dd000000"
text: boulderResCv.resultData[2]
}
Label {
id: boulderResZoneLa
anchors {
right: parent.right
bottom: parent.bottom
margins: boulderResCv.height * 0.05
}
height: parent.height / 2
width: parent.width / 2
visible: parseInt(text) > 0
fontSizeMode: Text.Fit
font.pixelSize: height
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#dd000000"
text: boulderResCv.resultData[1]
}
Label {
id: boulderResTopLa
anchors {
left: parent.left
top: parent.top
margins: boulderResCv.height * 0.05
}
height: parent.height / 2
width: parent.width / 2
visible: parseInt(text) > 0
fontSizeMode: Text.Fit
font.pixelSize: height
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#dd000000"
text: boulderResCv.resultData[0]
}
}
}
}
}

View file

@ -0,0 +1,97 @@
import QtQuick 2.10
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
Row {
id: multiGenResRow
property bool active: (parseInt(widgetData[ "route_order" ]) === -1) && (generalResRep.model > 0)
height: parent.height
width: active ? parent.width - resultLa.width:0
enabled: active
Repeater {
id: generalResRep
property var routes: getRoutes()
model: routes.length
function getRoutes() {
var obj = widgetData["route_names"]
var routes = []
for(var prop in obj) {
// go through the whole array and search for data keys
if (obj.hasOwnProperty(prop) && prop > -1) {
routes.push([prop, obj[prop]])
//console.log("found " + obj[prop] + " at index " + prop)
}
}
routes.sort(function(a, b) {
return a[0] - b[0];
});
return routes
}
delegate: Item {
id: boulderGenResItm
anchors.verticalCenter: parent.verticalCenter
width: parent.width / ( generalResRep.model )
height: parent.height
visible: multiGenResRow.active
Rectangle {
anchors {
left: parent.left
}
width: 1
height: parent.height
visible: index === 0
color: Material.primaryTextColor
}
Rectangle {
anchors {
right: parent.right
}
width: 1
height: parent.height
color: Material.primaryTextColor
}
Label {
id: boulderGenResLa
anchors.centerIn: parent
height: parent.height
width: parent.width * 0.9
fontSizeMode: Text.Fit
font.pixelSize: Math.abs( height * 0.6 )
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: widgetData["participants"][partDel.thisIndex]["result"+(generalResRep.routes[index][0])] === undefined ?
"":
widgetData[ "participants" ][partDel.thisIndex]["result"+(generalResRep.routes[index][0])]
}
}
}
}

View file

@ -107,370 +107,29 @@ ColoredItemDelegate {
Layout.preferredWidth: partDelCol.showSideBySide ? parent.width * 0.5 : parent.width
Layout.preferredHeight: partDelCol.showSideBySide ? parent.height : parent.height * 0.5
visible: multiResRow.active || multiGenResRow.active || resultLa.acitve
visible: boulderResRow.active || generalResRow.active || speedQualificationResRow.active || resultLa.active
Row {
id: multiResRow
property bool active: parseInt(widgetData[ "route_order" ]) > -1 && boulderResRep.model > 0
height: parent.height
width: active ? parent.width * 0.75:0
enabled: parseInt(widgetData[ "route_order" ]) > -1 && boulderResRep.model > 0
Repeater {
id: boulderResRep
model: parseInt(widgetData[ "route_num_problems" ])
function getDataForIcon(index){
// TODO: clean
var resultString = widgetData[ "participants" ][partDel.thisIndex]["boulder"+(index+1)]
var numTrys = widgetData[ "participants" ][partDel.thisIndex]["try"+(index+1)]
var resultList = []
if (resultString !== undefined) {
resultString = resultString.replace("t", "")
resultString = resultString.replace("z", "")
resultString = resultString.replace("b", "")
resultList = resultString.split(" ")
while (resultList.length < 2){
resultList.unshift(0)
}
}
else {
resultList = [-1,-1]
BoulderResultRow {
id: boulderResRow
}
if (numTrys !== undefined) {
resultList.push(numTrys)
}
else {
resultList.push(-1)
GeneralResultRow {
id: generalResRow
}
return resultList
}
delegate: Item {
id: boulderResItm
anchors.verticalCenter: parent.verticalCenter
width: parent.width / ( boulderResRep.model )
height: parent.height
Canvas {
id: boulderResCv
property var resultData: boulderResRep.getDataForIcon(index)
onResultDataChanged: {
boulderResCv.requestPaint()
}
anchors.centerIn: parent
height: parent.height > parent.width ? parent.width * 0.9:parent.height * 0.9
width: height
onPaint: {
var width = 24//boulderResCv.width * 0.9
var height = width
var radius = width * 0.3
var offsetX = width * 0.05
var offsetY = height * 0.05
//console.log("drawing result rect with width: " + width + " and height: " + height)
var context = getContext("2d");
// clear all remainings from other routes
context.clearRect(0, 0, width, height);
context.beginPath();
context.moveTo(0 + offsetX + radius, 0 + offsetY);
// top line
context.lineTo(width - radius + offsetX, 0 + offsetY);
// top right corner
context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 0);
// right line
context.lineTo(width + offsetX, height - radius + offsetY);
// bottom right corner
context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI);
// bottom line
context.lineTo(0 + radius + offsetX, height + offsetY);
// bottom left corner
context.arc(radius + offsetY, height - radius + offsetY, radius, 0.5 * Math.PI, Math.PI);
// left line
context.lineTo(0 + offsetX, radius + offsetY);
// top left corner
context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI);
// fill
if(resultData[0] !== -1 || resultData[2] !== -1) {
// if there is a result available -> draw background
context.fillStyle = "#b7b7b7";
}
else {
context.fillStyle = "transparent";
}
context.fill();
// outline
context.lineWidth = 1;
context.strokeStyle = Material.primaryTextColor;
context.stroke();
if(resultData[1] > 0){
// the first triangle
context.beginPath();
// top right corner
context.arc(width-radius + offsetX, radius + offsetY, radius, 1.75 * Math.PI, 0);
// right line
context.lineTo(width + offsetX, height - radius + offsetY);
// bottom right corner
context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI);
// bottom line
context.lineTo(0 + radius + offsetX, height + offsetY);
// bottom left corner
context.arc(radius + offsetX, height - radius + offsetY, radius, 0.5 * Math.PI, 0.75 * Math.PI);
context.closePath();
context.fillStyle = "#44ed38";
context.fill();
// outline
context.lineWidth = 1;
context.strokeStyle = Material.primaryTextColor;
context.stroke();
if(resultData[0] > 0){
// the second triangle
context.beginPath();
// bottom left corner
context.arc(radius + offsetX, height - radius + offsetY, radius, 0.75 * Math.PI, 1 * Math.PI);
// left line
context.lineTo(0 + offsetX, radius + offsetY);
// top left corner
context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI);
// top line
context.lineTo(width - radius + offsetX, 0 + offsetY);
// top right corner
context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 1.75 * Math.PI);
context.closePath();
context.fillStyle = "#44ed38";
context.fill();
// outline
context.lineWidth = 1;
context.strokeStyle = Material.primaryTextColor;
context.stroke();
}
}
}
Label {
id: boulderResTrysLa
anchors.centerIn: parent
height: parent.height / 2
width: parent.width / 2
visible: !boulderResZoneLa.visible && boulderResCv.resultData[2] > 0
fontSizeMode: Text.Fit
font.pixelSize: height
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#dd000000"
text: boulderResCv.resultData[2]
}
Label {
id: boulderResZoneLa
anchors {
right: parent.right
bottom: parent.bottom
margins: boulderResCv.height * 0.05
}
height: parent.height / 2
width: parent.width / 2
visible: parseInt(text) > 0
fontSizeMode: Text.Fit
font.pixelSize: height
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#dd000000"
text: boulderResCv.resultData[1]
}
Label {
id: boulderResTopLa
anchors {
left: parent.left
top: parent.top
margins: boulderResCv.height * 0.05
}
height: parent.height / 2
width: parent.width / 2
visible: parseInt(text) > 0
fontSizeMode: Text.Fit
font.pixelSize: height
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#dd000000"
text: boulderResCv.resultData[0]
}
}
}
}
}
Row {
id: multiGenResRow
property bool active: ((parseInt(widgetData[ "route_order" ]) === -1) && (generalResRep.model > 0)) ? true:false
height: parent.height
width: active ? parent.width - resultLa.width:0
enabled: ((parseInt(widgetData[ "route_order" ]) === -1) && (generalResRep.model > 0)) ? true:false
Repeater {
id: generalResRep
property var routes: getRoutes()
model: routes.length
function getRoutes() {
var obj = widgetData["route_names"]
var routes = []
for(var prop in obj) {
// go through the whole array and search for data keys
if (obj.hasOwnProperty(prop) && prop > -1) {
routes.push([prop, obj[prop]])
//console.log("found " + obj[prop] + " at index " + prop)
}
}
routes.sort(function(a, b) {
return a[0] - b[0];
});
return routes
}
delegate: Item {
id: boulderGenResItm
anchors.verticalCenter: parent.verticalCenter
width: parent.width / ( generalResRep.model )
height: parent.height
visible: multiGenResRow.active
Rectangle {
anchors {
left: parent.left
}
width: 1
height: parent.height
visible: index === 0
color: Material.primaryTextColor
}
Rectangle {
anchors {
right: parent.right
}
width: 1
height: parent.height
color: Material.primaryTextColor
}
Label {
id: boulderGenResLa
anchors.centerIn: parent
height: parent.height
width: parent.width * 0.9
fontSizeMode: Text.Fit
font.pixelSize: Math.abs( height * 0.6 )
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: widgetData["participants"][partDel.thisIndex]["result"+(generalResRep.routes[index][0])] === undefined ?
"":
widgetData[ "participants" ][partDel.thisIndex]["result"+(generalResRep.routes[index][0])]
}
}
}
SpeedQualificationResultRow {
id: speedQualificationResRow
}
Label {
id: resultLa
property bool acitve: ( boulderResRep.model > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1
property bool active: ( parseInt(widgetData[ "route_num_problems" ]) > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1 && !speedQualificationResRow.active
width: enabled ? parent.width * 0.25:0
height: enabled ? parent.height:0
enabled: ( boulderResRep.model > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1
enabled: active
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter

View file

@ -1,7 +1,7 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QZXing 3.1
import QZXing 3.3
import QtGraphicalEffects 1.0
Dialog {

View file

@ -0,0 +1,79 @@
import QtQuick 2.10
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
Row {
id: control
property bool active: (parseInt(widgetData[ "route_order" ]) === 0) && (widgetData["discipline"] === "speed") && (thisData["result_l"] !== undefined || thisData["result_r"] !== undefined)
property var thisData: widgetData["participants"][partDel.thisIndex]
height: parent.height
width: active ? parent.width - resultLa.width:0
enabled: active
Repeater {
id: generalResRep
model: 2
delegate: Item {
id: boulderGenResItm
anchors.verticalCenter: parent.verticalCenter
width: parent.width / ( generalResRep.model )
height: parent.height
visible: control.active
Rectangle {
anchors {
left: parent.left
}
width: 1
height: parent.height
visible: index === 0
color: Material.primaryTextColor
}
Rectangle {
anchors {
right: parent.right
}
width: 1
height: parent.height
color: Material.primaryTextColor
}
Label {
id: boulderGenResLa
property string thisKey: "result_"+(["l", "r"][index])
anchors.centerIn: parent
height: parent.height
width: parent.width * 0.9
fontSizeMode: Text.Fit
font.pixelSize: Math.abs( height * 0.6 )
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.bold: thisData["result_l"] !== undefined && thisData["result_r"] !== undefined && thisData[thisKey] === thisData["result"]
text: control.thisData[thisKey] ?? ""
}
}
}
}

View file

@ -1,7 +1,7 @@
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QZXing 3.1
import QZXing 3.3
import QtMultimedia 5.12
import QtQuick.Shapes 1.12
import QtQuick.Controls.Material 2.12

View file

@ -32,5 +32,8 @@
<file>Pages/QrCodeScanPage.qml</file>
<file>Components/MovingLabel.qml</file>
<file>Components/SpeedFlowChart.js</file>
<file>Components/BoulderResultRow.qml</file>
<file>Components/GeneralResultRow.qml</file>
<file>Components/SpeedQualificationResultRow.qml</file>
</qresource>
</RCC>