From ef53f6da748621582dd0e103c147216edcba9727 Mon Sep 17 00:00:00 2001 From: Erik Melin <31467290+erikmelin@users.noreply.github.com> Date: Mon, 6 Aug 2018 11:11:35 +0200 Subject: [PATCH] MeOS version 3.5.916 Update 2 --- code/TabRunner.cpp | 69 ++++++++++++++------------ code/TabSI.cpp | 31 +++++++----- code/TabTeam.cpp | 6 +-- code/Table.cpp | 2 + code/csvparser.cpp | 3 ++ code/meosversion.cpp | 86 +++++--------------------------- code/oClass.cpp | 25 +++++++--- code/oClass.h | 2 +- code/oEvent.cpp | 7 +++ code/oRunner.cpp | 113 +++++++++++++++++++++++++++++++------------ code/oRunner.h | 15 ++++-- code/oTeam.cpp | 23 +++++++++ code/oTeam.h | 5 +- code/restserver.cpp | 9 ++-- 14 files changed, 227 insertions(+), 169 deletions(-) diff --git a/code/TabRunner.cpp b/code/TabRunner.cpp index 8c48adc..6da43ce 100644 --- a/code/TabRunner.cpp +++ b/code/TabRunner.cpp @@ -166,12 +166,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) { //r->apply(false); vector mp; r->evaluateCard(true, mp, 0, false); - /* - if (parent!=r) { - parent->synchronize(); - parent->apply(false); - }*/ - + gdi.selectItemByData("Runners", parent->getId()); runnerId = r->getId(); @@ -267,31 +262,28 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) { gdi.selectItemByData("RCourse", r->getCourseId()); updateNumShort(gdi, r->getCourse(false), r); - int cno = parent->getCardNo(); + int cno = r->getCardNo(); gdi.setText("CardNo", cno > 0 ? itow(cno) : L""); warnDuplicateCard(gdi, cno, r); - gdi.check("RentCard", parent->getDI().getInt("CardFee") != 0); + gdi.check("RentCard", r->isHiredCard()); bool hasFee = gdi.hasField("Fee"); if (hasFee) gdi.setText("Fee", oe->formatCurrency(parent->getDI().getInt("Fee"))); - if (parent != r) { - gdi.disableInput("CardNo"); - gdi.disableInput("RentCard"); - if (hasFee) - gdi.disableInput("Fee"); - gdi.disableInput("RClass"); - } - else { - gdi.enableInput("CardNo"); - gdi.enableInput("RentCard"); - if (hasFee) - gdi.enableInput("Fee"); - gdi.enableInput("RClass"); - } + bool canEditClass = parent == r || (parent->getClassRef(false) && + parent->getClassRef(false)->getQualificationFinal()); + + gdi.setInputStatus("RClass", canEditClass); + gdi.enableInput("CardNo"); + gdi.enableInput("RentCard"); + if (hasFee) + gdi.setInputStatus("Fee", parent == r); + + if(gdi.hasField("Club")) + gdi.setInputStatus("Club", parent == r); enableControlButtons(gdi, true, r->isVacant()); @@ -537,8 +529,8 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) { throw meosException("Internal error runner index"); cardNoChanged = r->getCardNo() != cardNo; - if (r->getName() != name || (r->getClubId() != clubId && clubId != 0)) - r->updateFromDB(name, clubId, classId, cardNo, r->getBirthYear()); + if (!r->matchName(name) || (r->getClubId() != clubId && clubId != 0)) + r->updateFromDB(name, clubId, classId, cardNo, r->getBirthYear(), false); } if (cardNoChanged && cardNo>0) { @@ -580,11 +572,17 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) { } } - r->setCardNo(cardNo, true); - if (gdi.isChecked("RentCard")) + if (r->getCardNo() != cardNo) { + r->setCardNo(cardNo, true); + } + const bool hireChecked = gdi.isChecked("RentCard"); + const bool hireState = r->isHiredCard(); + if (hireChecked && !hireState) { r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee")); - else + } + else if (!hireChecked && hireState) { r->getDI().setInt("CardFee", 0); + } if (gdi.hasField("Fee")) r->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee"))); @@ -926,10 +924,17 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data) gdi.getSelectedItem("RClass", lbi); pRunner r = oe->addRunner(oe->getAutoRunnerName(), 0,0,0,0, false); - if (signed(lbi.data)>0) - r->setClassId(lbi.data, true); - else - r->setClassId(oe->getFirstClassId(false), true); + int clsId = lbi.data; + if (clsId > 0) { + pClass tCls = oe->getClass(clsId); + if (tCls && tCls->getParentClass() != nullptr && tCls->getParentClass() != tCls) { + clsId = tCls->getParentClass()->getId(); + } + } + if (clsId <= 0) + clsId = oe->getFirstClassId(false); + + r->setClassId(clsId, true); fillRunnerList(gdi); oe->fillClubs(gdi, "Club"); @@ -1402,7 +1407,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data) if (pc) clubId = pc->getId(); } - r->updateFromDB(name, clubId, r->getClassId(false), cardNo, birthYear); + r->updateFromDB(name, clubId, r->getClassId(false), cardNo, birthYear, false); r->setName(name, true); r->setCardNo(cardNo, true); r->setClub(club); diff --git a/code/TabSI.cpp b/code/TabSI.cpp index 539e50e..3b1b6df 100644 --- a/code/TabSI.cpp +++ b/code/TabSI.cpp @@ -864,7 +864,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data) } } int birthYear = 0; - r->updateFromDB(name, clubId, lbi.data, cardNo, birthYear); + r->updateFromDB(name, clubId, lbi.data, cardNo, birthYear, false); r->setName(name, true); r->setClubId(clubId); r->setClassId(lbi.data, true); @@ -2378,7 +2378,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool statusline += lang.tl(L", Prel. bomtid: ") + runner->getMissedTimeS(); gdi.addStringUT(rc.top+6+lh, rc.left+20, 0, statusline); - if (runner->getDI().getInt("CardFee") != 0) + if (runner->isHiredCard()) rentCardInfo(gdi, rc.right-rc.left); gdi.scrollToBottom(); } @@ -2414,7 +2414,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool gdi.addStringUT(rc.top+6+lh, rc.left+20, 0, msg); - if (runner->getDI().getInt("CardFee") != 0) + if (runner->isHiredCard()) rentCardInfo(gdi, rc.right-rc.left); gdi.scrollToBottom(); @@ -3015,6 +3015,10 @@ void TabSI::showModeCardData(gdioutput &gdi) { gdi.addButton("CreateCompetition", "Create Competition", SportIdentCB); if (savedCards.empty()) gdi.disableInput("CreateCompetition"); + +#ifdef _DEBUG + gdi.addButton("Import", "Importera från fil...", SportIdentCB); +#endif } gdi.dropLine(3); gdi.popX(); @@ -3111,7 +3115,7 @@ void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const { name = wstring(c.firstName) + L" " + c.lastName; clubName = c.club; } - else { + else if (useDatabase) { const RunnerWDBEntry *r = oe->getRunnerDatabase().getRunnerByCard(c.CardNumber); if (r) { r->getName(name); @@ -3271,12 +3275,6 @@ void TabSI::createCompetitionFromCards(gdioutput &gdi) { cards.push_back(p); } - zeroTime -= 3600; - if (zeroTime < 0) - zeroTime += 3600 * 24; - zeroTime -= zeroTime % 1800; - oe->setZeroTime(formatTime(zeroTime)); - int course = 0; for (size_t k = 0; k < cards.size(); k++) { if (!hashCount.count(cards[k].first)) @@ -3306,7 +3304,7 @@ void TabSI::createCompetitionFromCards(gdioutput &gdi) { if (abs(dist) > 3) { pCourse pc = oe->addCourse(lang.tl("Bana ") + itow(++course)); - for (unsigned j = 0; j < cards[k].second->nPunch; k++) { + for (unsigned j = 0; j < cards[k].second->nPunch; j++) { pc->addControl(cards[k].second->Punch[j].Code); } oe->addClass(lang.tl(L"Klass ") + itow(course), pc->getId()); @@ -3314,6 +3312,13 @@ void TabSI::createCompetitionFromCards(gdioutput &gdi) { } } + // Define a new zero time + zeroTime -= 3600; + if (zeroTime < 0) + zeroTime += 3600 * 24; + zeroTime -= zeroTime % 1800; + oe->setZeroTime(formatTime(zeroTime)); + // Add competitors for (size_t k = 0; k < cards.size(); k++) { if (oe->isCardRead(*cards[k].second)) @@ -3489,8 +3494,8 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) { checkedCardFlags[cno] == CNFRentAndNotRent) { int yp = gdi.getCY(); wstring cp = r[k]->getCompleteIdentification(); - bool rent = r[k]->getDI().getInt("CardFee") != 0; - wstring info = rent ? (L" (" + lang.tl("Hyrd") + L")") : L""; + bool hire = r[k]->isHiredCard(); + wstring info = hire ? (L" (" + lang.tl("Hyrd") + L")") : L""; gdi.addStringUT(yp, cx, 0, itow(cno) + info); gdi.addStringUT(yp, cx + col2, 0, cp); } diff --git a/code/TabTeam.cpp b/code/TabTeam.cpp index 2df6381..13259e8 100644 --- a/code/TabTeam.cpp +++ b/code/TabTeam.cpp @@ -424,13 +424,13 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) { int cardNo = gdi.getTextNo(bf2); if (r) { - bool newName = name != r->getName(); + bool newName = !r->matchName(name); int oldId = gdi.getExtraInt(bf); // Same runner set if (oldId == r->getId()) { if (newName) { r->updateFromDB(name, r->getClubId(), r->getClassId(false), - cardNo, 0); + cardNo, 0, false); r->setName(name, true); } r->setCardNo(cardNo, true); @@ -449,7 +449,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) { r->setClub(t->getClub()); r->resetPersonalData(); r->updateFromDB(name, r->getClubId(), r->getClassId(false), - cardNo, 0); + cardNo, 0, false); } } else diff --git a/code/Table.cpp b/code/Table.cpp index 56e5280..c8fecc2 100644 --- a/code/Table.cpp +++ b/code/Table.cpp @@ -250,6 +250,8 @@ void Table::filter(int col, const wstring &filt, bool forceFilter) if (filt==oldFilter && (!forceFilter || filt.empty())) return; else if (wcsncmp(oldFilter.c_str(), filt.c_str(), oldFilter.length())==0) { + if (sortIndex.empty()) + return; //Filter more... baseIndex.resize(2); baseIndex[0]=sortIndex[0]; diff --git a/code/csvparser.cpp b/code/csvparser.cpp index afc70de..417c520 100644 --- a/code/csvparser.cpp +++ b/code/csvparser.cpp @@ -617,6 +617,9 @@ bool csvparser::importOCAD_CSV(oEvent &event, const wstring &file, bool addClass for (size_t k=firstIndex; k &supp, vector developSupp) { - supp.emplace_back(L"Centrum OK"); - supp.emplace_back(L"Ove Persson, Piteå IF"); - supp.emplace_back(L"OK Rodhen"); - supp.emplace_back(L"Täby Extreme Challenge"); - supp.emplace_back(L"Thomas Engberg, VK Uvarna"); - supp.emplace_back(L"Eilert Edin, Sidensjö IK"); - supp.emplace_back(L"Göran Nordh, Trollhättans SK"); - supp.emplace_back(L"Roger Gustavsson, OK Tisaren"); - supp.emplace_back(L"Sundsvalls OK"); - supp.emplace_back(L"OK Gipens OL-skytte"); - supp.emplace_back(L"Helsingborgs SOK"); - supp.emplace_back(L"OK Gipens OL-skytte"); - supp.emplace_back(L"Rune Thurén, Vallentuna-Össeby OL"); - supp.emplace_back(L"Roland Persson, Kalmar OK"); - supp.emplace_back(L"Robert Jessen, Främmestads IK"); - supp.emplace_back(L"Anders Platt, Järla Orientering"); - supp.emplace_back(L"Almby IK, Örebro"); - supp.emplace_back(L"Peter Rydesäter, Rehns BK"); - supp.emplace_back(L"IK Hakarpspojkarna"); - supp.emplace_back(L"Rydboholms SK"); - supp.emplace_back(L"IFK Kiruna"); - supp.emplace_back(L"Peter Andersson, Söders SOL"); - supp.emplace_back(L"Björkfors GoIF"); - supp.emplace_back(L"OK Ziemelkurzeme"); - supp.emplace_back(L"Big Foot Orienteers"); - supp.emplace_back(L"FIF Hillerød"); - supp.emplace_back(L"Anne Udd"); - supp.emplace_back(L"OK Orinto"); - supp.emplace_back(L"SOK Träff"); - supp.emplace_back(L"Gamleby OK"); - supp.emplace_back(L"Vänersborgs SK"); - supp.emplace_back(L"Henrik Ortman, Västerås SOK"); - supp.emplace_back(L"Leif Olofsson, Sjuntorp"); - supp.emplace_back(L"Vallentuna/Össeby OL"); - supp.emplace_back(L"Oskarström OK"); - supp.emplace_back(L"Skogslöparna"); - supp.emplace_back(L"OK Milan"); - supp.emplace_back(L"Tjalve IF"); - supp.emplace_back(L"OK Skärmen"); - supp.emplace_back(L"Østkredsen"); - supp.emplace_back(L"OK Roskilde"); - supp.emplace_back(L"Holbæk Orienteringsklub"); - supp.emplace_back(L"Bodens BK"); - supp.emplace_back(L"OK Tyr, Karlstad"); - supp.emplace_back(L"Göteborg-Majorna OK"); - supp.emplace_back(L"OK Järnbärarna, Kopparberg"); - supp.emplace_back(L"FK Åsen"); - supp.emplace_back(L"Ballerup OK"); - supp.emplace_back(L"Olivier Benevello, Valbonne SAO"); - supp.emplace_back(L"Tommy Wåhlin, OK Enen"); - supp.emplace_back(L"Hjobygdens OK"); - supp.emplace_back(L"Tisvilde Hegn OK"); - supp.emplace_back(L"Lindebygdens OK"); - supp.emplace_back(L"OK Flundrehof"); - supp.emplace_back(L"Vittjärvs IK"); - supp.emplace_back(L"Annebergs GIF"); - supp.emplace_back(L"Lars-Eric Gahlin, Östersunds OK"); - supp.emplace_back(L"Sundsvalls OK:s Veteraner"); - supp.emplace_back(L"OK Skogshjortarna"); - supp.emplace_back(L"Kinnaströms SK"); - supp.emplace_back(L"OK Pan Århus"); - supp.emplace_back(L"Jan Ernberg, Täby OK"); - supp.emplace_back(L"Stjärnorps SK"); - supp.emplace_back(L"Mölndal Outdoor IF"); - supp.emplace_back(L"Roland Elg, Fjärås AIK"); - supp.emplace_back(L"Tenhults SOK"); supp.emplace_back(L"Järfälla OK"); - supp.emplace_back(L"Lars Jonasson"); supp.emplace_back(L"Anders Larsson, OK Nackhe"); supp.emplace_back(L"Hans Wilhelmsson"); supp.emplace_back(L"Patrice Lavallee, Noyon Course d'Orientation"); @@ -147,7 +80,6 @@ void getSupporters(vector &supp, vector developSupp) supp.emplace_back(L"Lars Ove Karlsson, Västerås SOK"); supp.emplace_back(L"OK Djerf"); supp.emplace_back(L"OK Vivill"); - supp.emplace_back(L"IFK Mora OK"); supp.emplace_back(L"Sonny Andersson, Huskvarna"); supp.emplace_back(L"Hässleholms OK Skolorientering"); supp.emplace_back(L"IBM-klubben Orientering"); @@ -167,7 +99,6 @@ void getSupporters(vector &supp, vector developSupp) supp.emplace_back(L"Gävle OK"); supp.emplace_back(L"Kenneth Gattmalm, Jönköpings OK"); supp.emplace_back(L"Søllerød OK"); - supp.emplace_back(L"O-travel"); supp.emplace_back(L"Bengt Bengtsson"); supp.emplace_back(L"OK Landehof"); supp.emplace_back(L"OK Orinto"); @@ -184,14 +115,23 @@ void getSupporters(vector &supp, vector developSupp) supp.emplace_back(L"Christoffer Ohlsson, Uddevalla OK"); supp.emplace_back(L"O-Ringen AB"); supp.emplace_back(L"Hans Carlstedt, Sävedalens AIK"); + supp.emplace_back(L"IFK Mora OK"); supp.emplace_back(L"Attunda OK"); + supp.emplace_back(L"OK Tyr, Karlstad"); 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"); supp.emplace_back(L"Degerfors OK"); supp.emplace_back(L"OK Tjärnen"); - //reverse(supp.begin(), supp.end()); + supp.emplace_back(L"Leksands OK"); + supp.emplace_back(L"O-Travel"); + supp.emplace_back(L"Kamil Pipek, OK Lokomotiva Pardubice"); + supp.emplace_back(L"Richard HEYRIES"); + supp.emplace_back(L"Ingemar Carlsson"); + + reverse(supp.begin(), supp.end()); } diff --git a/code/oClass.cpp b/code/oClass.cpp index 766033f..9aeb1db 100644 --- a/code/oClass.cpp +++ b/code/oClass.cpp @@ -1903,6 +1903,16 @@ public: int baseRes; if (r.getInputStatus() == StatusOK) { int t = r.getInputPlace(); + + if (t == 0) { + const oRunner *rr = dynamic_cast(&r); + if (rr && rr->getTeam() && rr->getLegNumber() > 0) { + const pRunner rPrev = rr->getTeam()->getRunner(rr->getLegNumber() - 1); + if (rPrev && rPrev->getStatus() == StatusOK) + t = rPrev->getPlace(); + } + } + if (t > 0) baseRes = t; else @@ -3929,9 +3939,12 @@ void oClass::drawSeeded(ClassSeedMethod seed, int leg, int firstStart, vector r; oe->getRunners(Id, 0, r, true); vector< pair > seedIx; - + if (seed == SeedResult) { + oe->reEvaluateAll(set(), true); + oe->calculateResults(oEvent::ResultType::RTClassResult, false); + } for (size_t k = 0; k < r.size(); k++) { - if (r[k]->tLeg != leg) + if (r[k]->tLeg != leg && leg != -1) continue; pair sx; @@ -4213,9 +4226,9 @@ oClass *oClass::getVirtualClass(int instance, bool allowCreation) { return this; // Fallback } -const oClass *oClass::getVirtualClass(int instance) const { +const pClass oClass::getVirtualClass(int instance) const { if (instance == 0) - return this; + return pClass(this); if (parentClass) return parentClass->getVirtualClass(instance); @@ -4223,7 +4236,7 @@ const oClass *oClass::getVirtualClass(int instance) const { return virtualClasses[instance]; if (instance >= getNumQualificationFinalClasses()) - return this; // Invalid + return pClass(this); // Invalid virtualClasses.resize(getNumQualificationFinalClasses()); int virtId = Id + instance * MaxClassId; @@ -4235,7 +4248,7 @@ const oClass *oClass::getVirtualClass(int instance) const { configureInstance(instance, false); if (virtualClasses[instance]) return virtualClasses[instance]; - return this; // Fallback + return pClass(this); // Fallback } void oClass::configureInstance(int instance, bool allowCreation) const { diff --git a/code/oClass.h b/code/oClass.h index 8620e41..8d0bd97 100644 --- a/code/oClass.h +++ b/code/oClass.h @@ -346,7 +346,7 @@ public: } oClass *getVirtualClass(int instance, bool allowCreation); - const oClass *getVirtualClass(int instance) const; + const pClass getVirtualClass(int instance) const; ClassStatus getClassStatus() const; diff --git a/code/oEvent.cpp b/code/oEvent.cpp index fc21f89..82d7b7f 100644 --- a/code/oEvent.cpp +++ b/code/oEvent.cpp @@ -1785,7 +1785,14 @@ int oEvent::getFirstClassId(bool teamClass) const { for (oClassList::const_iterator it = Classes.begin(); it != Classes.end(); ++it) { if (it->isRemoved()) continue; + + if (it->getQualificationFinal()) + return it->Id; // Both team and single + int ns = it->getNumStages(); + if (ns > 0 && it->getNumDistinctRunners() == 1) + return it->Id; // Both team and single + if (teamClass && ns > 0) return it->Id; else if (!teamClass && ns == 0) diff --git a/code/oRunner.cpp b/code/oRunner.cpp index 9ad800d..e5ef9e2 100644 --- a/code/oRunner.cpp +++ b/code/oRunner.cpp @@ -2035,31 +2035,33 @@ void oRunner::setClub(const wstring &clubName) tParentRunner->setClub(clubName); else { oAbstractRunner::setClub(clubName); - - for (size_t k=0;kClub!=Club) { - multiRunner[k]->Club = Club; - multiRunner[k]->updateChanged(); - } + propagateClub(); } } -pClub oRunner::setClubId(int clubId) -{ +pClub oRunner::setClubId(int clubId) { if (tParentRunner) tParentRunner->setClubId(clubId); else { oAbstractRunner::setClubId(clubId); - for (size_t k=0;kClub!=Club) { - multiRunner[k]->Club = Club; - multiRunner[k]->updateChanged(); - } + propagateClub(); } return Club; } +void oRunner::propagateClub() { + for (size_t k = 0; k < multiRunner.size(); k++) { + if (multiRunner[k] && multiRunner[k]->Club != Club) { + multiRunner[k]->Club = Club; + multiRunner[k]->updateChanged(); + } + } + if (tInTeam && Class && Class->getNumDistinctRunners() == 1 && tInTeam->getClubRef() != Club) { + tInTeam->Club = Club; + tInTeam->updateChanged(); + } +} void oAbstractRunner::setStartNo(int no, bool tmpOnly) { if (tmpOnly) { @@ -2191,6 +2193,27 @@ void oRunner::setCardNo(int cno, bool matchCard, bool updateFromDatabase) } } +bool oRunner::isHiredCard() const { + if (getDCI().getInt("CardFee") != 0) + return true; + if (tParentRunner && tParentRunner != this) + return tParentRunner->isHiredCard(getCardNo()); + + return isHiredCard(CardNo); +} + +bool oRunner::isHiredCard(int cno) const { + if (cno == CardNo) + return getDCI().getInt("CardFee") != 0; + + for (pRunner r : multiRunner) { + if (r && r->getCardNo() == cno && r->getDCI().getInt("CardFee") != 0) + return true; + } + return false; +} + + int oRunner::setCard(int cardId) { pCard c=cardId ? oe->getCard(cardId) : 0; @@ -3197,7 +3220,7 @@ bool oRunner::inputData(int id, const wstring &input, throw std::exception("Tomt namn inte tillåtet."); if (sName != input && tRealName != input) { - updateFromDB(input, getClubId(), getClassId(false), getCardNo(), getBirthYear()); + updateFromDB(input, getClubId(), getClassId(false), getCardNo(), getBirthYear(), false); setName(input, true); synchronizeAll(); } @@ -3243,7 +3266,7 @@ bool oRunner::inputData(int id, const wstring &input, else pc = oe->getClubCreate(0, input); - updateFromDB(getName(), pc ? pc->getId():0, getClassId(false), getCardNo(), getBirthYear()); + updateFromDB(getName(), pc ? pc->getId():0, getClassId(false), getCardNo(), getBirthYear(), false); setClub(pc ? pc->getName() : L""); synchronize(true); @@ -3336,6 +3359,20 @@ void oRunner::fillInput(int id, vector< pair > &out, size_t &se int oRunner::getSplitTime(int controlNumber, bool normalized) const { + if (!Card) { + if (controlNumber == 0) + return getPunchTime(0, false); + else { + int ct = getPunchTime(controlNumber, false); + if (ct > 0) { + int dt = getPunchTime(controlNumber - 1, false); + if (dt > 0 && ct > dt) + return ct - dt; + } + } + + return -1; + } const vector &st = getSplitTimes(normalized); if (controlNumber>0 && controlNumber == st.size() && FinishTime>0) { int t = st.back().time; @@ -3360,11 +3397,9 @@ int oRunner::getTimeAdjust(int controlNumber) const return 0; } -int oRunner::getNamedSplit(int controlNumber) const -{ +int oRunner::getNamedSplit(int controlNumber) const { pCourse crs=getCourse(true); - if (!crs || unsigned(controlNumber)>=unsigned(crs->nControls) - || unsigned(controlNumber)>=splitTimes.size()) + if (!crs || unsigned(controlNumber)>=unsigned(crs->nControls)) return -1; pControl ctrl=crs->Controls[controlNumber]; @@ -3372,24 +3407,25 @@ int oRunner::getNamedSplit(int controlNumber) const return -1; int k=controlNumber-1; - + int ct = getPunchTime(controlNumber, false); + if (ct <= 0) + return -1; + //Measure from previous named control - while(k>=0) { - pControl c=crs->Controls[k]; + while (k >= 0) { + pControl c = crs->Controls[k]; if (c && c->hasName()) { - if (splitTimes[controlNumber].time>0 && splitTimes[k].time>0) - return max(splitTimes[controlNumber].time - splitTimes[k].time, -1); + int dt = getPunchTime(k, false); + if (dt > 0 && ct > dt) + return max(ct - dt, -1); else return -1; } k--; } //Measure from start time - if (splitTimes[controlNumber].time>0) - return max(splitTimes[controlNumber].time - tStartTime, -1); - - return -1; + return ct; } wstring oRunner::getSplitTimeS(int controlNumber, bool normalized) const @@ -3404,6 +3440,20 @@ wstring oRunner::getNamedSplitS(int controlNumber) const int oRunner::getPunchTime(int controlNumber, bool normalized) const { + if (!Card) { + pCourse pc = getCourse(false); + if (!pc || controlNumber > pc->getNumControls()) + return -1; + + if (controlNumber == pc->getNumControls()) + return getFinishTime() - tStartTime; + + int ccId = pc->getCourseControlId(controlNumber); + pFreePunch fp = oe->getPunch(Id, ccId, CardNo); + if (fp) + return fp->Time - tStartTime; + return -1; + } const vector &st = getSplitTimes(normalized); if ( unsigned(controlNumber)isVacant() && !it->isRemoved()) - it->updateFromDB(it->sName, it->getClubId(), it->getClassId(false), it->getCardNo(), it->getBirthYear()); + it->updateFromDB(it->sName, it->getClubId(), it->getClassId(false), it->getCardNo(), it->getBirthYear(), true); } } bool oRunner::updateFromDB(const wstring &name, int clubId, int classId, - int cardNo, int birthYear) { + int cardNo, int birthYear, bool forceUpdate) { if (!oe->useRunnerDb()) return false; + uint64_t oldId = getExtIdentifier(); + if (oldId && !forceUpdate && oe->getRunnerDatabase().getRunnerById(oldId) == 0) + return false; // Keep data if database is not installed pRunner db_r = 0; if (cardNo>0) { diff --git a/code/oRunner.h b/code/oRunner.h index 43cf015..a869b93 100644 --- a/code/oRunner.h +++ b/code/oRunner.h @@ -257,7 +257,7 @@ public: pClub getClubRef() {return Club;} virtual int classInstance() const = 0; - const oClass *getClassRef(bool virtualClass) const { + const pClass getClassRef(bool virtualClass) const { return (virtualClass && Class) ? Class->getVirtualClass(classInstance()) : Class; } @@ -508,6 +508,11 @@ protected: mutable pCourse tAdaptedCourse; mutable int tAdaptedCourseRevision; + /** Internal propagate club.*/ + void propagateClub(); + + bool isHiredCard(int card) const; + public: /** Get a runner reference (drawing) */ pRunner getReference() const; @@ -627,7 +632,7 @@ public: /** Use db to pdate runner */ bool updateFromDB(const wstring &name, int clubId, int classId, - int cardNo, int birthYear); + int cardNo, int birthYear, bool forceUpdate); void printSplits(gdioutput &gdi) const; @@ -644,8 +649,8 @@ public: int legToRun() const {return tInTeam ? tLeg : tDuplicateLeg;} void setName(const wstring &n, bool manualUpdate); void setClassId(int id, bool isManualUpdate); - void setClub(const wstring &name); - pClub setClubId(int clubId); + void setClub(const wstring &name) override; + pClub setClubId(int clubId) override; // Start number is equal to bib-no, but bib // is only set when it should be shown in lists etc. @@ -739,6 +744,8 @@ public: int getCourseId() const {if (Course) return Course->Id; else return 0;} void setCourseId(int id); + bool isHiredCard() const; + int getCardNo() const {return tParentRunner && CardNo == 0 ? tParentRunner->CardNo : CardNo;} void setCardNo(int card, bool matchCard, bool updateFromDatabase = false); /** Sets the card to a given card. An existing card is marked as unpaired. diff --git a/code/oTeam.cpp b/code/oTeam.cpp index 892bff5..17f73c5 100644 --- a/code/oTeam.cpp +++ b/code/oTeam.cpp @@ -2258,3 +2258,26 @@ int oTeam::getRogainingPatrolOvertime() const { getRogainingPatrolPoints(false); return tTeamPatrolRogainingAndVersion.second.overtime; } + +void oTeam::setClub(const wstring &clubName) { + oAbstractRunner::setClub(clubName); + propagateClub(); +} + +pClub oTeam::setClubId(int clubId) { + oAbstractRunner::setClubId(clubId); + propagateClub(); + return Club; +} + +void oTeam::propagateClub() { + + if (Class && Class->getNumDistinctRunners() == 1) { + for (pRunner r : Runners) { + if (r && r->Club != Club) { + r->Club = Club; + r->updateChanged(); + } + } + } +} diff --git a/code/oTeam.h b/code/oTeam.h index 039f963..64f59f0 100644 --- a/code/oTeam.h +++ b/code/oTeam.h @@ -51,6 +51,7 @@ private: void speakerLegInfo(int leg, int specifiedLeg, int courseControlId, int &missingLeg, int &totalLeg, RunnerStatus &status, int &runningTime) const; + void propagateClub(); protected: //pRunner Runners[maxRunnersTeam]; @@ -127,9 +128,11 @@ public: void resetResultCalcCache() const; vector< vector > &getResultCache(ResultCalcCacheSymbol symb) const; void setResultCache(ResultCalcCacheSymbol symb, int leg, vector &data) const; - void markClassChanged(int controlId); + void setClub(const wstring &name) override; + pClub setClubId(int clubId) override; + /// Returns team fee (including participating runners fees) int getTeamFee() const; diff --git a/code/restserver.cpp b/code/restserver.cpp index ef2cdcf..e283548 100644 --- a/code/restserver.cpp +++ b/code/restserver.cpp @@ -98,15 +98,12 @@ void RestServer::handleRequest(const shared_ptr &session) { chrono::duration elapsed_seconds = end - start; responseTimes.push_back(int(1000 * elapsed_seconds.count())); } - // lock.unlock(); session->fetch(content_length, [request, answer](const shared_ptr< Session > session, const Bytes & body) { - //fprintf(stdout, "%.*s\n", (int)body.size(), body.data()); - /*while (!answer->state) { - std::this_thread::yield(); - }*/ - session->close(restbed::OK, answer->answer, { { "Content-Length", itos(answer->answer.length()) },{ "Connection", "close" } }); + session->close(restbed::OK, answer->answer, { { "Content-Length", itos(answer->answer.length()) }, + { "Connection", "close" }, + { "Access-Control-Allow-Origin", "*" } }); }); }