Compare commits
6 commits
main
...
orangerot/
Author | SHA1 | Date | |
---|---|---|---|
Orangerot | 173ce00cf2 | ||
Orangerot | a2202f311e | ||
Orangerot | 184d0e538b | ||
Orangerot | 82cbc4cf2c | ||
Orangerot | 4956818d53 | ||
Orangerot | 8cf2692f65 |
|
@ -23,12 +23,16 @@ qt_add_qml_module(itat_challenge_olympics
|
||||||
SOURCES
|
SOURCES
|
||||||
src/model/Competitor.cpp
|
src/model/Competitor.cpp
|
||||||
src/model/Competitor.h
|
src/model/Competitor.h
|
||||||
|
src/model/CompetitorWithResults.cpp
|
||||||
|
src/model/CompetitorWithResults.h
|
||||||
src/model/EventInfo.cpp
|
src/model/EventInfo.cpp
|
||||||
src/model/EventInfo.h
|
src/model/EventInfo.h
|
||||||
src/model/FilterModel.cpp
|
src/model/FilterModel.cpp
|
||||||
src/model/FilterModel.h
|
src/model/FilterModel.h
|
||||||
src/model/SportModel.cpp
|
src/model/MedalWinner.cpp
|
||||||
src/model/SportModel.h
|
src/model/MedalWinner.h
|
||||||
|
src/model/Sport.cpp
|
||||||
|
src/model/Sport.h
|
||||||
|
|
||||||
RESOURCES
|
RESOURCES
|
||||||
res/pictograms/ARC_small.svg
|
res/pictograms/ARC_small.svg
|
||||||
|
@ -47,9 +51,7 @@ qt_add_qml_module(itat_challenge_olympics
|
||||||
res/pictograms/CSP_small.svg
|
res/pictograms/CSP_small.svg
|
||||||
res/pictograms/CTR_small.svg
|
res/pictograms/CTR_small.svg
|
||||||
res/pictograms/DIV_small.svg
|
res/pictograms/DIV_small.svg
|
||||||
res/pictograms/EDR_small.svg
|
res/pictograms/EQU_small.svg
|
||||||
res/pictograms/EJP_small.svg
|
|
||||||
res/pictograms/EVE_small.svg
|
|
||||||
res/pictograms/FBL_small.svg
|
res/pictograms/FBL_small.svg
|
||||||
res/pictograms/FEN_small.svg
|
res/pictograms/FEN_small.svg
|
||||||
res/pictograms/GAR_small.svg
|
res/pictograms/GAR_small.svg
|
||||||
|
@ -79,7 +81,6 @@ qt_add_qml_module(itat_challenge_olympics
|
||||||
res/pictograms/WLF_small.svg
|
res/pictograms/WLF_small.svg
|
||||||
res/pictograms/WPO_small.svg
|
res/pictograms/WPO_small.svg
|
||||||
res/pictograms/WRE_small.svg
|
res/pictograms/WRE_small.svg
|
||||||
res/pictograms/WRG_small.svg
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(itat_challenge_olympics PRIVATE Qt6::Core Qt6::Quick Qt6::Network)
|
target_link_libraries(itat_challenge_olympics PRIVATE Qt6::Core Qt6::Quick Qt6::Network)
|
||||||
|
|
|
@ -165,6 +165,6 @@ application.qml -[hidden]u- Application
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
- **Silas Stulz** - *Initial Work*
|
- **Silas Stulz** (ugmgt, 2468197) - *Initial Work*
|
||||||
- **Gero Beckmann** - *Initial Work*
|
- **Gero Beckmann** (ukpfm, 2409754) - *Initial Work*
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ import QtQuick.Controls
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
id: root
|
id: root
|
||||||
required property string eventName
|
property string eventName
|
||||||
required property list<QtObject> competitors
|
property list<string> competitors
|
||||||
|
|
||||||
header: ToolBar {
|
header: ToolBar {
|
||||||
ToolButton {
|
ToolButton {
|
||||||
|
@ -33,25 +33,15 @@ Page {
|
||||||
spacing: 20
|
spacing: 20
|
||||||
model: competitors
|
model: competitors
|
||||||
delegate: ItemDelegate {
|
delegate: ItemDelegate {
|
||||||
required property string name
|
text: modelData
|
||||||
required property string noc
|
|
||||||
required property string mark
|
|
||||||
required property string statistic
|
|
||||||
required property string gold
|
|
||||||
required property string silver
|
|
||||||
required property string bronze
|
|
||||||
width: listView.width - listView.leftMargin - listView.rightMargin
|
width: listView.width - listView.leftMargin - listView.rightMargin
|
||||||
height: 32
|
height: avatar.implicitHeight + 32
|
||||||
Text {
|
leftPadding: avatar.implicitWidth + 32
|
||||||
anchors.left: parent.left
|
|
||||||
text: name + " (" + noc + ")"
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
anchors.right: parent.right
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
text: mark + " " + statistic + " | " + gold + "🥇 " + silver + "🥈 " + bronze + "🥉"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: avatar
|
||||||
|
// source: "images/" + modelData.replace(" ", "_") + ".png"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,7 @@ Page {
|
||||||
model: filter
|
model: filter
|
||||||
delegate: ItemDelegate {
|
delegate: ItemDelegate {
|
||||||
required property string eventName
|
required property string eventName
|
||||||
required property list<QtObject> competitors
|
required property list<string> competitors
|
||||||
text: eventName
|
text: eventName
|
||||||
width: listView.width - listView.leftMargin - listView.rightMargin
|
width: listView.width - listView.leftMargin - listView.rightMargin
|
||||||
height: avatar.height
|
height: avatar.height
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 720 720">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.cls-1 {
|
|
||||||
clip-path: url(#clippath);
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-2 {
|
|
||||||
fill: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-2, .cls-3 {
|
|
||||||
stroke-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-3 {
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<clipPath id="clippath">
|
|
||||||
<rect class="cls-2" width="720" height="720"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
<g class="cls-1">
|
|
||||||
<path class="cls-3" d="M0,149.7C0,99.6,31.6,57,75.9,40.5L116.4,0v33.3l99.8,49.9-16.6,33.3h-83.2v149.7c-64.3-.1-116.4-52.2-116.4-116.5ZM215.4,216c30.4-30.4,79.6-30.4,110,0l5.9,5.9,28.7-28.7,11.3,11.3-68,68,35.6,45.1-24.6,24.6-57.4-23.2-24.2,24.2-17.2-17.2c-30.5-30.3-30.5-79.6-.1-110ZM269.2,306.7l41.3,16.8,7-7-25.6-32.5-22.7,22.7ZM603.6,116.4v149.7c64.3,0,116.4-52.1,116.4-116.4s-31.6-92.7-75.9-109.2L603.6,0v33.3l-99.8,49.9,16.6,33.3h83.2ZM603.6,453.9v149.7h-83.2l-16.6,33.3,99.8,49.9v33.2l40.5-40.5c44.3-16.5,75.9-59.1,75.9-109.2s-52.1-116.4-116.4-116.4ZM116.4,603.6v-149.7c-64.3,0-116.4,52.1-116.4,116.4s31.6,92.7,75.9,109.2l40.5,40.5v-33.3l99.8-49.9-16.6-33.3h-83.2ZM490,237.1l64-59c2-1.8,3.3-4.1,3.7-6.2s0-4.2-1.4-5.6l-1.3-1.3-1.3-1.3c-1.4-1.4-3.4-1.8-5.6-1.4s-4.4,1.7-6.2,3.7l-59,64-252.9,252.9-64,59c-2,1.8-3.3,4.1-3.7,6.2s0,4.2,1.4,5.6l1.3,1.3,1.3,1.3c1.4,1.4,3.4,1.8,5.6,1.4s4.4-1.7,6.2-3.7l59-64,252.9-252.9ZM504.6,504c-30.4,30.4-79.6,30.4-110,0l-5.9-5.9-28.7,28.6-11.3-11.3,68-68-35.6-45.1,24.6-24.6,57.4,23.3,24.2-24.2,17.2,17.2c30.5,30.3,30.5,79.6,0,110ZM450.8,413.3l-41.3-16.8-7,7,25.6,32.5,22.7-22.7Z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
@ -1,28 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 720 720">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.cls-1 {
|
|
||||||
clip-path: url(#clippath);
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-2 {
|
|
||||||
fill: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-2, .cls-3 {
|
|
||||||
stroke-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-3 {
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<clipPath id="clippath">
|
|
||||||
<rect class="cls-2" width="720" height="720"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
<g class="cls-1">
|
|
||||||
<path class="cls-3" d="M0,149.7C0,99.6,31.6,57,75.9,40.5L116.4,0v33.3l99.8,49.9-16.6,33.3h-83.2v149.7c-64.3-.1-116.4-52.2-116.4-116.5ZM215.4,216c30.4-30.4,79.6-30.4,110,0l5.9,5.9,28.7-28.7,11.3,11.3-68,68,35.6,45.1-24.6,24.6-57.4-23.2-24.2,24.2-17.2-17.2c-30.5-30.3-30.5-79.6-.1-110ZM269.2,306.7l41.3,16.8,7-7-25.6-32.5-22.7,22.7ZM603.6,116.4v149.7c64.3,0,116.4-52.1,116.4-116.4s-31.6-92.7-75.9-109.2L603.6,0v33.3l-99.8,49.9,16.6,33.3h83.2ZM603.6,453.9v149.7h-83.2l-16.6,33.3,99.8,49.9v33.2l40.5-40.5c44.3-16.5,75.9-59.1,75.9-109.2s-52.1-116.4-116.4-116.4ZM116.4,603.6v-149.7c-64.3,0-116.4,52.1-116.4,116.4s31.6,92.7,75.9,109.2l40.5,40.5v-33.3l99.8-49.9-16.6-33.3h-83.2ZM490,237.1l64-59c2-1.8,3.3-4.1,3.7-6.2s0-4.2-1.4-5.6l-1.3-1.3-1.3-1.3c-1.4-1.4-3.4-1.8-5.6-1.4s-4.4,1.7-6.2,3.7l-59,64-252.9,252.9-64,59c-2,1.8-3.3,4.1-3.7,6.2s0,4.2,1.4,5.6l1.3,1.3,1.3,1.3c1.4,1.4,3.4,1.8,5.6,1.4s4.4-1.7,6.2-3.7l59-64,252.9-252.9ZM504.6,504c-30.4,30.4-79.6,30.4-110,0l-5.9-5.9-28.7,28.6-11.3-11.3,68-68-35.6-45.1,24.6-24.6,57.4,23.3,24.2-24.2,17.2,17.2c30.5,30.3,30.5,79.6,0,110ZM450.8,413.3l-41.3-16.8-7,7,25.6,32.5,22.7-22.7Z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.7 KiB |
|
@ -1,28 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 720 720">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.cls-1 {
|
|
||||||
clip-path: url(#clippath);
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-2 {
|
|
||||||
fill: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-2, .cls-3 {
|
|
||||||
stroke-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cls-3 {
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<clipPath id="clippath">
|
|
||||||
<rect class="cls-2" width="720" height="720"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
<g class="cls-1">
|
|
||||||
<path class="cls-3" d="M492.6,467.2c39.5-48.8,48.1-114.2,25.8-170.2,10.9-10.3,14-15.4,18.5-25.8.4-.8.7-1.7,1.1-2.6,1-2.2,3.5-5,7.3-8.1h0c40.1,74.6,32,168.4-24.4,235.2l-28.4-28.5ZM486.2,147.4l90.7-58.9,19.5,19.5-23,23c-2.1,2.1-3.2,4.9-3.2,7.8s1.2,5.7,3.2,7.8c2.1,2.1,4.9,3.2,7.8,3.2s5.7-1.2,7.8-3.2l23-23.1,19.5,19.5-58.9,90.7-2.8,1.2c-20.7,8.8-36.8,20.3-40.8,29.4-.4,1-.8,1.8-1.2,2.7-4.9,11.1-6.9,14.7-25.8,31.2-13.5,11.8-28.7,23.7-33.3,26.7l-9.7,6.4-4.8-10.6c-6-13.1-12.7-23-21.3-31.5l-2.3-2.3c-8.4-8.5-18.4-15.2-31.4-21.2l-10.6-4.8,6.4-9.7c3-4.5,14.9-19.7,26.7-33.3,16.5-18.8,20.1-20.9,31.2-25.8.8-.4,1.7-.8,2.7-1.2,9.1-4.1,20.6-20.1,29.4-40.8l1.2-2.7ZM435.3,277.6l13.6-13.6c-10-9.3-21.3-16.9-33.7-22.7-5.9,7.3-10.3,13.2-11.8,15.4,13.3,6.1,23.5,12.9,31.9,20.9ZM478.7,304.8c-5.8-12.4-13.4-23.7-22.7-33.7l-13.6,13.6c8,8.4,14.8,18.6,20.9,31.9,2.2-1.5,8.2-6,15.4-11.8ZM494.2,154.1c-6.5,15.3-19.3,39.3-34.5,46.1-11.9,5.3-13.3,4.9-30.4,24.4-1.2,1.3-2.3,2.7-3.5,4,12.6,6.3,24.2,14.4,34.5,24.1l26.4-26.4,7.1,7.1-26.4,26.4c9.7,10.3,17.7,21.9,24.1,34.5,1.4-1.2,2.7-2.3,4-3.5,19.5-17.1,19.1-18.5,24.4-30.4,6.8-15.2,30.7-28,46.1-34.5l52.8-81.3-6.7-6.7-16,16c-4.1,4.1-9.5,6.2-14.9,6.2s-10.8-2.1-14.9-6.2c-8.2-8.2-8.2-21.6,0-29.8l16-16-6.7-6.7-81.4,52.7ZM448.9,183c.8-.4,1.7-.7,2.6-1.1,2.2-1,5-3.5,8.1-7.3h0c-74.6-40.2-168.3-32.1-235.2,24.4l28.4,28.4c48.8-39.5,114.2-48.1,170.2-25.8,10.4-10.9,15.5-14,25.9-18.6ZM720,360l-131.8-131.8-8.9,13.6h0l118.2,118.2-156,156,11.3,11.3,167.3-167.3ZM0,360l131.8,131.8,8.9-13.6h.1l-118.2-118.2,156-156-11.3-11.3L0,360ZM233.8,572.6l-90.7,58.9-19.5-19.5,23-23c2.1-2.1,3.2-4.9,3.2-7.8s-1.2-5.7-3.2-7.8c-2.1-2.1-4.9-3.2-7.8-3.2s-5.7,1.1-7.8,3.2l-23,23.1-19.5-19.5,58.9-90.7,2.8-1.2c20.7-8.8,36.8-20.3,40.8-29.4.4-1,.8-1.8,1.2-2.7,4.9-11.1,6.9-14.7,25.8-31.2,13.5-11.8,28.7-23.7,33.3-26.7l9.7-6.4,4.8,10.6c6,13.1,12.7,23,21.3,31.5l2.3,2.3c8.4,8.5,18.4,15.2,31.4,21.2l10.6,4.8-6.4,9.7c-3,4.5-14.9,19.7-26.7,33.3-16.5,18.8-20.1,20.9-31.2,25.8-.8.4-1.7.8-2.7,1.2-9.1,4.1-20.6,20.1-29.4,40.8l-1.2,2.7ZM284.7,442.4l-13.7,13.7c10,9.3,21.3,16.9,33.7,22.7,5.9-7.3,10.3-13.2,11.8-15.4-13.2-6.2-23.4-13-31.8-21ZM241.3,415.2c5.8,12.4,13.4,23.7,22.7,33.7l13.6-13.6c-8-8.4-14.8-18.6-20.9-31.9-2.2,1.5-8.2,6-15.4,11.8ZM225.8,565.9c6.5-15.3,19.3-39.3,34.5-46.1,11.9-5.3,13.3-4.9,30.4-24.4,1.2-1.3,2.3-2.7,3.5-4-12.6-6.3-24.2-14.4-34.5-24.1l-26.4,26.4-7.1-7.1,26.4-26.4c-9.7-10.3-17.7-21.9-24.1-34.5-1.4,1.2-2.7,2.3-4,3.5-19.5,17.1-19.1,18.5-24.4,30.4-6.8,15.2-30.7,28-46.1,34.5l-52.8,81.3,6.7,6.7,16-16c4.1-4.1,9.5-6.2,14.9-6.2s10.8,2.1,14.9,6.2c8.2,8.2,8.2,21.6,0,29.8l-16,16,6.7,6.7,81.4-52.7ZM360,697.4l-118.1-118.1h0c0,0-13.6,9-13.6,9l131.7,131.7,167.3-167.3-11.3-11.3-156,156ZM360,22.6l118.1,118.1h0c0-.1,13.6-9,13.6-9L360,0l-167.3,167.3,11.3,11.3L360,22.6ZM199,224.4c-56.4,66.9-64.6,160.6-24.4,235.2h.1c3.8-3.1,6.3-5.9,7.3-8.1.4-.9.8-1.8,1.1-2.6,4.6-10.4,7.6-15.5,18.5-25.8-22.3-56-13.7-121.5,25.8-170.2l-28.4-28.5ZM271.1,537c-.8.4-1.7.7-2.6,1.1-2.2,1-5,3.5-8.1,7.3h0c74.6,40.2,168.3,32.1,235.2-24.3l-28.4-28.4c-48.7,39.5-114.2,48.1-170.2,25.8-10.4,10.8-15.5,13.9-25.9,18.5ZM391.1,379.8l262.6,262.6-11.3,11.3-262.6-262.6c-14.3,9.1-33.4,7.5-45.9-5s-14.1-31.6-5-45.9L66.3,77.7l11.3-11.3,262.6,262.6c14.3-9.1,33.4-7.5,45.9,5s14.1,31.5,5,45.8ZM347.5,336.2l36.3,36.3c5.3-10.1,3.7-23-4.8-31.5s-21.3-10.1-31.5-4.8ZM372.5,383.8l-36.3-36.3c-5.3,10.1-3.7,23,4.8,31.5s21.3,10.1,31.5,4.8Z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.9 KiB |
140
src/api/OlympicsAPI.cpp
Normal file
140
src/api/OlympicsAPI.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
|
||||||
|
#include "OlympicsAPI.h"
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
// networking
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
// json parsing
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QVariantMap>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief OlympicsAPI::getSportData Requests the current data from the Olympics API of a certain discipline.
|
||||||
|
* @param sport The discipline to request.
|
||||||
|
* @return The current information provided by the API endpoint.
|
||||||
|
*/
|
||||||
|
QJsonObject OlympicsAPI::getSportData(OlympicsAPI::Disciplines sport) {
|
||||||
|
string shortName = this->getDisciplineShort(sport);
|
||||||
|
|
||||||
|
if (USE_API_REQUEST) {
|
||||||
|
// create custom temporary event loop on stack
|
||||||
|
QEventLoop eventLoop;
|
||||||
|
|
||||||
|
// "quit()" the event-loop, when the network request "finished()"
|
||||||
|
QNetworkAccessManager mgr;
|
||||||
|
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
|
||||||
|
|
||||||
|
QString endpoint = (API_LINK + shortName).c_str();
|
||||||
|
|
||||||
|
// the HTTP request
|
||||||
|
QNetworkRequest req( (QUrl( endpoint )) );
|
||||||
|
QNetworkReply *reply = mgr.get(req);
|
||||||
|
eventLoop.exec(); // blocks stack until "finished()" has been called
|
||||||
|
|
||||||
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
//success
|
||||||
|
|
||||||
|
QString strReply = (QString)reply->readAll();
|
||||||
|
|
||||||
|
//parse json
|
||||||
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8());
|
||||||
|
|
||||||
|
QJsonObject jsonObj = jsonResponse.object();
|
||||||
|
|
||||||
|
delete reply;
|
||||||
|
|
||||||
|
return jsonObj;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//failure
|
||||||
|
delete reply;
|
||||||
|
|
||||||
|
throw invalid_argument("API request failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if API is not used, open locally stored data
|
||||||
|
QString filePath = ("../../res/mock/" + shortName + ".json").c_str();
|
||||||
|
QFile file( filePath );
|
||||||
|
|
||||||
|
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
throw invalid_argument("Could not open file to read data of the given discipline.");
|
||||||
|
} else {
|
||||||
|
QString text = file.readAll();
|
||||||
|
file.close();
|
||||||
|
return (QJsonDocument::fromJson(text.toUtf8())).object();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief OlympicsAPI::getDisciplineShort Get the discipline's short name defined by the IOC (International Olympic Committee)
|
||||||
|
* @param sport The sport you want to get the name from.
|
||||||
|
* @return The short name as a string.
|
||||||
|
*/
|
||||||
|
string OlympicsAPI::getDisciplineShort(OlympicsAPI::Disciplines sport) {
|
||||||
|
switch (sport) {
|
||||||
|
case OlympicsAPI::Disciplines::AquaticsArtisticSwimming: return "SWA";
|
||||||
|
case OlympicsAPI::Disciplines::AquaticsDiving: return "DIV";
|
||||||
|
case OlympicsAPI::Disciplines::AquaticsMarathonSwimming: return "OWS";
|
||||||
|
case OlympicsAPI::Disciplines::AquaticsSwimming: return "SWM";
|
||||||
|
case OlympicsAPI::Disciplines::AquaticsWaterPolo: return "WPO";
|
||||||
|
case OlympicsAPI::Disciplines::Archery: return "ARC";
|
||||||
|
case OlympicsAPI::Disciplines::Athletics: return "ATH";
|
||||||
|
case OlympicsAPI::Disciplines::Badminton: return "BDM";
|
||||||
|
case OlympicsAPI::Disciplines::Basketball3v3: return "BK3";
|
||||||
|
case OlympicsAPI::Disciplines::Basketball: return "BKB";
|
||||||
|
case OlympicsAPI::Disciplines::Boxing: return "BOX";
|
||||||
|
case OlympicsAPI::Disciplines::Breaking: return "BKG";
|
||||||
|
case OlympicsAPI::Disciplines::CanoeingSprint: return "CSP";
|
||||||
|
case OlympicsAPI::Disciplines::CanoeingSlalom: return "CSL";
|
||||||
|
case OlympicsAPI::Disciplines::CyclingBMXFreestyle: return "BMF";
|
||||||
|
case OlympicsAPI::Disciplines::CyclingBMXRacing: return "BMX";
|
||||||
|
case OlympicsAPI::Disciplines::CyclingMaountainBike: return "MTB";
|
||||||
|
case OlympicsAPI::Disciplines::CyclingRoad: return "CRD";
|
||||||
|
case OlympicsAPI::Disciplines::CyclingTrack: return "CTR";
|
||||||
|
case OlympicsAPI::Disciplines::EquestrianDressage: return "EDR";
|
||||||
|
case OlympicsAPI::Disciplines::EquestrianEventing: return "EVE";
|
||||||
|
case OlympicsAPI::Disciplines::EquestrianJumping: return "EJP";
|
||||||
|
case OlympicsAPI::Disciplines::Fencing: return "FEN";
|
||||||
|
case OlympicsAPI::Disciplines::FieldHockey: return "HOC";
|
||||||
|
case OlympicsAPI::Disciplines::Football: return "FBL";
|
||||||
|
case OlympicsAPI::Disciplines::Golf: return "GLF";
|
||||||
|
case OlympicsAPI::Disciplines::GymnasticsArtistic: return "GAR";
|
||||||
|
case OlympicsAPI::Disciplines::GymnasticsRhythmic: return "GRY";
|
||||||
|
case OlympicsAPI::Disciplines::GymnasticsTrampoline: return "GTR";
|
||||||
|
case OlympicsAPI::Disciplines::HandballIndoor: return "HBL";
|
||||||
|
case OlympicsAPI::Disciplines::Judo: return "JUD";
|
||||||
|
case OlympicsAPI::Disciplines::ModernPentathlon: return "MPN";
|
||||||
|
case OlympicsAPI::Disciplines::Rowing: return "ROW";
|
||||||
|
case OlympicsAPI::Disciplines::Rugby7: return "RU7";
|
||||||
|
case OlympicsAPI::Disciplines::Sailing: return "SAL";
|
||||||
|
case OlympicsAPI::Disciplines::Shooting: return "SHO";
|
||||||
|
case OlympicsAPI::Disciplines::Skateboarding: return "SKB";
|
||||||
|
case OlympicsAPI::Disciplines::SportClimbing: return "CLB";
|
||||||
|
case OlympicsAPI::Disciplines::Surfing: return "SRF";
|
||||||
|
case OlympicsAPI::Disciplines::TableTennis: return "TTE";
|
||||||
|
case OlympicsAPI::Disciplines::Taekwondo: return "TKW";
|
||||||
|
case OlympicsAPI::Disciplines::Tennis: return "TEN";
|
||||||
|
case OlympicsAPI::Disciplines::Triathlon: return "TRI";
|
||||||
|
case OlympicsAPI::Disciplines::VolleyballBeach: return "VBV";
|
||||||
|
case OlympicsAPI::Disciplines::VolleyballIndoor: return "VVO";
|
||||||
|
case OlympicsAPI::Disciplines::Weightlifting: return "WLF";
|
||||||
|
case OlympicsAPI::Disciplines::WrestlingFreestyle: return "WRE";
|
||||||
|
case OlympicsAPI::Disciplines::WrestlingGrecoRoman: return "WRG";
|
||||||
|
default: return "ARC"; // default, which should not be possible, because of enum
|
||||||
|
}
|
||||||
|
}
|
77
src/api/OlympicsAPI.h
Normal file
77
src/api/OlympicsAPI.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
|
||||||
|
#ifndef ITAT_CHALLANGE_OLYMPICS_OLYMPICSAPI_H
|
||||||
|
#define ITAT_CHALLANGE_OLYMPICS_OLYMPICSAPI_H
|
||||||
|
|
||||||
|
|
||||||
|
#define API_LINK "https://sph-s-api.olympics.com/summer/schedules/api/ENG/schedule/discipline/"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
// TODO: change this to true to use the olympics api, instead of the mock date in res/mock/
|
||||||
|
#define USE_API_REQUEST false
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class OlympicsAPI {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Disciplines {
|
||||||
|
AquaticsArtisticSwimming,
|
||||||
|
AquaticsDiving,
|
||||||
|
AquaticsMarathonSwimming,
|
||||||
|
AquaticsSwimming,
|
||||||
|
AquaticsWaterPolo,
|
||||||
|
Archery,
|
||||||
|
Athletics,
|
||||||
|
Badminton,
|
||||||
|
Basketball3v3,
|
||||||
|
Basketball,
|
||||||
|
Boxing,
|
||||||
|
Breaking,
|
||||||
|
CanoeingSprint,
|
||||||
|
CanoeingSlalom,
|
||||||
|
CyclingBMXFreestyle,
|
||||||
|
CyclingBMXRacing,
|
||||||
|
CyclingMaountainBike,
|
||||||
|
CyclingRoad,
|
||||||
|
CyclingTrack,
|
||||||
|
EquestrianDressage,
|
||||||
|
EquestrianEventing,
|
||||||
|
EquestrianJumping,
|
||||||
|
Fencing,
|
||||||
|
FieldHockey,
|
||||||
|
Football,
|
||||||
|
Golf,
|
||||||
|
GymnasticsArtistic,
|
||||||
|
GymnasticsRhythmic,
|
||||||
|
GymnasticsTrampoline,
|
||||||
|
HandballIndoor,
|
||||||
|
Judo,
|
||||||
|
ModernPentathlon,
|
||||||
|
Rowing,
|
||||||
|
Rugby7,
|
||||||
|
Sailing,
|
||||||
|
Shooting,
|
||||||
|
Skateboarding,
|
||||||
|
SportClimbing,
|
||||||
|
Surfing,
|
||||||
|
TableTennis,
|
||||||
|
Taekwondo,
|
||||||
|
Tennis,
|
||||||
|
Triathlon,
|
||||||
|
VolleyballBeach,
|
||||||
|
VolleyballIndoor,
|
||||||
|
Weightlifting,
|
||||||
|
WrestlingFreestyle,
|
||||||
|
WrestlingGrecoRoman
|
||||||
|
};
|
||||||
|
|
||||||
|
QJsonObject getSportData(Disciplines sport);
|
||||||
|
string getDisciplineShort(Disciplines sport);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ITAT_CHALLANGE_OLYMPICS_OLYMPICSAPI_H
|
|
@ -20,8 +20,8 @@
|
||||||
// console output
|
// console output
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
// #include <iostream>
|
// #include <iostream>
|
||||||
|
#include "../model/Sport.h"
|
||||||
#include "../model/FilterModel.h"
|
#include "../model/FilterModel.h"
|
||||||
#include "../model/SportModel.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,126 +1,15 @@
|
||||||
|
|
||||||
#include "Competitor.h"
|
#include "Competitor.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads certain properties from a competitor json object.
|
|
||||||
* These are: code, name, noc, results
|
|
||||||
*
|
|
||||||
* For further information on 'results' see [Competitor::setResult].
|
|
||||||
*
|
|
||||||
* Does not set the amounts of medals. For this, call [Competitor::setMedals].
|
|
||||||
*
|
|
||||||
* @param competitor The competitor as a QJsonObject.
|
|
||||||
* @return True if successful.
|
|
||||||
*/
|
|
||||||
bool Competitor::setCompetitor(const QJsonObject &competitor) {
|
bool Competitor::setCompetitor(const QJsonObject &competitor) {
|
||||||
if (!competitor.contains("code")
|
if (!competitor.contains("code")
|
||||||
|| !competitor.contains("name")
|
|| !competitor.contains("name")
|
||||||
|| !competitor.contains("noc")) {
|
|| !competitor.contains("noc")) {
|
||||||
return false;
|
throw invalid_argument("Not a competitor object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
setCode(competitor["code"].toInt());
|
this->code = competitor["code"].toString();
|
||||||
setName(competitor["name"].toString());
|
this->name = competitor["name"].toString();
|
||||||
setNOC(competitor["noc"].toString());
|
this->noc = competitor["noc"].toString();
|
||||||
|
|
||||||
if (!competitor.contains("results")) return false;
|
|
||||||
QJsonObject results = competitor["results"].toObject();
|
|
||||||
return setResults(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies all values of a given competitor.
|
|
||||||
*
|
|
||||||
* @param competitor The competitor to copy.
|
|
||||||
*/
|
|
||||||
void Competitor::setCompetitor(const Competitor &competitor) {
|
|
||||||
setCode(competitor.m_code);
|
|
||||||
setName(competitor.m_name);
|
|
||||||
setNOC(competitor.m_noc);
|
|
||||||
setMark(competitor.m_mark);
|
|
||||||
setMedalType(competitor.m_medalType);
|
|
||||||
setStatistic(competitor.m_statistic);
|
|
||||||
setGold(competitor.m_gold);
|
|
||||||
setSilver(competitor.m_silver);
|
|
||||||
setBronze(competitor.m_bronze);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces/sets the results of a competitor.
|
|
||||||
*
|
|
||||||
* @param results The results of the competitor.
|
|
||||||
* @return True, if successful.
|
|
||||||
*/
|
|
||||||
bool Competitor::setResults(const QJsonObject &results) {
|
|
||||||
if (!results.contains("mark")
|
|
||||||
|| !results.contains("medalType")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setMark(results["mark"].toString());
|
|
||||||
setMedalType(results["medalType"].toString());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces/sets the won medals of a competitor.
|
|
||||||
*
|
|
||||||
* @param medals The won medals with their amount.
|
|
||||||
* @return True, if successful.
|
|
||||||
*/
|
|
||||||
bool Competitor::setMedals(const map<QString, int> &medals) {
|
|
||||||
if (medals.find("ME_GOLD") == medals.end()
|
|
||||||
|| medals.find("ME_SILVER") == medals.end()
|
|
||||||
|| medals.find("ME_BRONZE") == medals.end()) return false;
|
|
||||||
|
|
||||||
setGold(medals.find("ME_GOLD")->second);
|
|
||||||
setSilver(medals.find("ME_SILVER")->second);
|
|
||||||
setBronze(medals.find("ME_BRONZE")->second);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static compare method, which can compare the result times or points of two competitors.
|
|
||||||
* Returns true, if the left competitor (lComp) got a real lesser score than the right competitor (rComp).
|
|
||||||
*
|
|
||||||
* @param lComp First competitor to compare.
|
|
||||||
* @param rComp Second competitor to compare.
|
|
||||||
* @return True, if the second competitor got a higher score.
|
|
||||||
*/
|
|
||||||
bool Competitor::compareMark(Competitor lComp, Competitor rComp) {
|
|
||||||
QString l = lComp.mark();
|
|
||||||
QString r = rComp.mark();
|
|
||||||
|
|
||||||
// check if values are numerical (-> not time values)
|
|
||||||
if (!l.contains(":") || !r.contains(":")) {
|
|
||||||
return l.toFloat() < r.toFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
// compare time values if not numerical
|
|
||||||
QString lTime(""), rTime("");
|
|
||||||
|
|
||||||
for (QChar c : l) if (c.isDigit()) lTime.append(c);
|
|
||||||
for (QChar c : r) if (c.isDigit()) rTime.append(c);
|
|
||||||
|
|
||||||
return lTime.compare(rTime) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static compare method, which can compare the amount of medals of two competitors.
|
|
||||||
* Gold has the highest priority, then m_silver and finally m_bronze.
|
|
||||||
*
|
|
||||||
* @param lComp First competitor to compare.
|
|
||||||
* @param rComp Second competitor to compare.
|
|
||||||
* @return True, if the second competitor got more or higher medals.
|
|
||||||
*/
|
|
||||||
bool Competitor::compareMedals(Competitor lComp, Competitor rComp) {
|
|
||||||
// create difference between medal amounts
|
|
||||||
int gold = lComp.gold() - rComp.gold();
|
|
||||||
int silver = lComp.silver() - rComp.silver();
|
|
||||||
int bronze = lComp.bronze() - rComp.bronze();
|
|
||||||
|
|
||||||
// compare medal differences
|
|
||||||
return gold < 0 || (gold == 0 && (silver < 0 || (silver == 0 && bronze < 0)));
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,95 +1,39 @@
|
||||||
|
|
||||||
#pragma once
|
#ifndef ITAT_CHALLANGE_OLYMPICS_COMPETITOR_H
|
||||||
|
#define ITAT_CHALLANGE_OLYMPICS_COMPETITOR_H
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QObject>
|
#include <stdexcept>
|
||||||
#include <qqml.h>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class Competitor : public QObject {
|
class Competitor {
|
||||||
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(int code READ code NOTIFY codeChanged)
|
|
||||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
|
||||||
Q_PROPERTY(QString noc READ noc NOTIFY nocChanged)
|
|
||||||
|
|
||||||
// results in a certain event/category
|
|
||||||
Q_PROPERTY(QString mark READ mark NOTIFY markChanged)
|
|
||||||
Q_PROPERTY(QString medalType READ medalType NOTIFY medalTypeChanged)
|
|
||||||
Q_PROPERTY(QString statistic READ statistic NOTIFY statisticChanged)
|
|
||||||
|
|
||||||
// medal amounts in the whole discipline
|
|
||||||
Q_PROPERTY(int gold READ gold NOTIFY goldChanged)
|
|
||||||
Q_PROPERTY(int silver READ silver NOTIFY silverChanged)
|
|
||||||
Q_PROPERTY(int bronze READ bronze NOTIFY bronzeChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Competitor(QObject *parent) : QObject(parent) {}
|
Competitor(const Competitor &competitor) {
|
||||||
|
this->code = competitor.code;
|
||||||
|
this->name = competitor.name;
|
||||||
|
this->noc = competitor.noc;
|
||||||
|
}
|
||||||
|
|
||||||
// getter
|
Competitor(const QJsonObject &competitor) {
|
||||||
int code() const { return this->m_code; }
|
setCompetitor(competitor);
|
||||||
QString name() const { return this->m_name; }
|
}
|
||||||
QString noc() const { return this->m_noc; }
|
|
||||||
QString mark() const { return this->m_mark; }
|
|
||||||
QString medalType() const { return this->m_medalType; }
|
|
||||||
QString statistic() const { return this->m_statistic; }
|
|
||||||
int gold() const { return this->m_gold; }
|
|
||||||
int silver() const { return this->m_silver; }
|
|
||||||
int bronze() const { return this->m_bronze; }
|
|
||||||
|
|
||||||
// setter
|
QString getCode() { return this->code; }
|
||||||
void setCode(int code) { this->m_code = code; }
|
QString getName() { return this->name; }
|
||||||
void setName(QString name) { this->m_name = name; }
|
QString getNOC() { return this->noc; }
|
||||||
void setNOC(QString noc) { this->m_noc = noc; }
|
|
||||||
void setMark(QString mark) { this->m_mark = mark; }
|
|
||||||
void setMedalType(QString medalType) { this->m_medalType = medalType; }
|
|
||||||
void setStatistic(QString stat) { this->m_statistic = stat; }
|
|
||||||
void setGold(int gold) { this->m_gold = gold; }
|
|
||||||
void setSilver(int silver) { this->m_silver = silver; }
|
|
||||||
void setBronze(int bronze) { this->m_bronze = bronze; }
|
|
||||||
|
|
||||||
bool setResults(const QJsonObject &results);
|
|
||||||
bool setMedals(const map<QString, int> &medals);
|
|
||||||
|
|
||||||
bool setCompetitor(const QJsonObject &competitor);
|
bool setCompetitor(const QJsonObject &competitor);
|
||||||
void setCompetitor(const Competitor &competitor);
|
|
||||||
|
|
||||||
static bool compareName(Competitor lComp, Competitor rComp) {
|
|
||||||
return lComp.m_name.compare(rComp.m_name) < 0;
|
|
||||||
}
|
|
||||||
static bool compareNOC(Competitor lComp, Competitor rComp) {
|
|
||||||
return lComp.m_noc.compare(rComp.m_noc) < 0;
|
|
||||||
}
|
|
||||||
static bool compareMark(Competitor lComp, Competitor rComp);
|
|
||||||
static bool compareMedals(Competitor lComp, Competitor rComp);
|
|
||||||
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void codeChanged();
|
|
||||||
void nameChanged();
|
|
||||||
void nocChanged();
|
|
||||||
void markChanged();
|
|
||||||
void medalTypeChanged();
|
|
||||||
void statisticChanged();
|
|
||||||
void goldChanged();
|
|
||||||
void silverChanged();
|
|
||||||
void bronzeChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_code;
|
QString code;
|
||||||
QString m_name;
|
QString name;
|
||||||
QString m_noc;
|
QString noc;
|
||||||
|
|
||||||
QString m_mark;
|
|
||||||
QString m_medalType;
|
|
||||||
QString m_statistic;
|
|
||||||
|
|
||||||
int m_gold;
|
|
||||||
int m_silver;
|
|
||||||
int m_bronze;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ITAT_CHALLANGE_OLYMPICS_COMPETITOR_H
|
||||||
|
|
15
src/model/CompetitorWithResults.cpp
Normal file
15
src/model/CompetitorWithResults.cpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
#include "CompetitorWithResults.h"
|
||||||
|
|
||||||
|
bool CompetitorWithResults::setResults(const QJsonObject &results) {
|
||||||
|
if (!results.contains("mark")
|
||||||
|
|| !results.contains("medalType")) {
|
||||||
|
throw invalid_argument("Results object of competitor is incomplete.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->results = {
|
||||||
|
{QString("mark"), results["mark"].toString()},
|
||||||
|
{QString("medalType"), results["medalType"].toString()}
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
28
src/model/CompetitorWithResults.h
Normal file
28
src/model/CompetitorWithResults.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
#ifndef ITAT_CHALLANGE_OLYMPICS_COMPETITORWITHRESULTS_H
|
||||||
|
#define ITAT_CHALLANGE_OLYMPICS_COMPETITORWITHRESULTS_H
|
||||||
|
|
||||||
|
#include "Competitor.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
class CompetitorWithResults : public Competitor {
|
||||||
|
|
||||||
|
public:
|
||||||
|
CompetitorWithResults(const QJsonObject &competitor) : Competitor(competitor) {
|
||||||
|
if (!competitor.contains("results")) throw invalid_argument("Competitor does not contain results.");
|
||||||
|
QJsonObject results = competitor["results"].toObject();
|
||||||
|
setResults(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setResults(const QJsonObject &results);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QString, QString> results;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ITAT_CHALLANGE_OLYMPICS_COMPETITORWITHRESULTS_H
|
|
@ -1,21 +1,22 @@
|
||||||
|
#include <QObject>
|
||||||
#include "EventInfo.h"
|
#include "EventInfo.h"
|
||||||
|
|
||||||
EventInfo::EventInfo(QObject *parent) : QObject(parent) {
|
EventInfo::EventInfo(QObject *parent) : QObject(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EventInfo::eventName() const {
|
QString EventInfo::eventName() const {
|
||||||
return this->m_eventName;
|
return m_eventName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventInfo::setEventName(const QString &newEventName) {
|
void EventInfo::setEventName(const QString &newEventName) {
|
||||||
m_eventName = newEventName;
|
m_eventName = newEventName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Competitor*> EventInfo::competitors() const {
|
QList<QString> EventInfo::competitors() const {
|
||||||
return m_competitors;
|
return m_competitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventInfo::setCompetitors(const QList<Competitor*> &newCompetitors) {
|
void EventInfo::setCompetitors(const QList<QString> &newCompetitors) {
|
||||||
this->m_competitors = newCompetitors;
|
m_competitors = newCompetitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,28 @@
|
||||||
#pragma once
|
#ifndef ITAT_CHALLANGE_OLYMPICS_EVENT_H
|
||||||
|
#define ITAT_CHALLANGE_OLYMPICS_EVENT_H
|
||||||
|
|
||||||
#include "Competitor.h"
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QAbstractListModel>
|
|
||||||
#include <qqml.h>
|
#include <qqml.h>
|
||||||
|
|
||||||
class EventInfo : public QObject {
|
class EventInfo : QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
// QML_ELEMENT
|
// QML_ELEMENT
|
||||||
|
|
||||||
Q_PROPERTY(QString eventName READ eventName CONSTANT)
|
Q_PROPERTY(QString eventName READ eventName WRITE setEventName);
|
||||||
Q_PROPERTY(QList<Competitor*> competitors READ competitors CONSTANT)
|
Q_PROPERTY(QList<QString> competitors READ competitors WRITE setCompetitors);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EventInfo(QObject *parent = nullptr);
|
explicit EventInfo(QObject *parent = nullptr);
|
||||||
|
|
||||||
QString eventName() const;
|
QString eventName() const;
|
||||||
void setEventName(const QString &newEventName);
|
void setEventName(const QString &newEventName);
|
||||||
|
|
||||||
QList<Competitor*> competitors() const;
|
QList<QString> competitors() const;
|
||||||
void setCompetitors(const QList<Competitor*> &newCompetitors);
|
void setCompetitors(const QList<QString> &newCompetitors);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_eventName;
|
QString m_eventName;
|
||||||
QList<Competitor*> m_competitors;
|
QList<QString> m_competitors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "FilterModel.h"
|
#include "FilterModel.h"
|
||||||
#include "SportModel.h"
|
#include "Sport.h"
|
||||||
|
|
||||||
FilterModel::FilterModel(QObject *parent)
|
FilterModel::FilterModel(QObject *parent)
|
||||||
: QSortFilterProxyModel(parent) {
|
: QSortFilterProxyModel(parent) {
|
||||||
|
|
18
src/model/MedalWinner.cpp
Normal file
18
src/model/MedalWinner.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#include "MedalWinner.h"
|
||||||
|
|
||||||
|
bool MedalWinner::setMedals(const QJsonObject &medals) {
|
||||||
|
if (!medals.contains("ME_GOLD")
|
||||||
|
|| !medals.contains("ME_SILVER")
|
||||||
|
|| !medals.contains("ME_BRONZE")) {
|
||||||
|
throw invalid_argument("Medal object of competitor is incomplete.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->wonMedals = {
|
||||||
|
{QString("ME_GOLD"), medals["ME_GOLD"].toString()},
|
||||||
|
{QString("ME_SILVER"), medals["ME_SILVER"].toString()},
|
||||||
|
{QString("ME_BRONZE"), medals["ME_BRONZE"].toString()}
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
35
src/model/MedalWinner.h
Normal file
35
src/model/MedalWinner.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#ifndef ITAT_CHALLANGE_OLYMPICS_MEDALWINNER_H
|
||||||
|
#define ITAT_CHALLANGE_OLYMPICS_MEDALWINNER_H
|
||||||
|
|
||||||
|
#include "Competitor.h"
|
||||||
|
#include <QMap>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
class MedalWinner : public Competitor {
|
||||||
|
|
||||||
|
public:
|
||||||
|
MedalWinner(const MedalWinner &medalWinner) : Competitor(medalWinner) {
|
||||||
|
this->wonMedals = {
|
||||||
|
{QString("ME_GOLD"), medalWinner.wonMedals.value("ME_GOLD")},
|
||||||
|
{QString("ME_SILVER"), medalWinner.wonMedals.value("ME_SILVER")},
|
||||||
|
{QString("ME_BRONZE"), medalWinner.wonMedals.value("ME_BRONZE")}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
MedalWinner(const QJsonObject &competitor) : Competitor(competitor) {
|
||||||
|
if (competitor.contains("medals")) throw invalid_argument("Competitor has no medals.");
|
||||||
|
QJsonObject medals = competitor["medals"].toObject();
|
||||||
|
setMedals(medals);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setMedals(const QJsonObject &medals);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QString, QString> wonMedals;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ITAT_CHALLANGE_OLYMPICS_MEDALWINNER_H
|
|
@ -1,4 +1,4 @@
|
||||||
#include "SportModel.h"
|
#include "Sport.h"
|
||||||
#include "Competitor.h"
|
#include "Competitor.h"
|
||||||
|
|
||||||
// categories
|
// categories
|
||||||
|
@ -8,7 +8,8 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
// sorting and filtering
|
// sorting and filtering
|
||||||
//#include <algorithm>
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
// float to string formatting
|
// float to string formatting
|
||||||
|
@ -41,7 +42,7 @@ QVariant SportModel::data(const QModelIndex &index, int role) const {
|
||||||
return event->eventName();
|
return event->eventName();
|
||||||
|
|
||||||
case Competitors:
|
case Competitors:
|
||||||
return QVariant::fromValue(event->competitors());
|
return event->competitors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,14 +82,14 @@ void SportModel::parseData() {
|
||||||
qDeleteAll(m_sportList);
|
qDeleteAll(m_sportList);
|
||||||
m_sportList.clear();
|
m_sportList.clear();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QByteArray strReply = m_reply->readAll();
|
QByteArray strReply = m_reply->readAll();
|
||||||
|
|
||||||
//parse json
|
//parse json
|
||||||
// qDebug() << "Response:" << strReply;
|
// qDebug() << "Response:" << strReply;
|
||||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(strReply);
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(strReply);
|
||||||
|
|
||||||
map<QString, map<QString, int>> medals = getMedalsOfCompetitors();
|
|
||||||
|
|
||||||
QJsonArray sports = jsonDocument["units"].toArray();
|
QJsonArray sports = jsonDocument["units"].toArray();
|
||||||
for (const auto &sport : sports) {
|
for (const auto &sport : sports) {
|
||||||
QJsonObject entry = sport.toObject();
|
QJsonObject entry = sport.toObject();
|
||||||
|
@ -96,20 +97,15 @@ void SportModel::parseData() {
|
||||||
EventInfo *event = new EventInfo(this);
|
EventInfo *event = new EventInfo(this);
|
||||||
event->setEventName(entry["eventUnitName"].toString());
|
event->setEventName(entry["eventUnitName"].toString());
|
||||||
|
|
||||||
QList<Competitor*> competitors;
|
QList<QString> competitors;
|
||||||
for (const auto &competitor : entry["competitors"].toArray()) {
|
for (const auto &competitor : entry["competitors"].toArray()) {
|
||||||
Competitor *comp = new Competitor(this);
|
competitors << competitor.toObject()["name"].toString();
|
||||||
comp->setCompetitor(competitor.toObject());
|
|
||||||
if (medals.find(comp->name()) != medals.end()) comp->setMedals(medals.find(comp->name())->second);
|
|
||||||
competitors << comp;
|
|
||||||
}
|
}
|
||||||
addRelativeToFirst(competitors);
|
|
||||||
event->setCompetitors(competitors);
|
event->setCompetitors(competitors);
|
||||||
|
|
||||||
qDebug() << entry["eventUnitName"].toString();
|
qDebug() << entry["eventUnitName"].toString();
|
||||||
m_sportList << event;
|
m_sportList << event;
|
||||||
}
|
}
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,17 +124,60 @@ QJsonArray filter(QJsonArray input, function<bool (QJsonObject)> eval) {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static compare function for specific attribute in competitors
|
||||||
|
function<bool (const QJsonValue &left, const QJsonValue &right)> genCompare(QString attribute) {
|
||||||
|
return [attribute](const QJsonValue &left, const QJsonValue &right) {
|
||||||
|
QString l = left.toObject()[attribute].toString();
|
||||||
|
QString r = right.toObject()[attribute].toString();
|
||||||
|
return l.compare(r) < 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// static compare function for the results of a competitor in a specific competition (also called mark)
|
||||||
|
bool compareMark(const QJsonValue &left, const QJsonValue &right) {
|
||||||
|
// check if one competitor has no mark
|
||||||
|
QJsonObject l = left.toObject();
|
||||||
|
if (!l.contains("results")) return true;
|
||||||
|
QJsonObject r = right.toObject();
|
||||||
|
if (!r.contains("results")) return false;
|
||||||
|
|
||||||
|
QString lMark = l["results"].toObject()["mark"].toString();
|
||||||
|
QString rMark = r["results"].toObject()["mark"].toString();
|
||||||
|
|
||||||
|
// check if the marks are numerical values
|
||||||
|
if (!lMark.contains(":") && !rMark.contains(":")) return lMark.toFloat() < rMark.toFloat();
|
||||||
|
|
||||||
|
// compare time values if not numerical
|
||||||
|
QString lTime(""), rTime("");
|
||||||
|
|
||||||
|
for (QChar c : lMark) if (c.isDigit()) lTime.append(c);
|
||||||
|
for (QChar c : rMark) if (c.isDigit()) rTime.append(c);
|
||||||
|
|
||||||
|
return lTime.compare(rTime) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static compare function for the amount of medals a competitor has gotten
|
||||||
|
bool compareMedals(const QJsonValue &left, const QJsonValue &right) {
|
||||||
|
QJsonObject lMedals = left.toObject()["medals"].toObject();
|
||||||
|
QJsonObject rMedals = right.toObject()["medals"].toObject();
|
||||||
|
|
||||||
|
int gold = lMedals["ME_GOLD"].toInt() - rMedals["ME_GOLD"].toInt();
|
||||||
|
int silver = lMedals["ME_SILVER"].toInt() - rMedals["ME_SILVER"].toInt();
|
||||||
|
int bronze = lMedals["ME_BRONZE"].toInt() - rMedals["ME_BRONZE"].toInt();
|
||||||
|
|
||||||
|
return gold < 0 || (gold == 0 && (silver < 0 || (silver == 0 && bronze < 0)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::lastName Reduce the full name to the part that is marked in capital letters (probably last name).
|
* @brief Sport::lastName Reduce the full name to the part that is marked in capital letters (probably last name).
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
*/
|
*/
|
||||||
void SportModel::lastName(QList<Competitor*> &competitors) {
|
void Sport::lastName(QJsonArray &competitors) {
|
||||||
// validate competitors
|
// validate competitors
|
||||||
if (competitors.isEmpty()) return;
|
if (competitors.isEmpty() || !competitors[0].toObject().contains("name")) return;
|
||||||
|
|
||||||
for (int i = 0; i < competitors.size(); i++) {
|
for (int i = 0; i < competitors.size(); ++i) {
|
||||||
Competitor* comp = competitors.value(i);
|
string fullName = competitors[i].toObject()["name"].toString().toUtf8().constData();
|
||||||
string fullName = comp->name().toUtf8().constData();
|
|
||||||
|
|
||||||
// regex to identify names, written in CAPS
|
// regex to identify names, written in CAPS
|
||||||
regex r("[A-Z']{2,}");
|
regex r("[A-Z']{2,}");
|
||||||
|
@ -151,10 +190,15 @@ void SportModel::lastName(QList<Competitor*> &competitors) {
|
||||||
for (string s : m) lastName = lastName + s + " ";
|
for (string s : m) lastName = lastName + s + " ";
|
||||||
|
|
||||||
// remove last space
|
// remove last space
|
||||||
QString name = QString(lastName.substr(0, lastName.size() - 1).c_str());
|
QJsonValue nameValue = QJsonValue(QString(lastName.substr(0, lastName.size() - 1).c_str()));
|
||||||
|
|
||||||
// replace competitor name in list
|
// create new object with replaced name
|
||||||
comp->setName(name);
|
QJsonObject comp(competitors[i].toObject());
|
||||||
|
comp.remove("name");
|
||||||
|
comp.insert("name", nameValue);
|
||||||
|
|
||||||
|
// replace competitor in array
|
||||||
|
competitors.replace(i, comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,21 +206,21 @@ void SportModel::lastName(QList<Competitor*> &competitors) {
|
||||||
* @brief Sport::validateDiscipline Validates the discipline object. Checks for the units attribute.
|
* @brief Sport::validateDiscipline Validates the discipline object. Checks for the units attribute.
|
||||||
* @return True, if discipline contains units.
|
* @return True, if discipline contains units.
|
||||||
*/
|
*/
|
||||||
bool SportModel::validateDiscipline() {
|
bool Sport::validateDiscipline() {
|
||||||
return this->o_discipline.contains("units");
|
return this->discipline.contains("units");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::getCategories Reads all possible categories (also called units).
|
* @brief Sport::getCategories Reads all possible categories (also called units).
|
||||||
* @return A set of all category names.
|
* @return A set of all category names.
|
||||||
*/
|
*/
|
||||||
set<QString> SportModel::getCategories() {
|
set<QString> Sport::getCategories() {
|
||||||
set<QString> categoryNames;
|
set<QString> categoryNames;
|
||||||
|
|
||||||
if (!validateDiscipline()) return categoryNames;
|
if (!validateDiscipline()) return categoryNames;
|
||||||
|
|
||||||
// search in each unit for the category (named "eventUnitName")
|
// search in each unit for the category (named "eventUnitName")
|
||||||
for (const QJsonValueRef &unitRef : this->o_discipline["units"].toArray()) {
|
for (const QJsonValueRef &unitRef : this->discipline["units"].toArray()) {
|
||||||
QJsonObject unit = unitRef.toObject();
|
QJsonObject unit = unitRef.toObject();
|
||||||
|
|
||||||
// validate unit
|
// validate unit
|
||||||
|
@ -189,16 +233,44 @@ set<QString> SportModel::getCategories() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::getMedalsOfCompetitor Filters all competitors, who have at least one medal. These objects are different from getCompetitorsByCategory !!!
|
* @brief Sport::getCompetitorsByCategory Searches for all competitors, who took part in the given category.
|
||||||
* @return All competitors, who won at least one medal. Structure of one competitor: {code, name, m_noc, medals{ME_GOLD, ME_SILVER, ME_BRONZE}}
|
* @param category The category to search in.
|
||||||
|
* @return An QJsonArray with all competitors as QJsonValueRef, which can be casted to QJsonObject.
|
||||||
*/
|
*/
|
||||||
map<QString, map<QString, int>> SportModel::getMedalsOfCompetitors() {
|
QJsonArray Sport::getCompetitorsByCategory(QString category) {
|
||||||
map<QString, map<QString, int>> competitors;
|
QJsonArray competitors;
|
||||||
|
|
||||||
if (!validateDiscipline()) return competitors;
|
if (!validateDiscipline()) return competitors;
|
||||||
|
|
||||||
|
for (const QJsonValueRef &unitRef : this->discipline["units"].toArray()) {
|
||||||
|
QJsonObject unit = unitRef.toObject();
|
||||||
|
|
||||||
|
// validate unit
|
||||||
|
if (!unit.contains("eventUnitName") || !unit.contains("competitors")) continue;
|
||||||
|
|
||||||
|
// search all units with the same category
|
||||||
|
if (unit["eventUnitName"].toString().compare(category, Qt::CaseSensitive) != 0) continue;
|
||||||
|
|
||||||
|
// add all competitors from one unit
|
||||||
|
for (const QJsonValueRef &compRef : unit["competitors"].toArray()) {
|
||||||
|
competitors.push_back(compRef.toObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QJsonArray(competitors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sport::getCompetitorsWithMedal Filters all competitors, who have at least one medal. These objects are different from getCompetitorsByCategory !!!
|
||||||
|
* @return All competitors, who won at least one medal. Structure of one competitor: {code, name, noc, medals{ME_GOLD, ME_SILVER, ME_BRONZE}}
|
||||||
|
*/
|
||||||
|
QJsonArray Sport::getCompetitorsWithMedal() {
|
||||||
|
map<QString, QJsonObject> competitors;
|
||||||
|
|
||||||
|
if (!validateDiscipline()) return QJsonArray();
|
||||||
|
|
||||||
// filter all units, which have medal events
|
// filter all units, which have medal events
|
||||||
QJsonArray units = filter(this->o_discipline["units"].toArray(), [](QJsonObject unit){
|
QJsonArray units = filter(this->discipline["units"].toArray(), [](QJsonObject unit){
|
||||||
// search all units with Final, Gold or Bronze in their name, because these are the categories with the medal winners
|
// search all units with Final, Gold or Bronze in their name, because these are the categories with the medal winners
|
||||||
QString unitName = unit["eventUnitName"].toString();
|
QString unitName = unit["eventUnitName"].toString();
|
||||||
return unitName.contains("Bronze", Qt::CaseSensitive)
|
return unitName.contains("Bronze", Qt::CaseSensitive)
|
||||||
|
@ -233,19 +305,56 @@ map<QString, map<QString, int>> SportModel::getMedalsOfCompetitors() {
|
||||||
|
|
||||||
// check if competitor has other medal(s)
|
// check if competitor has other medal(s)
|
||||||
if (competitors.find(name) == competitors.end()) {
|
if (competitors.find(name) == competitors.end()) {
|
||||||
map<QString, int> emptyMedalObject = {
|
competitors.insert({name, createCompetitorWithMedals(medalComp)});
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the medal count
|
||||||
|
QJsonObject updatedMedalCount = QJsonObject(competitors.find(name)->second["medals"].toObject());
|
||||||
|
|
||||||
|
int amount = updatedMedalCount[medalType].toInt() + 1;
|
||||||
|
updatedMedalCount.remove(medalType);
|
||||||
|
updatedMedalCount.insert(medalType, amount);
|
||||||
|
|
||||||
|
// create new medals QJsonObject and set it in the map
|
||||||
|
competitors.find(name)->second["medals"] = updatedMedalCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert map to QJsonArray
|
||||||
|
QJsonArray output;
|
||||||
|
for (const pair<QString, QJsonObject> &competitor : competitors) {
|
||||||
|
output.append(competitor.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sport::createCompetitorWithMedals Creates a competitor QJsonObject with the following attributes: code, name, noc, medals{ME_GOLD, ME_SILVER, ME_BRONZE}
|
||||||
|
* @param comp The original competitor object.
|
||||||
|
* @return A competitor object with medal counts.
|
||||||
|
*/
|
||||||
|
QJsonObject Sport::createCompetitorWithMedals(QJsonObject comp) {
|
||||||
|
// repair competitor if something is missing
|
||||||
|
if (!comp.contains("code")) comp.insert("code", "0");
|
||||||
|
if (!comp.contains("name")) comp.insert("code", "");
|
||||||
|
if (!comp.contains("noc")) comp.insert("code", "");
|
||||||
|
|
||||||
|
// create new competitor QJsonObject and add it to the competitor map
|
||||||
|
QJsonObject medals {
|
||||||
{"ME_GOLD", 0},
|
{"ME_GOLD", 0},
|
||||||
{"ME_SILVER", 0},
|
{"ME_SILVER", 0},
|
||||||
{"ME_BRONZE", 0}
|
{"ME_BRONZE", 0}
|
||||||
};
|
};
|
||||||
competitors.insert({name, emptyMedalObject});
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the medal count
|
QJsonObject medalComp {
|
||||||
competitors.find(name)->second.find(medalType)->second++;
|
{"code", comp["code"].toString()},
|
||||||
}
|
{"name", comp["name"].toString()},
|
||||||
}
|
{"noc", comp["noc"].toString()},
|
||||||
return competitors;
|
{"medals", medals}
|
||||||
|
};
|
||||||
|
|
||||||
|
return medalComp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,8 +362,8 @@ map<QString, map<QString, int>> SportModel::getMedalsOfCompetitors() {
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
* @param name The (part of the) name to search for.
|
* @param name The (part of the) name to search for.
|
||||||
*/
|
*/
|
||||||
void SportModel::filterByName(QList<Competitor*> &competitors, QString name) {
|
void Sport::filterByName(QJsonArray &competitors, QString name) {
|
||||||
filterCompetitors(competitors, name);
|
filterCompetitors(competitors, QString("name"), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -262,8 +371,8 @@ void SportModel::filterByName(QList<Competitor*> &competitors, QString name) {
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
* @param nocShort The (part of the) national olympics comittee short name to search for.
|
* @param nocShort The (part of the) national olympics comittee short name to search for.
|
||||||
*/
|
*/
|
||||||
void SportModel::filterByCountry(QList<Competitor*> &competitors, QString nocShort) {
|
void Sport::filterByCountry(QJsonArray &competitors, QString nocShort) {
|
||||||
filterCompetitors(competitors, nocShort);
|
filterCompetitors(competitors, QString("noc"), nocShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,12 +381,16 @@ void SportModel::filterByCountry(QList<Competitor*> &competitors, QString nocSho
|
||||||
* @param attribute The attribute to filter by.
|
* @param attribute The attribute to filter by.
|
||||||
* @param filter The string, which should be contained.
|
* @param filter The string, which should be contained.
|
||||||
*/
|
*/
|
||||||
void SportModel::filterCompetitors(QList<Competitor*> &competitors, QString filter) {
|
void Sport::filterCompetitors(QJsonArray &competitors, QString attribute, QString filter) {
|
||||||
for (int i = 0; i < competitors.size(); i++) {
|
for (int i = 0; i < competitors.size(); i++) {
|
||||||
if (!competitors.value(i)->noc().contains(filter)) {
|
QJsonObject comp = competitors[i].toObject();
|
||||||
competitors.remove(i);
|
|
||||||
|
if (!comp.contains(attribute) || !comp[attribute].toString().contains(filter, Qt::CaseInsensitive)) {
|
||||||
|
// remove the competitor, if the attribute does not fit the filter string
|
||||||
|
competitors.removeAt(i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,77 +398,89 @@ void SportModel::filterCompetitors(QList<Competitor*> &competitors, QString filt
|
||||||
* @brief Sport::sortByName Sort the competitors by their name (alphabetical, ascending).
|
* @brief Sport::sortByName Sort the competitors by their name (alphabetical, ascending).
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
*/
|
*/
|
||||||
//void SportModel::sortByName(QList<Competitor*> &competitors) {
|
void Sport::sortByName(QJsonArray &competitors) {
|
||||||
// if (competitors.isEmpty()) return;
|
sortCompetitors(competitors, genCompare( QString("name") ));
|
||||||
// std::sort(competitors.begin(), competitors.end(), Competitor::compareName);
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::sortByCountry Sort the competitors by their national olympic comittee short name (alphabetical, ascending).
|
* @brief Sport::sortByCountry Sort the competitors by their national olympic comittee short name (alphabetical, ascending).
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
*/
|
*/
|
||||||
//void SportModel::sortByCountry(QList<Competitor*> &competitors) {
|
void Sport::sortByCountry(QJsonArray &competitors) {
|
||||||
// if (competitors.isEmpty()) return;
|
sortCompetitors(competitors, genCompare( QString("noc") ));
|
||||||
// std::sort(competitors.begin(), competitors.end(), Competitor::compareNOC);
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::sortByResult Sort the competitors by their results in one specific category (numerical, ascending).
|
* @brief Sport::sortByResult Sort the competitors by their results in one specific category (numerical, ascending).
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
*/
|
*/
|
||||||
//void SportModel::sortByResult(QList<Competitor*> &competitors) {
|
void Sport::sortByResult(QJsonArray &competitors) {
|
||||||
// if (competitors.isEmpty()) return;
|
if (competitors.isEmpty()) return;
|
||||||
// std::sort(competitors.begin(), competitors.end(), Competitor::compareMark);
|
|
||||||
//}
|
QJsonObject comp = competitors[0].toObject();
|
||||||
|
|
||||||
|
if (comp.contains("results")) sortCompetitors(competitors, compareMark);
|
||||||
|
else if (comp.contains("medals")) sortCompetitors(competitors, compareMedals);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::sortByMedals Sort the competitors by their medal amounts in one specific category (numerical, ascending).
|
* @brief Sport::sortCompetitors Sorts the given QJsonArray according to the compare function.
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
|
* @param compare A function to compare two competitors with each other. This defines the order.
|
||||||
*/
|
*/
|
||||||
//void SportModel::sortByMedals(QList<Competitor*> &competitors) {
|
void Sport::sortCompetitors(QJsonArray &competitors, function<bool (const QJsonValue &left, const QJsonValue &right)> compare) {
|
||||||
// if (competitors.isEmpty()) return;
|
make_heap(competitors.begin(), competitors.end(), compare);
|
||||||
// std::sort(competitors.begin(), competitors.end(), Competitor::compareMedals);
|
sort_heap(competitors.begin(), competitors.end(), compare);
|
||||||
//}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::reverseOrder Reverses the order of the competitors.
|
* @brief Sport::reverseOrder Reverses the order of the competitors.
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
*/
|
*/
|
||||||
void SportModel::reverseOrder(QList<Competitor*> &competitors) {
|
void Sport::reverseOrder(QJsonArray &competitors) {
|
||||||
int iterations = competitors.size() / 2; // automatically rounds down
|
int iterations = competitors.size() / 2; // automatically rounds down
|
||||||
|
|
||||||
for (int i = 0; i < iterations; i++) {
|
for (int i = 0; i < iterations; i++) {
|
||||||
Competitor *left = competitors.value(i);
|
QJsonObject temp = competitors[i].toObject();
|
||||||
Competitor *right = competitors.value(competitors.size() - 1 - i);
|
competitors[i] = competitors[competitors.size() - 1 - i].toObject();
|
||||||
|
competitors[competitors.size() - 1 - i] = temp;
|
||||||
competitors.replace(i, right);
|
|
||||||
competitors.replace(competitors.size() - 1 - i, left);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sport::addRelativeToFirst Adds a relative value to the result of all competitors. Relative to the first competitor in the QJsonArray.
|
* @brief Sport::addRelativeToFirst Adds a relative value to the result of all competitors. Relative to the first competitor in the QJsonArray.
|
||||||
* Stores the m_statistic in obj->results->stat for each competitor.
|
* Stores the statistic in obj->results->stat for each competitor.
|
||||||
* @param competitors The competitors of one category.
|
* @param competitors The competitors of one category.
|
||||||
*/
|
*/
|
||||||
void SportModel::addRelativeToFirst(QList<Competitor*> &competitors) {
|
void Sport::addRelativeToFirst(QJsonArray &competitors) {
|
||||||
if (competitors.isEmpty()) return;
|
if (competitors.isEmpty()) return;
|
||||||
|
|
||||||
QString reference = competitors.value(0)->mark();
|
QJsonObject reference = competitors[0].toObject();
|
||||||
|
|
||||||
|
// validate competitors
|
||||||
|
if (!reference.contains("results")) return;
|
||||||
|
|
||||||
|
QString refVal = reference["results"].toObject()["mark"].toString();
|
||||||
|
|
||||||
for (int i = 0; i < competitors.size(); i++) {
|
for (int i = 0; i < competitors.size(); i++) {
|
||||||
Competitor *comp = competitors.value(i);
|
QJsonObject competitor = competitors[i].toObject();
|
||||||
|
QJsonObject results = competitor["results"].toObject();
|
||||||
|
|
||||||
QString result = comp->mark();
|
if (results.contains("stat")) results.remove("stat");
|
||||||
|
|
||||||
// format relative float value to string with 2 digits after decimal point and sign
|
// format relative float value to string with 2 digits after decimal point and sign
|
||||||
stringstream sstream;
|
stringstream sstream;
|
||||||
sstream << fixed << setprecision(2) << calcRelativeStat(reference, result);
|
sstream << fixed << setprecision(2) << calcRelativeStat(refVal, results["mark"].toString());
|
||||||
QString stat(sstream.str().c_str());
|
QString stat(sstream.str().c_str());
|
||||||
stat.append("%");
|
stat.append("%");
|
||||||
if (stat.at(0).isNumber()) stat = QString("+").append(stat);
|
if (stat.at(0).isNumber()) stat = QString("+").append(stat);
|
||||||
|
|
||||||
comp->setStatistic(stat);
|
results.insert("stat", stat);
|
||||||
|
|
||||||
|
competitor.remove("results");
|
||||||
|
competitor.insert("results", results);
|
||||||
|
|
||||||
|
competitors.replace(i, competitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -366,7 +491,7 @@ void SportModel::addRelativeToFirst(QList<Competitor*> &competitors) {
|
||||||
* @param val The value to calculate the deviation from.
|
* @param val The value to calculate the deviation from.
|
||||||
* @return The deviation from ref to val in percent.
|
* @return The deviation from ref to val in percent.
|
||||||
*/
|
*/
|
||||||
float SportModel::calcRelativeStat(QString ref, QString val) {
|
float Sport::calcRelativeStat(QString ref, QString val) {
|
||||||
// check if the value is not a time
|
// check if the value is not a time
|
||||||
if (!ref.contains(":") && !val.contains(":")) {
|
if (!ref.contains(":") && !val.contains(":")) {
|
||||||
float fRef = ref.toFloat();
|
float fRef = ref.toFloat();
|
|
@ -0,0 +1,127 @@
|
||||||
|
#ifndef ITAT_CHALLANGE_OLYMPICS_SPORT_H
|
||||||
|
#define ITAT_CHALLANGE_OLYMPICS_SPORT_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <qcontainerfwd.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QString>
|
||||||
|
#include "EventInfo.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class SportModel : public QAbstractListModel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString discipline READ discipline WRITE setDiscipline NOTIFY disciplineChanged);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Role {
|
||||||
|
EventName = Qt::UserRole + 1,
|
||||||
|
Competitors
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit SportModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
virtual int rowCount(const QModelIndex &parent) const override;
|
||||||
|
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
virtual QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
|
||||||
|
QString discipline() const;
|
||||||
|
void setDiscipline(const QString &discipline);
|
||||||
|
public slots:
|
||||||
|
void request(QString discipline);
|
||||||
|
void parseData();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void disciplineChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<EventInfo*> m_sportList;
|
||||||
|
QString m_discipline;
|
||||||
|
QNetworkAccessManager m_networkManager;
|
||||||
|
QNetworkReply *m_reply = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sport {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Sport(QJsonObject discipline) {
|
||||||
|
this->discipline = discipline;
|
||||||
|
}
|
||||||
|
|
||||||
|
set<QString> getCategories();
|
||||||
|
QJsonArray getCompetitorsByCategory(QString category);
|
||||||
|
QJsonArray getCompetitorsWithMedal();
|
||||||
|
|
||||||
|
// filter to change the current competitor array
|
||||||
|
void lastName(QJsonArray &competitors);
|
||||||
|
void filterByName(QJsonArray &competitors, QString name);
|
||||||
|
void filterByCountry(QJsonArray &competitors, QString nocShort);
|
||||||
|
|
||||||
|
// sort functions to change the order of the current competitor array
|
||||||
|
void sortByName(QJsonArray &competitors);
|
||||||
|
void sortByCountry(QJsonArray &competitors);
|
||||||
|
void sortByResult(QJsonArray &competitors);
|
||||||
|
void reverseOrder(QJsonArray &competitors);
|
||||||
|
|
||||||
|
// statistic function(s)
|
||||||
|
void addRelativeToFirst(QJsonArray &competitors);
|
||||||
|
|
||||||
|
void setDiscipline(QJsonObject discipline) {
|
||||||
|
this->discipline = QJsonObject(discipline);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Analysis of provided competitor objects:
|
||||||
|
*
|
||||||
|
* Attributes:
|
||||||
|
* - code
|
||||||
|
* - noc (national olympics comittee)
|
||||||
|
* - name (sometimes the country name? mostly the competitors name)
|
||||||
|
* - order
|
||||||
|
* [- results] (only if the results are out!)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Analysis of provided result objects:
|
||||||
|
*
|
||||||
|
* Attributes:
|
||||||
|
* - position
|
||||||
|
* - mark
|
||||||
|
* - medalType
|
||||||
|
* - irk
|
||||||
|
* [- winnerLoserTie] (only if provided in the discipline?)
|
||||||
|
*
|
||||||
|
* Analysis of where to find the medal winners:
|
||||||
|
*
|
||||||
|
* Search for ... in category name.
|
||||||
|
* - "Bronze"
|
||||||
|
* - "Gold"
|
||||||
|
* - "Final"
|
||||||
|
*
|
||||||
|
* ! ATTENTION !
|
||||||
|
* When searching for "Final" there might be "Final A", "Final B", etc.
|
||||||
|
* The results will only be in ONE of these categories!
|
||||||
|
* -> which is good... cause then we can count occurences.
|
||||||
|
*/
|
||||||
|
QJsonObject discipline;
|
||||||
|
|
||||||
|
void filterCompetitors(QJsonArray &competitors, QString attribute, QString filter);
|
||||||
|
void sortCompetitors(QJsonArray &competitors, function<bool (const QJsonValue &left, const QJsonValue &right)> compare);
|
||||||
|
|
||||||
|
bool validateDiscipline();
|
||||||
|
QJsonObject createCompetitorWithMedals(QJsonObject medalComp);
|
||||||
|
|
||||||
|
float calcRelativeStat(QString ref, QString val);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,83 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <qcontainerfwd.h>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QString>
|
|
||||||
#include <QList>
|
|
||||||
#include "EventInfo.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
class SportModel : public QAbstractListModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(QString discipline READ discipline WRITE setDiscipline NOTIFY disciplineChanged);
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum Role
|
|
||||||
{
|
|
||||||
EventName = Qt::UserRole + 1,
|
|
||||||
Competitors
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit SportModel(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
void setDiscipline(QJsonObject discipline)
|
|
||||||
{
|
|
||||||
this->o_discipline = QJsonObject(discipline);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int rowCount(const QModelIndex &parent) const override;
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
|
||||||
virtual QHash<int, QByteArray> roleNames() const override;
|
|
||||||
|
|
||||||
set<QString> getCategories();
|
|
||||||
map<QString, map<QString, int>> getMedalsOfCompetitors();
|
|
||||||
|
|
||||||
// filter to change the current competitor list
|
|
||||||
void lastName(QList<Competitor*> &competitors);
|
|
||||||
void filterByName(QList<Competitor*> &competitors, QString name);
|
|
||||||
void filterByCountry(QList<Competitor*> &competitors, QString nocShort);
|
|
||||||
|
|
||||||
// sort functions to change the order of the current competitor list
|
|
||||||
// void sortByName(QList<Competitor*> &competitors);
|
|
||||||
// void sortByCountry(QList<Competitor*> &competitors);
|
|
||||||
// void sortByResult(QList<Competitor*> &competitors);
|
|
||||||
// void sortByMedals(QList<Competitor*> &competitors);
|
|
||||||
void reverseOrder(QList<Competitor*> &competitors);
|
|
||||||
|
|
||||||
// statistic function
|
|
||||||
void addRelativeToFirst(QList<Competitor*> &competitors);
|
|
||||||
|
|
||||||
QString discipline() const;
|
|
||||||
void setDiscipline(const QString &discipline);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void request(QString discipline);
|
|
||||||
void parseData();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void disciplineChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QList<EventInfo *> m_sportList;
|
|
||||||
QString m_discipline;
|
|
||||||
QNetworkAccessManager m_networkManager;
|
|
||||||
QNetworkReply *m_reply = nullptr;
|
|
||||||
|
|
||||||
// data from api
|
|
||||||
QJsonObject o_discipline;
|
|
||||||
bool validateDiscipline();
|
|
||||||
|
|
||||||
void filterCompetitors(QList<Competitor*> &competitors, QString filter); // TODO ref instead of obj
|
|
||||||
|
|
||||||
// function for statistic calculation
|
|
||||||
float calcRelativeStat(QString ref, QString val);
|
|
||||||
|
|
||||||
};
|
|
Loading…
Reference in a new issue