Chore: refactor speed flowchart (fixes #26) #36
4 changed files with 343 additions and 245 deletions
289
resources/qml/Components/SpeedFlowChart.js
Normal file
289
resources/qml/Components/SpeedFlowChart.js
Normal file
|
@ -0,0 +1,289 @@
|
|||
.pragma library
|
||||
|
||||
/**
|
||||
* Function to extract results from PartiipantFromApi
|
||||
* @param {ParticipantFromApi} fromApi
|
||||
* @return {Result[]}
|
||||
*/
|
||||
function _extractResults(fromApi) {
|
||||
const results = Array(7);
|
||||
|
||||
const existingResults = Object.keys(fromApi).filter(key =>
|
||||
key.match(/result[0-9]/),
|
||||
);
|
||||
|
||||
for (const result of existingResults) {
|
||||
let roundNumber = 0;
|
||||
const match = result.match(/result([0-9])/);
|
||||
if (match !== undefined && match !== null) {
|
||||
roundNumber = parseInt(match[1]);
|
||||
}
|
||||
if (roundNumber < 0) {
|
||||
continue;
|
||||
}
|
||||
results[roundNumber] = {
|
||||
rank: parseInt(fromApi[`result_rank${roundNumber}`] as string),
|
||||
result: fromApi[`result${roundNumber}`] as string,
|
||||
};
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to clean up participants from the api
|
||||
* @param {ParticipantFromApi} fromApi
|
||||
* @return {Participant}
|
||||
*/
|
||||
function participantFromApiParticipant(
|
||||
fromApi,
|
||||
) {
|
||||
const results = _extractResults(fromApi);
|
||||
|
||||
return {
|
||||
id: fromApi.PerId,
|
||||
firstName: fromApi.firstname,
|
||||
lastName: fromApi.lastname,
|
||||
results: results,
|
||||
overallRank: fromApi.result_rank,
|
||||
startNumber: parseInt(fromApi.start_number),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} roundNumber
|
||||
* @param {RouteNames} routeNames
|
||||
* @return {string | undefined}
|
||||
*/
|
||||
function getRoundName(
|
||||
roundNumber,
|
||||
routeNames,
|
||||
) {
|
||||
if (roundNumber < 2 || roundNumber > 6) return undefined;
|
||||
|
||||
return routeNames[roundNumber];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} name
|
||||
* @return {number}
|
||||
*/
|
||||
function getRoundRank(name) {
|
||||
const match = name.match(/1\/([842])/);
|
||||
if (match === undefined || match === null || match.length !== 2) {
|
||||
return 2;
|
||||
}
|
||||
return parseInt(match[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SpeedRoundPair} pair
|
||||
* @param {number} roundIndex
|
||||
*/
|
||||
function computeWinnerOfPair(pair, roundIndex) {
|
||||
if (
|
||||
!(pair.laneA && pair.laneA.participant.results[roundIndex] && pair.laneA.participant.results[roundIndex].rank) ||
|
||||
!(pair.laneB && pair.laneB.participant.results[roundIndex] && pair.laneB.participant.results[roundIndex].rank)
|
||||
)
|
||||
return;
|
||||
|
||||
pair.laneA.result = pair.laneA.participant.results[roundIndex];
|
||||
pair.laneB.result = pair.laneB.participant.results[roundIndex];
|
||||
|
||||
if (pair.winner === undefined) {
|
||||
pair.winner =
|
||||
pair.laneA.participant.results[roundIndex].rank >
|
||||
pair.laneB.participant.results[roundIndex].rank
|
||||
? 'B'
|
||||
: 'A';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SpeedRoundPair} pair
|
||||
* @param {number} roundNumber
|
||||
* @return {Participant | undefined}
|
||||
*/
|
||||
function getWinnerOfPair(
|
||||
pair,
|
||||
roundNumber,
|
||||
) {
|
||||
computeWinnerOfPair(pair, roundNumber);
|
||||
return {
|
||||
['A']: pair.laneA ? pair.laneA.participant : undefined,
|
||||
['B']: pair.laneB ? pair.laneB.participant : undefined,
|
||||
['']: undefined,
|
||||
}[pair.winner ? pair.winner:''];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SpeedRoundPair} pair
|
||||
* @param {number} roundNumber
|
||||
* @return {Participant | undefined}
|
||||
*/
|
||||
function getLooserOfPair(
|
||||
pair,
|
||||
roundNumber,
|
||||
) {
|
||||
computeWinnerOfPair(pair, roundNumber);
|
||||
return {
|
||||
['A']: pair.laneB ? pair.laneB.participant : undefined,
|
||||
['B']: pair.laneA ? pair.laneA.participant : undefined,
|
||||
['']: undefined,
|
||||
}[pair.winner ? pair.winner:''];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} roundIndex index of the new round
|
||||
* @param {string} roundName name of the new round
|
||||
* @param {SpeedRound} previousRound
|
||||
* @param {number} roundRank
|
||||
* @param {boolean} takeLooser
|
||||
* @return {SpeedRound}
|
||||
*/
|
||||
function computeRoundFromPreviousRound(
|
||||
roundIndex,
|
||||
roundName,
|
||||
previousRound,
|
||||
roundRank,
|
||||
takeLooser = false,
|
||||
) {
|
||||
const getAdvancingParticipant = takeLooser
|
||||
? getLooserOfPair
|
||||
: getWinnerOfPair;
|
||||
const nextRoundPairs = new Array(roundRank / 2).fill(0).map((_, i) => {
|
||||
const laneAParticipant = getAdvancingParticipant(
|
||||
previousRound.pairs[i * 2],
|
||||
previousRound.roundIndex,
|
||||
);
|
||||
const laneBParticipant = getAdvancingParticipant(
|
||||
previousRound.pairs[i * 2 + 1],
|
||||
previousRound.roundIndex,
|
||||
);
|
||||
|
||||
return {
|
||||
laneA:
|
||||
laneAParticipant === undefined
|
||||
? undefined
|
||||
: {
|
||||
participant: laneAParticipant,
|
||||
},
|
||||
laneB:
|
||||
laneBParticipant === undefined
|
||||
? undefined
|
||||
: {
|
||||
participant: laneBParticipant,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
pairs: nextRoundPairs,
|
||||
roundIndex: roundIndex,
|
||||
roundName: roundName,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SpeedCompetitionCategoryResult} result The result to process
|
||||
* @return {SpeedFlowchartResult}
|
||||
*/
|
||||
function convertResultsToSpeedFlowchartResult(
|
||||
result,
|
||||
) {
|
||||
const rounds = [];
|
||||
const convertedParticipants = result.participants
|
||||
.map(fromApi => participantFromApiParticipant(fromApi))
|
||||
// sort by qualification result
|
||||
.sort((a, b) => a.results[0].rank - b.results[0].rank);
|
||||
|
||||
const roundIndices = Object.keys(result.route_names)
|
||||
.map(number => parseInt(number))
|
||||
.filter(number => number > 0);
|
||||
|
||||
// process first round
|
||||
const firstRoundName = getRoundName(roundIndices[0], result.route_names);
|
||||
const tmpRoundName = getRoundName(roundIndices[0], result.route_names);
|
||||
const firstRoundRank = getRoundRank(
|
||||
tmpRoundName ? tmpRoundName:'',
|
||||
);
|
||||
|
||||
const getOpponent = (ofRank) => {
|
||||
return convertedParticipants[firstRoundRank * 2 - 1 - ofRank];
|
||||
};
|
||||
|
||||
// Should be:
|
||||
// 0, 1, 2, 3, 4, 5, 6, 7
|
||||
// - 1,16, 8, 9, 4,13, 5,12, 2,15, 7,10, 3,14, 6,11
|
||||
// - 1, 8, 4, 5, 2, 7, 3, 6 for firstRoundNumber=8
|
||||
// - 1, 4, 2, 3 for firstRoundNumber=4
|
||||
// - 1, 2 for firstRoundNumber=2
|
||||
// TODO: come up with a proper alogorithm maybe
|
||||
const ranksOfLaneAInOrder = [
|
||||
[1, 2],
|
||||
[1, 4, 2, 3],
|
||||
[1, 8, 4, 5, 2, 7, 3, 6],
|
||||
][Math.floor(firstRoundRank / 4)];
|
||||
|
||||
const firstRoundPairs = ranksOfLaneAInOrder.map(rank => {
|
||||
return {
|
||||
laneA: { participant: convertedParticipants[rank - 1] },
|
||||
laneB: { participant: getOpponent(rank - 1) },
|
||||
};
|
||||
});
|
||||
|
||||
const firstRound = {
|
||||
pairs: firstRoundPairs,
|
||||
roundIndex: roundIndices[0],
|
||||
roundName: firstRoundName,
|
||||
};
|
||||
|
||||
rounds.push(firstRound);
|
||||
|
||||
// compute following rounds
|
||||
let roundIndex = roundIndices[1];
|
||||
for (let roundRank = firstRoundRank; roundRank > 2; roundRank /= 2) {
|
||||
rounds.push(
|
||||
computeRoundFromPreviousRound(
|
||||
roundIndex,
|
||||
result.route_names[roundIndex] ? result.route_names[roundIndex]:'',
|
||||
rounds[rounds.length - 1],
|
||||
roundRank,
|
||||
),
|
||||
);
|
||||
roundIndex++;
|
||||
}
|
||||
|
||||
// compute final and semi final
|
||||
const semifinalRoundIndex = roundIndex++;
|
||||
const semifinal = computeRoundFromPreviousRound(
|
||||
semifinalRoundIndex,
|
||||
result.route_names[semifinalRoundIndex] ? result.route_names[semifinalRoundIndex]:'',
|
||||
rounds[rounds.length - 1],
|
||||
2,
|
||||
true,
|
||||
);
|
||||
computeWinnerOfPair(semifinal.pairs[0], semifinalRoundIndex);
|
||||
rounds.push(semifinal);
|
||||
|
||||
const finalRoundIndex = roundIndex;
|
||||
const final = computeRoundFromPreviousRound(
|
||||
finalRoundIndex,
|
||||
result.route_names[finalRoundIndex] ? result.route_names[finalRoundIndex]:'',
|
||||
rounds[rounds.length - 2],
|
||||
2,
|
||||
);
|
||||
computeWinnerOfPair(final.pairs[0], finalRoundIndex);
|
||||
rounds.push(final);
|
||||
|
||||
return {
|
||||
rounds: rounds,
|
||||
};
|
||||
}
|
|
@ -22,6 +22,8 @@ import QtQuick.Layouts 1.3
|
|||
import QtQuick.Controls.Material 2.1
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "SpeedFlowChart.js" as SpeedFlowChart
|
||||
|
||||
Item {
|
||||
id: control
|
||||
|
||||
|
@ -32,8 +34,6 @@ Item {
|
|||
property int refreshes: 0
|
||||
property int roundRefreshes: 1
|
||||
|
||||
property int roundCount: 0
|
||||
|
||||
onFlowchartDataChanged: {
|
||||
prepareData()
|
||||
}
|
||||
|
@ -42,181 +42,20 @@ Item {
|
|||
|
||||
if(!control.enabled || control.flowchartData === undefined || control.flowchartData['route_names'] === undefined)
|
||||
return
|
||||
/*refreshes += 1
|
||||
|
||||
if(refreshes > 2){
|
||||
roundRefreshes += 1
|
||||
}
|
||||
|
||||
console.log("refreshes: " + refreshes + " rounds: " + roundRefreshes)
|
||||
|
||||
// create competition like data (just testing)
|
||||
for(var part in flowchartData['participants']){
|
||||
if(flowchartData['participants'].hasOwnProperty(part)){
|
||||
|
||||
for(var r = 2 + roundRefreshes; r < 7; r++){
|
||||
delete flowchartData['participants'][part]["result"+r]
|
||||
delete flowchartData['participants'][part]["result_rank"+r]
|
||||
}
|
||||
|
||||
if(parseInt(flowchartData['participants'][part]["result_rank0"]) > 14 + refreshes) {
|
||||
delete flowchartData['participants'][part]["result_rank2"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete flowchartData['route_names'][2]
|
||||
delete flowchartData['route_names'][3]
|
||||
delete flowchartData['route_names'][4]
|
||||
delete flowchartData['route_names'][5]
|
||||
delete flowchartData['route_names'][6]
|
||||
*/
|
||||
|
||||
//flowchartData['route_names'] = flowchartData['route_names'].slice(0,)
|
||||
|
||||
// array to store the restructured data
|
||||
var allData = []
|
||||
control.allFlowchartData = []
|
||||
|
||||
control.rounds = Object.keys(control.flowchartData['route_names']).length > 2 ? control.flowchartData['route_names']["2"].includes("8") ? 2:1 : 0
|
||||
|
||||
//console.log(JSON.stringify(flowchartData['route_names']))
|
||||
|
||||
for(var round in flowchartData['route_names']){
|
||||
if(flowchartData['route_names'].hasOwnProperty(round) && parseInt(round) >= 0){
|
||||
//console.log(round)
|
||||
|
||||
if(parseInt(round) === 0){
|
||||
// this is the first round
|
||||
|
||||
// find pairs (always wors vs. best (1-16; 1-15; ...)) (they are sorted by the rank of the better athlete (1-2-3-4-5-6-7-8)
|
||||
|
||||
var qualificationResults = []
|
||||
|
||||
for(var x = 0; x < flowchartData['participants'].length; x++){
|
||||
qualificationResults.push(flowchartData['participants'][x])
|
||||
}
|
||||
|
||||
qualificationResults.sort(function(a, b) {
|
||||
return parseInt(a["result_rank0"]) - parseInt(b["result_rank0"]);
|
||||
});
|
||||
|
||||
var nextRoundPairs = []
|
||||
var totalMatches = (parseInt(Object.keys(control.flowchartData['route_names']).length > 2 ? control.flowchartData['route_names']["2"].includes("8") ? 2:1 : 0) + 2)
|
||||
var nextRoundMatches = Math.pow(2, totalMatches-1)
|
||||
|
||||
for(var i = 0; i < nextRoundMatches; i++){
|
||||
nextRoundPairs.push([qualificationResults[i], qualificationResults[nextRoundMatches*2-i-1]])
|
||||
}
|
||||
|
||||
// build second round pairs (sorted by the rank of the better athlete and worst vs. best (1-8; 2-7; ... ))
|
||||
|
||||
var sortedFirstRoundPairs = []
|
||||
|
||||
for(i = 0; i < nextRoundMatches; i += 1){
|
||||
sortedFirstRoundPairs.push([nextRoundPairs.shift(), nextRoundPairs.pop()])
|
||||
}
|
||||
|
||||
// sort these pairs (containing two pairs of athletes) by the rank of the better athlete (1-4;2-3)
|
||||
|
||||
var finalSortedFirstRoundPairs = []
|
||||
|
||||
for(i=0; i < nextRoundMatches/4; i++){
|
||||
finalSortedFirstRoundPairs.push(sortedFirstRoundPairs[i])
|
||||
finalSortedFirstRoundPairs.push(sortedFirstRoundPairs[nextRoundMatches/2-i-1])
|
||||
}
|
||||
|
||||
// convert the list of pairs of pairs of athletes back to a single list of pairs of athletes
|
||||
|
||||
var finalFirstRoundPairs = []
|
||||
|
||||
for(i=0; i < finalSortedFirstRoundPairs.length; i++){
|
||||
finalFirstRoundPairs.push(finalSortedFirstRoundPairs[i][0])
|
||||
finalFirstRoundPairs.push(finalSortedFirstRoundPairs[i][1])
|
||||
}
|
||||
|
||||
// push the first round to all data
|
||||
finalFirstRoundPairs.push(2)
|
||||
finalFirstRoundPairs.push(flowchartData['route_names'][2])
|
||||
allData.push(finalFirstRoundPairs)
|
||||
|
||||
}
|
||||
else if(parseInt(round) > 0 ){
|
||||
// this is not the first round
|
||||
|
||||
var nextRound = []
|
||||
|
||||
// only used when the current round is the 1/2 final
|
||||
var smallFinal = []
|
||||
var Final = []
|
||||
|
||||
for(var i = 0; i < allData[allData.length-1].length-2; i+=1){
|
||||
|
||||
var thisPair = allData[allData.length-1][i]
|
||||
var thisWinner
|
||||
var thisLooser
|
||||
var thisWinnerIsFirstOfNewPair = i%2 === 0
|
||||
|
||||
if(thisPair[0] === undefined || thisPair[1] === undefined){
|
||||
continue
|
||||
}
|
||||
|
||||
if(thisWinnerIsFirstOfNewPair){
|
||||
nextRound.push([])
|
||||
}
|
||||
|
||||
//thisPair[0]["result_rank"] = thisPair[0]["result_rank"+round]
|
||||
//thisPair[1]["result_rank"] = thisPair[1]["result_rank"+round]
|
||||
|
||||
if(parseInt(thisPair[0]["result_rank"+round]) < parseInt(thisPair[1]["result_rank"+round])){
|
||||
thisWinner = thisPair[0]
|
||||
thisLooser = thisPair[1]
|
||||
}
|
||||
else if(parseInt(thisPair[0]["result_rank"+round]) > parseInt(thisPair[1]["result_rank"+round])) {
|
||||
thisWinner = thisPair[1]
|
||||
thisLooser = thisPair[0]
|
||||
}
|
||||
else {
|
||||
// no result yet!!
|
||||
//console.log("got no winner yet, rank 0: " + thisPair[0]["result_rank"+round] + " rank 1: " + thisPair[1]["result_rank"+round])
|
||||
continue
|
||||
}
|
||||
|
||||
//console.log(thisWinner['firstname']+" has won in round " + round)
|
||||
|
||||
if(round - control.rounds === 2){
|
||||
// if we are in the 1/2 final
|
||||
|
||||
Final.push(thisWinner)
|
||||
smallFinal.push(thisLooser)
|
||||
}
|
||||
else {
|
||||
nextRound[nextRound.length-1].push(thisWinner)
|
||||
}
|
||||
}
|
||||
|
||||
if(smallFinal.length > 0 && Final.length > 0){
|
||||
|
||||
// Final
|
||||
allData.push([Final, parseInt(round)+2, flowchartData['route_names'][String(parseInt(round)+2)] + " / " + flowchartData['route_names'][String(parseInt(round)+1)] ])
|
||||
// small Final
|
||||
allData.push([smallFinal, parseInt(round)+1])
|
||||
|
||||
//break
|
||||
}
|
||||
else {
|
||||
nextRound.push(parseInt(round) + 1 )
|
||||
nextRound.push(flowchartData['route_names'][parseInt(round) + 1])
|
||||
allData.push(nextRound)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
control.allFlowchartData = allData
|
||||
control.roundCount = (parseInt(Object.keys(control.flowchartData['route_names']).length > 2 ? control.flowchartData['route_names']["2"].includes("8") ? 2:1 : 0) + 2)
|
||||
//console.log(JSON.stringify(allData))
|
||||
var flowchartResult = SpeedFlowChart.convertResultsToSpeedFlowchartResult(control.flowchartData)
|
||||
const l = flowchartResult.rounds.length;
|
||||
const dummy = { dummy: true };
|
||||
flowchartResult.rounds[l - 2].pairs = [
|
||||
dummy,
|
||||
...flowchartResult.rounds[l - 1].pairs,
|
||||
...flowchartResult.rounds[l - 2].pairs,
|
||||
];
|
||||
flowchartResult.rounds[l - 2].roundName = `${
|
||||
flowchartResult.rounds[l - 1].roundName
|
||||
} / ${flowchartResult.rounds[l - 2].roundName}`;
|
||||
flowchartResult.rounds.pop();
|
||||
control.allFlowchartData = flowchartResult
|
||||
}
|
||||
|
||||
ListView {
|
||||
|
@ -238,19 +77,18 @@ Item {
|
|||
orientation: ListView.LeftToRight
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
|
||||
model: control.roundCount
|
||||
model: control.allFlowchartData.rounds.length
|
||||
|
||||
delegate: Item {
|
||||
id: roundItem
|
||||
|
||||
property int thisIndex: index
|
||||
property int thisRound: thisRoundIsValid ? control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-2]:-1
|
||||
property bool thisRoundIsValid: control.allFlowchartData !== undefined
|
||||
&& control.allFlowchartData[roundItem.thisIndex] !== undefined
|
||||
&& control.allFlowchartData[roundItem.thisIndex].length > 2
|
||||
property var thisData: control.allFlowchartData.rounds[thisIndex]
|
||||
|
||||
property bool thisIsLastRound: thisIndex === control.roundCount - 1
|
||||
property bool thisIsSemiFinal: thisIndex === control.roundCount - 2 && rectRep.model === 2
|
||||
property bool thisRoundIsValid: true
|
||||
|
||||
property bool thisIsLastRound: thisIndex === roundListView.model - 1
|
||||
property bool thisIsSemiFinal: thisIndex === roundListView.model - 2
|
||||
|
||||
property int tileSize: (roundItem.height / 8 - roundNameLa.height) * 1.45
|
||||
|
||||
|
@ -272,50 +110,26 @@ Item {
|
|||
font.pixelSize: height * 0.6
|
||||
minimumPixelSize: 1
|
||||
font.bold: true
|
||||
text: roundItem.thisRoundIsValid
|
||||
&& control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-1] !== undefined ?
|
||||
control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-1] :
|
||||
text: roundItem.thisData.roundName ?
|
||||
roundItem.thisData.roundName :
|
||||
"-"
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: rectRep
|
||||
model: Math.max( Math.pow(2, control.roundCount-1) * Math.pow(0.5, (roundItem.thisIndex)), 2)
|
||||
model: roundItem.thisData.pairs.length
|
||||
|
||||
delegate: Item {
|
||||
id: matchItm
|
||||
|
||||
property bool lowerPart: (index%2 > 0)
|
||||
|
||||
property var matchData: roundItem.thisRoundIsValid ?
|
||||
control.allFlowchartData[
|
||||
thisIsSmallFinal ?
|
||||
roundItem.thisIndex+1 :
|
||||
roundItem.thisIndex
|
||||
][ thisIsSmallFinal ? 0:matchItm.thisIndex]:
|
||||
undefined
|
||||
|
||||
property var thisData: roundItem.thisData.pairs[index]
|
||||
property int thisIndex: index
|
||||
property int thisRound: parseInt(roundItem.thisRound) - (thisIsSmallFinal ? 1:0)
|
||||
property var thisMatchData: thisMatchDataIsValid ? matchData:[]
|
||||
|
||||
property bool thisMatchDataIsValid: (matchData !== undefined && matchData !== null && typeof matchData === "object" && matchData.length > 0)
|
||||
property bool thisMatchIsOver: thisMatchDataIsValid && thisMatchData[0]['result_rank'+thisRound] !== undefined && thisMatchData[1]['result_rank'+thisRound] !== undefined
|
||||
|
||||
property bool thisIsFinal: roundItem.thisIsLastRound && thisIndex === rectRep.model - 2
|
||||
property bool thisIsSmallFinal: roundItem.thisIsLastRound && thisIndex === rectRep.model - 1
|
||||
|
||||
property int winnerIndex: thisMatchIsOver ? (parseInt(thisMatchData[0]['result_rank'+thisRound]) < parseInt(thisMatchData[1]['result_rank'+thisRound]) ? 0:1) : -1
|
||||
|
||||
height: !roundItem.thisIsLastRound ?
|
||||
(roundItem.height - roundNameLa.height) / rectRep.model - roundCol.spacing :
|
||||
(thisIsFinal ?
|
||||
(roundItem.height - roundNameLa.height) * 0.5 + roundItem.tileSize * 0.5 :
|
||||
(roundItem.height - roundNameLa.height) - (roundItem.height - roundNameLa.height) * 0.5 + roundItem.tileSize * 0.5
|
||||
)
|
||||
|
||||
height: (roundItem.height - roundNameLa.height) / rectRep.model - roundCol.spacing
|
||||
width: roundItem.width
|
||||
|
||||
onMatchDataChanged: {
|
||||
onThisDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
|
||||
|
@ -365,6 +179,7 @@ Item {
|
|||
|
||||
RectangularGlow {
|
||||
id: effect
|
||||
visible: matchRect.visible
|
||||
anchors.fill: matchRect
|
||||
glowRadius: 0
|
||||
spread: 0
|
||||
|
@ -381,10 +196,11 @@ Item {
|
|||
bottom: matchItm.thisIsFinal ? parent.bottom:undefined
|
||||
}
|
||||
|
||||
//anchors.verticalCenterOffset: matchItm.lowerPart ? 10:10
|
||||
visible: !matchItm.thisData.dummy
|
||||
|
||||
width: parent.width
|
||||
height: roundItem.tileSize
|
||||
//scale: 0.9
|
||||
|
||||
color: Material.dialogColor
|
||||
radius: height * 0.2
|
||||
|
||||
|
@ -399,6 +215,13 @@ Item {
|
|||
model: 2
|
||||
|
||||
delegate: RowLayout {
|
||||
id: laneRow
|
||||
|
||||
property var thisData: index === 0 ? matchItm.thisData.laneA : matchItm.thisData.laneB
|
||||
property var participant: thisData ? thisData.participant : undefined
|
||||
property var result: thisData ? thisData.result : undefined
|
||||
property var lane: index === 0 ? "A":"B"
|
||||
property bool isWinner: matchItm.thisData.winner === laneRow.lane
|
||||
|
||||
height: parent.height / 2 - parent.spacing
|
||||
width: parent.width
|
||||
|
@ -417,11 +240,11 @@ Item {
|
|||
font.bold: true
|
||||
opacity: 0.7
|
||||
|
||||
text: matchItm.thisMatchData[index] !== undefined ?
|
||||
text: laneRow.participant ?
|
||||
(
|
||||
parseInt(matchItm.thisMatchData[index]['result_rank0']) < 10 ?
|
||||
matchItm.thisMatchData[index]['result_rank0'] + " ":
|
||||
matchItm.thisMatchData[index]['result_rank0']
|
||||
laneRow.participant.results[0].rank < 10 ?
|
||||
laneRow.participant.results[0].rank + " ":
|
||||
laneRow.participant.results[0].rank
|
||||
):
|
||||
""
|
||||
}
|
||||
|
@ -436,21 +259,22 @@ Item {
|
|||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.pixelSize: height * 0.5
|
||||
font.bold: matchItm.winnerIndex === index
|
||||
font.bold: laneRow.isWinner
|
||||
elide: "ElideRight"
|
||||
|
||||
color: matchItm.winnerIndex === index ? Material.color(Material.Green):Material.primaryTextColor
|
||||
color: laneRow.isWinner ? Material.color(Material.Green):Material.primaryTextColor
|
||||
|
||||
text: matchItm.thisMatchData[index] !== undefined ? matchItm.thisMatchData[index]['firstname'] + " " + matchItm.thisMatchData[index]['lastname'] :"-"
|
||||
text: laneRow.participant ? laneRow.participant.firstName + " " + laneRow.participant.lastName :"-"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredHeight: parent.height * 0.8
|
||||
Layout.preferredWidth: parent.width * 0.13
|
||||
|
||||
visible: laneRow.participant && laneRow.participant.startNumber ? true:false
|
||||
radius: height / 2
|
||||
|
||||
border.width: 1
|
||||
border.width: parent.height * 0.03
|
||||
border.color: Material.frameColor
|
||||
color: "transparent"
|
||||
|
||||
|
@ -467,7 +291,7 @@ Item {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
|
||||
text: matchItm.thisMatchData[index] !== undefined ? matchItm.thisMatchData[index]["start_number"]:""
|
||||
text: laneRow.participant ? laneRow.participant.startNumber:""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,15 +309,11 @@ Item {
|
|||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignRight
|
||||
font.pixelSize: height * 0.5
|
||||
font.bold: matchItm.winnerIndex === index
|
||||
font.bold: laneRow.isWinner
|
||||
|
||||
color: matchItm.winnerIndex === index ? Material.color(Material.Green):Material.primaryTextColor
|
||||
color: laneRow.isWinner ? Material.color(Material.Green):Material.primaryTextColor
|
||||
|
||||
text: matchItm.thisMatchData[index] !== undefined && matchItm.thisMatchData[index]['result'+matchItm.thisRound] !== undefined ?
|
||||
( parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]) ?
|
||||
(parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]).toFixed(2))
|
||||
: matchItm.thisMatchData[index]['result'+matchItm.thisRound] )
|
||||
: "-"
|
||||
text: laneRow.result ? laneRow.result.result : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -516,7 +336,7 @@ Item {
|
|||
id: blueRockBadgeComponent
|
||||
|
||||
BlueRockBadge {
|
||||
width: roundItem.width
|
||||
width: roundItem.width * 0.8
|
||||
height: width * 0.25
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,18 +190,6 @@ Window {
|
|||
|
||||
Material.theme: appSettings.read("darkTheme") === "true" ? Material.Dark:Material.Light
|
||||
|
||||
Component.onCompleted: {
|
||||
//loadingDl.open()
|
||||
//app.openAthlete() // dorian: 53139 , rustam: 6933 , helen: 53300
|
||||
//openWidget({nation:'GER'})
|
||||
//mainStack.push("Pages/AthleteSearchPage.qml")
|
||||
//openWidget({comp: 11651, cat: 26})
|
||||
//openWidget({person: 6623})
|
||||
//console.log(JSON.stringify(serverConn.getParamsFromUrl("")))
|
||||
//openWidgetFromUrl("https://l.bluerock.dev/?comp=11501&cat=GER_M")
|
||||
//openWidgetFromUrl("https://www.digitalrock.de/egroupware/ranking/json.php?cat=12&comp=12171&type=")
|
||||
}
|
||||
|
||||
FontLoader {
|
||||
id: fa5solid
|
||||
source: "qrc:/fonts/fa5solid.otf"
|
||||
|
|
|
@ -31,5 +31,6 @@
|
|||
<file>Components/SharePopup.qml</file>
|
||||
<file>Pages/QrCodeScanPage.qml</file>
|
||||
<file>Components/MovingLabel.qml</file>
|
||||
<file>Components/SpeedFlowChart.js</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Loading…
Reference in a new issue