From d399c562f5fad76ed8018c712a635f49715a8fed Mon Sep 17 00:00:00 2001 From: Steru Date: Sat, 3 Aug 2024 20:19:05 +0200 Subject: Added another filter and sort functions. Also using mock data to test. --- src/api/OlympicsAPI.cpp | 60 +++++++++++++++++++++------------- src/api/OlympicsAPI.h | 13 ++------ src/discipline/Sport.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++++++- src/discipline/Sport.h | 36 ++++++++++++++++++--- 4 files changed, 155 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/api/OlympicsAPI.cpp b/src/api/OlympicsAPI.cpp index edcb021..4fe9701 100644 --- a/src/api/OlympicsAPI.cpp +++ b/src/api/OlympicsAPI.cpp @@ -12,6 +12,7 @@ #include // json parsing +#include #include #include #include @@ -29,41 +30,54 @@ using namespace std; QJsonObject OlympicsAPI::getSportData(OlympicsAPI::Disciplines sport) { string shortName = this->getDisciplineShort(sport); - // create custom temporary event loop on stack - QEventLoop eventLoop; + 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())); + // "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(); + 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 + // 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 + if (reply->error() == QNetworkReply::NoError) { + //success - QString strReply = (QString)reply->readAll(); + QString strReply = (QString)reply->readAll(); - //parse json - QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8()); + //parse json + QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8()); - QJsonObject jsonObj = jsonResponse.object(); + QJsonObject jsonObj = jsonResponse.object(); - delete reply; + delete reply; - return jsonObj; - } - else { - //failure - delete reply; + return jsonObj; + } + else { + //failure + delete reply; - throw invalid_argument("API request failed."); + 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(); + } } /** diff --git a/src/api/OlympicsAPI.h b/src/api/OlympicsAPI.h index 8efaa26..f1168b6 100644 --- a/src/api/OlympicsAPI.h +++ b/src/api/OlympicsAPI.h @@ -8,17 +8,10 @@ #include #include -using namespace std; +// TODO: change this to true to use the olympics api, instead of the mock date in res/mock/ +#define USE_API_REQUEST false -/* - * TODO: - * Replace api request code snippet in main with: - * - OlympicsAPI api; - QJsonObject archery = api.getSportData(api.Archery); - qDebug() << "Competitor:" << archery["units"][0]["competitors"][0]["name"].toString(); - * - */ +using namespace std; class OlympicsAPI { diff --git a/src/discipline/Sport.cpp b/src/discipline/Sport.cpp index ed8331d..05ba95e 100644 --- a/src/discipline/Sport.cpp +++ b/src/discipline/Sport.cpp @@ -1,12 +1,34 @@ #include "Sport.h" #include +#include #include #include #include #include +// 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) { + 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; +} + /** * @brief Sport::getCategories Reads all possible categories (also called units). @@ -44,5 +66,65 @@ QJsonArray Sport::getCompetitorsByCategory(QString category) { } } - return competitors; + return QJsonArray(competitors); +} + +/** + * @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); +} + +void Sport::filterCompetitors(QJsonArray &competitors, QString attribute, QString filter) { + for (int i = 0; i < competitors.size(); i++) { + + if (!competitors[i].toObject()[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) { + sortCompetitors(competitors, compareMark); +} + +void Sport::sortCompetitors(QJsonArray &competitors, function compare) { + make_heap(competitors.begin(), competitors.end(), compare); + sort_heap(competitors.begin(), competitors.end(), compare); +} + diff --git a/src/discipline/Sport.h b/src/discipline/Sport.h index 9c993fb..3b1c7f4 100644 --- a/src/discipline/Sport.h +++ b/src/discipline/Sport.h @@ -23,18 +23,46 @@ public: set getCategories(); QJsonArray getCompetitorsByCategory(QString category); - // chainable - QJsonObject filterByName(QJsonObject discipline, QString name); - QJsonObject filterByCountry(QJsonObject discipline, QString name); + // filter to change the current competitor array + 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 setDiscipline(QJsonObject discipline) { - this->discipline = 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?) + */ QJsonObject discipline; + void filterCompetitors(QJsonArray& competitors, QString attribute, QString filter); + void sortCompetitors(QJsonArray &competitors, function compare); + }; -- cgit v1.2.3