/* blueROCK - for digital rock Copyright (C) 2019 Dorian Zedler This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import QtQuick 2.10 import QtQuick.Controls 2.4 import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.1 import QtGraphicalEffects 1.0 import "SpeedFlowChart.js" as SpeedFlowChart Item { id: control property var flowchartData property var allFlowchartData property int rounds: 0 property int refreshes: 0 property int roundRefreshes: 1 onFlowchartDataChanged: { prepareData() } function prepareData() { if(!control.enabled || control.flowchartData === undefined || control.flowchartData['route_names'] === undefined) return 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 console.log(JSON.stringify(flowchartResult, null, 2)) } ListView { id: roundListView property int columnWidth: height * 0.4 property int columnHeight: height anchors { top: parent.top bottom: parent.bottom horizontalCenter: parent.horizontalCenter } width: Math.min((columnWidth + spacing) * model, control.width) spacing: app.height * 0.05 orientation: ListView.LeftToRight boundsBehavior: ListView.StopAtBounds model: control.allFlowchartData.rounds.length delegate: Item { id: roundItem property int thisIndex: index property var thisData: control.allFlowchartData.rounds[thisIndex] 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 width: roundListView.columnWidth height: roundListView.columnHeight Column { id: roundCol anchors.fill: parent Label { id: roundNameLa width: parent.width height: control.height * 0.05 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter fontSizeMode: Text.Fit font.pixelSize: height * 0.6 minimumPixelSize: 1 font.bold: true text: roundItem.thisData.roundName ? roundItem.thisData.roundName : "-" } Repeater { id: rectRep model: roundItem.thisData.pairs.length delegate: Item { id: matchItm property bool lowerPart: (index%2 > 0) property var thisData: roundItem.thisData.pairs[index] property int thisIndex: index height: (roundItem.height - roundNameLa.height) / rectRep.model - roundCol.spacing width: roundItem.width onThisDataChanged: { fadeInPa.start() } ParallelAnimation { id: fadeInPa NumberAnimation { target: matchItm; property: "opacity"; from: 0; to: 1.0; duration: 400 } NumberAnimation { target: matchItm; property: "scale"; from: 0.8; to: 1.0; duration: 400 } } Canvas { id: lineCanvas width: app.width; height: app.height contextType: "2d" visible: !roundItem.thisIsLastRound property int targetYFactor: matchItm.lowerPart ? -1:1 Path { id: firstPartPath startX: matchItm.width startY: matchItm.height * 0.5 PathQuad { id: firstPartPathQuad relativeX: roundListView.spacing * 0.5 relativeY: matchItm.height * 0.25 * lineCanvas.targetYFactor relativeControlX: relativeX relativeControlY: 0 } PathQuad { relativeX: roundListView.spacing * 0.5 relativeY: matchItm.height * 0.25 * lineCanvas.targetYFactor relativeControlX: 0 relativeControlY: relativeY } } onPaint: { context.strokeStyle = "lightgrey" context.lineWidth = matchRect.height * 0.05 context.path = firstPartPath; context.stroke(); } } RectangularGlow { id: effect visible: matchRect.visible anchors.fill: matchRect glowRadius: 0 spread: 0 opacity: 0.3 color: "black" cornerRadius: matchRect.radius } Rectangle { id: matchRect anchors { centerIn: !matchItm.thisIsFinal ? parent:undefined bottom: matchItm.thisIsFinal ? parent.bottom:undefined } visible: !matchItm.thisData.dummy width: parent.width height: roundItem.tileSize color: Material.dialogColor radius: height * 0.2 Column { spacing: 0 anchors.fill: parent anchors.margins: matchRect.radius * 0.5 Repeater { // for the two athletes 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 spacing: height * 0.1 Label { Layout.preferredHeight: parent.height Layout.preferredWidth: parent.width * 0.08 height: parent.height verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.pixelSize: height * 0.4 font.bold: true opacity: 0.7 text: laneRow.participant ? ( laneRow.participant.results[0].rank < 10 ? laneRow.participant.results[0].rank + " ": laneRow.participant.results[0].rank ): "" } Label { Layout.preferredHeight: parent.height Layout.maximumWidth: parent.width * 0.6 height: parent.height verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft font.pixelSize: height * 0.5 font.bold: laneRow.isWinner elide: "ElideRight" color: laneRow.isWinner ? Material.color(Material.Green):Material.primaryTextColor 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: parent.height * 0.03 border.color: Material.frameColor color: "transparent" Label { anchors.fill: parent padding: parent.parent.height * 0.1 leftPadding: padding * 2 rightPadding: leftPadding font.pixelSize: parent.height * 0.5 font.bold: true verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: laneRow.participant ? laneRow.participant.startNumber:"" } } Item { Layout.fillHeight: true Layout.fillWidth: true } Label { Layout.preferredHeight: parent.height Layout.preferredWidth: parent.width * 0.15 height: parent.height verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignRight font.pixelSize: height * 0.5 font.bold: laneRow.isWinner color: laneRow.isWinner ? Material.color(Material.Green):Material.primaryTextColor text: laneRow.result ? laneRow.result.result : "" } } } } } } } } Loader { id: blueRockBadgeLoader x: (parent.width - width) / 2 y: (parent.height - roundNameLa.height - height) / 2 + roundNameLa.height sourceComponent: roundItem.thisIsSemiFinal ? blueRockBadgeComponent:undefined Component { id: blueRockBadgeComponent BlueRockBadge { width: roundItem.width * 0.8 height: width * 0.25 } } } } } }