summaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/model')
-rw-r--r--src/model/Competitor.cpp15
-rw-r--r--src/model/Competitor.h39
-rw-r--r--src/model/CompetitorWithResults.cpp15
-rw-r--r--src/model/CompetitorWithResults.h28
-rw-r--r--src/model/MedalWinner.cpp18
-rw-r--r--src/model/MedalWinner.h35
-rw-r--r--src/model/Sport.cpp423
-rw-r--r--src/model/Sport.h92
8 files changed, 665 insertions, 0 deletions
diff --git a/src/model/Competitor.cpp b/src/model/Competitor.cpp
new file mode 100644
index 0000000..a5d2e69
--- /dev/null
+++ b/src/model/Competitor.cpp
@@ -0,0 +1,15 @@
+
+#include "Competitor.h"
+
+bool Competitor::setCompetitor(const QJsonObject &competitor) {
+ if (!competitor.contains("code")
+ || !competitor.contains("name")
+ || !competitor.contains("noc")) {
+ throw invalid_argument("Not a competitor object.");
+ }
+
+ this->code = competitor["code"].toString();
+ this->name = competitor["name"].toString();
+ this->noc = competitor["noc"].toString();
+ return true;
+}
diff --git a/src/model/Competitor.h b/src/model/Competitor.h
new file mode 100644
index 0000000..919c2fa
--- /dev/null
+++ b/src/model/Competitor.h
@@ -0,0 +1,39 @@
+
+#ifndef ITAT_CHALLANGE_OLYMPICS_COMPETITOR_H
+#define ITAT_CHALLANGE_OLYMPICS_COMPETITOR_H
+
+#include <QString>
+#include <QMap>
+#include <QJsonObject>
+#include <stdexcept>
+
+using namespace std;
+
+class Competitor {
+
+public:
+ Competitor(const Competitor &competitor) {
+ this->code = competitor.code;
+ this->name = competitor.name;
+ this->noc = competitor.noc;
+ }
+
+ Competitor(const QJsonObject &competitor) {
+ setCompetitor(competitor);
+ }
+
+ QString getCode() { return this->code; }
+ QString getName() { return this->name; }
+ QString getNOC() { return this->noc; }
+
+ bool setCompetitor(const QJsonObject &competitor);
+
+private:
+ QString code;
+ QString name;
+ QString noc;
+
+};
+
+
+#endif //ITAT_CHALLANGE_OLYMPICS_COMPETITOR_H
diff --git a/src/model/CompetitorWithResults.cpp b/src/model/CompetitorWithResults.cpp
new file mode 100644
index 0000000..d29441d
--- /dev/null
+++ b/src/model/CompetitorWithResults.cpp
@@ -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;
+}
diff --git a/src/model/CompetitorWithResults.h b/src/model/CompetitorWithResults.h
new file mode 100644
index 0000000..cb952f2
--- /dev/null
+++ b/src/model/CompetitorWithResults.h
@@ -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
diff --git a/src/model/MedalWinner.cpp b/src/model/MedalWinner.cpp
new file mode 100644
index 0000000..c4cb663
--- /dev/null
+++ b/src/model/MedalWinner.cpp
@@ -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;
+}
diff --git a/src/model/MedalWinner.h b/src/model/MedalWinner.h
new file mode 100644
index 0000000..e771185
--- /dev/null
+++ b/src/model/MedalWinner.h
@@ -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
diff --git a/src/model/Sport.cpp b/src/model/Sport.cpp
new file mode 100644
index 0000000..21b9b9f
--- /dev/null
+++ b/src/model/Sport.cpp
@@ -0,0 +1,423 @@
+
+#include "Sport.h"
+
+// categories
+#include <set>
+
+// sorting and filtering
+#include <map>
+#include <algorithm>
+#include <regex>
+
+// float to string formatting
+#include <iostream>
+#include <iomanip>
+
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QJsonValueRef>
+#include <QString>
+
+// QJsonArray filter function, provide with input array and evaluation function
+QJsonArray filter(QJsonArray input, function<bool (QJsonObject)> eval) {
+ QJsonArray output;
+
+ for (const QJsonValueRef &elemRef :input) {
+ QJsonObject elem = elemRef.toObject();
+ if(eval(elem)) {
+ output.append(elem);
+ }
+ }
+
+ 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).
+ * @param competitors The competitors of one category.
+ */
+void Sport::lastName(QJsonArray &competitors) {
+ // validate competitors
+ if (competitors.isEmpty() || !competitors[0].toObject().contains("name")) return;
+
+ for (int i = 0; i < competitors.size(); ++i) {
+ string fullName = competitors[i].toObject()["name"].toString().toUtf8().constData();
+
+ // regex to identify names, written in CAPS
+ regex r("[A-Z']{2,}");
+ smatch m;
+
+ regex_search(fullName, m, r);
+
+ // combine found names again
+ string lastName = "";
+ for (string s : m) lastName = lastName + s + " ";
+
+ // remove last space
+ QJsonValue nameValue = QJsonValue(QString(lastName.substr(0, lastName.size() - 1).c_str()));
+
+ // create new object with replaced name
+ QJsonObject comp(competitors[i].toObject());
+ comp.remove("name");
+ comp.insert("name", nameValue);
+
+ // replace competitor in array
+ competitors.replace(i, comp);
+ }
+}
+
+/**
+ * @brief Sport::validateDiscipline Validates the discipline object. Checks for the units attribute.
+ * @return True, if discipline contains units.
+ */
+bool Sport::validateDiscipline() {
+ return this->discipline.contains("units");
+}
+
+/**
+ * @brief Sport::getCategories Reads all possible categories (also called units).
+ * @return A set of all category names.
+ */
+set<QString> Sport::getCategories() {
+ set<QString> categoryNames;
+
+ if (!validateDiscipline()) return categoryNames;
+
+ // search in each unit for the category (named "eventUnitName")
+ for (const QJsonValueRef &unitRef : this->discipline["units"].toArray()) {
+ QJsonObject unit = unitRef.toObject();
+
+ // validate unit
+ if (!unit.contains("eventUnitName")) continue;
+
+ categoryNames.insert(unit["eventUnitName"].toString());
+ }
+
+ return categoryNames;
+}
+
+/**
+ * @brief Sport::getCompetitorsByCategory Searches for all competitors, who took part in the given category.
+ * @param category The category to search in.
+ * @return An QJsonArray with all competitors as QJsonValueRef, which can be casted to QJsonObject.
+ */
+QJsonArray Sport::getCompetitorsByCategory(QString category) {
+ QJsonArray 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
+ 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
+ QString unitName = unit["eventUnitName"].toString();
+ return unitName.contains("Bronze", Qt::CaseSensitive)
+ || unitName.contains("Gold", Qt::CaseSensitive)
+ || unitName.contains("Final", Qt::CaseSensitive);
+ });
+
+ for (const QJsonValueRef &unitRef : units) {
+ QJsonObject unit = unitRef.toObject();
+
+ // validate unit
+ if (!unit.contains("competitors")) continue;
+
+ // filter all competitors, who won medals
+ QJsonArray medalComps = filter(unit["competitors"].toArray(), [](QJsonObject comp) {
+ if (!comp.contains("results")) return false;
+
+ QString medalType = comp["results"].toObject()["medalType"].toString();
+ return !medalType.isEmpty();
+ });
+
+ for (const QJsonValueRef &medalCompRef : medalComps) {
+ QJsonObject medalComp = medalCompRef.toObject();
+
+ // validate competitor (with medal)
+ if (!medalComp.contains("name")
+ || !medalComp.contains("results")
+ || !medalComp["results"].toObject().contains("medalType")) continue;
+
+ QString name = medalComp["name"].toString();
+ QString medalType = medalComp["results"].toObject()["medalType"].toString();
+
+ // check if competitor has other medal(s)
+ if (competitors.find(name) == competitors.end()) {
+ 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_SILVER", 0},
+ {"ME_BRONZE", 0}
+ };
+
+ QJsonObject medalComp {
+ {"code", comp["code"].toString()},
+ {"name", comp["name"].toString()},
+ {"noc", comp["noc"].toString()},
+ {"medals", medals}
+ };
+
+ return medalComp;
+}
+
+/**
+ * @brief Sport::filterByName Filter the competitors by name (case insensitive).
+ * @param competitors The competitors of one category.
+ * @param name The (part of the) name to search for.
+ */
+void Sport::filterByName(QJsonArray &competitors, QString name) {
+ filterCompetitors(competitors, QString("name"), name);
+}
+
+/**
+ * @brief Sport::filterByCountry Filter the competitors by their national olympics comittee (case insensitive, short form).
+ * @param competitors The competitors of one category.
+ * @param nocShort The (part of the) national olympics comittee short name to search for.
+ */
+void Sport::filterByCountry(QJsonArray &competitors, QString nocShort) {
+ filterCompetitors(competitors, QString("noc"), nocShort);
+}
+
+/**
+ * @brief Sport::filterCompetitors Filters the given QJsonArray by comparing the value of a certain attribute with the given filter string.
+ * @param competitors The competitors of one category.
+ * @param attribute The attribute to filter by.
+ * @param filter The string, which should be contained.
+ */
+void Sport::filterCompetitors(QJsonArray &competitors, QString attribute, QString filter) {
+ for (int i = 0; i < competitors.size(); i++) {
+ QJsonObject comp = competitors[i].toObject();
+
+ 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--;
+ }
+
+ }
+}
+
+/**
+ * @brief Sport::sortByName Sort the competitors by their name (alphabetical, ascending).
+ * @param competitors The competitors of one category.
+ */
+void Sport::sortByName(QJsonArray &competitors) {
+ sortCompetitors(competitors, genCompare( QString("name") ));
+}
+
+/**
+ * @brief Sport::sortByCountry Sort the competitors by their national olympic comittee short name (alphabetical, ascending).
+ * @param competitors The competitors of one category.
+ */
+void Sport::sortByCountry(QJsonArray &competitors) {
+ sortCompetitors(competitors, genCompare( QString("noc") ));
+}
+
+/**
+ * @brief Sport::sortByResult Sort the competitors by their results in one specific category (numerical, ascending).
+ * @param competitors The competitors of one category.
+ */
+void Sport::sortByResult(QJsonArray &competitors) {
+ if (competitors.isEmpty()) return;
+
+ QJsonObject comp = competitors[0].toObject();
+
+ if (comp.contains("results")) sortCompetitors(competitors, compareMark);
+ else if (comp.contains("medals")) sortCompetitors(competitors, compareMedals);
+}
+
+/**
+ * @brief Sport::sortCompetitors Sorts the given QJsonArray according to the compare function.
+ * @param competitors The competitors of one category.
+ * @param compare A function to compare two competitors with each other. This defines the order.
+ */
+void Sport::sortCompetitors(QJsonArray &competitors, function<bool (const QJsonValue &left, const QJsonValue &right)> compare) {
+ make_heap(competitors.begin(), competitors.end(), compare);
+ sort_heap(competitors.begin(), competitors.end(), compare);
+}
+
+/**
+ * @brief Sport::reverseOrder Reverses the order of the competitors.
+ * @param competitors The competitors of one category.
+ */
+void Sport::reverseOrder(QJsonArray &competitors) {
+ int iterations = competitors.size() / 2; // automatically rounds down
+
+ for (int i = 0; i < iterations; i++) {
+ QJsonObject temp = competitors[i].toObject();
+ competitors[i] = competitors[competitors.size() - 1 - i].toObject();
+ competitors[competitors.size() - 1 - i] = temp;
+ }
+}
+
+/**
+ * @brief Sport::addRelativeToFirst Adds a relative value to the result of all competitors. Relative to the first competitor in the QJsonArray.
+ * Stores the statistic in obj->results->stat for each competitor.
+ * @param competitors The competitors of one category.
+ */
+void Sport::addRelativeToFirst(QJsonArray &competitors) {
+ if (competitors.isEmpty()) return;
+
+ 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++) {
+ QJsonObject competitor = competitors[i].toObject();
+ QJsonObject results = competitor["results"].toObject();
+
+ if (results.contains("stat")) results.remove("stat");
+
+ // format relative float value to string with 2 digits after decimal point and sign
+ stringstream sstream;
+ sstream << fixed << setprecision(2) << calcRelativeStat(refVal, results["mark"].toString());
+ QString stat(sstream.str().c_str());
+ stat.append("%");
+ if (stat.at(0).isNumber()) stat = QString("+").append(stat);
+
+ results.insert("stat", stat);
+
+ competitor.remove("results");
+ competitor.insert("results", results);
+
+ competitors.replace(i, competitor);
+ }
+
+}
+
+/**
+ * @brief Sport::calcRelativeStat Calculates the relative deviation of val from ref in percent.
+ * @param ref The reference value.
+ * @param val The value to calculate the deviation from.
+ * @return The deviation from ref to val in percent.
+ */
+float Sport::calcRelativeStat(QString ref, QString val) {
+ // check if the value is not a time
+ if (!ref.contains(":") && !val.contains(":")) {
+ float fRef = ref.toFloat();
+
+ if (fRef == 0) return 0.0;
+ return ((val.toFloat() * 100)/ fRef) - 100;
+ }
+
+ regex r("\\d+");
+ smatch mref, mval;
+ string sref = ref.toUtf8().constData();
+ string sval = val.toUtf8().constData();
+
+ regex_search(sref, mref, r);
+ regex_search(sval, mval, r);
+
+ float timeRef = stof(mref.str(1)) * 60 * 100 + stof(mref.str(2)) * 100 + stof(mref.str(3));
+ float timeVal = stof(mval.str(1)) * 60 * 100 + stof(mval.str(2)) * 100 + stof(mval.str(3));
+
+ return ((timeVal * 100) / timeRef) - 100;
+}
diff --git a/src/model/Sport.h b/src/model/Sport.h
new file mode 100644
index 0000000..147f6e8
--- /dev/null
+++ b/src/model/Sport.h
@@ -0,0 +1,92 @@
+
+#ifndef ITAT_CHALLANGE_OLYMPICS_SPORT_H
+#define ITAT_CHALLANGE_OLYMPICS_SPORT_H
+
+
+#include <set>
+
+#include <QJsonObject>
+#include <QJsonDocument>
+#include <QString>
+
+using namespace std;
+
+
+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 //ITAT_CHALLANGE_OLYMPICS_SPORT_H