app/sources/provider/brproviderdr.cpp
2021-03-07 20:39:07 +01:00

518 lines
19 KiB
C++

#include "brproviderdr.h"
BRProviderDr::BRProviderDr(QObject *parent) : BRProvider(parent)
{
// leagues source:
// - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/dav_calendar.php
// - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/sac_calendar.php
this->leagues.insert(
BRWidget::DAV,
{
{
{"id", 0},
{"name", "Deutsche Meisterschaft"},
{"color", "#A8F0A8"},
{"leagueIDs", QVariantList({59, 57, 60})}
},
{
{"id", 1},
{"name", "Deutscher Jugendcup"},
{"color", "#D8FFD8"},
{"leagueIDs", QVariantList({58})}
},
{
{"id", 2},
{"name", "Landesmeisterschaft"},
{"color", "#F0F0F0"},
{"leagueIDs", QVariantList({61, 56})}
}
});
this->leagues.insert(
BRWidget::SAC,
{
{
{"id", 0},
{"name", "Erwachsene"},
{"color", "#A8F0A8"},
{"leagueIDs", QVariantList({57, 59, 60})}
},
{
{"id", 1},
{"name", "Jugend"},
{"color", "#D8FFD8"},
{"leagueIDs", QVariantList({65})}
},
{
{"id", 2},
{"name", "RegioCups"},
{"color", "#F0F0F0"},
{"leagueIDs", QVariantList({64})}
},
{
{"id", 3},
{"name", "Iceclimbing"},
{"color", "#F0F0F0"},
{"leagueIDs", QVariantList({84})}
}
});
}
BRWidget::BRWidgetStatusCode BRProviderDr::getWidgetData(BRCalendar::BRCalendarData* calendarData)
{
// load some data
QString nationStr = calendarData->calendar->getFederation() == BRWidget::SAC ? "SUI":"GER";
qDebug() << "Nation str: " << nationStr << " federation: " << calendarData->calendar->getFederation();
int year = QDate::currentDate().year();
QString requestUrl = "https://www.digitalrock.de/egroupware/ranking/json.php?nation=" + nationStr + "&year=" + QString::number(year);
QVariantMap ret = this->serverRequest(QUrl(requestUrl));
if(ret["status"] != 200) {
// request was a failure
return BRWidget::BRWidgetStatusCode(ret["status"].toInt());
}
QVariantMap data = QJsonDocument::fromJson(ret["text"].toString().toUtf8()).toVariant().toMap();
data.insert("year", year);
data.insert("federation", calendarData->calendar->getFederation());
// create seasons
QVariantList seasons = data["years"].toList();
for(QVariant seasonVar : seasons) {
int seasonId = seasonVar.toString().toInt();
BRSeason* season = this->getSeason(
calendarData->calendar->getFederation(),
seasonId,
this->parseSeasonData(seasonId, data)
);
calendarData->seasons.append(season);
if(seasonId == year)
calendarData->currentSeason = season;
}
return BRWidget::Success;
}
BRWidget::BRWidgetStatusCode BRProviderDr::getWidgetData(BRSeason::BRSeasonData* seasonData) {
// load some data
QString nationStr = seasonData->season->getFederation() == BRWidget::SAC ? "SUI":"GER";
qDebug() << "Nation str: " << nationStr << " federation: " << seasonData->season->getFederation();
int year = seasonData->season->getYear();
QString requestUrl = "https://www.digitalrock.de/egroupware/ranking/json.php?nation=" + nationStr + "&year=" + QString::number(year);
QVariantMap ret = this->serverRequest(QUrl(requestUrl));
if(ret["status"] != 200) {
// request was a failure
return BRWidget::BRWidgetStatusCode(ret["status"].toInt());
}
QVariantMap data = QJsonDocument::fromJson(ret["text"].toString().toUtf8()).toVariant().toMap();
data.insert("year", year);
data.insert("federation", seasonData->season->getFederation());
// populate season
QVariantList seasons = data["years"].toList();
this->parseSeasonData(seasonData, year, data);
return BRWidget::Success;
}
BRSeason::BRSeasonData BRProviderDr::parseSeasonData(int id, QVariantMap rawData) {
BRSeason::BRSeasonData data;
this->parseSeasonData(&data, id, rawData);
return data;
}
void BRProviderDr::parseSeasonData(BRSeason::BRSeasonData* seasonData, int id, QVariantMap rawData) {
seasonData->year = id;
seasonData->nativeMultiLeagueSupport = true;
seasonData->name = QString::number(id);
qDebug() << "Parsing season: " << seasonData->name;
BRWidget::BRFederation federation = BRWidget::BRFederation(rawData["federation"].toInt(0));
// insert the leagues if the season is the current one
if(seasonData->name == rawData["year"].toString())
for(QVariantMap leagueVar : this->leagues[federation]) {
BRLeague* league = this->getLeague(federation, leagueVar["id"].toInt(), this->parseLeagueData(leagueVar, rawData));
seasonData->leagues.append(league);
}
}
BRWidget::BRWidgetStatusCode BRProviderDr::getWidgetData(BRLeague::BRLeagueData* leagueData) {
Q_UNUSED(leagueData)
return BRWidget::NotImplementedError;
}
BRLeague::BRLeagueData BRProviderDr::parseLeagueData(QVariantMap leagueProperties, QVariantMap rawData) {
BRLeague::BRLeagueData data;
BRWidget::BRFederation federation = BRWidget::BRFederation(rawData["federation"].toInt(0));
data.name = leagueProperties["name"].toString();
data.color = QColor(leagueProperties["color"].toString());
data.enabled = true;
qDebug() << "- Parsing league: " << data.name;
// parse competitions
QVariantList competitionsVar = rawData["competitions"].toList();
// TODO: make more efficient
for(QVariant competitionVar : competitionsVar) {
QVariantMap competitionMap = competitionVar.toMap();
// check if this competition is part of this league
if(leagueProperties["leagueIDs"].toList().contains(competitionMap["cat_id"].toInt())) {
BRCompetition* competition = this->getCompetition(federation, competitionVar.toMap()["WetId"].toInt(), this->parseCompetitionData(competitionMap, rawData["cats"].toList(), federation));
data.competitions.append(competition);
}
}
// if this is league with id 0
if(leagueProperties["id"].toInt() == 0) {
// parse cups
QVariantList cupsVar = rawData["cups"].toList();
for(QVariant cupVar : cupsVar) {
QVariantMap cupMap = cupVar.toMap();
BRCup* cup = this->getCup(federation, cupMap["SerId"].toInt(), this->parseCupData(rawData["cats"].toList(), cupMap, federation));
data.cups.append(cup);
}
}
return data;
}
BRWidget::BRWidgetStatusCode BRProviderDr::getWidgetData(BRCompetition::BRCompetitionData* competitionData) {
if(competitionData->competition->getCurrentCategory() == nullptr)
return BRWidget::OpeationNotSupportedError;
// reload all data
BRCategory* currentCategory = competitionData->competition->getCurrentCategory();
QVariantMap ret;
int retryCount = 0;
// handle route not found errors
do {
retryCount ++;
// load category data
QString competitionId = QString::number(currentCategory->getCompetition()->getId());
QString categoryId = QString::number(currentCategory->getId());
QString requestUrl = "https://www.digitalrock.de/egroupware/ranking/json.php?comp=" + competitionId + "&cat=" + categoryId;
if(currentCategory->getCurrentRound() != nullptr && currentCategory->getCurrentRound()->getId() >= 0)
requestUrl += "&route=" + QString::number(currentCategory->getCurrentRound()->getId());
ret = this->serverRequest(QUrl(requestUrl));
// handle route not found errors
if(ret["status"] != 200 && (ret["status"] != 404 || retryCount > 1)) {
// request was a failure
return BRWidget::BRWidgetStatusCode(ret["status"].toInt());
}
// if 404 is returned, the route probaply does not exist -> try again without route
currentCategory->setCurrentRound(currentCategory->getGeneralResult());
} while(ret["status"] != 200);
QVariantMap data = QJsonDocument::fromJson(ret["text"].toString().toUtf8()).toVariant().toMap();
this->parseCompetitionData(competitionData, data, competitionData->competition->getFederation());
return BRWidget::Success;
}
BRCompetition::BRCompetitionData BRProviderDr::parseCompetitionData(QVariantMap rawData, QVariantList globalCategoriesList, BRWidget::BRFederation federation) {
// Load competition data from calendar
BRCompetition::BRCompetitionData data;
data.name = rawData["name"].toString();
qDebug() << "-- Parsing competition: " << data.name;
if(rawData.contains("date"))
data.startDate = QDate::fromString(rawData["date"].toString(), "yyyy-MM-dd");
if(rawData.contains("date_end"))
data.endDate = QDate::fromString(rawData["date_end"].toString(), "yyyy-MM-dd");
if(rawData.contains("homepage"))
data.eventWebsiteUrl = rawData["homepage"].toString();
// load infosheet URLs
for(int i = 0; i < 2; i++) {
QString infosheetName = QStringList({"info", "info2"})[i];
if(rawData.contains(infosheetName)) {
QString url = rawData[infosheetName].toString();
if(federation == BRWidget::DAV)
url = "http://ranking.alpenverein.de/" + QString::number(data.startDate.year()) + "/GER/" + rawData["rkey"].toString() + ".pdf";
data.infosheetUrls.append(url);
}
}
// load categories
QVariantList categoriesList = rawData["cats"].toList();
data.categories.clear();
for(QVariant categoryVar : categoriesList) {
QVariantMap categoryMap = categoryVar.toMap();
// parse discipline
QString discipline;
if(rawData.contains("discipline")) {
// all categories have the same discipline
discipline = rawData["discipline"].toString();
// remove numbers (the Year of a competition is in the discipline somtimes)
discipline = discipline.remove( QRegExp("/[0-9]/g") );
}
else
// categories discipline may differ
// search category in global categories list
for(QVariant globalCategoryVar : globalCategoriesList) {
QVariantMap globalCategoryMap = globalCategoryVar.toMap();
if(categoryMap["GrpId"].toInt() == globalCategoryMap["GrpId"].toInt()) {
// TODO: gender
discipline = globalCategoryMap["discipline"].toString();
break;
}
}
categoryMap.insert("discipline", discipline);
BRCategory* category = this->getCategory(federation, categoryMap["GrpId"].toInt(), this->parseCategoryData(categoryMap));
data.categories.append(category);
}
data.currentCategory = nullptr;
return data;
}
void BRProviderDr::parseCompetitionData(BRCompetition::BRCompetitionData* competitionData, QVariantMap rawData, BRWidget::BRFederation federation) {
// load competition data from category page (?comp=X&cat=Y)
competitionData->name = rawData["comp_name"].toString();
// reload categories
// As digitalrock does not allow to get rounds in the competiton calendar
// we need to populate all categories with their rounds when the first category is loaded.
// for that, all categories are recreated
QVariantList categoriesList = rawData["categorys"].toList();
// store old categories
QMap<int, BRCategory*> oldCategories;
for(BRCategory* category : competitionData->categories)
if(!oldCategories.contains(category->getId()))
oldCategories.insert(category->getId(), category);
competitionData->categories.clear();
for(QVariant categoryVar : categoriesList) {
QVariantMap categoryMap = categoryVar.toMap();
int categoryId = categoryMap["GrpId"].toInt();
BRCategory::BRCategoryData categoryData;
categoryData.name = categoryMap["name"].toString();
// restore data that is not available in competition view of the API
if(oldCategories.contains(categoryId)) {
categoryData.status = oldCategories[categoryId]->getStatus();
categoryData.discipline = oldCategories[categoryId]->getDiscipline();
}
categoryData.currentRound = nullptr;
categoryData.generalResult = nullptr;
qDebug() << "Loading category: " << categoryData.name << " with discipline: " << categoryData.discipline;
QVariantMap roundList;
// check if route_names are given:
if(rawData.contains("route_names"))
roundList = rawData["route_names"].toMap();
// load rounds
for(QString roundId : roundList.keys()) {
if(roundId.toInt() < 0)
continue;
BRRound::BRRoundData roundData;
roundData.name = roundList[roundId].toString();
BRRound* round = this->getRound(competitionData->competition->getFederation(), roundId.toInt(), roundData);
categoryData.rounds.append(round);
// if this was the previous round -> restore it!
if(round->getId() == rawData["route_order"].toInt())
categoryData.currentRound = round;
}
// general result
BRRound::BRRoundData generalResultRoundData;
generalResultRoundData.name = "Gesamtergebnis";
categoryData.generalResult = this->getRound(competitionData->competition->getFederation(), -1, generalResultRoundData, true);
// set default round if it was not restored
if(categoryData.currentRound == nullptr)
categoryData.currentRound = categoryData.generalResult;
BRCategory* category = this->getCategory(federation, categoryId, categoryData);
competitionData->categories.append(category);
// restore current category and load its reults
if(category->getId() == rawData["GrpId"]) {
competitionData->currentCategory = category;
// if we have a currentRound or a general result
if(categoryData.currentRound != nullptr) {
qDebug() << "-- Current Round is: " << categoryData.currentRound->getName() << " with id: " << categoryData.currentRound->getId();
BRRound::BRRoundData roundData = categoryData.currentRound->getData();
this->parseRoundData(&roundData, rawData);
this->setRoundData(categoryData.currentRound, roundData);
// if we have a general result -> load all other round results
if(categoryData.currentRound->isGeneralResult()) {
for(BRRound* round : categoryData.rounds) {
BRRound::BRRoundData roundData = round->getData();
this->parseRoundData(&roundData, rawData, QString::number(round->getId()));
this->setRoundData(round, roundData);
}
}
}
}
// delete old categories
for(int categoryId : oldCategories.keys()) {
oldCategories[categoryId]->deleteLater();
}
}
}
BRCup::BRCupData BRProviderDr::parseCupData(QVariantList categoriesList, QVariantMap rawData, BRWidget::BRFederation federation) {
BRCup::BRCupData data;
data.name = rawData["name"].toString();
qDebug() << "- Parsing Cup: " << data.name;
// parse categories
for(QVariant categoryName : rawData["cats"].toList()) {
// find category name in cats:
for(QVariant categoryVar : categoriesList) {
QVariantMap categoryMap = categoryVar.toMap();
if(categoryMap["rkey"].toString() == categoryName.toString()) {
BRCategory* category = this->getCategory(federation, rawData["GrpId"].toInt(), this->parseCategoryData(categoryMap));
data.categories.append(category);
break;
}
}
}
return data;
}
BRCategory::BRCategoryData BRProviderDr::parseCategoryData(QVariantMap rawData) {
BRCategory::BRCategoryData data;
// TODO: gender
data.name = rawData["name"].toString();
data.currentRound = nullptr;
data.generalResult = nullptr;
QMap<int, BRCategory::BRCategoryStatus> statusTranslations = {
{4, BRCategory::Registration},
{2, BRCategory::Startlist},
{1, BRCategory::Result},
{0, BRCategory::Result}
};
QMap<QString, BRCategory::BRDiscipline> disciplineTranslations = {
{"boulder", BRCategory::Boulder},
{"lead", BRCategory::Lead},
{"speed", BRCategory::Speed}
};
if(disciplineTranslations.contains(rawData["discipline"].toString()))
data.discipline = disciplineTranslations[rawData["discipline"].toString()];
else
data.discipline = BRCategory::UnknownDiscipline;
// parse status
if(rawData.contains("status") && statusTranslations.contains(rawData["status"].toInt()))
data.status = statusTranslations[rawData["status"].toInt()];
else
data.status = BRCategory::UnknownStatus;
qDebug() << "-- Parsing category: " << data.name << " with discipline: " << data.discipline << " and status: " << data.status;
return data;
}
void BRProviderDr::parseCategoryData(BRCategory::BRCategoryData* categoryData, QVariantMap rawData) {
// category is already set-up -> only load rounds!
}
void BRProviderDr::parseRoundData(BRRound::BRRoundData* roundData, QVariantMap rawData, QString resultKeyAttachment) {
roundData->results = {};
// load results
QVariantList resultList = rawData["participants"].toList();
for(QVariant resultVar : resultList) {
QVariantMap resultMap = resultVar.toMap();
// load athlete
BRAthlete* athlete = this->getAthlete(roundData->round->getFederation(), resultMap["PerId"].toInt(), this->parseAthletedata(resultMap));
// load result
// TODO: start number
BRResult::BRResultData resultData;
resultData.startNumber = resultMap["start_number"].toInt();
resultData.athlete = athlete;
resultData.rank = resultMap["result_rank" + resultKeyAttachment].toInt();
resultData.details = nullptr;
// load details:
// - check if we have a general result
if(roundData->round->isGeneralResult())
resultData.details = new BRResultDetailsGeneralResult();
else
resultData.details = new BRResultDetailsUnknown(resultMap["result" + resultKeyAttachment].toString());
BRResult* result = this->getResult(resultData);
roundData->results.append(result);
}
}
BRAthlete::BRAthleteData BRProviderDr::parseAthletedata(QVariantMap rawData) {
BRAthlete::BRAthleteData data;
data.firstName = rawData["firstname"].toString();
data.lastName = rawData["lastname"].toString();
data.federation = rawData["federation"].toString();
data.federationUrl = rawData["fed_url"].toUrl();
data.nation = rawData["nation"].toString();
data.city = rawData["city"].toString();
data.yearOfBirth = rawData["birthyear"].toInt();
qDebug() << "--- Parsing athlete: " << data.firstName << " " << data.lastName;
return data;
}
BRResult::BRResultData BRProviderDr::parseResultData(QVariantMap rawData) {
}