From 5f446d5b5002140dc82292c8cc1e5e9189ec3764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otakar=20Hir=C5=A1?= Date: Fri, 17 Jan 2025 16:14:55 +0100 Subject: [PATCH 1/3] feat: nationality support --- .../quickevent/plugins/Oris/src/alphatoioc.h | 250 ++++++++++++++++++ .../plugins/Oris/src/orisimporter.cpp | 4 +- .../app/quickevent/plugins/Oris/src/src.pri | 1 + .../plugins/Oris/src/xmlimporter.cpp | 9 +- .../plugins/Relays/src/relaysplugin.cpp | 21 +- .../plugins/Runs/src/runsplugin.cpp | 16 +- quickevent/app/quickevent/src/appversion.h | 2 +- 7 files changed, 289 insertions(+), 14 deletions(-) create mode 100644 quickevent/app/quickevent/plugins/Oris/src/alphatoioc.h diff --git a/quickevent/app/quickevent/plugins/Oris/src/alphatoioc.h b/quickevent/app/quickevent/plugins/Oris/src/alphatoioc.h new file mode 100644 index 000000000..63e55a304 --- /dev/null +++ b/quickevent/app/quickevent/plugins/Oris/src/alphatoioc.h @@ -0,0 +1,250 @@ +#ifndef ALPHATOIOC_H +#define ALPHATOIOC_H + +#include +#include + +QMap isoAlpha2ToIoc = { + {"AF", "AFG"}, + {"AL", "ALB"}, + {"DZ", "ALG"}, + {"AS", "ASA"}, + {"AD", "AND"}, + {"AO", "ANG"}, + {"AI", "AIA"}, + {"AG", "ANT"}, + {"AR", "ARG"}, + {"AM", "ARM"}, + {"AW", "ARU"}, + {"AU", "AUS"}, + {"AT", "AUT"}, + {"AZ", "AZE"}, + {"BS", "BAH"}, + {"BH", "BRN"}, + {"BD", "BAN"}, + {"BB", "BAR"}, + {"BY", "BLR"}, + {"BE", "BEL"}, + {"BZ", "BIZ"}, + {"BJ", "BEN"}, + {"BM", "BER"}, + {"BT", "BHU"}, + {"BO", "BOL"}, + {"BQ", "AHO"}, + {"BA", "BIH"}, + {"BW", "BOT"}, + {"BR", "BRA"}, + {"VG", "IVB"}, + {"BN", "BRU"}, + {"BG", "BUL"}, + {"BF", "BUR"}, + {"BI", "BDI"}, + {"CV", "CPV"}, + {"KH", "CAM"}, + {"CM", "CMR"}, + {"CA", "CAN"}, + {"KY", "CAY"}, + {"CF", "CAF"}, + {"TD", "CHA"}, + {"CL", "CHI"}, + {"CN", "CHN"}, + {"HK", "HKG"}, + {"MO", "MAC"}, + {"CO", "COL"}, + {"KM", "COM"}, + {"CG", "CGO"}, + {"CK", "COK"}, + {"CR", "CRC"}, + {"HR", "CRO"}, + {"CU", "CUB"}, + {"CY", "CYP"}, + {"CZ", "CZE"}, + {"KP", "PRK"}, + {"CD", "COD"}, + {"DK", "DEN"}, + {"DJ", "DJI"}, + {"DM", "DMA"}, + {"DO", "DOM"}, + {"EC", "ECU"}, + {"EG", "EGY"}, + {"SV", "ESA"}, + {"GQ", "GEQ"}, + {"ER", "ERI"}, + {"EE", "EST"}, + {"SZ", "SWZ"}, + {"ET", "ETH"}, + {"FK", "FLK"}, + {"FO", "FAR"}, + {"FJ", "FIJ"}, + {"FI", "FIN"}, + {"FR", "FRA"}, + {"GF", "FGU"}, + {"PF", "FPO"}, + {"GA", "GAB"}, + {"GM", "GAM"}, + {"GE", "GEO"}, + {"DE", "GER"}, + {"GH", "GHA"}, + {"GI", "GIB"}, + {"GR", "GRE"}, + {"GL", "GRL"}, + {"GD", "GRN"}, + {"GP", "GUD"}, + {"GU", "GUM"}, + {"GT", "GUA"}, + {"GN", "GUI"}, + {"GW", "GBS"}, + {"GY", "GUY"}, + {"HT", "HAI"}, + {"HN", "HON"}, + {"HU", "HUN"}, + {"IS", "ISL"}, + {"IN", "IND"}, + {"ID", "INA"}, + {"IR", "IRI"}, + {"IQ", "IRQ"}, + {"IE", "IRL"}, + {"IL", "ISR"}, + {"IT", "ITA"}, + {"CI", "CIV"}, + {"JM", "JAM"}, + {"JP", "JPN"}, + {"JO", "JOR"}, + {"KZ", "KAZ"}, + {"KE", "KEN"}, + {"KI", "KIR"}, + {"KW", "KUW"}, + {"KG", "KGZ"}, + {"LA", "LAO"}, + {"LV", "LAT"}, + {"LB", "LIB"}, + {"LS", "LES"}, + {"LR", "LBR"}, + {"LY", "LBA"}, + {"LI", "LIE"}, + {"LT", "LTU"}, + {"LU", "LUX"}, + {"MG", "MAD"}, + {"MW", "MAW"}, + {"MY", "MAS"}, + {"MV", "MDV"}, + {"ML", "MLI"}, + {"MT", "MLT"}, + {"MH", "MSH"}, + {"MQ", "MRT"}, + {"MR", "MTN"}, + {"MU", "MRI"}, + {"YT", "MAY"}, + {"MX", "MEX"}, + {"FM", "FSM"}, + {"MC", "MON"}, + {"MN", "MGL"}, + {"ME", "MGO"}, + {"MS", "MNT"}, + {"MA", "MAR"}, + {"MZ", "MOZ"}, + {"MM", "MYA"}, + {"NA", "NAM"}, + {"NR", "NRU"}, + {"NP", "NEP"}, + {"NL", "NED"}, + {"NC", "NCD"}, + {"NZ", "NZL"}, + {"NI", "NCA"}, + {"NE", "NIG"}, + {"NG", "NGR"}, + {"NU", "NIU"}, + {"NF", "NFI"}, + {"MP", "NMA"}, + {"MK", "MKD"}, + {"NO", "NOR"}, + {"OM", "OMA"}, + {"PK", "PAK"}, + {"PW", "PLW"}, + {"PA", "PAN"}, + {"PG", "PNG"}, + {"PY", "PAR"}, + {"PE", "PER"}, + {"PH", "PHI"}, + {"PL", "POL"}, + {"PT", "POR"}, + {"PR", "PUR"}, + {"QA", "QAT"}, + {"KR", "KOR"}, + {"MD", "MDA"}, + {"RE", "REU"}, + {"RO", "ROU"}, + {"RU", "RUS"}, + {"RW", "RWA"}, + {"SH", "HEL"}, + {"KN", "SKN"}, + {"LC", "LCA"}, + {"PM", "SPM"}, + {"VC", "VIN"}, + {"WS", "SAM"}, + {"SM", "SMR"}, + {"ST", "STP"}, + {"SA", "KSA"}, + {"SN", "SEN"}, + {"RS", "SRB"}, + {"SC", "SEY"}, + {"SL", "SLE"}, + {"SG", "SIN"}, + {"SK", "SVK"}, + {"SI", "SLO"}, + {"SB", "SOL"}, + {"SO", "SOM"}, + {"ZA", "RSA"}, + {"ES", "ESP"}, + {"LK", "SRI"}, + {"PS", "PLE"}, + {"SD", "SUD"}, + {"SR", "SUR"}, + {"SE", "SWE"}, + {"CH", "SUI"}, + {"SY", "SYR"}, + {"TW", "TPE"}, + {"TJ", "TJK"}, + {"TH", "THA"}, + {"TL", "TLS"}, + {"TG", "TOG"}, + {"TO", "TGA"}, + {"TT", "TTO"}, + {"TN", "TUN"}, + {"TR", "TUR"}, + {"TM", "TKM"}, + {"TC", "TKS"}, + {"TV", "TUV"}, + {"UG", "UGA"}, + {"UA", "UKR"}, + {"AE", "UAE"}, + {"GB", "GBR"}, + {"TZ", "TAN"}, + {"US", "USA"}, + {"VI", "ISV"}, + {"UY", "URU"}, + {"UZ", "UZB"}, + {"VU", "VAN"}, + {"VE", "VEN"}, + {"VN", "VIE"}, + {"WF", "WAF"}, + {"YE", "YEM"}, + {"ZM", "ZAM"}, + {"ZW", "ZIM"} +}; + +QString convertToIOC(const QString& alpha2Code) +{ + // Convert to uppercase to ensure consistent lookup + QString normalizedCode = alpha2Code.toUpper(); + + // Check if the code exists in the map + if (isoAlpha2ToIoc.contains(normalizedCode)) { + return isoAlpha2ToIoc.value(normalizedCode); + } + + // Return empty optional if no mapping exists + return QString(); +} + +#endif // ALPHATOIOC_H diff --git a/quickevent/app/quickevent/plugins/Oris/src/orisimporter.cpp b/quickevent/app/quickevent/plugins/Oris/src/orisimporter.cpp index 55dc69f91..b91c10592 100644 --- a/quickevent/app/quickevent/plugins/Oris/src/orisimporter.cpp +++ b/quickevent/app/quickevent/plugins/Oris/src/orisimporter.cpp @@ -1,5 +1,6 @@ #include "chooseoriseventdialog.h" #include "orisimporter.h" +#include "alphatoioc.h" #include #include @@ -558,6 +559,7 @@ void OrisImporter::syncEventEntries(int event_id, std::function success qfWarning() << "class id:" << class_id << "not found in the class definitions"; class_id = 0; } + QString country_code = convertToIOC(competitor_o.value(QStringLiteral("Nationality")).toString()); doc->setValue("classId", (class_id == 0)? QVariant(QVariant::Int): QVariant(class_id)); doc->setSiid(siid); doc->setValue("firstName", first_name); @@ -565,6 +567,7 @@ void OrisImporter::syncEventEntries(int event_id, std::function success doc->setValue("registration", reg_no); doc->setValue("iofId", !iof_id.isEmpty() ? iof_id : QVariant(QVariant::Int)); doc->setValue("licence", competitor_o.value(QStringLiteral("Licence")).toString()); + doc->setValue("countryCode", country_code); doc->setValue("note", note); doc->setValue("importId", import_id); doc->setProperty(KEY_RUNS, runs); @@ -846,4 +849,3 @@ void OrisImporter::importClubs(std::function success_callback) }); } - diff --git a/quickevent/app/quickevent/plugins/Oris/src/src.pri b/quickevent/app/quickevent/plugins/Oris/src/src.pri index ab48bf505..7ab1c12aa 100644 --- a/quickevent/app/quickevent/plugins/Oris/src/src.pri +++ b/quickevent/app/quickevent/plugins/Oris/src/src.pri @@ -1,6 +1,7 @@ message(including $$PWD) HEADERS += \ + $$PWD/alphatoioc.h \ $$PWD/orisimporter.h \ $$PWD/chooseoriseventdialog.h \ $$PWD/orisplugin.h \ diff --git a/quickevent/app/quickevent/plugins/Oris/src/xmlimporter.cpp b/quickevent/app/quickevent/plugins/Oris/src/xmlimporter.cpp index 48ad87cb6..7b81fb7c1 100644 --- a/quickevent/app/quickevent/plugins/Oris/src/xmlimporter.cpp +++ b/quickevent/app/quickevent/plugins/Oris/src/xmlimporter.cpp @@ -205,6 +205,8 @@ bool XmlImporter::importEntries(QXmlStreamReader &reader, const XmlCreators crea doc.setSiid(person.siNumber); doc.setValue("firstName", person.nameGiven); doc.setValue("lastName", person.nameFamily); + doc.setValue("country", person.nationalityName); + doc.setValue("countryCode", person.nationalityCode); if (creator == XmlCreators::Oris) { doc.setValue("registration", person.regCz); doc.setValue("note", person.noteOris); @@ -225,7 +227,6 @@ bool XmlImporter::importEntries(QXmlStreamReader &reader, const XmlCreators crea else if (!person.countryName.isEmpty()) doc.setValue("club",person.countryName); } - doc.setValue("country",person.nationalityName); if (person.iofId.has_value()) doc.setValue("importId",person.iofId.value()); } @@ -359,6 +360,7 @@ bool XmlImporter::importEntries(QXmlStreamReader &reader, const XmlCreators crea doc.setValue("club",leg.second.countryName); } doc.setValue("country",leg.second.nationalityName); + doc.setValue("countryCode",leg.second.nationalityCode); if (leg.second.iofId.has_value()) doc.setValue("importId",leg.second.iofId.value()); if (leg.second.iofId.has_value()) @@ -672,7 +674,7 @@ bool XmlImporter::importRegistration(QXmlStreamReader &reader, const XmlCreators } qf::core::sql::Transaction transaction; q.exec("DELETE FROM registrations", qf::core::Exception::Throw); - q.prepare("INSERT INTO registrations (firstName, lastName, registration, licence, clubAbbr, country, siId, importId) VALUES (:firstName, :lastName, :registration, :licence, :clubAbbr, :country, :siId, :importId)", qf::core::Exception::Throw); + q.prepare("INSERT INTO registrations (firstName, lastName, registration, licence, clubAbbr, country, countryCode, siId, importId) VALUES (:firstName, :lastName, :registration, :licence, :clubAbbr, :country, :countryCode, :siId, :importId)", qf::core::Exception::Throw); // load data from XML int items_processed = 0; while(reader.readNextStartElement()) { @@ -704,7 +706,8 @@ bool XmlImporter::importRegistration(QXmlStreamReader &reader, const XmlCreators else q.bindValue(":importId", 0); } - q.bindValue(":country",person.nationalityCode); + q.bindValue(":country", person.nationalityName); + q.bindValue(":countryCode", person.nationalityCode); q.exec(qf::core::Exception::Throw); items_processed++; } diff --git a/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp b/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp index bbcbc29a8..de55f8146 100644 --- a/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp +++ b/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp @@ -119,6 +119,7 @@ struct Leg QString iofId; Organization org; QString country; + QString countryCode; int runId = 0; //int courseId = 0; int time = 0; @@ -275,7 +276,7 @@ qf::core::utils::TreeTable RelaysPlugin::nLegsClassResultsTable(int class_id, in qfs::QueryBuilder qb; qb.select2("competitors", "id, registration, iofId") .select2("runs", "id, relayId, leg, isRunning") - .select2("competitors", "firstName, lastName, club, country") + .select2("competitors", "firstName, lastName, club, country, countryCode") .select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName") .from("runs") .join("runs.competitorId", "competitors.id") @@ -305,6 +306,7 @@ qf::core::utils::TreeTable RelaysPlugin::nLegsClassResultsTable(int class_id, in leg.org.id = club.first; leg.org.shortName = club.second; leg.country = q.value("competitors.country").toString(); + leg.countryCode = q.value("competitors.countryCode").toString(); break; } } @@ -466,6 +468,7 @@ qf::core::utils::TreeTable RelaysPlugin::nLegsClassResultsTable(int class_id, in tt2_row.setValue("orgName", leg.org.name); tt2_row.setValue("orgShortName", leg.org.shortName); tt2_row.setValue("country", leg.country); + tt2_row.setValue("countryCode", leg.countryCode); //tt2_row.setValue("courseId", leg.courseId); tt2.setRow(ix2, tt2_row); qfDebug() << '\t' << leg.pos << leg.fullName; @@ -699,6 +702,14 @@ QString RelaysPlugin::resultsIofXml30() auto family = tt_leg_row.value(QStringLiteral("lastName")); auto given = tt_leg_row.value(QStringLiteral("firstName")); append_list(person, QVariantList{"Name", QVariantList{"Family", family}, QVariantList{"Given", given}}); + QString country_code = tt_leg_row.value(QStringLiteral("countryCode")).toString(); + if (!country_code.isEmpty()) { + append_list(person, + QVariantList{"Nationality", + QVariantMap{{"code", country_code}}, + tt_leg_row.value(QStringLiteral("country")) + }); + } append_list(member_result, person); QString club_name = tt_leg_row.value(QStringLiteral("orgName")).toString(); @@ -956,6 +967,14 @@ QString RelaysPlugin::startListIofXml30() auto family = tt_leg_row.value(QStringLiteral("lastName")); auto given = tt_leg_row.value(QStringLiteral("firstName")); append_list(person, QVariantList{"Name", QVariantList{"Family", family}, QVariantList{"Given", given}}); + QString country_code = tt_leg_row.value(QStringLiteral("countryCode")).toString(); + if (!country_code.isEmpty()) { + append_list(person, + QVariantList{"Nationality", + QVariantMap{{"code", country_code}}, + tt_leg_row.value(QStringLiteral("country")) + }); + } append_list(member_start, person); QVariantList start{"Start"}; diff --git a/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp b/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp index e56972c7a..a77ec5fcd 100644 --- a/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp +++ b/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp @@ -597,7 +597,7 @@ qf::core::utils::TreeTable RunsPlugin::stageResultsTable(int stage_id, const QSt { qf::core::sql::QueryBuilder qb; - qb.select2("competitors", "registration, iofId, lastName, firstName, startNumber, club, country") + qb.select2("competitors", "registration, iofId, lastName, firstName, startNumber, club, country, countryCode") .select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName") .select2("runs", "*") .select2("clubs", "name, abbr, importId") @@ -891,9 +891,9 @@ QString RunsPlugin::resultsIofXml30Stage(int stage_id) QVariantList{"Given", tt2_row.value(QStringLiteral("competitors.firstName"))}, } ); - if (is_iof_race) { - auto nationality = tt2_row.value(QStringLiteral("competitors.country")); - QString nat_code = getClubAbbrFromName(nationality.toString()); + auto nationality = tt2_row.value(QStringLiteral("competitors.country")); + QString nat_code = tt2_row.value(QStringLiteral("competitors.countryCode")).toString(); + if (!nat_code.isEmpty()) { person.insert(person.count(), QVariantList{"Nationality", QVariantMap{{"code", nat_code}}, nationality}); } person_result.insert(person_result.count(),person); @@ -1147,7 +1147,7 @@ qf::core::utils::TreeTable RunsPlugin::startListClassesTable(const QString &wher tt.appendColumn("courses.startNumber", QMetaType(QMetaType::Int)); qfs::QueryBuilder qb2; - qb2.select2("competitors", "lastName, firstName, registration, iofId, startNumber, country, club") + qb2.select2("competitors", "lastName, firstName, registration, iofId, startNumber, country, countryCode, club") .select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName") .select2("runs", "id, siId, startTimeMs") .select2("clubs","name, abbr, importId") @@ -2437,9 +2437,9 @@ QString RunsPlugin::startListStageIofXml30(int stage_id) auto family = tt2_row.value(QStringLiteral("competitors.lastName")); auto given = tt2_row.value(QStringLiteral("competitors.firstName")); append_list(person, QVariantList{"Name", QVariantList{"Family", family}, QVariantList{"Given", given}}); - if (is_iof_race) { - auto nationality = tt2_row.value(QStringLiteral("competitors.country")); - QString nat_code = getClubAbbrFromName(nationality.toString()); + auto nationality = tt2_row.value(QStringLiteral("competitors.country")); + QString nat_code = tt2_row.value(QStringLiteral("competitors.countryCode")).toString(); + if (!nat_code.isEmpty()) { append_list(person, QVariantList{"Nationality", QVariantMap{{"code", nat_code}}, nationality}); } QVariantList xml_start{"Start", (iof_xml_race_number != 0) ? QVariantMap{{"raceNumber", iof_xml_race_number}} : QVariantMap{}}; diff --git a/quickevent/app/quickevent/src/appversion.h b/quickevent/app/quickevent/src/appversion.h index 711aaef79..f46db1a0c 100644 --- a/quickevent/app/quickevent/src/appversion.h +++ b/quickevent/app/quickevent/src/appversion.h @@ -1,4 +1,4 @@ #pragma once -#define APP_VERSION "2.6.30" +#define APP_VERSION "2.7.0" From 70090727ff4cda910e9338b3e88a5d27650b9509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otakar=20Hir=C5=A1?= Date: Fri, 17 Jan 2025 20:20:59 +0100 Subject: [PATCH 2/3] fix: missing countryCode in query --- quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp b/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp index de55f8146..f95fc35eb 100644 --- a/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp +++ b/quickevent/app/quickevent/plugins/Relays/src/relaysplugin.cpp @@ -513,7 +513,7 @@ QVariant RelaysPlugin::startListByClassesTableData(const QString &class_filter) } { qf::core::sql::QueryBuilder qb; - qb.select2("competitors", "registration, iofId") + qb.select2("competitors", "registration, iofId, country, countryCode") .select("competitors.firstName, competitors.lastName, COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName") .select2("runs", "id, leg, siId, startTimeMs") .from("runs") From be8e6ae0b6bd82d279215a09c0c8844f83337307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otakar=20Hir=C5=A1?= Date: Fri, 17 Jan 2025 22:08:01 +0100 Subject: [PATCH 3/3] fix: commit db change --- quickevent/app/quickevent/plugins/Event/qml/DbSchema.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quickevent/app/quickevent/plugins/Event/qml/DbSchema.qml b/quickevent/app/quickevent/plugins/Event/qml/DbSchema.qml index a26668a12..d33edcc05 100644 --- a/quickevent/app/quickevent/plugins/Event/qml/DbSchema.qml +++ b/quickevent/app/quickevent/plugins/Event/qml/DbSchema.qml @@ -165,6 +165,7 @@ Schema { Field { name: 'licence'; type: String { length: 1 } }, Field { name: 'club'; type: String { } }, Field { name: 'country'; type: String { } }, + Field { name: 'countryCode'; type: String { } }, Field { name: 'siId'; type: Int { } }, Field { name: 'ranking'; type: Int { } }, Field { name: 'note'; type: String { } }, @@ -345,6 +346,7 @@ Schema { Field { name: 'licence'; type: String { length: 1 } }, Field { name: 'clubAbbr'; type: String { } }, Field { name: 'country'; type: String { } }, + Field { name: 'countryCode'; type: String { } }, Field { name: 'siId'; type: Int { } }, //Field { name: 'nameSearchKey'; type: String {} }, Field { name: 'importId'; type: Int { } }