diff options
| author | Steru <jerrydream111@gmail.com> | 2024-08-04 22:56:15 +0200 | 
|---|---|---|
| committer | Steru <jerrydream111@gmail.com> | 2024-08-04 22:56:15 +0200 | 
| commit | 77f8836508a4c28c7c6c1352ff891c5d36d00237 (patch) | |
| tree | c32cacf93e74ae546fe225e8f8cb351768ed4b90 /src | |
| parent | 0445396ffa371cdc546d7198efc0677ad42b7aa5 (diff) | |
Added method to get medal winners. Adjusted sort result method to also work with the medal winners.
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/OlympicsAPI.cpp | 28 | ||||
| -rw-r--r-- | src/discipline/Sport.cpp | 144 | ||||
| -rw-r--r-- | src/discipline/Sport.h | 22 | 
3 files changed, 164 insertions, 30 deletions
| diff --git a/src/api/OlympicsAPI.cpp b/src/api/OlympicsAPI.cpp index 4fe9701..0334800 100644 --- a/src/api/OlympicsAPI.cpp +++ b/src/api/OlympicsAPI.cpp @@ -121,20 +121,20 @@ string OlympicsAPI::getDisciplineShort(OlympicsAPI::Disciplines sport) {      case OlympicsAPI::Disciplines::ModernPentathlon: return "MPN";      case OlympicsAPI::Disciplines::Rowing: return "ROW";      case OlympicsAPI::Disciplines::Rugby7: return "RU7"; -    case OlympicsAPI::Disciplines::Sailing: return "SAL"; break; -    case OlympicsAPI::Disciplines::Shooting: return "SHO"; break; -    case OlympicsAPI::Disciplines::Skateboarding: return "SKB"; break; -    case OlympicsAPI::Disciplines::SportClimbing: return "CLB"; break; -    case OlympicsAPI::Disciplines::Surfing: return "SRF"; break; -    case OlympicsAPI::Disciplines::TableTennis: return "TTE"; break; -    case OlympicsAPI::Disciplines::Taekwondo: return "TKW"; break; -    case OlympicsAPI::Disciplines::Tennis: return "TEN"; break; -    case OlympicsAPI::Disciplines::Triathlon: return "TRI"; break; -    case OlympicsAPI::Disciplines::VolleyballBeach: return "VBV"; break; -    case OlympicsAPI::Disciplines::VolleyballIndoor: return "VVO"; break; -    case OlympicsAPI::Disciplines::Weightlifting: return "WLF"; break; -    case OlympicsAPI::Disciplines::WrestlingFreestyle: return "WRE"; break; -    case OlympicsAPI::Disciplines::WrestlingGrecoRoman: return "WRG"; break; +    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      }  } diff --git a/src/discipline/Sport.cpp b/src/discipline/Sport.cpp index 42e82aa..1ea8019 100644 --- a/src/discipline/Sport.cpp +++ b/src/discipline/Sport.cpp @@ -1,6 +1,7 @@  #include "Sport.h"  #include <set> +#include <map>  #include <algorithm>  #include <regex> @@ -8,6 +9,21 @@  #include <QJsonArray>  #include <QJsonValueRef>  #include <QString> +#include <QTime> + +// 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) { @@ -20,21 +36,44 @@ function<bool (const QJsonValue &left, const QJsonValue &right)> genCompare(QStr  // 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; -    float lMark = l["results"].toObject()["mark"].toString().toFloat(); -    float rMark = r["results"].toObject()["mark"].toString().toFloat(); -    return lMark < rMark; +    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(QJsonArray &competitors) {      for (int i = 0; i < competitors.size(); ++i) {          string fullName = competitors[i].toObject()["name"].toString().toUtf8().constData(); @@ -64,7 +103,7 @@ void Sport::lastName(QJsonArray& competitors) {  set<QString> Sport::getCategories() {      set<QString> categoryNames; -    for (const QJsonValueRef& unit : this->discipline["units"].toArray()) { +    for (const QJsonValueRef &unit : this->discipline["units"].toArray()) {          categoryNames.insert(unit.toObject()["eventUnitName"].toString());      } @@ -79,21 +118,97 @@ set<QString> Sport::getCategories() {  QJsonArray Sport::getCompetitorsByCategory(QString category) {      QJsonArray competitors; -    for (const QJsonValueRef& unitRef : this->discipline["units"].toArray()) { +    for (const QJsonValueRef &unitRef : this->discipline["units"].toArray()) {          QJsonObject unit = unitRef.toObject();          // search all units with the same category -        if (QString::compare(unit["eventUnitName"].toString(), category, Qt::CaseSensitive) == 0) { +        if (unit["eventUnitName"].toString().compare(category, Qt::CaseSensitive) != 0) continue; + +        // add all competitors from one unit +        for (const QJsonValueRef &comp : unit["competitors"].toArray()) { +            competitors.push_back(comp.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; + +    // 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(); + +        // filter all competitors, who won medals +        QJsonArray medalComps = filter(unit["competitors"].toArray(), [](QJsonObject comp) { +            if (!comp.contains("results")) return false; -            // add all competitors from one unit -            for (const QJsonValueRef& comp : unit["competitors"].toArray()) { -                competitors.push_back(comp.toObject()); +            QString medalType = comp["results"].toObject()["medalType"].toString(); +            return !medalType.isEmpty(); +        }); + +        for (const QJsonValueRef &medalCompRef : medalComps) { +            QJsonObject medalComp = medalCompRef.toObject(); + +            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;          }      } -    return QJsonArray(competitors); +    // convert map to QJsonArray +    QJsonArray output; +    for (const pair<QString, QJsonObject> &competitor : competitors) { +        output.append(competitor.second); +    } + +    return output; +} + +QJsonObject Sport::createCompetitorWithMedals(QJsonObject comp) { +    // 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;  }  /** @@ -147,7 +262,12 @@ void Sport::sortByCountry(QJsonArray &competitors) {   * @param competitors The competitors of one category.   */  void Sport::sortByResult(QJsonArray &competitors) { -    sortCompetitors(competitors, compareMark); +    if (competitors.isEmpty()) return; + +    QJsonObject comp = competitors[0].toObject(); + +    if (comp.contains("results")) sortCompetitors(competitors, compareMark); +    else if (comp.contains("medals")) sortCompetitors(competitors, compareMedals);  }  void Sport::sortCompetitors(QJsonArray &competitors, function<bool (const QJsonValue &left, const QJsonValue &right)> compare) { diff --git a/src/discipline/Sport.h b/src/discipline/Sport.h index 78968fe..9156b82 100644 --- a/src/discipline/Sport.h +++ b/src/discipline/Sport.h @@ -22,11 +22,12 @@ public:      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); +    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); @@ -58,11 +59,24 @@ private:       * - 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 filterCompetitors(QJsonArray &competitors, QString attribute, QString filter);      void sortCompetitors(QJsonArray &competitors,  function<bool (const QJsonValue &left, const QJsonValue &right)> compare); +    QJsonObject createCompetitorWithMedals(QJsonObject medalComp);  }; | 
