diff --git a/code/TabCompetition.cpp b/code/TabCompetition.cpp index b6cb7bd..92f5450 100644 --- a/code/TabCompetition.cpp +++ b/code/TabCompetition.cpp @@ -2361,7 +2361,7 @@ void TabCompetition::copyrightLine(gdioutput &gdi) const gdi.dropLine(0.4); gdi.fillDown(); - gdi.addString("", 0, makeDash(L"#Copyright © 2007-2018 Melin Software HB")); + gdi.addString("", 0, makeDash(L"#Copyright © 2007-2019 Melin Software HB")); gdi.dropLine(1); gdi.popX(); @@ -2374,7 +2374,7 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const gdi.clearPage(false); gdi.addString("", 2, makeDash(L"Om MeOS - ett Mycket Enkelt OrienteringsSystem")).setColor(colorDarkBlue); gdi.dropLine(2); - gdi.addStringUT(1, makeDash(L"Copyright © 2007-2018 Melin Software HB")); + gdi.addStringUT(1, makeDash(L"Copyright © 2007-2019 Melin Software HB")); gdi.dropLine(); gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright " "(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB," diff --git a/code/TabSI.cpp b/code/TabSI.cpp index 3b1b6df..4579379 100644 --- a/code/TabSI.cpp +++ b/code/TabSI.cpp @@ -3684,8 +3684,8 @@ oClub *TabSI::extractClub(gdioutput &gdi) const { oClub *dbClub = nullptr; if (gdi.hasField("Club")) { int clubId = gdi.getExtraInt("Club"); - if (clubId >= 0) { - dbClub = db.getClub(clubId); + if (clubId > 0) { + dbClub = db.getClub(clubId-1); if (dbClub && !stringMatch(dbClub->getName(), gdi.getText("Club"))) dbClub = nullptr; } @@ -3702,8 +3702,8 @@ RunnerWDBEntry *TabSI::extractRunner(gdioutput &gdi) const { int rId = gdi.getExtraInt("Name"); wstring name = gdi.getText("Name"); RunnerWDBEntry *dbR = nullptr; - if (rId >= 0) { - dbR = db.getRunnerByIndex(rId); + if (rId > 0) { + dbR = db.getRunnerByIndex(rId-1); if (dbR) { wstring fname = dbR->getFamilyName(); wstring gname = dbR->getGivenName(); @@ -3847,8 +3847,9 @@ void TabSI::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) { auto bi = gdi.setText(info.getTarget(), info.getCurrent().c_str()); if (bi) { int ix = info.getCurrentInt(); - bi->setExtra(ix); - if (bi->id == "Name") { + + bi->setExtra(ix+1); + if (bi->id == "Name" && ix >= 0) { auto r = oe->getRunnerDatabase().getRunnerByIndex(ix); int year = r ? r->getBirthYear() : 0; if (year > 0) { diff --git a/code/csvparser.cpp b/code/csvparser.cpp index 417c520..769b1ec 100644 --- a/code/csvparser.cpp +++ b/code/csvparser.cpp @@ -888,7 +888,7 @@ void csvparser::checkSIConfigHeader(const vector &sp) { else if (key == L"First name") { siconfigmap[sicFirstName] = k; } - else if (key == L"Last name") { + else if (key == L"Last name" || key == L"name") { siconfigmap[sicLastName] = k; } else if (key == L"No. of records" || key == L"No. of punches") { diff --git a/code/download.cpp b/code/download.cpp index 678c3dd..d234c5d 100644 --- a/code/download.cpp +++ b/code/download.cpp @@ -287,7 +287,8 @@ void Download::postFile(const wstring &url, const wstring &file, const wstring & InternetCrackUrl(url.c_str(), url.length(), ICU_ESCAPE, &uc); int port = INTERNET_DEFAULT_HTTP_PORT; - if (uc.nScheme == INTERNET_SCHEME_HTTPS) + bool https = uc.nScheme == INTERNET_SCHEME_HTTPS; + if (https) port = INTERNET_DEFAULT_HTTPS_PORT; else if (uc.nPort>0) port = uc.nPort; @@ -296,7 +297,7 @@ void Download::postFile(const wstring &url, const wstring &file, const wstring & bool vsuccess = false; int errorCode = 0; try { - vsuccess = httpSendReqEx(hConnect, path, headers, file, fileOut, pw, errorCode); + vsuccess = httpSendReqEx(hConnect, https, path, headers, file, fileOut, pw, errorCode); } catch (std::exception &) { InternetCloseHandle(hConnect); @@ -315,7 +316,7 @@ void Download::postFile(const wstring &url, const wstring &file, const wstring & } } -bool Download::httpSendReqEx(HINTERNET hConnect, const wstring &dest, +bool Download::httpSendReqEx(HINTERNET hConnect, bool https, const wstring &dest, const vector< pair > &headers, const wstring &upFile, const wstring &outFile, ProgressWindow &pw, @@ -324,8 +325,19 @@ bool Download::httpSendReqEx(HINTERNET hConnect, const wstring &dest, INTERNET_BUFFERS BufferIn; memset(&BufferIn, 0, sizeof(BufferIn)); BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS ); + TCHAR szAccept[] = L"*/*"; + LPCTSTR AcceptTypes[2] = { 0, 0 }; + AcceptTypes[0] = szAccept; + DWORD flags = INTERNET_FLAG_NO_CACHE_WRITE | + INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | + INTERNET_FLAG_IGNORE_CERT_CN_INVALID | + INTERNET_FLAG_KEEP_CONNECTION; - HINTERNET hRequest = HttpOpenRequest (hConnect, L"POST", dest.c_str(), NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0); + if (https) + flags |= INTERNET_FLAG_SECURE; + + HINTERNET hRequest = HttpOpenRequest (hConnect, L"POST", dest.c_str(), HTTP_VERSION, NULL, AcceptTypes, + flags, 0); DWORD dwBytesRead = 0; DWORD dwBytesWritten = 0; @@ -396,12 +408,15 @@ bool Download::httpSendReqEx(HINTERNET hConnect, const wstring &dest, DWORD error = GetLastError(); errorCode = error; if (error == ERROR_INTERNET_FORCE_RETRY) - retry--; - else if (error == ERROR_INTERNET_TIMEOUT) { - throw std::exception("Fick inget svar i tid (ERROR_INTERNET_TIMEOUT)"); - } + retry--; else { InternetCloseHandle(hRequest); + if (error == ERROR_INTERNET_TIMEOUT) { + throw std::exception("Fick inget svar i tid (ERROR_INTERNET_TIMEOUT)"); + } + else if (error == ERROR_INTERNET_CONNECTION_RESET) { + throw std::exception("Inget svar (ERROR_INTERNET_CONNECTION_RESET)"); + } return false; } } diff --git a/code/download.h b/code/download.h index 27f6f72..a09d9c5 100644 --- a/code/download.h +++ b/code/download.h @@ -60,7 +60,7 @@ private: bool success; void initThread(); - bool httpSendReqEx(HINTERNET hConnect, const wstring &dest, const vector< pair > &headers, + bool httpSendReqEx(HINTERNET hConnect, bool https, const wstring &dest, const vector< pair > &headers, const wstring &upFile, const wstring &outFile, ProgressWindow &pw, int &errroCode) const; public: diff --git a/code/generalresult.cpp b/code/generalresult.cpp index 4876659..1fddd35 100644 --- a/code/generalresult.cpp +++ b/code/generalresult.cpp @@ -140,7 +140,7 @@ void GeneralResult::calculateTeamResults(vector &teams, oListInfo::Resu for (size_t k = 0; k < teams.size(); k++) { if (resType == oListInfo::Classwise) { teamScore[k].principalSort = teams[k]->Class ? teams[k]->Class->getSortIndex() * 50000 - + teams[k]->Class->getId() : 0; + + teams[k]->Class->getId() : 0; } else teamScore[k].principalSort = 0; @@ -152,8 +152,8 @@ void GeneralResult::calculateTeamResults(vector &teams, oListInfo::Resu teams[k]->tmpResult.points = deducePoints(*teams[k]); teamScore[k].score = score(*teams[k], teams[k]->tmpResult.status, - teams[k]->tmpResult.runningTime, - teams[k]->tmpResult.points); + teams[k]->tmpResult.runningTime, + teams[k]->tmpResult.points); storeOutput(teams[k]->tmpResult.outputTimes, teams[k]->tmpResult.outputNumbers); @@ -167,11 +167,11 @@ void GeneralResult::calculateTeamResults(vector &teams, oListInfo::Resu int iPlace = 1; int leadtime = 0; for (size_t k = 0; k < teamScore.size(); k++) { - if (k>0 && teamScore[k-1].principalSort != teamScore[k].principalSort) { + if (k > 0 && teamScore[k - 1].principalSort != teamScore[k].principalSort) { place = 1; iPlace = 1; } - else if (k>0 && teamScore[k-1].score != teamScore[k].score) { + else if (k > 0 && teamScore[k - 1].score != teamScore[k].score) { place = iPlace; } @@ -214,7 +214,7 @@ void GeneralResult::sortTeamMembers(vector &runners) const { ::sort(runnerScore.begin(), runnerScore.end()); for (size_t k = 0; k < runners.size(); k++) { - runners[k] = pRunner(runnerScore[k].tr); + runners[k] = pRunner(runnerScore[k].tr); } } @@ -230,7 +230,7 @@ template void GeneralResult::sort(vector &rt, SortOrder so) const vector< pair > arr(rt.size()); const int maxT = 3600 * 100; - for(size_t k = 0; k < rt.size(); k++) { + for (size_t k = 0; k < rt.size(); k++) { arr[k].first = 0; if (ps == ClassWise) { pClass sclass = rt[k]->getClassRef(true); @@ -245,12 +245,12 @@ template void GeneralResult::sort(vector &rt, SortOrder so) const const oAbstractRunner::TempResult &tr = rt[k]->getTempResult(0); if (so == SortByFinishTime || so == ClassFinishTime) { ord = tr.getFinishTime(); - if (ord == 0 || tr.getStatus()>1) + if (ord == 0 || tr.getStatus() > 1) ord = maxT; } else if (so == SortByFinishTimeReverse) { ord = tr.getFinishTime(); - if (ord == 0 || tr.getStatus()>1) + if (ord == 0 || tr.getStatus() > 1) ord = maxT; else ord = maxT - ord; @@ -265,14 +265,14 @@ template void GeneralResult::sort(vector &rt, SortOrder so) const stable_sort(arr.begin(), arr.end()); - for(size_t k = 0; k < rt.size(); k++) { + for (size_t k = 0; k < rt.size(); k++) { rt[k] = (T*)arr[k].second; } } -void GeneralResult::calculateIndividualResults(vector &runners, - oListInfo::ResultType resType, - bool sortRunners, +void GeneralResult::calculateIndividualResults(vector &runners, + oListInfo::ResultType resType, + bool sortRunners, int inputNumber) const { if (runners.empty()) @@ -284,11 +284,11 @@ void GeneralResult::calculateIndividualResults(vector &runners, const oRunner *r = runners[k]; if (resType == oListInfo::Classwise) { runnerScore[k].principalSort = r->Class ? r->Class->getSortIndex() * 50000 - + r->Class->getId() : 0; + + r->Class->getId() : 0; } else if (resType == oListInfo::Legwise) { runnerScore[k].principalSort = r->Class ? r->Class->getSortIndex() * 50000 - + r->Class->getId() : 0; + + r->Class->getId() : 0; int ln = r->getLegNumber(); const oTeam *pt = r->getTeam(); @@ -298,7 +298,7 @@ void GeneralResult::calculateIndividualResults(vector &runners, int dummy; tcls->splitLegNumberParallel(r->getLegNumber(), ln, dummy); } - } + } runnerScore[k].principalSort = runnerScore[k].principalSort * 50 + ln; } else if (resType == oListInfo::Coursewise) { @@ -327,8 +327,8 @@ void GeneralResult::calculateIndividualResults(vector &runners, runners[k]->tmpResult.points = deducePoints(*runners[k]); runnerScore[k].score = score(*runners[k], runners[k]->tmpResult.status, - runners[k]->tmpResult.runningTime, - runners[k]->tmpResult.points, false); + runners[k]->tmpResult.runningTime, + runners[k]->tmpResult.points, false); storeOutput(runners[k]->tmpResult.outputTimes, runners[k]->tmpResult.outputNumbers); @@ -342,11 +342,11 @@ void GeneralResult::calculateIndividualResults(vector &runners, int iPlace = 1; int leadtime = 0; for (size_t k = 0; k < runnerScore.size(); k++) { - if (k>0 && runnerScore[k-1].principalSort != runnerScore[k].principalSort) { + if (k > 0 && runnerScore[k - 1].principalSort != runnerScore[k].principalSort) { place = 1; iPlace = 1; } - else if (k>0 && runnerScore[k-1].score != runnerScore[k].score) { + else if (k > 0 && runnerScore[k - 1].score != runnerScore[k].score) { place = iPlace; } @@ -389,8 +389,8 @@ void GeneralResult::prepareCalculations(oTeam &team) const { r->tmpResult.timeAfter = 0;//XXX? r->tmpResult.points = deducePoints(*r); r->tmpResult.internalScore = score(*r, r->tmpResult.status, - r->tmpResult.runningTime, - r->tmpResult.points, true); + r->tmpResult.runningTime, + r->tmpResult.points, true); storeOutput(r->tmpResult.outputTimes, r->tmpResult.outputNumbers); @@ -400,9 +400,9 @@ void GeneralResult::prepareCalculations(oTeam &team) const { void GeneralResult::prepareCalculations(oRunner &runner) const { int from = getListParamTimeFromControl(); - runner.tmpResult.startTime = runner.getStartTime(); - - if (from>0) { + runner.tmpResult.startTime = runner.getStartTime(); + + if (from > 0) { int rt; RunnerStatus stat; runner.getSplitTime(from, stat, rt); @@ -415,7 +415,7 @@ void GeneralResult::storeOutput(vector ×, vector &numbers) const } int GeneralResult::score(oTeam &team, RunnerStatus st, int rt, int points) const { - return (100*RunnerStatusOrderMap[st] + team.getNumShortening()) * 900000 + rt; + return (100 * RunnerStatusOrderMap[st] + team.getNumShortening()) * 900000 + rt; } RunnerStatus GeneralResult::deduceStatus(oTeam &team) const { @@ -434,8 +434,8 @@ int GeneralResult::score(oRunner &runner, RunnerStatus st, int time, int points, if (asTeamMember) { return runner.getLegNumber(); } - else - return (RunnerStatusOrderMap[st]*100 + runner.getNumShortening()) * 900000 + time; + else + return (RunnerStatusOrderMap[st] * 100 + runner.getNumShortening()) * 900000 + time; } RunnerStatus GeneralResult::deduceStatus(oRunner &runner) const { @@ -480,19 +480,19 @@ RunnerStatus TotalResultAtControl::deduceStatus(oRunner &runner) const { RunnerStatus singleStat = ResultAtControl::deduceStatus(runner); if (singleStat != StatusOK) return singleStat; - + RunnerStatus inputStatus = StatusOK; if (runner.getTeam() && getListParamTimeFromControl() <= 0) { // Only use input time when start time is used const pTeam t = runner.getTeam(); - if (runner.getLegNumber()>0 && t->getClassRef(false)) { + if (runner.getLegNumber() > 0 && t->getClassRef(false)) { // Find base leg int legIx = runner.getLegNumber(); const pClass cls = t->getClassRef(false); while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx))) legIx--; if (legIx > 0) - inputStatus = t->getLegStatus(legIx-1, true); + inputStatus = t->getLegStatus(legIx - 1, true); } else { inputStatus = t->getInputStatus(); @@ -507,7 +507,7 @@ RunnerStatus TotalResultAtControl::deduceStatus(oRunner &runner) const { int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const { int singleTime = ResultAtControl::deduceTime(runner, startTime); - + if (singleTime == 0) return 0; @@ -515,14 +515,14 @@ int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const { if (runner.getTeam() && getListParamTimeFromControl() <= 0) { // Only use input time when start time is used const pTeam t = runner.getTeam(); - if (runner.getLegNumber()>0 && t->getClassRef(false)) { + if (runner.getLegNumber() > 0 && t->getClassRef(false)) { // Find base leg int legIx = runner.getLegNumber(); const pClass cls = t->getClassRef(false); while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx))) legIx--; if (legIx > 0) - inputTime = t->getLegRunningTime(legIx-1, true); + inputTime = t->getLegRunningTime(legIx - 1, true); } else { inputTime = t->getInputTime(); @@ -543,8 +543,8 @@ int TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int if (runner.getTeam()) { const pTeam t = runner.getTeam(); - if (runner.getLegNumber()>0) { - inputStatus = t->getLegStatus(runner.getLegNumber()-1, true); + if (runner.getLegNumber() > 0) { + inputStatus = t->getLegStatus(runner.getLegNumber() - 1, true); } else { inputStatus = t->getInputStatus(); @@ -760,15 +760,15 @@ int DynamicResult::deducePoints(oTeam &team) const { } int DynamicResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const { - if (getMethod(MRScore)) { - parser.addSymbol("ComputedTime", time); - parser.addSymbol("ComputedStatus", st); - parser.addSymbol("ComputedPoints", points); - return getMethod(MRScore)->evaluate(parser); - } - else if (getMethodSource(MRScore).empty()) + if (getMethod(MRScore)) { + parser.addSymbol("ComputedTime", time); + parser.addSymbol("ComputedStatus", st); + parser.addSymbol("ComputedPoints", points); + return getMethod(MRScore)->evaluate(parser); + } + else if (getMethodSource(MRScore).empty()) return GeneralResult::score(runner, st, time, points, asTeamMember); - else throw meosException("Syntax error"); + else throw meosException("Syntax error"); } RunnerStatus DynamicResult::deduceStatus(oRunner &runner) const { @@ -780,7 +780,7 @@ RunnerStatus DynamicResult::deduceStatus(oRunner &runner) const { } int DynamicResult::deduceTime(oRunner &runner, int startTime) const { - if (getMethod(MDeduceRTime)) + if (getMethod(MDeduceRTime)) return getMethod(MDeduceRTime)->evaluate(parser); else if (getMethodSource(MDeduceRTime).empty()) return GeneralResult::deduceTime(runner, startTime); @@ -788,7 +788,7 @@ int DynamicResult::deduceTime(oRunner &runner, int startTime) const { } int DynamicResult::deducePoints(oRunner &runner) const { - if (getMethod(MDeduceRPoints)) + if (getMethod(MDeduceRPoints)) return getMethod(MDeduceRPoints)->evaluate(parser); else if (getMethodSource(MDeduceRPoints).empty()) return GeneralResult::deducePoints(runner); @@ -814,14 +814,14 @@ void DynamicResult::save(xmlparser &xml) const { origin = gEvent->getName() + L" (" + getLocalDate() + L")"; xml.write("Origin", origin); xml.write("Date", getLocalTime()); -// xml.write("Tag", tag); -// xml.write("UID", getUniqueId()); + // xml.write("Tag", tag); + // xml.write("UID", getUniqueId()); for (map::const_iterator it = symb2Method.begin(); it != symb2Method.end(); ++it) { if (!methods[it->second].source.empty()) { xml.startTag("Rule", "name", it->first); - xml.write("Description", methods[it->second].description); - xml.write("Method", methods[it->second].source); + xml.write("Description", methods[it->second].description); + xml.write("Method", methods[it->second].source); xml.endTag(); } } @@ -910,10 +910,10 @@ void DynamicResult::getMethodTypes(vector< pair > &mt) c void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const { if (clear) parser.clearSymbols(); - const bool isRunner = m == MRScore || - m == MDeduceRPoints || - m == MDeduceRStatus || - m == MDeduceRTime; + const bool isRunner = m == MRScore || + m == MDeduceRPoints || + m == MDeduceRStatus || + m == MDeduceRTime; parser.declareSymbol("Status", "Runner/team status", false); parser.declareSymbol("Start", "Runner/team start time", false); @@ -936,13 +936,13 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const { parser.declareSymbol("InputTime", "Runner/team input running time", false); parser.declareSymbol("InputPlace", "Runner/team input place", false); parser.declareSymbol("InputPoints", "Runner/team input points", false); - + parser.declareSymbol("Fee", "Runner/team fee", false); parser.declareSymbol("ClubId", "Club id number", false); parser.declareSymbol("DistrictId", "District id number", false); parser.declareSymbol("Bib", "Nummerlapp", false); - + parser.declareSymbol("InputNumber", "User input number", false); parser.declareSymbol("Shorten", "Number of shortenings", false); @@ -954,7 +954,7 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const { parser.declareSymbol("Course", "Runner's course", true); parser.declareSymbol("CourseId", "Runner's course id", false); parser.declareSymbol("CourseLength", "Length of course", false); - + parser.declareSymbol("SplitTimes", "Runner's split times", true); parser.declareSymbol("SplitTimesAccumulated", "Runner's total running time to control", true); @@ -997,7 +997,7 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const { parser.declareSymbol("StatusMAX", "Status code for a time over the maximum", false); parser.declareSymbol("StatusDQ", "Status code for disqualification", false); parser.declareSymbol("StatusNotCompetiting", "Status code for not competing", false); - + parser.declareSymbol("ShortestClassTime", "Shortest time in class", false); if (m == MRScore || m == MTScore) { @@ -1019,7 +1019,7 @@ void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inp compile(false); oe.calculateResults(oEvent::RTClassResult); oe.calculateResults(oEvent::RTTotalResult); - + declareSymbols(MRScore, true); if (prepareForTeam) { declareSymbols(MTScore, false); @@ -1047,9 +1047,9 @@ void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inp void DynamicResult::prepareCommon(oAbstractRunner &runner) const { parser.clearVariables(); - int st = runner.getStatus(); + int st = runner.getStatus(); int ft = runner.getFinishTime(); - if (st == StatusUnknown && ft>0) + if (st == StatusUnknown && ft > 0) st = StatusOK; parser.addSymbol("Status", st); parser.addSymbol("Start", runner.getStartTime()); @@ -1076,7 +1076,7 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner) const { parser.addSymbol("Fee", runner.getDCI().getInt("Fee")); - const pClub pc = runner.getClubRef(); + const pClub pc = runner.getClubRef(); if (pc) { parser.addSymbol("ClubId", pc->getId()); parser.addSymbol("DistrictId", pc->getDCI().getInt("District")); @@ -1125,7 +1125,7 @@ void DynamicResult::prepareCalculations(oTeam &team) const { parser.removeSymbol("SplitTimesAccumulated"); parser.removeSymbol("LegTimeDeviation"); parser.removeSymbol("BirthYear"); - + parser.addSymbol("RunnerOutputNumbers", runnerOutputNumbers); parser.addSymbol("RunnerOutputTimes", runnerOutputTimes); @@ -1148,7 +1148,7 @@ void DynamicResult::prepareCalculations(oTeam &team) const { pClass cls = team.getClassRef(true); if (cls) { - int nl = max(1, cls->getNumStages()-1); + int nl = max(1, cls->getNumStages() - 1); parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(nl, false)); } } @@ -1183,7 +1183,7 @@ void DynamicResult::prepareCalculations(oRunner &runner) const { pTeam t = runner.getTeam(); if (t) { - int leg = runner.getLegNumber(); + int leg = runner.getLegNumber(); t->setResultCache(oTeam::RCCCardTimes, leg, times); t->setResultCache(oTeam::RCCCardPunches, leg, codes); t->setResultCache(oTeam::RCCCardControls, leg, controls); @@ -1214,12 +1214,12 @@ void DynamicResult::prepareCalculations(oRunner &runner) const { eCrs.push_back(ctrl->getFirstNumber()); if (size_t(k) < sp.size()) { if (sp[k].status == SplitData::OK) { - eAccTime.push_back(sp[k].time-start); - eSplitTime.push_back(sp[k].time-st); + eAccTime.push_back(sp[k].time - start); + eSplitTime.push_back(sp[k].time - st); st = sp[k].time; } else if (sp[k].status == SplitData::NoTime) { - eAccTime.push_back(st-start); + eAccTime.push_back(st - start); eSplitTime.push_back(0); } else if (sp[k].status == SplitData::Missing) { @@ -1230,14 +1230,14 @@ void DynamicResult::prepareCalculations(oRunner &runner) const { } } if (runner.getFinishTime() > 0) { - eAccTime.push_back(runner.getFinishTime()-start); - eSplitTime.push_back(runner.getFinishTime()-st); + eAccTime.push_back(runner.getFinishTime() - start); + eSplitTime.push_back(runner.getFinishTime() - st); } else if (!eAccTime.empty()) { eAccTime.push_back(0); eSplitTime.push_back(-1); } - + parser.addSymbol("CourseLength", crs->getLength()); parser.addSymbol("CourseId", crs->getId()); parser.addSymbol("Course", eCrs); @@ -1245,7 +1245,7 @@ void DynamicResult::prepareCalculations(oRunner &runner) const { parser.addSymbol("SplitTimesAccumulated", eAccTime); pTeam t = runner.getTeam(); if (t) { - int leg = runner.getLegNumber(); + int leg = runner.getLegNumber(); t->setResultCache(oTeam::RCCCourse, leg, eCrs); t->setResultCache(oTeam::RCCSplitTime, leg, eSplitTime); } @@ -1329,6 +1329,7 @@ void DynamicResult::debugDumpVariables(gdioutput &gdi, bool includeSymbols) cons void GeneralResult::calculateIndividualResults(vector &runners, const pair & controlId, bool totalResults, + bool inclForestRunners, const string &resTag, oListInfo::ResultType resType, int inputNumber, @@ -1341,15 +1342,24 @@ void GeneralResult::calculateIndividualResults(vector &runners, GeneralResultInfo ri; if (controlId.second == oPunch::PunchFinish && controlId.first == oPunch::PunchStart) { - + if (!totalResults) { oe.calculateResults(oEvent::RTClassResult, true); for (pRunner r : runners) { ri.status = r->getStatus(); if (ri.status == StatusUnknown) { - if (r->getFinishTime() == 0) - continue; - ri.status = StatusOK; // Preliminary status + if (r->getFinishTime() == 0) { + if (!inclForestRunners) + continue; + else { + if (r->getClubId() == cVacantId) + continue; + ri.status = StatusUnknown; + } + } + else { + ri.status = StatusOK; // Preliminary status + } } if (ri.status == StatusOK) ri.place = r->getPlace(); @@ -1367,9 +1377,18 @@ void GeneralResult::calculateIndividualResults(vector &runners, for (pRunner r : runners) { ri.status = r->getTotalStatus(); if (ri.status == StatusUnknown && r->getInputStatus() == StatusOK) { - if (r->getFinishTime() == 0) - continue; - ri.status = StatusOK; // Preliminary status + if (r->getFinishTime() == 0) { + if (!inclForestRunners) + continue; + else { + if (r->getClubId() == cVacantId) + continue; + ri.status = StatusUnknown; + } + } + else { + ri.status = StatusOK; // Preliminary status + } } if (ri.status == StatusOK) ri.place = r->getTotalPlace(); @@ -1421,7 +1440,7 @@ void GeneralResult::calculateIndividualResults(vector &runners, gResult = &oe.getGeneralResult(resTag, srcDMY); else { if (controlId.second == oPunch::PunchFinish && - controlId.first == oPunch::PunchStart && !totalResults) + controlId.first == oPunch::PunchStart && !totalResults) specialInstance = make_shared(); else if (!totalResults) specialInstance = make_shared(); @@ -1439,9 +1458,12 @@ void GeneralResult::calculateIndividualResults(vector &runners, const auto &tmp = r->getTempResult(0); ri.status = tmp.getStatus(); if (ri.status == StatusUnknown) { - if (r->getFinishTime() == 0) - continue; - ri.status = StatusOK; // Preliminary status + if (r->getFinishTime() == 0) { + if (!inclForestRunners) + continue; + } + else + ri.status = StatusOK; // Preliminary status } if (ri.status == StatusOK) ri.place = tmp.getPlace(); @@ -1449,13 +1471,14 @@ void GeneralResult::calculateIndividualResults(vector &runners, ri.place = 0; if ((controlId.first != oPunch::PunchStart || - controlId.second != oPunch::PunchFinish) && ri.status == StatusMP && r->getStatus() != StatusMP) { - continue; + controlId.second != oPunch::PunchFinish) && ri.status == StatusMP && r->getStatus() != StatusMP) { + if (!inclForestRunners) + continue; } ri.score = tmp.getPoints(); ri.time = tmp.getRunningTime(); - + if (controlId.first != oPunch::PunchStart && ri.time <= 0 && ri.status == StatusOK) continue; // Wrong order, skip @@ -1466,16 +1489,16 @@ void GeneralResult::calculateIndividualResults(vector &runners, } } -shared_ptr - GeneralResult::calculateTeamResults(vector &teams, - int leg, - const pair &controlId, - bool totalResults, - const string &resTag, - oListInfo::ResultType resType, - int inputNumber, - oEvent &oe, - vector &results) { +shared_ptr +GeneralResult::calculateTeamResults(vector &teams, + int leg, + const pair &controlId, + bool totalResults, + const string &resTag, + oListInfo::ResultType resType, + int inputNumber, + oEvent &oe, + vector &results) { shared_ptr out = make_shared(); out->leg = leg; out->controlId = controlId; @@ -1516,7 +1539,7 @@ shared_ptr for (pTeam r : teams) { const auto &tmp = r->getTempResult(0); ri.status = tmp.getStatus(); - if (ri.status == StatusUnknown || ri.status == StatusMP) + if (ri.status == StatusUnknown || ri.status == StatusMP) continue; ri.place = tmp.getPlace(); ri.score = tmp.getPoints(); @@ -1572,16 +1595,16 @@ int GeneralResult::GeneralResultInfo::getNumSubresult(const BaseResultContext &c if (nb == -1) nb = cls->getNumStages(); - int pb = cls->getPreceedingLeg(leg)+1; - + int pb = cls->getPreceedingLeg(leg) + 1; + context.resIntervalCache[cid] = make_pair(pb, nb); return nb - pb; } } -bool GeneralResult::GeneralResultInfo::getSubResult(const BaseResultContext &context, +bool GeneralResult::GeneralResultInfo::getSubResult(const BaseResultContext &context, int ix, GeneralResultInfo &out) const { - + if (getNumSubresult(context) == 0) return false; // Ensure cache is setup int base = context.resIntervalCache[src->getClassId(false)].first; diff --git a/code/generalresult.h b/code/generalresult.h index b89dd03..4c79c7e 100644 --- a/code/generalresult.h +++ b/code/generalresult.h @@ -122,6 +122,7 @@ public: static void calculateIndividualResults(vector &runners, const pair &controlId, bool totalResults, + bool inclForestRunners, const string &resTag, oListInfo::ResultType resType, int inputNumber, diff --git a/code/infoserver.cpp b/code/infoserver.cpp index c4b4862..416a4c6 100644 --- a/code/infoserver.cpp +++ b/code/infoserver.cpp @@ -85,6 +85,9 @@ InfoRadioControl::InfoRadioControl(int id) : InfoBase(id) { InfoClass::InfoClass(int id) : InfoBase(id) { } +InfoMeosStatus::InfoMeosStatus() : InfoBase(0) { +} + InfoOrganization::InfoOrganization(int id) : InfoBase(id) { } @@ -381,6 +384,23 @@ void InfoClass::serialize(xmlbuffer &xml, bool diffOnly) const { xml.write("cls", prop, name); } +void InfoMeosStatus::setOnDatabase(const bool flag) { + onDatabase = flag; +} + +void InfoMeosStatus::setEventNameId(const wstring & str) { + eventNameId = str; +} + +void InfoMeosStatus::serialize(xmlbuffer &xml, bool diffOnly) const { + vector> prop; + prop.push_back(make_pair("version", getMeosCompectVersion())); + prop.push_back(make_pair("eventNameId", eventNameId)); + prop.push_back(make_pair("onDatabase", itow(onDatabase))); // 1 is true, 0 is false + + xml.write("status", prop, L""); +} + bool InfoOrganization::synchronize(oClub &c) { const wstring &n = c.getDisplayName(); if (n == name) @@ -445,6 +465,10 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) { } int s = bc.getStatus(); + int rt = bc.getRunningTime() * 10; + if (rt > 0 && s == RunnerStatus::StatusUnknown) + s = RunnerStatus::StatusOK; + if (status != s) { status = s; ch = true; @@ -459,7 +483,6 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) { ch = true; } - int rt = bc.getRunningTime() * 10; if (rt != runningTime) { runningTime = rt; ch = true; diff --git a/code/infoserver.h b/code/infoserver.h index d762cc4..fd1742b 100644 --- a/code/infoserver.h +++ b/code/infoserver.h @@ -125,6 +125,18 @@ class InfoClass : public InfoBase { friend class InfoCompetition; }; +class InfoMeosStatus : public InfoBase { + protected: + wstring eventNameId; // event Name Id, actual name of the database, can also be matched in oevent table of meosmain + bool onDatabase; // true if currently on database + public: + void serialize(xmlbuffer &xml, bool diffOnly) const; + InfoMeosStatus(); + virtual ~InfoMeosStatus() {} + void setEventNameId(const wstring &); + void setOnDatabase(const bool); +}; + class InfoOrganization : public InfoBase { protected: wstring name; diff --git a/code/iof30interface.cpp b/code/iof30interface.cpp index 0614252..5c08d0c 100644 --- a/code/iof30interface.cpp +++ b/code/iof30interface.cpp @@ -1637,7 +1637,7 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea if (sar) { string type; sar.getObjectString("type", type); - if (type == "groupedWithRef") { + if (type == "groupedWithRef" || type == "GroupedWith") { xmlobject pRef = sar.getObject("Person"); if (pRef) { wstring sid; @@ -2655,7 +2655,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o } if (teamMember) - writeLegOrder(xml, rPerson); + writeLegOrder(xml, rPerson.getClassRef(false), rPerson.getLegNumber()); wstring bib = rPerson.getBib(); if (!bib.empty()) @@ -3113,6 +3113,44 @@ void IOF30Interface::writePersonStart(xmlparser &xml, const oRunner &r, bool inc xml.endTag(); } +void IOF30Interface::writeTeamNoPersonStart(xmlparser &xml, const oTeam &t, int leg, bool includeRaceNumber) { + xml.startTag("TeamMemberStart"); + + const pClub pc = t.getClubRef(); + pClass cls = t.getClassRef(false); + if (pc && !pc->isVacant()) + writeClub(xml, *pc, false); + + { + if (!includeRaceNumber || (getStageNumber() == 0 && (cls && cls->getLegRunnerIndex(leg)==0))) + xml.startTag("Start"); + else { + int rn = getStageNumber(); + if (rn == 0) + rn = 1; + if (includeStageRaceInfo) + rn += cls->getLegRunnerIndex(leg); + + xml.startTag("Start", "raceNumber", itos(rn)); + } + + writeLegOrder(xml, cls, leg); + + wstring bib = t.getBib(); + if (!bib.empty()) + xml.write("BibNumber", bib); + int startTime = 0; + if (cls && cls->getStartType(leg) == StartTypes::STTime) + startTime = cls->getStartData(leg); + if (startTime > 0) + xml.write("StartTime", oe.getAbsDateTimeISO(startTime, true, useGMT)); + + xml.endTag(); + } + + xml.endTag(); +} + void IOF30Interface::writeTeamStart(xmlparser &xml, const oTeam &t) { xml.startTag("TeamStart"); @@ -3126,9 +3164,13 @@ void IOF30Interface::writeTeamStart(xmlparser &xml, const oTeam &t) { if (!bib.empty()) xml.write("BibNumber", bib); + pClass cls = t.getClassRef(false); + for (int k = 0; k < t.getNumRunners(); k++) { if (t.getRunner(k)) writePersonStart(xml, *t.getRunner(k), true, true); + else if (cls && !cls->isOptional(k)) + writeTeamNoPersonStart(xml, t, k, includeStageRaceInfo); } writeAssignedFee(xml, t, 0); @@ -3150,7 +3192,7 @@ void IOF30Interface::writeStart(xmlparser &xml, const oRunner &r, xml.startTag("Start", "raceNumber", itos(rn)); } if (teamMember) - writeLegOrder(xml, r); + writeLegOrder(xml, r.getClassRef(false), r.getLegNumber()); wstring bib = r.getBib(); if (!bib.empty()) @@ -3171,12 +3213,11 @@ void IOF30Interface::writeStart(xmlparser &xml, const oRunner &r, xml.endTag(); } -void IOF30Interface::writeLegOrder(xmlparser &xml, const oRunner &r) const { +void IOF30Interface::writeLegOrder(xmlparser &xml, const oClass *pc, int legNo) const { // Team member race result - int legNumber, legOrder; - const oClass *pc = r.getClassRef(false); + int legNumber, legOrder; if (pc) { - bool par = pc->splitLegNumberParallel(r.getLegNumber(), legNumber, legOrder); + bool par = pc->splitLegNumberParallel(legNo, legNumber, legOrder); xml.write("Leg", legNumber + 1); if (par) xml.write("LegOrder", legOrder + 1); diff --git a/code/iof30interface.h b/code/iof30interface.h index 6a270ee..0396cc7 100644 --- a/code/iof30interface.h +++ b/code/iof30interface.h @@ -214,6 +214,8 @@ class IOF30Interface { const vector &t); void writePersonStart(xmlparser &xml, const oRunner &r, bool includeCourse, bool teamMember); + + void writeTeamNoPersonStart(xmlparser &xml, const oTeam &t, int leg, bool includeRaceNumber); void writeTeamStart(xmlparser &xml, const oTeam &t); @@ -222,7 +224,7 @@ class IOF30Interface { pCourse haveSameCourse(const vector &r) const; - void writeLegOrder(xmlparser &xml, const oRunner &r) const; + void writeLegOrder(xmlparser &xml, const oClass *pc, int legNo) const; // Returns zero if no stage number int getStageNumber(); diff --git a/code/meosversion.cpp b/code/meosversion.cpp index 304a93e..57602cd 100644 --- a/code/meosversion.cpp +++ b/code/meosversion.cpp @@ -27,9 +27,9 @@ //V2: ABCDEFGHIHJKMN //V31: a //V33: abcde -//V35: abcdef +//V35: abcdefg int getMeosBuild() { - string revision("$Rev: 742 $"); + string revision("$Rev: 804 $"); return 174 + atoi(revision.substr(5, string::npos).c_str()); } @@ -41,12 +41,12 @@ int getMeosBuild() { //V33: abcdefghij //V34: abcdfge wstring getMeosDate() { - wstring date(L"$Date: 2018-08-04 08:53:52 +0200 (lö, 04 aug 2018) $"); + wstring date(L"$Date: 2019-01-07 21:22:06 +0100 (må, 07 jan 2019) $"); return date.substr(7,10); } wstring getBuildType() { - return L"U2"; // No parantheses (...) + return L"U3"; // No parantheses (...) } wstring getMajorVersion() { @@ -121,7 +121,6 @@ void getSupporters(vector &supp, vector developSupp) supp.emplace_back(L"Siguldas Takas, Latvia"); supp.emplace_back(L"Eric Teutsch, Ottawa Orienteering Club, Canada"); supp.emplace_back(L"Silkeborg OK, Denmark"); - supp.emplace_back(L"Almby IK, Örebro"); supp.emplace_back(L"Erik Ivarsson Sandberg"); supp.emplace_back(L"Stenungsunds OK"); supp.emplace_back(L"OK Leipzig"); @@ -132,6 +131,14 @@ void getSupporters(vector &supp, vector developSupp) supp.emplace_back(L"Kamil Pipek, OK Lokomotiva Pardubice"); supp.emplace_back(L"Richard HEYRIES"); supp.emplace_back(L"Ingemar Carlsson"); + supp.emplace_back(L"Tolereds AIK"); + supp.emplace_back(L"OK Snab"); + supp.emplace_back(L"OK 73"); + supp.emplace_back(L"Helsingborgs SOK"); + supp.emplace_back(L"Sala OK"); + supp.emplace_back(L"OK Roskilde"); + supp.emplace_back(L"Almby IK, Örebro"); + supp.emplace_back(L"Ligue PACA"); reverse(supp.begin(), supp.end()); } diff --git a/code/oDataContainer.cpp b/code/oDataContainer.cpp index 28d3078..a72e5e7 100644 --- a/code/oDataContainer.cpp +++ b/code/oDataContainer.cpp @@ -836,7 +836,7 @@ string oDataContainer::generateSQLSet(const oBase *ob, bool forceSetAll) const { ob->getDataBuffers(data, oldData, strptr); string sql; - char bf[256]; + char bf[1024*8]; for (size_t kk = 0; kk < ordered.size(); kk++) { const oDataInfo &di=ordered[kk]; diff --git a/code/oEvent.h b/code/oEvent.h index 7e61bd7..7f01c4b 100644 --- a/code/oEvent.h +++ b/code/oEvent.h @@ -1208,7 +1208,14 @@ protected: bool addXMLTeamEntry(const xmlobject &xentry, int ClubId); bool addXMLClass(const xmlobject &xclub); bool addXMLClub(const xmlobject &xclub, bool importToDB); - bool addXMLRank(const xmlobject &xrank, map<__int64, int> &externIdToRunnerId); + // Fill in the output map. Set flag to true if match is made on id, false if on name. + enum class RankStatus { + IdMatch, + NameMatch, + Ambivalent + }; + + bool addXMLRank(const xmlobject &xrank, const map<__int64, int> &externIdToRunnerId, map> &output); bool addXMLEvent(const xmlobject &xevent); bool addXMLCourse(const xmlobject &xcourse, bool addClasses); diff --git a/code/oImportExport.cpp b/code/oImportExport.cpp index 5515c88..b121031 100644 --- a/code/oImportExport.cpp +++ b/code/oImportExport.cpp @@ -491,27 +491,37 @@ void oEvent::importXML_EntryData(gdioutput &gdi, const wstring &file, xmlList xl; xo.getObjects(xl); - - xmlList::const_iterator it; - + map<__int64, int> ext2Id; - for (oRunnerList::iterator it = Runners.begin(); it != Runners.end(); ++it) { + for (auto it = Runners.begin(); it != Runners.end(); ++it) { if (it->skip()) continue; __int64 ext = it->getExtIdentifier(); if (ext != 0) ext2Id[ext] = it->getId(); } - - for(it=xl.begin(); it != xl.end(); ++it){ - if (it->is("Competitor")){ - if (addXMLRank(*it, ext2Id)) - imp++; - else - fail++; + map> rankList; + for (auto it = xl.begin(); it != xl.end(); ++it) { + if (it->is("Competitor")) { + addXMLRank(*it, ext2Id, rankList); } } - + for (auto it : rankList) { + if (it.second.second == RankStatus::Ambivalent) + fail++; + else { + pRunner r = getRunner(it.first, 0); + if (r) { + r->getDI().setInt("Rank", it.second.first); + r->synchronize(); + imp++; + } + else { + fail++; + } + } + } + gdi.addString("", 0, "Klart. Antal importerade: X#" + itos(imp)); if (fail>0) gdi.addString("", 0, "Antal ignorerade: X#" + itos(fail)); @@ -1734,7 +1744,8 @@ bool oEvent::addXMLClub(const xmlobject &xclub, bool savetoDB) } -bool oEvent::addXMLRank(const xmlobject &xrank, map<__int64, int> &externIdToRunnerId) +bool oEvent::addXMLRank(const xmlobject &xrank, const map<__int64, int> &externIdToRunnerId, + map> &output) { if (!xrank) return false; @@ -1757,10 +1768,10 @@ bool oEvent::addXMLRank(const xmlobject &xrank, map<__int64, int> &externIdToRun else if (cit->is("Club")) club=*cit; else if (cit->is("Rank")){ - if (cit->getObjectString("Name", tmp)=="Swedish Ranking List") - rank=*cit; - else if (cit->getObjectString("Name", tmp)=="Swedish Vacancy List") + if (cit->getObjectString("Name", tmp).find("Vacancy") != string::npos) vrank=*cit; + else + rank = *cit; } ++cit; } @@ -1771,12 +1782,14 @@ bool oEvent::addXMLRank(const xmlobject &xrank, map<__int64, int> &externIdToRun person.getObjectString("PersonId", pid); const __int64 extId = oBase::converExtIdentifierString(pid); int id = oBase::idFromExtId(extId); - if (externIdToRunnerId.count(extId)) - id = externIdToRunnerId[extId]; + auto res = externIdToRunnerId.find(extId); + if (res != externIdToRunnerId.end()) + id = res->second; pRunner r = getRunner(id, 0); - - if (!r){ + bool idMatch = r != nullptr; + + if (r == nullptr){ xmlobject pname = person.getObject("PersonName"); if (!pname) return false; @@ -1803,15 +1816,26 @@ bool oEvent::addXMLRank(const xmlobject &xrank, map<__int64, int> &externIdToRun if (!r) return false; //No runner here! - oDataInterface DI=r->getDI(); + if (rank) { + int pos = rank.getObjectInt("RankPosition"); + if (idMatch) + output[r->getId()] = make_pair(pos, RankStatus::IdMatch); + else { + auto ores = output.find(r->getId()); + if (ores == output.end()) + output[r->getId()] = make_pair(pos, RankStatus::NameMatch); + else if (ores->second.second == RankStatus::NameMatch) + output[r->getId()] = make_pair(pos, RankStatus::Ambivalent); // Not clear. Do not match. + } + } + + + /* oDataInterface DI=r->getDI(); if (rank) DI.setInt("Rank", rank.getObjectInt("RankPosition")); -// if (vrank) -// DI.setInt("VacRank", vrank.getObjectInt("RankPosition")); - - r->synchronize(); + r->synchronize();*/ return true; } diff --git a/code/oRunner.cpp b/code/oRunner.cpp index e5ef9e2..0eb8f61 100644 --- a/code/oRunner.cpp +++ b/code/oRunner.cpp @@ -4516,9 +4516,9 @@ bool oRunner::matchName(const wstring &pname) const nMatched++; // Suppert changed last name in the most common case - if (j == 0 && k == 0 && inNames.size() == 2 && myNames.size() == 2) { + /*if (j == 0 && k == 0 && inNames.size() == 2 && myNames.size() == 2) { return true; - } + }*/ break; } } diff --git a/code/restserver.cpp b/code/restserver.cpp index e283548..b87b58d 100644 --- a/code/restserver.cpp +++ b/code/restserver.cpp @@ -533,6 +533,7 @@ void RestServer::getData(oEvent &oe, const string &what, const multimapsecond); } + bool inclRunnersInForest = param.count("allrunners")>0; if (param.count("type")) { string type = param.find("type")->second; @@ -645,7 +646,8 @@ void RestServer::getData(oEvent &oe, const string &what, const multimap 0) { xmlparser mem; mem.openMemoryOutput(false);