From 492a726497785e8072e76a415dbbfdbd498e1b92 Mon Sep 17 00:00:00 2001 From: Steru Date: Thu, 15 Aug 2024 20:41:08 +0200 Subject: Reworked Sport class to work with QObjects instead of JSON objects. --- src/model/Competitor.h | 11 +++ src/model/CompetitorWithResults.h | 4 + src/model/Sport.cpp | 159 ++++++++++----------------------- src/model/Sport.h | 179 +++++++++++++++++++------------------- 4 files changed, 151 insertions(+), 202 deletions(-) (limited to 'src') diff --git a/src/model/Competitor.h b/src/model/Competitor.h index 1121a5b..e5b0251 100644 --- a/src/model/Competitor.h +++ b/src/model/Competitor.h @@ -39,8 +39,19 @@ public: QString getName() { return this->name; } QString getNOC() { return this->noc; } + void setCode(int code) { this->code = code; } + void setName(QString name) { this->name = name; } + void setNOC(QString noc) { this->noc = noc; } + bool setCompetitor(const QJsonObject &competitor); + static bool compareName(const Competitor &left, const Competitor &right) { + return left.name.compare(right.name) < 0; + } + static bool compareNOC(const Competitor &left, const Competitor &right) { + return left.noc.compare(right.noc) < 0; + } + private: int code; QString name; diff --git a/src/model/CompetitorWithResults.h b/src/model/CompetitorWithResults.h index a313db2..f57b773 100644 --- a/src/model/CompetitorWithResults.h +++ b/src/model/CompetitorWithResults.h @@ -15,6 +15,7 @@ class CompetitorWithResults : public Competitor { Q_PROPERTY(QString mark READ mark) Q_PROPERTY(QString medalType READ medalType) + Q_PROPERTY(QString statistic READ statistic WRITE setStatistic) public: CompetitorWithResults() : Competitor() { @@ -34,15 +35,18 @@ public: } bool setResults(const QJsonObject &results); + void setStatistic(QString stat) { this->statistic = stat; } QString getMark() { return this->mark; } QString getMedalType() { return this->medalType; } + QString getStatistic() { return this->statistic; } static bool compare(CompetitorWithResults lComp, CompetitorWithResults rComp); private: QString mark; QString medalType; + QString statistic; }; diff --git a/src/model/Sport.cpp b/src/model/Sport.cpp index c7a9c72..4b822fa 100644 --- a/src/model/Sport.cpp +++ b/src/model/Sport.cpp @@ -124,60 +124,16 @@ QJsonArray filter(QJsonArray input, function eval) { return output; } -// static compare function for specific attribute in competitors -function 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) { +void Sport::lastName(QList &competitors) { // validate competitors - if (competitors.isEmpty() || !competitors[0].toObject().contains("name")) return; + if (competitors.isEmpty()) return; - for (int i = 0; i < competitors.size(); ++i) { - string fullName = competitors[i].toObject()["name"].toString().toUtf8().constData(); + for (Competitor comp : competitors) { + string fullName = comp.getName().toUtf8().constData(); // regex to identify names, written in CAPS regex r("[A-Z']{2,}"); @@ -190,15 +146,10 @@ void Sport::lastName(QJsonArray &competitors) { for (string s : m) lastName = lastName + s + " "; // remove last space - QJsonValue nameValue = QJsonValue(QString(lastName.substr(0, lastName.size() - 1).c_str())); + QString name = 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); + // replace competitor name in list + comp.setName(name); } } @@ -237,8 +188,8 @@ set Sport::getCategories() { * @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; +QList Sport::getCompetitorsByCategory(QString category) { + QList competitors; if (!validateDiscipline()) return competitors; @@ -253,21 +204,21 @@ QJsonArray Sport::getCompetitorsByCategory(QString category) { // add all competitors from one unit for (const QJsonValueRef &compRef : unit["competitors"].toArray()) { - competitors.push_back(compRef.toObject()); + competitors.push_back(CompetitorWithResults(compRef.toObject())); } } - return QJsonArray(competitors); + return 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() { +QList Sport::getCompetitorsWithMedal() { map competitors; - if (!validateDiscipline()) return QJsonArray(); + if (!validateDiscipline()) return QList(); // filter all units, which have medal events QJsonArray units = filter(this->discipline["units"].toArray(), [](QJsonObject unit){ @@ -321,9 +272,9 @@ QJsonArray Sport::getCompetitorsWithMedal() { } // convert map to QJsonArray - QJsonArray output; + QList output; for (const pair &competitor : competitors) { - output.append(competitor.second); + output.append(MedalWinner(competitor.second)); } return output; @@ -362,8 +313,8 @@ QJsonObject Sport::createCompetitorWithMedals(QJsonObject comp) { * @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); +void Sport::filterByName(QList &competitors, QString name) { + filterCompetitors(competitors, name); } /** @@ -371,8 +322,8 @@ void Sport::filterByName(QJsonArray &competitors, QString name) { * @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); +void Sport::filterByCountry(QList &competitors, QString nocShort) { + filterCompetitors(competitors, nocShort); } /** @@ -381,16 +332,12 @@ void Sport::filterByCountry(QJsonArray &competitors, QString nocShort) { * @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); +void Sport::filterCompetitors(QList &competitors, QString filter) { + for (qsizetype i = 0; i < competitors.size(); i++) { + if (competitors.value(i).getNOC().contains(filter)) { + competitors.remove(i); i--; } - } } @@ -398,52 +345,49 @@ void Sport::filterCompetitors(QJsonArray &competitors, QString attribute, QStrin * @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") )); +void Sport::sortByName(QList &competitors) { + if (competitors.isEmpty()) return; + sort(competitors.begin(), competitors.end(), Competitor::compareName); } /** * @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") )); +void Sport::sortByCountry(QList &competitors) { + if (competitors.isEmpty()) return; + sort(competitors.begin(), competitors.end(), Competitor::compareNOC); } /** * @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) { +void Sport::sortByResult(QList &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); + sort(competitors.begin(), competitors.end(), CompetitorWithResults::compare); } /** - * @brief Sport::sortCompetitors Sorts the given QJsonArray according to the compare function. + * @brief Sport::sortByMedals Sort the competitors by their medal amounts in one specific category (numerical, ascending). * @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 compare) { - make_heap(competitors.begin(), competitors.end(), compare); - sort_heap(competitors.begin(), competitors.end(), compare); +void Sport::sortByMedals(QList &competitors) { + if (competitors.isEmpty()) return; + sort(competitors.begin(), competitors.end(), MedalWinner::compare); } /** * @brief Sport::reverseOrder Reverses the order of the competitors. * @param competitors The competitors of one category. */ -void Sport::reverseOrder(QJsonArray &competitors) { +void Sport::reverseOrder(QList &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; + Competitor temp = competitors.value(i); + competitors.replace(i, competitors.value(competitors.size() - 1 - i)); + competitors.replace(competitors.size() - 1 - i, temp); } } @@ -452,35 +396,22 @@ void Sport::reverseOrder(QJsonArray &competitors) { * Stores the statistic in obj->results->stat for each competitor. * @param competitors The competitors of one category. */ -void Sport::addRelativeToFirst(QJsonArray &competitors) { +void Sport::addRelativeToFirst(QList &competitors) { if (competitors.isEmpty()) return; - QJsonObject reference = competitors[0].toObject(); - - // validate competitors - if (!reference.contains("results")) return; - - QString refVal = reference["results"].toObject()["mark"].toString(); + QString reference = competitors.value(0).getMark(); - 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"); + for (CompetitorWithResults comp : competitors) { + QString results = comp.getMark(); // 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()); + sstream << fixed << setprecision(2) << calcRelativeStat(reference, 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); + comp.setStatistic(stat); } } diff --git a/src/model/Sport.h b/src/model/Sport.h index 6a68570..2ca83a3 100644 --- a/src/model/Sport.h +++ b/src/model/Sport.h @@ -1,6 +1,8 @@ #ifndef ITAT_CHALLANGE_OLYMPICS_SPORT_H #define ITAT_CHALLANGE_OLYMPICS_SPORT_H +#include "MedalWinner.h" +#include "CompetitorWithResults.h" #include #include #include @@ -9,33 +11,35 @@ #include #include #include +#include #include "EventInfo.h" using namespace std; -class SportModel : public QAbstractListModel { +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); +public: + enum Role + { + EventName = Qt::UserRole + 1, + Competitors + }; - virtual int rowCount(const QModelIndex &parent) const override; - virtual QVariant data(const QModelIndex &index, int role) const override; - virtual QHash roleNames() const override; + 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 roleNames() const override; - QString discipline() const; - void setDiscipline(const QString &discipline); - public slots: - void request(QString discipline); - void parseData(); + QString discipline() const; + void setDiscipline(const QString &discipline); +public slots: + void request(QString discipline); + void parseData(); signals: void disciplineChanged(); @@ -47,81 +51,80 @@ class SportModel : public QAbstractListModel { QNetworkReply *m_reply = nullptr; }; -class Sport { +class Sport +{ public: - - Sport(QJsonObject discipline) { - this->discipline = discipline; - } - - set 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); - } + Sport(QJsonObject discipline) + { + this->discipline = discipline; + } + + set getCategories(); + QList getCompetitorsByCategory(QString category); + QList getCompetitorsWithMedal(); + + // filter to change the current competitor array + void lastName(QList &competitors); + void filterByName(QList &competitors, QString name); + void filterByCountry(QList &competitors, QString nocShort); + + // sort functions to change the order of the current competitor array + void sortByName(QList &competitors); + void sortByCountry(QList &competitors); + void sortByResult(QList &competitors); + void sortByMedals(QList &competitors); + void reverseOrder(QList &competitors); + + // statistic function(s) + void addRelativeToFirst(QList &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 compare); - - bool validateDiscipline(); - QJsonObject createCompetitorWithMedals(QJsonObject medalComp); - - float calcRelativeStat(QString ref, QString val); - + /* + * 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(QList &competitors, QString filter); + + bool validateDiscipline(); + QJsonObject createCompetitorWithMedals(QJsonObject medalComp); + + float calcRelativeStat(QString ref, QString val); }; - -#endif +#endif -- cgit v1.2.3