diff --git a/DigitalRockRanking.pro b/DigitalRockRanking.pro new file mode 100644 index 0000000..a5e1b48 --- /dev/null +++ b/DigitalRockRanking.pro @@ -0,0 +1,42 @@ +QT += quick qml quickcontrols2 +CONFIG += c++11 + +android { + QT += androidextras + ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources +} + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Refer to the documentation for the +# deprecated API to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + sources/main.cpp \ + sources/serverconn.cpp + +RESOURCES += resources/qml/qml.qrc \ + resources/shared/shared.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Additional import path used to resolve QML modules just for Qt Quick Designer +QML_DESIGNER_IMPORT_PATH = + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +HEADERS += \ + headers/serverconn.h + +DISTFILES += \ + android-sources/AndroidManifest.xml diff --git a/DigitalRockRanking.pro.user b/DigitalRockRanking.pro.user new file mode 100644 index 0000000..544d316 --- /dev/null +++ b/DigitalRockRanking.pro.user @@ -0,0 +1,635 @@ + + + + + + EnvironmentId + {73fd4d96-a4f7-426d-9695-506509aacee9} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Android for armeabi-v7a (Clang Qt 5.11.3 for Android ARMv7) + Android for armeabi-v7a (Clang Qt 5.11.3 for Android ARMv7) + {0c845c7b-f333-4cf9-be32-0bca6d080fce} + 0 + 0 + 0 + + /home/dorian/builds/build-DigitalRockRanking-Android_for_armeabi_v7a_Clang_Qt_5_11_3_for_Android_ARMv7-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + + true + Copy application data + + Qt4ProjectManager.AndroidPackageInstallationStep + + + android-28 + + true + Build Android APK + + QmakeProjectManager.AndroidBuildApkStep + false + false + + 4 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/dorian/builds/build-DigitalRockRanking-Android_for_armeabi_v7a_Clang_Qt_5_11_3_for_Android_ARMv7-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + true + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + + true + Copy application data + + Qt4ProjectManager.AndroidPackageInstallationStep + + + android-28 + + true + Build Android APK + + QmakeProjectManager.AndroidBuildApkStep + false + false + + 4 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /home/dorian/builds/build-DigitalRockRanking-Android_for_armeabi_v7a_Clang_Qt_5_11_3_for_Android_ARMv7-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + true + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + + true + Copy application data + + Qt4ProjectManager.AndroidPackageInstallationStep + + + android-28 + + true + Build Android APK + + QmakeProjectManager.AndroidBuildApkStep + false + false + + 4 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + + true + Deploy to Android device + + Qt4ProjectManager.AndroidDeployQtStep + false + + 1 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy to Android device + + Qt4ProjectManager.AndroidDeployConfiguration2 + + 1 + + MWS0216A15001488 + 24 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + + + 0 + + DigitalRockRanking + DigitalRockRanking + Qt4ProjectManager.AndroidRunConfiguration:/home/dorian/DigitalRockRanking/DigitalRockRanking.pro + + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.Target.1 + + Desktop Qt 5.11.3 GCC 64bit + Desktop Qt 5.11.3 GCC 64bit + qt.qt5.5113.gcc_64_kit + 0 + 0 + 0 + + /home/dorian/builds/build-DigitalRockRanking-Desktop_Qt_5_11_3_GCC_64bit-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/dorian/builds/build-DigitalRockRanking-Desktop_Qt_5_11_3_GCC_64bit-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + true + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /home/dorian/builds/build-DigitalRockRanking-Desktop_Qt_5_11_3_GCC_64bit-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + true + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy Configuration + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + DigitalRockRanking + + Qt4ProjectManager.Qt4RunConfiguration:/home/dorian/DigitalRockRanking/DigitalRockRanking.pro + DigitalRockRanking.pro + + 3768 + false + true + true + false + false + true + + /home/dorian/builds/build-DigitalRockRanking-Desktop_Qt_5_11_3_GCC_64bit-Debug + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 20 + + + Version + 20 + + diff --git a/Questions.odt b/Questions.odt new file mode 100644 index 0000000..b4782dd Binary files /dev/null and b/Questions.odt differ diff --git a/android-sources/AndroidManifest.xml b/android-sources/AndroidManifest.xml new file mode 100644 index 0000000..a627afb --- /dev/null +++ b/android-sources/AndroidManifest.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-sources/libs/armeabi-v7a/libcrypto.so b/android-sources/libs/armeabi-v7a/libcrypto.so new file mode 100644 index 0000000..4448d85 Binary files /dev/null and b/android-sources/libs/armeabi-v7a/libcrypto.so differ diff --git a/android-sources/libs/armeabi-v7a/libssl.so b/android-sources/libs/armeabi-v7a/libssl.so new file mode 100644 index 0000000..e8ef374 Binary files /dev/null and b/android-sources/libs/armeabi-v7a/libssl.so differ diff --git a/android-sources/libs/x86/libcrypto.so b/android-sources/libs/x86/libcrypto.so new file mode 100644 index 0000000..a2e46cd Binary files /dev/null and b/android-sources/libs/x86/libcrypto.so differ diff --git a/android-sources/libs/x86/libssl.so b/android-sources/libs/x86/libssl.so new file mode 100644 index 0000000..3f3032a Binary files /dev/null and b/android-sources/libs/x86/libssl.so differ diff --git a/android-sources/res/drawable-hdpi/icon.png b/android-sources/res/drawable-hdpi/icon.png new file mode 100644 index 0000000..15f210f Binary files /dev/null and b/android-sources/res/drawable-hdpi/icon.png differ diff --git a/android-sources/res/drawable-ldpi/icon.png b/android-sources/res/drawable-ldpi/icon.png new file mode 100644 index 0000000..15f210f Binary files /dev/null and b/android-sources/res/drawable-ldpi/icon.png differ diff --git a/android-sources/res/drawable-mdpi/icon.png b/android-sources/res/drawable-mdpi/icon.png new file mode 100644 index 0000000..15f210f Binary files /dev/null and b/android-sources/res/drawable-mdpi/icon.png differ diff --git a/headers/serverconn.h b/headers/serverconn.h new file mode 100644 index 0000000..c0ed1c2 --- /dev/null +++ b/headers/serverconn.h @@ -0,0 +1,36 @@ +#ifndef SERVERCONN_H +#define SERVERCONN_H + +#include +#include +#include +#include +#include + +class ServerConn : public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariant foodplan READ getFoodplan NOTIFY foodplanChanged) +public: + explicit ServerConn(QObject *parent = nullptr); + +private: + QVariantMap senddata(QUrl serviceUrl, QUrlQuery pdata = QUrlQuery()); + + // variables + QVariant foodplan; + +signals: + void foodplanChanged(); + +public slots: + void refreshFoodplan(); + + QVariant getCalendar(QString nation); + QVariant getRanking(int competitionId, int categoryId, bool registrationData = false, const int routeNumber = -2); + + // functions for qml + QVariant getFoodplan(); +}; + +#endif // SERVERCONN_H diff --git a/resources/qml/Components/AppToolBar.qml b/resources/qml/Components/AppToolBar.qml new file mode 100644 index 0000000..4aeab97 --- /dev/null +++ b/resources/qml/Components/AppToolBar.qml @@ -0,0 +1,94 @@ +import QtQuick 2.6 +import QtQuick.Controls 2.1 +import QtGraphicalEffects 1.0 +import QtQuick.Controls.Material 2.3 + +Item { + id: control + height: 50 + property bool showErrorBar: true + + RectangularGlow { + id: toolBarEffect + glowRadius: 3 + spread: 0.2 + color: "black" + opacity: 0.3 + anchors.fill: toolBar + } + + Rectangle { + id: toolBar + color: "white" + anchors.fill: parent + + +// anchors { +// top: parent.top +// left: parent.left +// right: parent.right +// topMargin: -60 +// } + + Rectangle { + id: errorField + width: parent.width + height: 30 + enabled: app.is_error & app.state !== "notLoggedIn" & control.showErrorBar + anchors.top: parent.bottom + + color: "red" + onEnabledChanged: { + if(enabled){ + toolBar.state = 'moveIn' + } + else { + toolBar.state = 'moveOut' + } + } + + MouseArea { anchors.fill: parent; onClicked: { + toolBar.state = 'moveOut' + + console.log("clicked") + } + } + + Text { + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + id: errorText + font.family: "Helvetica" + color: "White" + font.pointSize: 8 + visible: parent.height !== 0 + text: "" + } + } + + states: [ + State { + name: "moveOut" + PropertyChanges { target: errorField; height: 0 } + }, + State { + name: "moveIn" + PropertyChanges { target: errorField; height: 30 } + } + ] + + transitions: [ + Transition { + to: "moveOut" + NumberAnimation { properties: "height"; easing.type: Easing.InOutQuad; duration: 200 } + }, + Transition { + to: "moveIn" + NumberAnimation { properties: "height"; easing.type: Easing.InOutQuad; duration: 200 } + } + ] + } +} diff --git a/resources/qml/Components/DataListView.qml b/resources/qml/Components/DataListView.qml new file mode 100644 index 0000000..0e9ee28 --- /dev/null +++ b/resources/qml/Components/DataListView.qml @@ -0,0 +1,50 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.4 + +ListView { + id: control + + property int status: -1 + + signal refresh() + + anchors.margins: 10 + anchors.rightMargin: 14 + + ScrollBar.vertical: ScrollBar { + parent: control.parent + + anchors { + top: control.top + left: control.right + margins: 10 + leftMargin: 3 + bottom: control.bottom + } + + width: 8 + + active: true + } + + onContentYChanged: { + if(contentY < -125){ + control.refresh() + } + } + + InfoArea { + id: infoArea + + anchors { + left: control.left + right: control.right + top: control.top + margins: app.landscape() ? control.width * 0.4:control.width * 0.3 + topMargin: control.height*( status === 901 ? 0.6:0.5) - height * 0.8 + } + + excludedCodes: [200, 902] + errorCode: control.status + } +} diff --git a/resources/qml/Components/FancyBusyIndicator.qml b/resources/qml/Components/FancyBusyIndicator.qml new file mode 100644 index 0000000..32d8421 --- /dev/null +++ b/resources/qml/Components/FancyBusyIndicator.qml @@ -0,0 +1,95 @@ +import QtQuick 2.3 +import QtQuick.Controls 2.4 +import QtQuick.Controls.Styles 1.2 + +BusyIndicator { + id: control + + property double animationSpeed: 0.5 + + contentItem: Item { + implicitWidth: 64 + implicitHeight: 64 + + Item { + id: item + + x: parent.width / 2 - 32 + y: parent.height / 2 - 32 + + width: 64 + height: 64 + + opacity: control.running ? 1 : 0 + + property int currentHeight: 0 + + onCurrentHeightChanged: { + } + + Behavior on opacity { + OpacityAnimator { + duration: 250 + } + } + + SequentialAnimation { + loops: Animation.Infinite + + running: true + + NumberAnimation { + target: item + + duration: 2000 * 1/control.animationSpeed + + to: 1000 + + properties: "currentHeight" + + easing.type: Easing.InOutQuad + + } + + NumberAnimation { + target: item + + duration: 2000 * 1/control.animationSpeed + + to: 0 + + properties: "currentHeight" + + easing.type: Easing.InOutQuad + + } + } + + Row { + + anchors.fill: parent + + spacing: item.width / 9 + + Repeater { + id: repeater + model: 5 + + Rectangle { + + property double heightMultiplier: Math.abs( Math.sin(( (item.currentHeight + (index*20))*0.01) * (Math.PI/2) ) ) + + anchors.verticalCenter: parent.verticalCenter + + width: item.width / 9 + height: ( heightMultiplier ) * ( item.height - 1 ) + 1 + + radius: width * 0.5 + + color: "#21be2b" + } + } + } + } + } +} diff --git a/resources/qml/Components/FancyButton.qml b/resources/qml/Components/FancyButton.qml new file mode 100644 index 0000000..2ec7623 --- /dev/null +++ b/resources/qml/Components/FancyButton.qml @@ -0,0 +1,88 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.4 +import QtGraphicalEffects 1.0 + +Button { + id: control + + property string image + property color backgroundColor: "white" + property color textColor: "black" + property real imageScale: 1 + property double glowRadius: 0.001 + property double glowSpread: 0.2 + property bool glowVisible: true + property double glowScale: 0.75 + property double glowOpacity: 1 + + scale: control.pressed ? 0.8:1 + + Behavior on scale { + PropertyAnimation { + duration: 100 + } + } + + Behavior on backgroundColor { + ColorAnimation { + duration: 200 + } + } + + contentItem: Text { + visible: false + } + + Text { + id: conetntText + text: qsTr(control.text) + anchors.centerIn: parent + font: parent.font + color: control.textColor + opacity: control.enabled ? 1:0.4 + } + + background: Item { + id: controlBackgroundContainer + + RectangularGlow { + id: effect + glowRadius: control.glowRadius + spread: control.glowSpread + color: "black" + + visible: control.glowVisible + + cornerRadius: controlBackground.radius + anchors.fill: controlBackground + scale: control.glowScale + opacity: control.glowOpacity + } + + Rectangle { + id: controlBackground + + anchors.fill: parent + + radius: height * 0.5 + + color: control.backgroundColor + + Image { + id: buttonIcon + source: control.image + + anchors.centerIn: parent + height: parent.height * 0.5 + width: height + + mipmap: true + + fillMode: Image.PreserveAspectFit + + scale: control.imageScale + } + } + } + +} diff --git a/resources/qml/Components/InfoArea.qml b/resources/qml/Components/InfoArea.qml new file mode 100644 index 0000000..6f4e646 --- /dev/null +++ b/resources/qml/Components/InfoArea.qml @@ -0,0 +1,98 @@ +/* + Fannyapp - Application to view the cover plan of the Fanny-Leicht-Gymnasium ins Stuttgart Vaihingen, Germany + Copyright (C) 2019 Itsblue Development + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ + +import QtQuick 2.9 +import QtQuick.Controls 2.4 + +Item { + id: infoArea + + property int alertLevel: app.getErrorInfo(infoArea.errorCode)[0] + // 0 - ok + // 1 - info + // 2 - error + property int errorCode: -1 + property var excludedCodes: [] + + visible: !(excludedCodes.indexOf(errorCode) >= 0) + + height: childrenRect.height + + Rectangle { + + radius: height * 0.5 + width: parent.width + height: width + + color: "transparent" + border.width: 5 + border.color: infoArea.alertLevel > 0 ? infoArea.alertLevel > 1 ? "red":"grey" : "green" + + opacity: infoArea.errorCode !== 200 && infoArea.errorCode !== (-1) ? 1:0 + + Behavior on opacity { + NumberAnimation { + duration: 500 + } + } + + Label { + anchors.centerIn: parent + font.pixelSize: parent.height * 0.8 + text: infoArea.alertLevel > 1 ? "!":"i" + color: infoArea.alertLevel > 0 ? infoArea.alertLevel > 1 ? "red":"grey" : "green" + } + + Label { + id: errorShortDescription + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.bottom + margins: parent.height * 0.1 + } + + width: app.width * 0.8 + + wrapMode: Label.Wrap + + horizontalAlignment: Label.AlignHCenter + + font.pixelSize: errorLongDescription.font.pixelSize * 1.8 + text: app.getErrorInfo(infoArea.errorCode)[1] + } + + Label { + id: errorLongDescription + anchors { + horizontalCenter: parent.horizontalCenter + top: errorShortDescription.bottom + margins: parent.height * 0.1 + } + + width: app.width * 0.8 + + wrapMode: Label.Wrap + + horizontalAlignment: Label.AlignHCenter + + text: app.getErrorInfo(infoArea.errorCode)[2] + } + } + +} + diff --git a/resources/qml/Components/RankingView.qml b/resources/qml/Components/RankingView.qml new file mode 100644 index 0000000..d0af5ce --- /dev/null +++ b/resources/qml/Components/RankingView.qml @@ -0,0 +1,274 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 + +DataListView { + id: control + + property var listData: ({}) + + onListDataChanged: { + model = listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length + } + + model: listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length + + delegate: ItemDelegate { + id: partDel + + property int ind: index + + width: parent.width + height: 70 + + text: "" + + Rectangle { + anchors.fill: parent + + width: partDel.width + + color: partDel.ind % 2 == 0 ? "white":"lightgrey" + + opacity: 0.2 + } + + Column { + id: partDelCol + + anchors.fill: parent + anchors.margins: 5 + + Row { + id: partDelFirstRow + + width: parent.width + height: parent.height - partDelSecondRow.height + + Label { + height: parent.height + width: parent.width * 0.1 + + fontSizeMode: Text.Fit + font.bold: true + font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.6:height * 0.4 ) + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: listData[ "participants" ][index]["result_rank"] + } + + Label { + height: parent.height + width: parent.width * 0.5 + + fontSizeMode: Text.Fit + font.bold: true + font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.6:height * 0.4 ) + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + + text: listData[ "participants" ][index]["firstname"] + " " + listData[ "participants" ][index]["lastname"] + } + + Label { + height: parent.height + width: parent.width * 0.4 + + fontSizeMode: Text.Fit + font.bold: false + font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.4:height * 0.3 ) + minimumPixelSize: 0 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: "(" + (listData[ "display_athlete" ] === "nation" ? listData[ "participants" ][index]["nation"] : listData[ "participants" ][index]["federation"]) + ")" + + onLinkActivated: { + Qt.openUrlExternally(link) + } + } + } + + Row { + id: partDelSecondRow + + width: parent.width + height: multiResRow.enabled || multiGenResRow.enabled || resultLa.enabled ? parent.height / 2:0 + + Row { + id: multiResRow + + height: parent.height + width: enabled ? parent.width * 0.75:0 + + enabled: parseInt(listData[ "route_order" ]) > -1 && boulderResRep.model > 0 + + Repeater { + id: boulderResRep + + model: parseInt(listData[ "route_num_problems" ]) + + delegate: Item { + id: boulderResItm + + anchors.verticalCenter: parent.verticalCenter + + width: parent.width / ( boulderResRep.model ) + height: parent.height + + Rectangle { + anchors { + left: parent.left + } + + width: 1 + height: parent.height + + visible: index === 0 + + color: "grey" + } + + Rectangle { + anchors { + right: parent.right + } + + width: 1 + height: parent.height + + color: "grey" + } + + Label { + anchors.centerIn: parent + + height: parent.height + width: parent.width * 0.9 + + fontSizeMode: Text.Fit + font.pixelSize: Math.abs( height * 0.6 ) + minimumPixelSize: 0 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: listData[ "participants" ][partDel.ind]["boulder"+(index+1)] === undefined ? "":listData[ "participants" ][partDel.ind]["boulder"+(index+1)] + } + + } + + } + + } + + Row { + id: multiGenResRow + + height: parent.height + width: enabled ? parent.width - resultLa.width:0 + + enabled: ((parseInt(listData[ "route_order" ]) === -1) && (generalResRep.model > 0)) ? true:false + + Repeater { + id: generalResRep + + property var routes: getRoutes() + model: routes.length + + function getRoutes() { + + var obj = listData["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: boulderGenResLa.text != "" + + Rectangle { + + anchors { + left: parent.left + } + + width: 1 + height: parent.height + + visible: index === 0 + + color: "grey" + } + + Rectangle { + anchors { + right: parent.right + } + + width: 1 + height: parent.height + + color: "grey" + } + + 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: 0 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: listData[ "participants" ][partDel.ind]["result"+(generalResRep.routes[index][0])] === undefined ? "":listData[ "participants" ][partDel.ind]["result"+(generalResRep.routes[index][0])] + } + + } + + } + } + + Label { + id: resultLa + + width: enabled ? parent.width * 0.25:0 + height: enabled ? parent.height:0 + + enabled: ( boulderResRep.model > 0 || listData["discipline"] !== "boulder" ) && parseInt(listData[ "route_order" ]) > -1 + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + fontSizeMode: Text.Fit + font.pixelSize: Math.abs( height * 0.6 ) + minimumPixelSize: 0 + + text: listData[ "participants" ][partDel.ind]["result"] === undefined ? "":listData[ "participants" ][partDel.ind]["result"] + } + } + } + } +} diff --git a/resources/qml/Components/RegistrationView.qml b/resources/qml/Components/RegistrationView.qml new file mode 100644 index 0000000..b2aab09 --- /dev/null +++ b/resources/qml/Components/RegistrationView.qml @@ -0,0 +1,45 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 + +DataListView { + id: control + + property var listData: ({}) + + model: listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length + + delegate: ItemDelegate { + id: partDel + + width: parent.width + + text: control.getText(index) + } + + function getText(index){ + + // ---------------------------- + // if we have registration data + + var fedName // federation name + + if(listData["federations"] !== undefined){ + // not an international competition -> get name of federation + + for(var i = 0; i < listData["federations"].length; i ++ ){ + //console.log("checking " + i + ": cat: " + parseInt(listData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) + if(listData["federations"][i]["fed_id"] === listData[ root.listKey ][index]["reg_fed_id"]){ + fedName = listData["federations"][i]["shortcut"] + } + } + } + else { + // an international competition -> get nation + + fedName = listData[ root.listKey ][index]["nation"] + } + + return listData[ "athletes" ][index]["firstname"] + " " + listData[ "athletes" ][index]["lastname"] + " (" + fedName + ")" + } + +} diff --git a/resources/qml/Pages/CompetitionCalendarPage.qml b/resources/qml/Pages/CompetitionCalendarPage.qml new file mode 100644 index 0000000..b761d14 --- /dev/null +++ b/resources/qml/Pages/CompetitionCalendarPage.qml @@ -0,0 +1,183 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import QtQuick.Controls.Material 2.3 + +import "../Components" + +Page { + id: root + + title: "calendar" + + property string nation: "" + property int status: -1 + + Component.onCompleted: { + var ret = serverConn.getCalendar(nation) + + if(ret["status"] === 200){ + root.status = 200 + calendarList.listData = ret["data"]["competitions"] + } + else { + root.status = ret["status"] + calendarList.listData = {} + } + } + + InfoArea { + id: infoArea + + anchors { + left: parent.left + right: parent.right + top: parent.top + margins: app.landscape() ? parent.width * 0.4:parent.width * 0.3 + topMargin: parent.height*( status === 901 ? 0.6:0.5) - height * 0.8 + } + + excludedCodes: [200, 902] + errorCode: root.status + } + + ListView { + id: calendarList + + property var listData + + anchors.fill: parent + + boundsBehavior: Flickable.StopAtBounds + + model: listData.length + + delegate: ItemDelegate { + id: competitionDel + + property string name: calendarList.listData[index]["name"] + property string date: calendarList.listData[index]["date_span"] + property var cats: calendarList.listData[index]["cats"] + property int catId: calendarList.listData[index]["cat_id"] + + width: parent.width + height: compDelCol.height + 10 + + onClicked: { + catSelectPu.appear(index) + } + + Rectangle { + id: delBackroundRect + + anchors.fill: parent + + opacity: 0.5 + + color: app.competitionCategoryColors[catId] + + } + + Column { + id: compDelCol + + anchors.centerIn: parent + + width: parent.width * 0.97 + + spacing: 10 + + Label { + id: nameLa + + width: parent.width + + font.bold: true + + wrapMode: Text.WordWrap + + text: name + } + + Label { + id: dateLa + + color: "grey" + + text: date + } + + Label { + id: catIdLa + + color: "grey" + + text: catId + } + } + + Rectangle { + id: bottomLineRa + + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + + height: 1 + + color: "lightgrey" + + } + } + } + + Dialog { + id: catSelectPu + + property int index: -1 + property var catObj: calendarList.listData[catSelectPu.index] !== undefined ? calendarList.listData[catSelectPu.index]["cats"]:undefined + + x: root.width / 2 - width / 2 + y: root.height / 2 - height / 2 + + width: root.width * 0.8 + height: root.height * 0.6 + + modal: true + focus: true + + title: qsTr("select category") + + function appear(index) { + catSelectPu.open() + catSelectPu.index = index + } + + contentItem: ListView { + id: catsLv + + width: parent.width + height: root.height * 0.6 + + model: catSelectPu.catObj !== undefined ? catSelectPu.catObj.length:0 + + delegate: Button { + id: catBt + + width: parent.width + + flat: true + + text: catSelectPu.catObj[index]["name"] + + onClicked: { + catSelectPu.close() + app.openResults(calendarList.listData[catSelectPu.index]["WetId"], catSelectPu.catObj[index]["GrpId"], (catSelectPu.catObj[index]["status"] === 4 || catSelectPu.catObj[index]["status"] === undefined)) + } + } + } + + } + +} diff --git a/resources/qml/Pages/RankingPage.qml b/resources/qml/Pages/RankingPage.qml new file mode 100644 index 0000000..ebeb810 --- /dev/null +++ b/resources/qml/Pages/RankingPage.qml @@ -0,0 +1,236 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import QtGraphicalEffects 1.0 + +import "../Components" + +Page { + id: root + + title: root.rankingData[compNameKey] + property string subTitle: getSubtitle() + property bool titleIsPageTitle: true + + property int status: -1 + + property bool debug: true + + property int comId: -1 + property int catId: -1 + property int routeNumber: -2 + property bool reg: false + + property var rankingData + + property string listKey: root.reg ? "athletes":"participants" + property string compNameKey: root.reg ? "name":"comp_name" + + Component.onCompleted: { + root.loadData(root.comId, root.catId, root.reg, root.routeNumber) + } + + function loadData(comp, cat, reg, route){ + loadingDl.open() + console.log("[info][QML] getting ranking data of comp: " + comp + " and cat: " + cat + " reg: " + reg) + var ret = serverConn.getRanking(comp, cat, reg, route) + + root.status = ret["status"] + + if(parseInt(ret["status"]) === 200){ + // request was successfull -> prepare data + if(root.reg){ + // if the data i sregistration data, athletes of other cats need to be removed + + var validAthletes = [] + + for(var i = 0; i < ret["data"]["athletes"].length; i++){ + if(parseInt(ret["data"]["athletes"][i]["cat"]) === cat){ + //console.log("found matching athlete at " + i) + validAthletes.push(ret["data"]["athletes"][i]) + } + } + ret["data"]["athletes"] = validAthletes + + root.rankingData = ret["data"] + } + else { + root.rankingData = ret["data"] + root.routeNumber = root.rankingData["route_order"] === undefined ? -2:root.rankingData["route_order"] + } + } + else { + root.rankingData = {} + } + + + if(ret["data"][ root.listKey ] === undefined || ret["data"][ root.listKey ].length < 1){ + root.status = 901 + } + + console.log("done! status: " + root.status) + loadingDl.close() + } + + function getSubtitle() { + var titleString + + //console.log("getting title, reg: " + root.reg) + + if(reg){ + for(var i = 0; i < root.rankingData["categorys"].length; i ++ ){ + //console.log("checking " + i + ": cat: " + parseInt(root.rankingData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) + if(parseInt(root.rankingData["categorys"][i]["GrpId"]) === root.catId){ + titleString = root.rankingData["categorys"][i]["name"] + } + } + } + else { + titleString = root.rankingData["route_name"] + } + + return titleString + + } + + Item { + id: regItm + // item for registration view + + anchors.fill: parent + + visible: root.reg + + RegistrationView { + id: regViewRv + + anchors.fill: parent + + status: root.status + + listData: root.reg ? root.rankingData:({}) + + } + } + + Item { + id: rankItm + // item for ranking data + + anchors.fill: parent + + visible: !root.reg + + RankingView { + id: rankViewRv + + anchors { + left: parent.left + right: parent.right + top: parent.top + bottom: routeSelectTb.top + } + + height: root.height - routeSelectTb.height + + status: root.status + + listData: root.reg ? ({}):root.rankingData + + onListDataChanged: { + console.log("list data changed") + } + } + + RectangularGlow { + id: toolBarEffect + glowRadius: 3 + spread: 0.2 + color: "black" + opacity: 0.3 + anchors.fill: routeSelectTb + } + + TabBar { + id: routeSelectTb + + property var tabs: getTabs() + property var tabIndexes: [] + + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + + height: tabs.length > 0 ? 50:0 + + position: TabBar.Footer + + Component.onCompleted: { + //currentIndex = getIndex(root.routeNumber) + setCurrentIndex(getIndex(root.routeNumber)) + } + + function getTabs() { + + var obj = root.rankingData["route_names"] + var buttonData = [] + + for(var prop in obj) { + // go through the whole array and search for data keys + if (obj.hasOwnProperty(prop)) { + buttonData.push([prop, obj[prop]]) + console.log("found " + obj[prop] + " at index " + prop) + } + } + + buttonData.sort(function(a, b) { + return a[0] - b[0]; + }); + + return buttonData + } + + function getIndex(routeNumber) { + console.log("getting index for route number: " + routeNumber) + + for(var i = 0; i < tabs.length; i++){ + //console.log(tabs[i]) + if(parseInt(tabs[i][0]) === routeNumber){ + console.log("found index: " + i) + return i + } + } + + + return 0 + } + + Repeater { + id: routeSelectButtonRep + + model: routeSelectTb.tabs.length + + onModelChanged: { + routeSelectTb.setCurrentIndex(routeSelectTb.getIndex(root.routeNumber)) + } + + delegate: TabButton { + text: routeSelectTb.tabs[index][1] + + width: Math.max(150, routeSelectTb.width / routeSelectButtonRep.model) //text.length * font.pixelSize + + + + onClicked: { + console.log("changing to index: " + index + " (" + routeSelectTb.tabs[index][0] + ", " + routeSelectTb.tabs[index][1] + ")") + if(root.routeNumber !== routeSelectTb.tabs[index][0]){ + root.routeNumber = routeSelectTb.tabs[index][0] + root.loadData(root.comId, root.catId, root.reg, root.routeNumber) + } + } + } + } + } + } +} diff --git a/resources/qml/Pages/StartPage.qml b/resources/qml/Pages/StartPage.qml new file mode 100644 index 0000000..059c5de --- /dev/null +++ b/resources/qml/Pages/StartPage.qml @@ -0,0 +1,67 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 + +import "../Components" + +Page { + id: root + + title: "start" + + Grid { + id: menuGr + + anchors.centerIn: parent + + rows: app.landscape() ? 1:3 + columns: app.landscape() ? 3:1 + + spacing: app.landscape() ? parent.height * 0.1:parent.width * 0.1 + + property int buttonSize: app.landscape() ? parent.width * 0.2:parent.height * 0.2 + + FancyButton { + id: ifscBt + + height: menuGr.buttonSize + width: height + + image: "qrc:/icons/ifsc.png" + + onClicked: { + app.openCalendar("") + } + + } + + FancyButton { + id: davBt + + height: menuGr.buttonSize + width: height + + image: "qrc:/icons/dav.png" + + onClicked: { + app.openCalendar("GER") + } + + } + + FancyButton { + id: sacBt + + height: menuGr.buttonSize + width: height + + image: "qrc:/icons/sac.png" + + onClicked: { + app.openCalendar("SUI") + } + + } + + } + +} diff --git a/resources/qml/main.qml b/resources/qml/main.qml new file mode 100644 index 0000000..bafbf1f --- /dev/null +++ b/resources/qml/main.qml @@ -0,0 +1,351 @@ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.4 + +import com.itsblue.digitalRockRanking 1.0 + +import "./Pages" +import "./Components" + +Window { + visible: true + width: 540 + height: 960 + title: qsTr("Digital Rock Ranking") + + Page { + id: app + + property var competitionCategoryColors: { + "61": "lightgrey", + "58": "lightgreen", + + "69": "#B8C8FF", + "70": "#F0F0F0", + "71": "#D8E8FF", + "256": "#D8E8FF" + } + + anchors.fill: parent + + Shortcut { + sequences: ["Esc", "Back"] + enabled: mainStack.depth > 1 + onActivated: { + if(!mainStack.currentItem.locked){ + mainStack.pop() + } + } + } + + ServerConn { + id: serverConn + + Component.onCompleted: { + //serverConn.refreshFoodplan() + } + } + + StackView { + id: mainStack + + anchors { + top: toolBar.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + + initialItem: startPgComp + + Component { + id: startPgComp + StartPage {} + } + + popEnter: Transition { + XAnimator { + from: (mainStack.mirrored ? -1 : 1) * -mainStack.width + to: 0 + duration: 500 + easing.type: Easing.OutCubic + } + } + + popExit: Transition { + XAnimator { + from: 0 + to: (mainStack.mirrored ? -1 : 1) * mainStack.width + duration: 500 + easing.type: Easing.OutCubic + } + } + + pushEnter: Transition { + XAnimator { + from: (mainStack.mirrored ? -1 : 1) * mainStack.width + to: 0 + duration: 500 + easing.type: Easing.OutCubic + } + } + + pushExit: Transition { + XAnimator { + from: 0 + to: (mainStack.mirrored ? -1 : 1) * -mainStack.width + duration: 500 + easing.type: Easing.OutCubic + } + } + } + + AppToolBar { + id: toolBar + + anchors { + top: parent.top + left: parent.left + right: parent.right + topMargin: -60 + } + + height: 50 + + Button { + id:toolButton + enabled: true + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + leftMargin: parent.width *0.02 + } + height: parent.height - parent.height * 0.5 + width: height + + onClicked: { + if(!mainStack.currentItem.locked){ + mainStack.pop() + } + } + + onPressed: toolButton.scale = 0.9 + onReleased: toolButton.scale = 1.0 + + background: Image { + source: "qrc:/icons/backDark.png" + height: parent.height + width: parent.width + fillMode: Image.PreserveAspectFit + Behavior on scale { + PropertyAnimation { + duration: 100 + } + } + } + } + + Label { + id: toolBarTitleLa + + + anchors { + verticalCenter: parent.verticalCenter + verticalCenterOffset: -toolBarSubTitleLa.anchors.verticalCenterOffset + left: toolButton.right + leftMargin: parent.width * 0.02 + right: parent.right + } + + elide: "ElideRight" + + font.bold: true + + color: "black" + + text: getText() + + function getText(){ + var titleString = ""; + + if(!mainStack.currentItem.titleIsPageTitle){ + for(var i=1; i 1){ + titleString += " > " + } + + titleString += mainStack.get(i).title + } + } + else { + titleString = mainStack.currentItem.title + } + + return(titleString) + } + } + + Label { + id: toolBarSubTitleLa + + anchors { + verticalCenter: parent.verticalCenter + verticalCenterOffset: toolBarSubTitleLa.text !== "" ? height/2:0 + left: toolButton.right + leftMargin: parent.width * 0.02 + right: parent.right + } + + elide: "ElideRight" + + font.bold: false + + color: "black" + + text: getText() + + function getText(){ + var titleString = ""; + + if(mainStack.currentItem.subTitle !== undefined){ + titleString = mainStack.currentItem.subTitle + } + + return(titleString) + } + } + + Behavior on anchors.topMargin { + NumberAnimation { + duration: 500 + easing.type: Easing.OutCubic + } + } + + states: [ + State { + name: "closed" + when: mainStack.depth === 1 + PropertyChanges { + target: toolBar + anchors.topMargin: -60 + } + }, + State { + name: "open" + when: mainStack.depth > 1 + PropertyChanges { + target: toolBar + anchors.topMargin: 0 + } + } + ] + } + + Dialog { + id: loadingDl + + x: ( app.width - width ) / 2 + y: ( app.height - height ) / 2 + + modal: true + closePolicy: Dialog.NoAutoClose + + contentItem: Column { + FancyBusyIndicator { + running: true + } + + Label { + + anchors.horizontalCenter: parent.horizontalCenter + + font.bold: true + + text: "loading..." + } + } + + } + + function landscape(){ + return app.height < app.width + } + + function openCalendar(nation){ + loadingDl.open() + mainStack.push(Qt.createComponent("qrc:/Pages/CompetitionCalendarPage.qml").createObject(null, {"nation": nation})) + loadingDl.close() + } + + function openResults(comp, cat, reg){ + // comp: (int) competiotion ID + // cat: (int) category ID + // reg: (bool) false: results; true: registrations + + //loadingDl.open() + mainStack.push(Qt.createComponent("qrc:/Pages/RankingPage.qml").createObject(null, {"comId": comp, "catId": cat, "reg": reg})) + //loadingDl.close() + } + + function getErrorInfo(errorCode) { + + var infoLevel + // 0 - ok + // 1 - info + // 2 - error + + var errorString + var errorDescription + + switch(errorCode) { + case 0: + infoLevel = 2 + errorString = "No connection to server" + errorDescription = "Please check your internet connection and try again." + break + case 401: + infoLevel = 2 + errorString = "Authentication required" + errorDescription = "The server asked for user credentinals, please chack them and try again" + break + case 500: + infoLevel = 2 + errorString = "Internal server error" + errorDescription = "The server was unable to process this request, this is probaply the servers vault. Please try again later." + break + case 900: + infoLevel = 2 + errorString = "Internal processing error" + errorDescription = "The server has sent some data that could ot be processed. Please try again later" + break + case 901: + infoLevel = 1 + errorString = "No Data" + errorDescription = "There is currently no data available. Please try again later." + break + case 902: + infoLevel = 1 + errorString = "Alte Daten" + errorDescription = "Es konnte keine Verbindung zum Server hergestellt werden, aber es sind noch alte Daten gespeichert." + break + case 903: + infoLevel = 1 + errorString = "Ungültiger Aufruf" + errorDescription = "Die aufgerufene Funktion ist momentan nicht verfügbar, bitte versuche es später erneut." + break + case 904: + infoLevel = 2 + errorString = "Incompatible API" + errorDescription = "Please make shure that you are using the latest version of this app and try again." + break + default: + infoLevel = 2 + errorString = "Unexpected error ("+errorCode+")" + errorDescription = "Unexpected error while getting data from the server. Please try again later." + } + + return([infoLevel, errorString, errorDescription]) + } + } +} diff --git a/resources/qml/qml.qrc b/resources/qml/qml.qrc new file mode 100644 index 0000000..badc274 --- /dev/null +++ b/resources/qml/qml.qrc @@ -0,0 +1,15 @@ + + + main.qml + Pages/CompetitionCalendarPage.qml + Pages/RankingPage.qml + Pages/StartPage.qml + Components/FancyButton.qml + Components/AppToolBar.qml + Components/FancyBusyIndicator.qml + Components/InfoArea.qml + Components/DataListView.qml + Components/RankingView.qml + Components/RegistrationView.qml + + diff --git a/resources/shared/icons/back.png b/resources/shared/icons/back.png new file mode 100644 index 0000000..d1740cd Binary files /dev/null and b/resources/shared/icons/back.png differ diff --git a/resources/shared/icons/backDark.png b/resources/shared/icons/backDark.png new file mode 100644 index 0000000..c55ab31 Binary files /dev/null and b/resources/shared/icons/backDark.png differ diff --git a/resources/shared/icons/dav.png b/resources/shared/icons/dav.png new file mode 100644 index 0000000..055d1d2 Binary files /dev/null and b/resources/shared/icons/dav.png differ diff --git a/resources/shared/icons/dig_rock.klein.jpg b/resources/shared/icons/dig_rock.klein.jpg new file mode 100644 index 0000000..7170811 Binary files /dev/null and b/resources/shared/icons/dig_rock.klein.jpg differ diff --git a/resources/shared/icons/dig_rock.klein.png b/resources/shared/icons/dig_rock.klein.png new file mode 100644 index 0000000..0eb0963 Binary files /dev/null and b/resources/shared/icons/dig_rock.klein.png differ diff --git a/resources/shared/icons/favicon.png b/resources/shared/icons/favicon.png new file mode 100644 index 0000000..15f210f Binary files /dev/null and b/resources/shared/icons/favicon.png differ diff --git a/resources/shared/icons/favicon.xcf b/resources/shared/icons/favicon.xcf new file mode 100644 index 0000000..5cdba7f Binary files /dev/null and b/resources/shared/icons/favicon.xcf differ diff --git a/resources/shared/icons/ifsc.png b/resources/shared/icons/ifsc.png new file mode 100644 index 0000000..993f23a Binary files /dev/null and b/resources/shared/icons/ifsc.png differ diff --git a/resources/shared/icons/json.php.json b/resources/shared/icons/json.php.json new file mode 100644 index 0000000..6a8f597 --- /dev/null +++ b/resources/shared/icons/json.php.json @@ -0,0 +1 @@ +{"WetId":"8422","GrpId":"11","route_order":"-1","route_name":"Gesamtergebnis m\u00e4nnliche Jugend A","route_result":"16.3.2019, 18:56:58","discipline":"boulder2018","comp_name":"1. Deutscher Jugendcup (B) 2019 - Bexbach","comp_date":"2019-03-16","nation":"GER","display_athlete":"fed_and_parent","route_names":{"0":"Qualifikation","2":"Finale","-1":"General Result"},"participants":[{"PerId":"52991","acl":"63","birthyear":2002,"city":"H\u00f6chberg","fed_id":"565","fed_parent":"460","federation":"W\u00fcrzburg","firstname":"Tim","lastname":"W\u00fcrthner","nation":"GER","parent_fed":"Bayern","result0":"5T6z\u00a06\u00a08","result2":"3T4z\u00a05\u00a014","result_modified":"1552740095","result_rank":1,"result_rank0":"5","result_rank2":"1","rkey":"TWU14M","start_number":"312","start_order":"12","top_tries":6,"tops":5,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=52991&cat=11","zone_tries":8,"zones":6},{"PerId":"53096","acl":"63","birthyear":2002,"city":"Hannover","fed_id":"325","fed_parent":"464","fed_url":"http:\/\/alpinclub-hannover.de\/","federation":"AlpinClub Hannover","firstname":"Lasse","lastname":"von Freier","nation":"GER","parent_fed":"Nord","result0":"6T6z\u00a09\u00a07","result2":"3T4z\u00a06\u00a013","result_modified":"1552739015","result_rank":2,"result_rank0":"1","result_rank2":"2","rkey":"LFR14M2","start_number":"317","start_order":"17","top_tries":9,"tops":6,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=53096&cat=11","zone_tries":7,"zones":6},{"PerId":"52993","acl":"63","birthyear":2003,"city":"Buxheim","fed_id":"474","fed_parent":"460","fed_url":"http:\/\/www.dav-ingolstadt.de\/","federation":"Ingolstadt","firstname":"Philipp","lastname":"Kuczora","nation":"GER","parent_fed":"Bayern","result0":"5T6z\u00a08\u00a09","result2":"3T4z\u00a08\u00a013","result_modified":"1552739372","result_rank":3,"result_rank0":"6","result_rank2":"3","rkey":"PKU14M","start_number":"308","start_order":"8","top_tries":8,"tops":5,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=52993&cat=11","zone_tries":9,"zones":6},{"PerId":"54545","acl":"63","birthyear":2003,"city":"Olching","fed_id":"40","fed_parent":"460","fed_url":"http:\/\/www.alpenverein-muenchen-oberland.de\/","federation":"M\u00fcnchen-Oberland","firstname":"Julius","lastname":"R\u00fcth","nation":"GER","parent_fed":"Bayern","result0":"5T6z\u00a010\u00a010","result2":"2T3z\u00a07\u00a016","result_modified":"1552740798","result_rank":4,"result_rank0":"8","result_rank2":"4","rkey":"JR15M","start_number":"310","start_order":"10","top_tries":10,"tops":5,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=54545&cat=11","zone_tries":10,"zones":6},{"PerId":"55798","acl":"63","birthyear":2002,"city":"Saarbr\u00fccken","fed_id":"515","fed_parent":"469","fed_url":"http:\/\/www.dav-saarbruecken.de\/","federation":"ASS Saarbr\u00fccken","firstname":"Nils","lastname":"Siegel","nation":"GER","parent_fed":"Saar","result0":"5T6z\u00a011\u00a08","result2":"2T3z\u00a09\u00a09","result_modified":"1552741078","result_rank":5,"result_rank0":"10","result_rank2":"5","rkey":"NSI16M","start_number":"327","start_order":"26","top_tries":11,"tops":5,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=55798&cat=11","zone_tries":8,"zones":6},{"PerId":"53136","acl":"63","birthyear":2002,"city":"Cleebronn","fed_id":"321","fed_parent":"461","fed_url":"http:\/\/www.dav-heilbronn.de\/","federation":"Heilbronn","firstname":"Luca","lastname":"Jung","nation":"GER","parent_fed":"Baden-W.","result0":"6T6z\u00a014\u00a010","result2":"2T3z\u00a09\u00a010","result_modified":"1552740354","result_rank":6,"result_rank0":"3","result_rank2":"6","rkey":"LJU14M","start_number":"302","start_order":"2","top_tries":14,"tops":6,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=53136&cat=11","zone_tries":10,"zones":6},{"PerId":"53058","acl":"63","birthyear":2002,"city":"Freising","fed_id":"182","fed_parent":"460","fed_url":"http:\/\/www.dav-freising.de\/","federation":"Freising","firstname":"Jannik","lastname":"Weiser","nation":"GER","parent_fed":"Bayern","result0":"5T6z\u00a010\u00a014","result2":"2T2z\u00a03\u00a03","result_modified":"1552740265","result_rank":7,"result_rank0":"9","result_rank2":"7","rkey":"JWE14M","start_number":"311","start_order":"11","top_tries":10,"tops":5,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=53058&cat=11","zone_tries":14,"zones":6},{"PerId":"52967","acl":"63","birthyear":2003,"city":"Landshut","fed_id":"277","fed_parent":"460","fed_url":"http:\/\/www.alpenverein-landshut.de\/","federation":"Landshut","firstname":"Ludwig","lastname":"Breu","nation":"GER","parent_fed":"Bayern","result0":"5T6z\u00a09\u00a011","result2":"2T2z\u00a05\u00a05","result_modified":"1552740942","result_rank":8,"result_rank0":"7","result_rank2":"8","rkey":"LBR14M","start_number":"306","start_order":"6","top_tries":9,"tops":5,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=52967&cat=11","zone_tries":11,"zones":6},{"PerId":"56552","acl":"63","birthyear":2002,"city":"Marburg","fed_id":"282","fed_parent":"462","fed_url":"http:\/\/alpenverein-frankfurtmain.de\/","federation":"Frankfurt\/Main","firstname":"Frederik","lastname":"Schmelzer","nation":"GER","parent_fed":"Hessen","result0":"6T6z\u00a016\u00a011","result2":"1T2z\u00a02\u00a03","result_modified":"1552740833","result_rank":9,"result_rank0":"4","result_rank2":"9","rkey":"FSC16M","start_number":"315","start_order":"15","top_tries":16,"tops":6,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=56552&cat=11","zone_tries":11,"zones":6},{"PerId":"63689","acl":"63","birthyear":2002,"city":"Namborn","fed_id":"180","fed_parent":"469","fed_url":"http:\/\/www.bergfreunde-saar.de\/","federation":"Bergfreunde Saar","firstname":"Elias","lastname":"Schmitt","nation":"GER","parent_fed":"Saar","result0":"6T6z\u00a010\u00a07","result2":"0T3z\u00a00\u00a010","result_modified":"1552739944","result_rank":10,"result_rank0":"2","result_rank2":"10","rkey":"ESC17M","start_number":"326","start_order":"25","top_tries":10,"tops":6,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=63689&cat=11","zone_tries":7,"zones":6},{"PerId":"55692","acl":"63","birthyear":2003,"city":"A\u00dflar-Werdorf","fed_id":"436","fed_parent":"462","fed_url":"http:\/\/www.dav-wetzlar.de\/","federation":"Wetzlar","firstname":"Henri","lastname":"Breuer","nation":"GER","parent_fed":"Hessen","result0":"4T6z\u00a05\u00a08","result_modified":"1552740352","result_rank":11,"result_rank0":"11","rkey":"HBR16M","start_number":"314","start_order":"14","top_tries":5,"tops":4,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=55692&cat=11","zone_tries":8,"zones":6},{"PerId":"53054","acl":"63","birthyear":2002,"city":"M\u00fcnchen","fed_id":"40","fed_parent":"460","fed_url":"http:\/\/www.alpenverein-muenchen-oberland.de\/","federation":"M\u00fcnchen-Oberland","firstname":"Luis","lastname":"Funk","nation":"GER","parent_fed":"Bayern","result0":"4T6z\u00a05\u00a010","result_modified":"1552740045","result_rank":12,"result_rank0":"12","rkey":"LFU14M","start_number":"307","start_order":"7","top_tries":5,"tops":4,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=53054&cat=11","zone_tries":10,"zones":6},{"PerId":"54374","acl":"63","birthyear":2002,"city":"Oberisling","fed_id":"185","fed_parent":"460","fed_url":"http:\/\/www.alpenverein-regensburg.de\/","federation":"Regensburg","firstname":"Luca","lastname":"Lindig","nation":"GER","parent_fed":"Bayern","result0":"4T6z\u00a011\u00a09","result_modified":"1552741938","result_rank":13,"result_rank0":"13","rkey":"LLI15M","start_number":"309","start_order":"9","top_tries":11,"tops":4,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=54374&cat=11","zone_tries":9,"zones":6},{"PerId":"53035","acl":"63","birthyear":2002,"city":"Burgrieden-Rot","fed_id":"658","fed_parent":"460","federation":"SG Ulm, Neu-Ulm, SSV Ulm","firstname":"Linus","lastname":"Bader","nation":"GER","parent_fed":"Bayern","result0":"4T5z\u00a05\u00a05","result_modified":"1552740500","result_rank":14,"result_rank0":"14","rkey":"LBA14M","start_number":"305","start_order":"5","top_tries":5,"tops":4,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=53035&cat=11","zone_tries":5,"zones":5},{"PerId":"55683","acl":"63","birthyear":2002,"city":"Herrenberg","fed_id":"339","fed_parent":"461","fed_url":"http:\/\/www.dav-tuebingen.de\/","federation":"T\u00fcbingen","firstname":"David","lastname":"Dongus","nation":"GER","parent_fed":"Baden-W.","result0":"4T5z\u00a010\u00a012","result_modified":"1552740967","result_rank":15,"result_rank0":"15","rkey":"DDO16M","start_number":"301","start_order":"1","top_tries":10,"tops":4,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=55683&cat=11","zone_tries":12,"zones":5},{"PerId":"66676","acl":"63","birthyear":2003,"city":"Vallgorguina","fed_id":"173","fed_parent":"465","fed_url":"http:\/\/www.dav-frankenthal.de\/","federation":"Frankenthal","firstname":"Cedric Lluc","lastname":"Milles","nation":"GER","parent_fed":"RL-Pfalz","result0":"4T4z\u00a07\u00a07","result_modified":"1552739722","result_rank":16,"result_rank0":"16","rkey":"CMI17M","start_number":"323","start_order":"22","top_tries":7,"tops":4,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=66676&cat=11","zone_tries":7,"zones":4},{"PerId":"63693","acl":"63","birthyear":2003,"city":"St. Wendel","fed_id":"852","fed_parent":"469","fed_url":"http:\/\/www.sbsb-saar.de\/index.php?id=379","federation":"Generation Rocklands","firstname":"Luca","lastname":"Kaul","nation":"GER","parent_fed":"Saar","result0":"3T5z\u00a05\u00a08","result_modified":"1552740715","result_rank":17,"result_rank0":"17","rkey":"LKA17M","start_number":"325","start_order":"24","top_tries":5,"tops":3,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=63693&cat=11","zone_tries":8,"zones":5},{"PerId":"55591","acl":"63","birthyear":2002,"city":"Gottmadingen","fed_id":"105","fed_parent":"461","fed_url":"http:\/\/www.dav-konstanz.de\/","federation":"Konstanz","firstname":"Sebastian","lastname":"Lucke","nation":"GER","parent_fed":"Baden-W.","result0":"3T5z\u00a07\u00a011","result_modified":"1552740555","result_rank":18,"result_rank0":"18","rkey":"SLU16M","start_number":"303","start_order":"3","top_tries":7,"tops":3,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=55591&cat=11","zone_tries":11,"zones":5},{"PerId":"52155","acl":"63","birthyear":2003,"city":"Dresden","fed_id":"168","fed_parent":"466","fed_url":"http:\/\/www.bergsteigerbund.de\/","federation":"S\u00e4chsischer Bergsteigerbund","firstname":"Albert","lastname":"Sch\u00f6nherr","nation":"GER","parent_fed":"Sachsen","result0":"2T4z\u00a02\u00a06","result_modified":"1552741036","result_rank":19,"result_rank0":"19","rkey":"ASC12M","start_number":"329","start_order":"28","top_tries":2,"tops":2,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=52155&cat=11","zone_tries":6,"zones":4},{"PerId":"63321","acl":"63","birthyear":2003,"city":"Zweibr\u00fccken","fed_id":"368","fed_parent":"465","fed_url":"http:\/\/alpenverein-zweibruecken.de\/","federation":"Zweibr\u00fccken","firstname":"Thorben","lastname":"Schulte","nation":"GER","parent_fed":"RL-Pfalz","result0":"2T4z\u00a05\u00a05","result_modified":"1552740228","result_rank":20,"result_rank0":"20","rkey":"TSC17M","start_number":"324","start_order":"23","top_tries":5,"tops":2,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=63321&cat=11","zone_tries":5,"zones":4},{"PerId":"56993","acl":"63","birthyear":2003,"city":"Hildesheim","fed_id":"193","fed_parent":"464","fed_url":"http:\/\/www.dav-hildesheim.de\/","federation":"Hildesheim","firstname":"Justus","lastname":"Aselmeier","nation":"GER","parent_fed":"Nord","result0":"2T3z\u00a03\u00a04","result_modified":"1552741051","result_rank":21,"result_rank0":"21","rkey":"JAS16M","start_number":"316","start_order":"16","top_tries":3,"tops":2,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=56993&cat=11","zone_tries":4,"zones":3},{"PerId":"51894","acl":"63","birthyear":2003,"city":"Bautzen","fed_id":"168","fed_parent":"466","fed_url":"http:\/\/www.bergsteigerbund.de\/","federation":"S\u00e4chsischer Bergsteigerbund","firstname":"Dominic","lastname":"Horn","nation":"GER","parent_fed":"Sachsen","result0":"2T3z\u00a03\u00a04","result_modified":"1552741003","result_rank":21,"result_rank0":"21","rkey":"DHO12M3","start_number":"328","start_order":"27","top_tries":3,"tops":2,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=51894&cat=11","zone_tries":4,"zones":3},{"PerId":"53251","acl":"63","birthyear":2002,"city":"Solingen","fed_id":"135","fed_parent":"463","fed_url":"http:\/\/www.dav-wuppertal.de\/","federation":"Wuppertal","firstname":"Nils","lastname":"Brandenburger","nation":"GER","parent_fed":"NRW","result0":"2T3z\u00a05\u00a06","result_modified":"1552740172","result_rank":23,"result_rank0":"23","rkey":"BNI14M2","start_number":"318","start_order":"18","top_tries":5,"tops":2,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=53251&cat=11","zone_tries":6,"zones":3},{"PerId":"69593","acl":"63","birthyear":2003,"city":"K\u00f6ln","fed_id":"170","fed_parent":"463","fed_url":"http:\/\/www.dav-koeln.de\/","federation":"Rheinland-K\u00f6ln","firstname":"Felix","lastname":"Sch\u00e4fer","nation":"GER","parent_fed":"NRW","result0":"1T3z\u00a03\u00a08","result_modified":"1552741233","result_rank":24,"result_rank0":"24","rkey":"FSC18M","start_number":"320","start_order":"20","top_tries":3,"tops":1,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=69593&cat=11","zone_tries":8,"zones":3},{"PerId":"54303","acl":"63","birthyear":2003,"city":"Stuttgart","fed_id":"290","fed_parent":"461","fed_url":"http:\/\/www.alpenverein-stuttgart.de\/","federation":"Stuttgart","firstname":"Jona","lastname":"Marx","nation":"GER","parent_fed":"Baden-W.","result0":"0T4z\u00a00\u00a05","result_modified":"1552741259","result_rank":25,"result_rank0":"25","rkey":"JMA15M","start_number":"304","start_order":"4","tops":0,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=54303&cat=11","zone_tries":5,"zones":4},{"PerId":"53284","acl":"63","birthyear":2003,"city":"Carlsberg","fed_id":"173","fed_parent":"465","fed_url":"http:\/\/www.dav-frankenthal.de\/","federation":"Frankenthal","firstname":"Eric","lastname":"Grabo","nation":"GER","parent_fed":"RL-Pfalz","result0":"0T3z\u00a00\u00a06","result_modified":"1552740130","result_rank":26,"result_rank0":"26","rkey":"EGR14M","start_number":"321","start_order":"21","tops":0,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=53284&cat=11","zone_tries":6,"zones":3},{"PerId":"54274","acl":"63","birthyear":2002,"city":"Berlin","fed_id":"104","fed_parent":"470","fed_url":"http:\/\/www.dav-berlin.de\/","federation":"Berlin","firstname":"Luis","lastname":"Fuchs","nation":"GER","parent_fed":"Berlin","result0":"0T2z\u00a00\u00a04","result_modified":"1552741070","result_rank":27,"result_rank0":"27","rkey":"LFU15M","start_number":"313","start_order":"13","tops":0,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=54274&cat=11","zone_tries":4,"zones":2},{"PerId":"54606","acl":"63","birthyear":2003,"city":"Freudenberg","fed_id":"210","fed_parent":"463","fed_url":"http:\/\/www.dav-aachen.de","federation":"Aachen","firstname":"Kalvin","lastname":"Klappert","nation":"GER","parent_fed":"NRW","result0":"0T1z\u00a00\u00a01","result_modified":"1552740876","result_rank":28,"result_rank0":"28","rkey":"KKL15M","start_number":"319","start_order":"19","tops":0,"url":"https:\/\/www.digitalrock.de\/egroupware\/ranking\/sitemgr\/digitalrock\/pstambl.html#person=54606&cat=11","zone_tries":1,"zones":1}],"see_also":[{"name":"Ranking after 1. Deutscher Jugendcup (B) 2019 - Bexbach","url":"https:\/\/www.digitalrock.de\/ranglist.php?type=ranking&cat=11&comp=8422"},{"name":"DAV Jugendcup 2019 after 1. Deutscher Jugendcup (B) 2019 - Bexbach","url":"https:\/\/www.digitalrock.de\/ranglist.php?type=ranking&cat=11&cup=796&comp=8422"}],"categorys":[{"GrpId":"48","route_order":"2","name":"weibliche Jugend A"},{"GrpId":"11","route_order":"2","name":"m\u00e4nnliche Jugend A"},{"GrpId":"49","route_order":"2","name":"weibliche Jugend B"},{"GrpId":"12","route_order":"2","name":"m\u00e4nnliche Jugend B"},{"GrpId":"213","route_order":"0","name":"Coaches"}],"etag":"\"8cd778beaec9d8d190e1a6a74dfd1fc7\"","expires":86400} \ No newline at end of file diff --git a/resources/shared/icons/sac.png b/resources/shared/icons/sac.png new file mode 100644 index 0000000..c16a111 Binary files /dev/null and b/resources/shared/icons/sac.png differ diff --git a/resources/shared/shared.qrc b/resources/shared/shared.qrc new file mode 100644 index 0000000..aabd3de --- /dev/null +++ b/resources/shared/shared.qrc @@ -0,0 +1,9 @@ + + + icons/dav.png + icons/ifsc.png + icons/sac.png + icons/back.png + icons/backDark.png + + diff --git a/sources/main.cpp b/sources/main.cpp new file mode 100644 index 0000000..8711658 --- /dev/null +++ b/sources/main.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "headers/serverconn.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + + QGuiApplication app(argc, argv); + + QQuickStyle::setStyle("Material"); + + qmlRegisterType("com.itsblue.digitalRockRanking", 1, 0, "ServerConn"); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; + + return app.exec(); +} diff --git a/sources/serverconn.cpp b/sources/serverconn.cpp new file mode 100644 index 0000000..a4e774e --- /dev/null +++ b/sources/serverconn.cpp @@ -0,0 +1,134 @@ +#include "headers/serverconn.h" + +ServerConn::ServerConn(QObject *parent) : QObject(parent) +{ +} + +void ServerConn::refreshFoodplan() { + QVariant tmpFoodplan; + + QVariantMap ret = this->senddata(QUrl("http://egw.ifsc-climbing.org/egw/ranking/json.php")); + + if(ret["status"] != 200){ + // request was a failure + return; + } + + QJsonDocument jsonReply = QJsonDocument::fromJson(ret["text"].toString().toUtf8()); + + this->foodplan = jsonReply.toVariant(); + + //qDebug() << this->foodplan; + + emit this->foodplanChanged(); +} + +QVariant ServerConn::getCalendar(QString nation){ + QVariantMap ret = this->senddata(QUrl("http://egw.ifsc-climbing.org/egw/ranking/json.php?year=2018&nation=" + nation)); + + if(ret["status"] != 200){ + // request was a failure + return QVariantMap({{"status", ret["status"]}, {"data", ""}}); + } + + QJsonDocument jsonReply = QJsonDocument::fromJson(ret["text"].toString().toUtf8()); + + QVariantMap rankingData = {{"status", 200}, {"data", jsonReply.toVariant()}}; + + return rankingData; +} + +QVariant ServerConn::getRanking(int competiotionId, int categoryId, bool registrationData, int routeNumber) { + + QString requestUrl = "http://egw.ifsc-climbing.org/egw/ranking/json.php?comp="+ QString::number( competiotionId ) +"&cat="+ QString::number( categoryId ) + (registrationData ? "&type=starters":"") + "&route=" + ((routeNumber == -2) ? "":QString::number(routeNumber)); + + qDebug() << requestUrl; + + QVariantMap ret = this->senddata(QUrl(requestUrl)); + + if(ret["status"] != 200){ + // request was a failure + return QVariantMap({{"status", ret["status"]}, {"data", ""}}); + } + + QJsonDocument jsonReply = QJsonDocument::fromJson(ret["text"].toString().toUtf8()); + + QVariantMap rankingData = {{"status", 200}, {"data", jsonReply.toVariant()}}; + + return rankingData; +} + +// ------------------------ +// --- Helper functions --- +// ------------------------ + +QVariantMap ServerConn::senddata(QUrl serviceUrl, QUrlQuery pdata) +{ + // create network manager + QNetworkAccessManager * networkManager = new QNetworkAccessManager(); + + QVariantMap ret; //this is a custom type to store the return-data + + // Create network request + QNetworkRequest request(serviceUrl); + request.setHeader(QNetworkRequest::ContentTypeHeader, + "application/x-www-form-urlencoded"); + + QSslConfiguration config = QSslConfiguration::defaultConfiguration(); + config.setProtocol(QSsl::TlsV1_2); + request.setSslConfiguration(config); + + //send a POST request with the given url and data to the server + + QNetworkReply *reply; + + if(pdata.isEmpty()){ + // if no post data is given -> send a GET request + reply = networkManager->get(request); + } + else { + // if post data is given -> send POST request + reply = networkManager->post(request, pdata.toString(QUrl::FullyEncoded).toUtf8()); + } + + // loop to wait until the request has finished before processing the data + QEventLoop loop; + // timer to cancel the request after 3 seconds + QTimer timer; + timer.setSingleShot(true); + + // quit the loop when the request finised + loop.connect(networkManager, SIGNAL(finished(QNetworkReply*)), SLOT(quit())); + // or the timer timed out + loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + // start the timer + timer.start(10000); + // start the loop + loop.exec(); + + //get the status code + QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + + ret.insert("status", status_code.toInt()); + + //get the full text response + ret.insert("text", QString::fromUtf8(reply->readAll())); + + // delete the reply object + delete reply; + + // delete the newtwork access manager object + delete networkManager; + + //return the data + return(ret); +} + +// ------------------------- +// --- Functions for QML --- +// ------------------------- + +QVariant ServerConn::getFoodplan() { + return this->foodplan; +} +