MeOS version 3.7.1188 RC2

This commit is contained in:
Erik Melin 2020-05-02 09:35:50 +02:00
parent 338fb3c34e
commit b6ee21cd40
37 changed files with 1262 additions and 621 deletions

View File

@ -22,7 +22,6 @@
************************************************************************/ ************************************************************************/
#include "Localizer.h" #include "Localizer.h"
#include <typeinfo.h>
#include "gdioutput.h" #include "gdioutput.h"

View File

@ -2138,10 +2138,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
else if (bi.id == "Module") { else if (bi.id == "Module") {
size_t ix = gdi.getSelectedItem("Module").first; size_t ix = gdi.getSelectedItem("Module").first;
if (ix < currentResultModuleTags.size()) { hideEditResultModule(gdi, ix);
const string &mtag = currentResultModuleTags[ix];
gdi.hideWidget("EditModule", mtag.empty());
}
} }
else if (bi.id=="Courses") else if (bi.id=="Courses")
EditChanged=true; EditChanged=true;
@ -2188,6 +2185,16 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
return 0; return 0;
} }
void TabClass::hideEditResultModule(gdioutput &gdi, int ix) const {
if (size_t(ix) < currentResultModuleTags.size()) {
const string &mtag = currentResultModuleTags[ix];
wstring srcFile;
gdi.hideWidget("EditModule", mtag.empty() ||
dynamic_cast<DynamicResult *>(oe->getGeneralResult(mtag, srcFile).get()) == nullptr);
}
}
void TabClass::readClassSettings(gdioutput &gdi) void TabClass::readClassSettings(gdioutput &gdi)
{ {
for (size_t k=0;k<cInfo.size();k++) { for (size_t k=0;k<cInfo.size();k++) {
@ -2554,10 +2561,11 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
pc->getDCI().fillInput("Status", out, selected); pc->getDCI().fillInput("Status", out, selected);
gdi.addItem("Status", out); gdi.addItem("Status", out);
gdi.selectItemByData("Status", selected); gdi.selectItemByData("Status", selected);
fillResultModules(gdi, pc);
} }
if (gdi.hasWidget("Module")) {
fillResultModules(gdi, pc);
}
gdi.check("AllowQuickEntry", pc->getAllowQuickEntry()); gdi.check("AllowQuickEntry", pc->getAllowQuickEntry());
if (gdi.hasWidget("NoTiming")) if (gdi.hasWidget("NoTiming"))
gdi.check("NoTiming", pc->getNoTiming()); gdi.check("NoTiming", pc->getNoTiming());
@ -3244,7 +3252,7 @@ bool TabClass::loadPage(gdioutput &gdi)
gdi.addSelection("StartBlock", 80, 300, 0, L"Startblock:"); gdi.addSelection("StartBlock", 80, 300, 0, L"Startblock:");
for (int k=1;k<=100;k++) { for (int k = 1; k <= 100; k++) {
gdi.addItem("StartBlock", itow(k), k); gdi.addItem("StartBlock", itow(k), k);
} }
@ -3258,8 +3266,19 @@ bool TabClass::loadPage(gdioutput &gdi)
st.emplace_back(lang.tl(sc.second), st.size()); st.emplace_back(lang.tl(sc.second), st.size());
gdi.addItem("Status", st); gdi.addItem("Status", st);
gdi.autoGrow("Status"); gdi.autoGrow("Status");
gdi.popX(); gdi.popX();
}
bool hasResultModuleClasses = false;
vector<pClass> cls;
oe->getClasses(cls, false);
for (pClass c : cls) {
if (c->getResultModuleTag().size() > 0) {
hasResultModuleClasses = true;
break;
}
}
if (showAdvanced || hasResultModuleClasses) {
gdi.dropLine(3); gdi.dropLine(3);
gdi.addSelection("Module", 100, 400, ClassesCB, L"Resultatuträkning:"); gdi.addSelection("Module", 100, 400, ClassesCB, L"Resultatuträkning:");
fillResultModules(gdi, nullptr); fillResultModules(gdi, nullptr);
@ -4882,5 +4901,5 @@ void TabClass::fillResultModules(gdioutput &gdi, pClass pc) {
gdi.addItem("Module", st); gdi.addItem("Module", st);
gdi.autoGrow("Module"); gdi.autoGrow("Module");
gdi.selectItemByData("Module", current); gdi.selectItemByData("Module", current);
gdi.hideWidget("EditModule", current == 0); hideEditResultModule(gdi, current);
} }

View File

@ -87,7 +87,7 @@ class TabClass :
bool warnDrawStartTime(gdioutput &gdi, const wstring &firstStart); bool warnDrawStartTime(gdioutput &gdi, const wstring &firstStart);
void static clearPage(gdioutput &gdi, bool autoRefresh); void static clearPage(gdioutput &gdi, bool autoRefresh);
void hideEditResultModule(gdioutput &gdi, int ix) const;
bool hasWarnedStartTime; bool hasWarnedStartTime;
bool hasWarnedDirect; bool hasWarnedDirect;
bool tableMode; bool tableMode;

View File

@ -144,12 +144,12 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
oClub::definedPayModes(*oe, dpm); oClub::definedPayModes(*oe, dpm);
pc->generateInvoice(gdi, pay, paid, dpm, ppm); pc->generateInvoice(gdi, pay, paid, dpm, ppm);
} }
gdi.addButton(gdi.getWidth()+20, gdi.scaleLength(15), gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, gdi.scaleLength(15), gdi.scaleLength(baseButtonWidth),
"Cancel", "Återgå", ClubsCB, "", true, false); "Cancel", "Återgå", ClubsCB, "", true, false);
gdi.addButton(gdi.getWidth()+20, gdi.scaleLength(45), gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, gdi.scaleLength(45), gdi.scaleLength(baseButtonWidth),
"Print", "Skriv ut...", ClubsCB, "Print", "Skriv ut...", ClubsCB,
"Skriv ut fakturan", true, false); "Skriv ut fakturan", true, false);
gdi.addButton(gdi.getWidth()+20, gdi.scaleLength(75), gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, gdi.scaleLength(75), gdi.scaleLength(baseButtonWidth),
"PDF", "PDF...", ClubsCB, "PDF", "PDF...", ClubsCB,
"Spara som PDF.", true, false); "Spara som PDF.", true, false);
gdi.refresh(); gdi.refresh();
@ -190,14 +190,14 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
oe->printInvoices(gdi, oEvent::InvoicePrintType(lbi.data), path, false); oe->printInvoices(gdi, oEvent::InvoicePrintType(lbi.data), path, false);
gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(baseButtonWidth),
"Cancel", "Återgå", ClubsCB, "", true, false); "Cancel", "Återgå", ClubsCB, "", true, false);
if (lbi.data>10) { // To file if (lbi.data>10) { // To file
gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(baseButtonWidth),
"Print", "Skriv ut...", ClubsCB, "Print", "Skriv ut...", ClubsCB,
"", true, false); "", true, false);
gdi.addButton(gdi.getWidth()+20, 75, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 75, gdi.scaleLength(baseButtonWidth),
"PDF", "PDF...", ClubsCB, "PDF", "PDF...", ClubsCB,
"Spara som PDF.", true, false); "Spara som PDF.", true, false);
gdi.refresh(); gdi.refresh();
@ -249,9 +249,9 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
gdi.clearPage(false); gdi.clearPage(false);
wstring nn; wstring nn;
oe->printInvoices(gdi, oEvent::IPTAllPrint, nn, true); oe->printInvoices(gdi, oEvent::IPTAllPrint, nn, true);
gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(120), "Cancel", gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(baseButtonWidth), "Cancel",
"Återgå", ClubsCB, "", true, false); "Återgå", ClubsCB, "", true, false);
gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(120), "Print", gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(baseButtonWidth), "Print",
"Skriv ut...", ClubsCB, "Skriv ut fakturan", true, false); "Skriv ut...", ClubsCB, "Skriv ut fakturan", true, false);
gdi.refresh(); gdi.refresh();

View File

@ -568,9 +568,9 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.clearPage(true); gdi.clearPage(true);
oe->generateCompetitionReport(gdi); oe->generateCompetitionReport(gdi);
gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(120), "Cancel", gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(baseButtonWidth), "Cancel",
"Återgå", CompetitionCB, "", true, false); "Återgå", CompetitionCB, "", true, false);
gdi.addButton(gdi.getWidth()+20, 18+gdi.getButtonHeight(), gdi.scaleLength(120), "Print", gdi.addButton(gdi.getWidth()+20, 18+gdi.getButtonHeight(), gdi.scaleLength(baseButtonWidth), "Print",
"Skriv ut...", CompetitionCB, "Skriv ut rapporten", true, false); "Skriv ut...", CompetitionCB, "Skriv ut rapporten", true, false);
gdi.refresh(); gdi.refresh();
@ -1615,7 +1615,9 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
loadPage(gdi); loadPage(gdi);
} }
else if (bi.id == "WelcomeOK") { else if (bi.id == "WelcomeOK") {
gdi.scaleSize(1.0/gdi.getScale()); gdi.setFont(oe->getPropertyInt("TextSize", 0),
oe->getPropertyString("TextFont", L"Arial"));
oe->setProperty("FirstTime", 0); oe->setProperty("FirstTime", 0);
loadPage(gdi); loadPage(gdi);
} }
@ -2403,6 +2405,7 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
"\n\nOriginal French Translation by Jerome Monclard" "\n\nOriginal French Translation by Jerome Monclard"
"\n\nAdaption to French conditions and extended translation by Pierre Gaufillet" "\n\nAdaption to French conditions and extended translation by Pierre Gaufillet"
"\n\nCzech Translation by Marek Kustka" "\n\nCzech Translation by Marek Kustka"
"\n\nSpanish Translation by Manuel Pedre"
"\n\nHelp with English documentation: Torbjörn Wikström"); "\n\nHelp with English documentation: Torbjörn Wikström");
gdi.dropLine(); gdi.dropLine();
@ -2626,7 +2629,7 @@ bool TabCompetition::loadPage(gdioutput &gdi)
rc.top = gdi.getCY() - gdi.scaleLength(30); rc.top = gdi.getCY() - gdi.scaleLength(30);
rc.left = gdi.getCX() - gdi.scaleLength(30); rc.left = gdi.getCX() - gdi.scaleLength(30);
int bw = gdi.scaleLength(150); int bw = gdi.scaleLength(baseButtonWidth+40);
gdi.addString("", 1, "Importera tävlingsdata"); gdi.addString("", 1, "Importera tävlingsdata");
gdi.addButton(gdi.getCX(), gdi.getCY(), bw, "Entries", "Anmälningar", gdi.addButton(gdi.getCX(), gdi.getCY(), bw, "Entries", "Anmälningar",
CompetitionCB, "", false, false); CompetitionCB, "", false, false);
@ -3229,7 +3232,7 @@ void TabCompetition::loadRunnerDB(gdioutput &gdi, int tableToShow, bool updateTa
void TabCompetition::welcomeToMeOS(gdioutput &gdi) { void TabCompetition::welcomeToMeOS(gdioutput &gdi) {
gdi.clearPage(false, false); gdi.clearPage(false, false);
gdi.scaleSize(1.8/gdi.getScale()); gdi.scaleSize(1.4*gdi.getScale());
gdi.dropLine(5); gdi.dropLine(5);
gdi.setCX(gdi.getCX() + 5*gdi.getLineHeight()); gdi.setCX(gdi.getCX() + 5*gdi.getLineHeight());

View File

@ -1009,10 +1009,10 @@ void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
gdi.dropLine(); gdi.dropLine();
} }
gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(baseButtonWidth),
"Print", "Skriv ut...", CourseCB, "Print", "Skriv ut...", CourseCB,
"Skriv ut listan.", true, false); "Skriv ut listan.", true, false);
gdi.addButton(gdi.getWidth()+20, 75, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 75, gdi.scaleLength(baseButtonWidth),
"PDF", "PDF...", CourseCB, "PDF", "PDF...", CourseCB,
"Spara som PDF.", true, false); "Spara som PDF.", true, false);

View File

@ -154,25 +154,25 @@ int ListsCB(gdioutput *gdi, int type, void *data)
} }
int TabList::baseButtons(gdioutput &gdi, int extraButtons) { int TabList::baseButtons(gdioutput &gdi, int extraButtons) {
gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 15, gdi.scaleLength(baseButtonWidth),
"Cancel", ownWindow ? "Stäng" : "Återgå", ListsCB, "", true, false); "Cancel", ownWindow ? "Stäng" : "Återgå", ListsCB, "", true, false);
gdi.addButton(gdi.getWidth()+20, 18+gdi.getButtonHeight(), gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 18+gdi.getButtonHeight(), gdi.scaleLength(baseButtonWidth),
"Print", "Skriv ut...", ListsCB, "Skriv ut listan.", true, false); "Print", "Skriv ut...", ListsCB, "Skriv ut listan.", true, false);
if (!ownWindow) { if (!ownWindow) {
gdi.addButton(gdi.getWidth() + 20, 21 + 2 * gdi.getButtonHeight(), gdi.scaleLength(120), gdi.addButton(gdi.getWidth() + 20, 21 + 2 * gdi.getButtonHeight(), gdi.scaleLength(baseButtonWidth),
"HTMLDesign", "Webb...", ListsCB, "Spara för webben.", true, false); "HTMLDesign", "Webb...", ListsCB, "Spara för webben.", true, false);
} }
gdi.addButton(gdi.getWidth()+20, 24+3*gdi.getButtonHeight(), gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 24+3*gdi.getButtonHeight(), gdi.scaleLength(baseButtonWidth),
"PDF", "PDF...", ListsCB, "Spara som PDF.", true, false); "PDF", "PDF...", ListsCB, "Spara som PDF.", true, false);
gdi.addButton(gdi.getWidth()+20, 27+4*gdi.getButtonHeight(), gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, 27+4*gdi.getButtonHeight(), gdi.scaleLength(baseButtonWidth),
"Copy", "Kopiera", ListsCB, "Kopiera till urklipp.", true, false); "Copy", "Kopiera", ListsCB, "Kopiera till urklipp.", true, false);
int ypos = 30+5*gdi.getButtonHeight(); int ypos = 30+5*gdi.getButtonHeight();
if (extraButtons == 1) { if (extraButtons == 1) {
int w, h; int w, h;
gdi.addButton(gdi.getWidth()+20, ypos, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, ypos, gdi.scaleLength(baseButtonWidth),
"EditInForest", "edit_in_forest", ListsCB, "", true, false).getDimension(gdi, w, h); "EditInForest", "edit_in_forest", ListsCB, "", true, false).getDimension(gdi, w, h);
ypos += h + 3; ypos += h + 3;
} }
@ -187,11 +187,11 @@ void TabList::generateList(gdioutput &gdi, bool forceUpdate)
int baseY = 15; int baseY = 15;
if (!gdi.isFullScreen()) { if (!gdi.isFullScreen()) {
gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(baseButtonWidth),
"Cancel", ownWindow ? "Stäng" : "Återgå", ListsCB, "", true, false); "Cancel", ownWindow ? "Stäng" : "Återgå", ListsCB, "", true, false);
baseY += 3 + gdi.getButtonHeight(); baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(baseButtonWidth),
"FullScreenLive", "Fullskärm", ListsCB, "Visa listan i fullskärm", true, false); "FullScreenLive", "Fullskärm", ListsCB, "Visa listan i fullskärm", true, false);
} }
SelectedList = "GeneralList"; SelectedList = "GeneralList";
@ -257,10 +257,10 @@ void TabList::generateList(gdioutput &gdi, bool forceUpdate)
int baseY = baseButtons(gdi, extra); int baseY = baseButtons(gdi, extra);
if (!ownWindow) { if (!ownWindow) {
gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(baseButtonWidth),
"Window", "Eget fönster", ListsCB, "Öppna i ett nytt fönster.", true, false); "Window", "Eget fönster", ListsCB, "Öppna i ett nytt fönster.", true, false);
gdi.addButton(gdi.getWidth()+20, baseY + 3 + 1*gdi.getButtonHeight(), gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, baseY + 3 + 1*gdi.getButtonHeight(), gdi.scaleLength(baseButtonWidth),
"Automatic", "Automatisera", ListsCB, "Skriv ut eller exportera listan automatiskt.", true, false); "Automatic", "Automatisera", ListsCB, "Skriv ut eller exportera listan automatiskt.", true, false);
baseY += 2*(3+gdi.getButtonHeight()); baseY += 2*(3+gdi.getButtonHeight());
@ -268,16 +268,16 @@ void TabList::generateList(gdioutput &gdi, bool forceUpdate)
if (currentList.supportUpdateClasses()) { if (currentList.supportUpdateClasses()) {
baseY += 3 + gdi.getButtonHeight(); baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(baseButtonWidth),
"ClassSelection", "Klassval...", ListsCB, "Välj klasser", true, false); "ClassSelection", "Klassval...", ListsCB, "Välj klasser", true, false);
} }
baseY += 3 + gdi.getButtonHeight(); baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(baseButtonWidth),
"ListDesign", "Utseende...", ListsCB, "Justera visningsinställningar", true, false); "ListDesign", "Utseende...", ListsCB, "Justera visningsinställningar", true, false);
if (!currentList.getParam().saved && !oe->isReadOnly()) { if (!currentList.getParam().saved && !oe->isReadOnly()) {
baseY += 3 + gdi.getButtonHeight(); baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(baseButtonWidth),
"Remember", "Kom ihåg listan...", ListsCB, "Spara den här listan som en favoritlista", true, false); "Remember", "Kom ihåg listan...", ListsCB, "Spara den här listan som en favoritlista", true, false);
} }
} }
@ -1266,7 +1266,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
} }
pair<gdioutput *, TabList *> TabList::makeOwnWindow(gdioutput &gdi) { pair<gdioutput *, TabList *> TabList::makeOwnWindow(gdioutput &gdi) {
gdioutput *gdi_new = createExtraWindow(uniqueTag("list"), makeDash(L"MeOS - ") + currentList.getName(), gdi.getWidth() + 64 + gdi.scaleLength(120)); gdioutput *gdi_new = createExtraWindow(uniqueTag("list"), makeDash(L"MeOS - ") + currentList.getName(), gdi.getWidth() + 64 + gdi.scaleLength(baseButtonWidth));
TabList *tl_new = 0; TabList *tl_new = 0;
if (gdi_new) { if (gdi_new) {
TabList &tl = dynamic_cast<TabList &>(*gdi_new->getTabs().get(TListTab)); TabList &tl = dynamic_cast<TabList &>(*gdi_new->getTabs().get(TListTab));
@ -2125,9 +2125,9 @@ void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
gdi.fillDown(); gdi.fillDown();
gdi.addSelection("AgeFilter", 200, 150, nullptr, L"Åldersfiltrering:"); gdi.addSelection("AgeFilter", 200, 150, nullptr, L"Åldersfiltrering:");
vector<pair<wstring, size_t>> ages; vector<pair<wstring, size_t>> ages;
ages.emplace_back(L"Alla", size_t(oListParam::AgeFilter::All)); ages.emplace_back(lang.tl("Alla"), size_t(oListParam::AgeFilter::All));
ages.emplace_back(L"Ungdom", size_t(oListParam::AgeFilter::OnlyYouth)); ages.emplace_back(lang.tl("Ungdom"), size_t(oListParam::AgeFilter::OnlyYouth));
ages.emplace_back(L"Vuxna", size_t(oListParam::AgeFilter::ExludeYouth)); ages.emplace_back(lang.tl("Vuxna"), size_t(oListParam::AgeFilter::ExludeYouth));
gdi.addItem("AgeFilter", ages); gdi.addItem("AgeFilter", ages);
gdi.selectItemByData("AgeFilter", int(currentList.getParam().ageFilter)); gdi.selectItemByData("AgeFilter", int(currentList.getParam().ageFilter));

View File

@ -268,7 +268,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
loadPage(gdi); loadPage(gdi);
} }
else if (bu.id == "LiveResult") { else if (bu.id == "LiveResult") {
gdioutput *gdi_new = createExtraWindow(uniqueTag("list"), makeDash(L"MeOS - Live"), gdi.getWidth() + 64 + gdi.scaleLength(120)); gdioutput *gdi_new = createExtraWindow(uniqueTag("list"), makeDash(L"MeOS - Live"), gdi.getWidth() + 64 + gdi.scaleLength(baseButtonWidth));
gdi_new->clearPage(false); gdi_new->clearPage(false);
gdi_new->addString("", boldLarge, "Liveresultat"); gdi_new->addString("", boldLarge, "Liveresultat");
@ -316,7 +316,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
else if (bu.id == "Window") { else if (bu.id == "Window") {
oe->setupTimeLineEvents(0); oe->setupTimeLineEvents(0);
gdioutput *gdi_new = createExtraWindow(uniqueTag("speaker"), makeDash(L"MeOS - Speakerstöd"), gdi.getWidth() + 64 + gdi.scaleLength(120)); gdioutput *gdi_new = createExtraWindow(uniqueTag("speaker"), makeDash(L"MeOS - Speakerstöd"), gdi.getWidth() + 64 + gdi.scaleLength(baseButtonWidth));
if (gdi_new) { if (gdi_new) {
TabSpeaker &tl = dynamic_cast<TabSpeaker &>(*gdi_new->getTabs().get(TSpeakerTab)); TabSpeaker &tl = dynamic_cast<TabSpeaker &>(*gdi_new->getTabs().get(TSpeakerTab));
tl.ownWindow = true; tl.ownWindow = true;
@ -355,7 +355,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
if (speakerSettings.empty()) if (speakerSettings.empty())
throw meosException("Inställningarna är ogiltiga"); throw meosException("Inställningarna är ogiltiga");
for (size_t k = 1; k < speakerSettings.size(); k++) { for (size_t k = 1; k < speakerSettings.size(); k++) {
gdioutput *gdi_new = createExtraWindow(uniqueTag("speaker"), makeDash(L"MeOS - Speakerstöd"), gdi.getWidth() + 64 + gdi.scaleLength(120)); gdioutput *gdi_new = createExtraWindow(uniqueTag("speaker"), makeDash(L"MeOS - Speakerstöd"), gdi.getWidth() + 64 + gdi.scaleLength(baseButtonWidth));
if (gdi_new) { if (gdi_new) {
TabSpeaker &tl = dynamic_cast<TabSpeaker &>(*gdi_new->getTabs().get(TSpeakerTab)); TabSpeaker &tl = dynamic_cast<TabSpeaker &>(*gdi_new->getTabs().get(TSpeakerTab));
tl.ownWindow = true; tl.ownWindow = true;

View File

@ -257,6 +257,7 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
gdi.selectItemByData("Status", 0); gdi.selectItemByData("Status", 0);
gdi.setText("TimeAdjust", makeDash(L"-")); gdi.setText("TimeAdjust", makeDash(L"-"));
gdi.setText("PointAdjust", makeDash(L"-")); gdi.setText("PointAdjust", makeDash(L"-"));
gdi.setText("TeamInfo", L"", true);
return; return;
} }
@ -278,6 +279,19 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
gdi.setText("TimeAdjust", getTimeMS(t->getTimeAdjustment())); gdi.setText("TimeAdjust", getTimeMS(t->getTimeAdjustment()));
gdi.setText("PointAdjust", -t->getPointAdjustment()); gdi.setText("PointAdjust", -t->getPointAdjustment());
gdi.selectItemByData("Status", t->getStatus()); gdi.selectItemByData("Status", t->getStatus());
auto ri = t->getRaceInfo();
BaseInfo *bi = gdi.setText("TeamInfo", ri.first, true);
TextInfo *ti = dynamic_cast<TextInfo*>(bi);
assert(ti);
if (ti) {
if (ri.second > 0)
ti->setColor(GDICOLOR::colorGreen);
else if (ri.second < 0)
ti->setColor(GDICOLOR::colorRed);
else
ti->setColor(GDICOLOR::colorDefault);
}
} }
bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) { bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
@ -1443,6 +1457,9 @@ bool TabTeam::loadPage(gdioutput &gdi)
gdi.popX(); gdi.popX();
gdi.selectItemByData("Status", 0); gdi.selectItemByData("Status", 0);
gdi.addString("TeamInfo", 0, "").setColor(colorRed);
gdi.dropLine(0.4);
if (oe->hasAnyRestartTime()) { if (oe->hasAnyRestartTime()) {
gdi.addCheckbox("NoRestart", "Förhindra omstart", 0, false, "Förhindra att laget deltar i någon omstart"); gdi.addCheckbox("NoRestart", "Förhindra omstart", 0, false, "Förhindra att laget deltar i någon omstart");
} }

View File

@ -2315,3 +2315,164 @@ Ingen nummerlapp = Bez startovního čísla
Rogaining results for a team, where each team member collects points individually = Rogainingové výsledky pro tým, kde každý člen sbírá body samostatně Rogaining results for a team, where each team member collects points individually = Rogainingové výsledky pro tým, kde každý člen sbírá body samostatně
prefsCodePage = Kódová tabulka pro 8-bitový text při importu/exportu. prefsCodePage = Kódová tabulka pro 8-bitový text při importu/exportu.
Inga klasser tillåter direktanmälan. På sidan klasser kan du ändra denna egenskap. = Žádná kategorie nemá povolený rychlý vstup.\n\nTuto vlastnost můžeš změnit na stránce Kategorie. Inga klasser tillåter direktanmälan. På sidan klasser kan du ändra denna egenskap. = Žádná kategorie nemá povolený rychlý vstup.\n\nTuto vlastnost můžeš změnit na stránce Kategorie.
%s m = %s m
Age (on last day of current year) = Věk (v poslední den tohoto roku)
Age above or equal implies senior/pensioner = Věk vyšší nebo roven značí seniory
Age below or equal implies youth = Věk nižší nebo roven značí mládež
AllPunches = Všechna ražení
Anmäl andra = Nová přihláška
Anmälan mottagen = Přijatá přihláška
Anmälan måste hanteras manuellt = Tvá přihláška vyžaduje manuální zpracování
Anmälningsdatum = Datum přihlášky
Anyone = Kdokoliv
Automatisk omladdning = Automatický update
Begränsa antal rader per sida = Limit řádek na stránce
Bricknummer = Číslo čipu
ClassAvailableMaps = Dostupné mapy pro kategorii
ClassKnockoutTotalResult = Kategorie, celkový knock-out výsledek
ClassLiveResult = Živé výsledky (rádiové časy), po kategoriích
ClassNumEntries = Počet přihlášek v kategorii
ClassTotalMaps = Celkový počet map pro kategorii
Classes together = Kategorie spolu
CoursePunches = Ražení (na trati)
Database is used and cannot be deleted = Databáze je používána a nemůže být smazána
Direkt tidtagning = Časomíra živě
EFilterAPIEntry = Přihlášky skrze API
EFilterWrongFee = Neočekávaný vklad
Ej omstart = Bez restartu
Endast grundläggande (enklast möjligt) = Jen základní funkčnost
Endast tidtagning = Jen časomíra
Endast tidtagning (utan banor) = Jen časomíra (bez tratí)
Endast tidtagning (utan banor), stafett = Jen časomíra (bez tratí), štafety
Externa adresser = Externí adresy
Felaktigt datum 'X' (Använd YYYY-MM-DD) = Neplatné datum 'X' (Použij YYYY-MM-DD)
Felaktigt rankingformat i X. Förväntat: Y = Neplatný formát rankingu v X.\nOčekáváno: Y
FilterAnyResult = radio-časy/výsledky
FilterNamedControl = Pojmenované kontroly
FilterNotFinish = Bez cíle
Finish order = Pořadí v cíli
First to finish = První v cíli
Flera lopp i valfri ordning = Vícero závodů v libovolném pořadí
Flytta ner = Přesuň dolů
Flytta upp = Přesuň vzhůru
Från första = Od prvního
Från löpardatabasen = Z databáze závodníků
Från löpardatabasen i befintliga klubbar = Z databáze závodníků ve stávajících klubech
Färre slingor = Méně okruhů
Förhindra att laget deltar i någon omstart = Zabraň týmu v účasti na restartu
Förhindra omstart = Zabraň restartu
Förväntad = Očekávaný
HTML Export = HTML Export
HTML Export för 'X' = HTML Export 'X'
HTML formaterad genom listinställningar = HTML formátovaný sestavou
Heat = Kolo
Hittar inte klass X = Kategorie X nenalezena
Importerar RAID patrull csv-fil = Importuj csv data RAID družstev
Importerar ranking = Importuj ranking
Individual result by finish time = Výsledky jednotlivců dle cílového času
Individuellt = Jednotlivec
Inkludera bana = Včetně trati
Kartor = Mapy
Klart. X värden tilldelade = Hotovo. Přířazeno X hodnot.
Klassen X är listad flera gånger = Kategorie X je uvedena vícekrát
Klassen är full = Kategorie je plná
Klassval för 'X' = Výběr kategorie pro 'X'
Knockout sammanställning = Přehled knockoutů
Knockout total = Knockout celkově
Kolumner = Sloupce
Kunde inte ladda upp löpardatabasen (X) = Nemohu odeslat databázi závodníků (X)
Kunde inte öppna databasen (X) = Nemohu se připojit k databázi (X)
Kvalschema = Kvalifikační schéma
Lag och stafett = Tým a štafeta
Lagra inställningar = Ulož nastavení
Lagändringblankett = Formulář změny týmu
LineBreak = Zalomení řádku
Liveresultat, radiotider = Živé výsledky s radio-časy
Lås funktion = Zamkni
Lås upp = Odemkni
Låst gaffling = Uzamčená větvení
Mappa rootadressen (http:///localhost:port/) till funktion = Mapuj bázovou adresu (http:///localhost:port/) na funkci
MeOS utvecklinsstöd = Podpora vývoje MeOSu
Med direktanmälan = S přímým přihlášením
Målstämpling tillåts inte (X) = Cílové ražení zamítnuto (X)
Ogiltig starttid X = Neplatný čas startu X
Ogiltigt startintervall X = Chybný startovní interval
Pages with columns = Stránka se sloupci
Pages with columns, no header = Stránka se sloupci, bez hlavičky
Plac. E[stageno] = Umís. E
Poäng E[stageno] = Body E
Poängreduktion = Srážka
PunchAbsTime = Ražení, skutečný čas
PunchName = Ražení, jméno kontroly
PunchNamedSplit = Čas od poslední pojmenované kontroly
PunchSplitTime = Čas od poslední kontroly (mezičas)
PunchTimeSinceLast = Čas od posledního ražení
PunchTotalTime = Celkový čas na kontrolu
PunchTotalTimeAfter = Ztráta na kontrole
Rad X är ogiltig = Řádek X je neplatný
Rader = Řádky
Radio = Rádio
Radio tillåts inte (X) = Radio-kontroly zamítnuty (X)
Referens = Reference
Registrera hyrbrickor = Registruj půjčené čipy
Result module = Výsledkový modul
Rogaining points before automatic reduction = Rogainingové body před automatickou srážkou
Runner check time = Čas checku
Runner/team earlier stage places = Závodník/tým: umístění v předchozích etapách
Runner/team earlier stage points = Závodník/tým: body v předchozích etapách
Runner/team earlier stage running times = Závodník/tým: časy v předchozích etapách
Runner/team earlier stage statuses = Závodník/tým: statusy v předchozích etapách
RunnerCheck = Čas pro ražení checku
RunnerExpectedFee = Očekávaný vklad závodníka
RunnerGrossTime = Závodníkův čas před úpravou
RunnerId = Závodníkovo externí ID
Senast sedd: X vid Y = Naposled viděn: X at Y
Slå ihop med befintlig lista = Spoj se stávajícím protokolem
StartTimeClass = Čas startu, kategorie
Startstämpling tillåts inte (X) = Ražení startu zamítnuto (X)
Status E[stageno] = Status E
Status code for cancelled entry = Status kód pro zrušenou přihlášku
Status code for no timing = Status kód pro režim bez časomíry
Status code for running out-of-competition = Status kód pro účast mimo soutěž (OOC)
Stigning = Stoupání
Support intermediate legs = Podpora volby úseku
TeamGrossTime = Čas týmu před úpravou
There is no result module with X as identifier = Není výsledkový modul s identifikátorem X
Tid E[stageno] = Čas E
Till sista = Poslední jako cíl
Till vilka klasser = Do kterých kategorií
Tillåt = Povol
Tillåt anmälan = Povol vstup
Timekeeping = Časomíra
Unexpected Fee = Neočekávané vklady
Utom tävlan = m.s.
Varning: Följande deltagare har ett osäkert resultat = Varování: Přiřazení následujících závodníků je nejisté
Varning: Kartorna är slut = Varování: Žádné mapy
Varvräkning = Počet kol
Varvräkning med mellantid = Počet kol s časem navíc
Vem får anmäla sig = Kdo se smí přihlásit
Vill du sätta hyrbricka på befintliga löpare med dessa brickor? = Chceš uplatnit zapůjčení čipu na tyto závodníky?
Vill du ta bort brickan från hyrbrickslistan? = Chceš odstranit čip ze seznamu zapůjčených?
Vill du ta bort schemat? = Chceš odstranit schéma?
Vill du tömma listan med hyrbrickor? = Chceš smazat seznam zapůjčených čipů?
Visa detaljerad rapport för viss deltagare = Zobraz podrobný výpis pro zvoleného závodníka
Visa rubrik = Zobraz název
Visa rubrik mellan listorna = Zobraz nadpis mezi seznamy
Without courses = Bez tratí
X anmälda = X přihlášek
X går vidare, klass enligt ranking = X kvalifikováno, kategorie dle rankingu
ask:outofmaps = Nejsou mapy. Chceš přesto závodníka přihlásit?
ask:removescheme = Pokud odstraníš schéma, výsledky zmizí. Chceš pokračovat?
ask:usecourseinclass = Trať není používána žádným závodníkem této kategorie.\n\nChceš ji přesto použít?
help:custom_text_lines = Můžeš vložit vybraná vlastní data napsáním [Jména symbolu]. Dostupné symboly jsou vidět v seznamu napravo.\n\n Příklad: Výborně [RunnerName]!
help:registerhiredcards = Předregistruj čipy pro zapůjčení předem a dostanou pak status zapůjčení automaticky, jakmile budou přířazeny závodníkovi.
htmlhelp = HTML can be exported as a structured table or as a freely formatted document (more similar to the MeOS lists). You can also use export templates for custom formatting: columns, JavaScript base page flips, automatic scrolling, etc. It is possible to add custom templates by adding '.template' files in MeOS data folder. If you use a template there is a number of parameters to set below. The exact interpretation depends on the template.\n\nIf you select <Store Settings> the list and its settings is stored permanently in the competition. You can then access the list by using MeOS as a web server (The service 'Information Server') or export the list automatically at regular intervals.
htmlhelp = HTML může být exportováno jako strukturovaná tabulka nebo jako volně formátovaný dokument (spíše podobný protokolům MeOSu). Můžeš také použít exportní šablony pro vlastní formátování: sloupce, JavaScriptové převracení stránek, automatické rolování, atd. Je možné přidat vlastní šablony přidáním '.template' souborů do datové složky MeOSu. Pokud použiješ šablonu, pak je třeba níže nastavit řadu parametrů. Přesná interpretace závisí na šabloně.\n\nPokud zvolíš <Ulož Nastavení>, protokol a jeho nastavení jsou trvale uloženy v závodě. Pak jej můžeš použít s MeOSem coby webovým servrem (Služba 'Informační Server') nebo exportovat protokol automaticky v pravidelných intervalech.
info:advanceinfo = Start služby pro okamžitý přenos výsledků selhal. Výsledky budou přijaty s několika-vteřinovým zpožděním. Toto je očekávané chování když je na počítači spuštěno vícero MeOS procesů.
info:pageswithcolumns = Zobraz protokol po stránkách, s udaným počtem sloupců. Automaticky obnov data po každém kole.
prefsLastExportTarget = Poslední cíl exportu
prefsServiceRootMap = Výchozí funkce kořene webového serveru
prefsshowheader = Zobrazuj hlavičky stránek
warn:printmodeonly = Věz, že vytvoříš pouze výtisk obsahu čipu.\n\nK uložení výsledku do závodu potřebuješ zvolit funkci vyčtení/rádio.
Åldersfiltrering = Věkový filtr
Övrigt = Různé

View File

@ -2493,3 +2493,4 @@ Först = First
Lottat = Drawn Lottat = Drawn
Sist = Last Sist = Last
Fakturadatum = Fakturadatum Fakturadatum = Fakturadatum
Youth Cup X = Youth Cup X

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,4 @@ enum FlowOperation {
FlowAborted FlowAborted
}; };
const int GDI_BUTTON_SPACING = 8;
#endif #endif

View File

@ -76,6 +76,10 @@ enum gdiFonts;
#define START_YP 30 #define START_YP 30
#define NOTIMEOUT 0x0AAAAAAA #define NOTIMEOUT 0x0AAAAAAA
constexpr int baseButtonWidth = 150;
constexpr int GDI_BUTTON_SPACING = 8;
typedef list<ToolInfo> ToolList; typedef list<ToolInfo> ToolList;
/* /*
enum FontEncoding { enum FontEncoding {

View File

@ -476,15 +476,15 @@ pair<int, int> GeneralResult::score(oTeam &team, RunnerStatus st, int rt, int po
} }
RunnerStatus GeneralResult::deduceStatus(oTeam &team) const { RunnerStatus GeneralResult::deduceStatus(oTeam &team) const {
return team.getStatus(); return team.deduceComputedStatus();
} }
int GeneralResult::deduceTime(oTeam &team) const { int GeneralResult::deduceTime(oTeam &team) const {
return team.getRunningTime(false); return team.deduceComputedRunningTime();//team.getRunningTime(false);
} }
int GeneralResult::deducePoints(oTeam &team) const { int GeneralResult::deducePoints(oTeam &team) const {
return team.getRogainingPoints(false, false); return team.deduceComputedPoints();//team.getRogainingPoints(false, false);
} }
pair<int,int> GeneralResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const { pair<int,int> GeneralResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
@ -1075,6 +1075,7 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
} }
void DynamicResult::getSymbols(vector< pair<wstring, size_t> > &symb) const { void DynamicResult::getSymbols(vector< pair<wstring, size_t> > &symb) const {
symb.clear();
parser.getSymbols(symb); parser.getSymbols(symb);
} }
@ -1162,7 +1163,7 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner, bool classResult) con
parser.addSymbol("Start", runner.getStartTime()); parser.addSymbol("Start", runner.getStartTime());
parser.addSymbol("Finish", ft); parser.addSymbol("Finish", ft);
parser.addSymbol("Time", runner.getRunningTime(useComputed)); parser.addSymbol("Time", runner.getRunningTime(useComputed));
parser.addSymbol("Place", runner.getPlace()); parser.addSymbol("Place", runner.getPlace(false));
parser.addSymbol("Points", runner.getRogainingPoints(useComputed, false)); parser.addSymbol("Points", runner.getRogainingPoints(useComputed, false));
parser.addSymbol("PointReduction", runner.getRogainingReduction(useComputed)); parser.addSymbol("PointReduction", runner.getRogainingReduction(useComputed));
parser.addSymbol("PointOvertime", runner.getRogainingOvertime(useComputed)); parser.addSymbol("PointOvertime", runner.getRogainingOvertime(useComputed));
@ -1173,7 +1174,7 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner, bool classResult) con
parser.addSymbol("TotalStatus", runner.getTotalStatus()); parser.addSymbol("TotalStatus", runner.getTotalStatus());
parser.addSymbol("TotalTime", runner.getTotalRunningTime()); parser.addSymbol("TotalTime", runner.getTotalRunningTime());
parser.addSymbol("TotalPlace", runner.getTotalPlace()); parser.addSymbol("TotalPlace", runner.getTotalPlace(false));
parser.addSymbol("InputStatus", runner.getInputStatus()); parser.addSymbol("InputStatus", runner.getInputStatus());
parser.addSymbol("InputTime", runner.getInputTime()); parser.addSymbol("InputTime", runner.getInputTime());
@ -1233,6 +1234,10 @@ void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
start[k] = res.getStartTime(); start[k] = res.getStartTime();
finish[k] = res.getFinishTime(); finish[k] = res.getFinishTime();
points[k] = res.getPoints(); points[k] = res.getPoints();
if (classResult) {
r->updateComputedResultFromTemp();
}
runnerOutputTimes[k] = res.outputTimes; runnerOutputTimes[k] = res.outputTimes;
runnerOutputNumbers[k] = res.outputNumbers; runnerOutputNumbers[k] = res.outputNumbers;
} }
@ -1276,7 +1281,7 @@ void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
pClass cls = team.getClassRef(true); pClass cls = team.getClassRef(true);
if (cls) { if (cls) {
int nl = max<int>(1, cls->getNumStages() - 1); int nl = max<int>(1, cls->getNumStages() - 1);
parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(nl, false, false)); parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, nl, false, false));
} }
} }
@ -1389,7 +1394,7 @@ void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const
pClass cls = runner.getClassRef(true); pClass cls = runner.getClassRef(true);
if (cls) { if (cls) {
int nl = runner.getLegNumber(); int nl = runner.getLegNumber();
parser.addSymbol("ShortestClassTime", cls->getBestLegTime(nl, false)); parser.addSymbol("ShortestClassTime", cls->getBestLegTime(oClass::AllowRecompute::Yes, nl, false));
} }
vector<int> delta; vector<int> delta;
vector<int> place; vector<int> place;

View File

@ -2706,13 +2706,14 @@ void IOF30Interface::writeResultList(xmlparser &xml, const set<int> &classes,
vector<pClass> c; vector<pClass> c;
oe.getClasses(c, false); oe.getClasses(c, false);
for (size_t k = 0; k < c.size(); k++) {
if (classes.empty() || classes.count(c[k]->getId())) {
vector<pRunner> rToUse; vector<pRunner> rToUse;
vector<pTeam> tToUse; vector<pTeam> tToUse;
for (size_t k = 0; k < c.size(); k++) {
if (classes.empty() || classes.count(c[k]->getId())) {
getRunnersToUse(c[k], rToUse, tToUse, leg, false); getRunnersToUse(c[k], rToUse, tToUse, leg, false);
oe.sortRunners(SortOrder::ClassResult, rToUse);
oe.sortTeams(SortOrder::ClassResult, -1, false, tToUse);
if (!rToUse.empty() || !tToUse.empty()) { if (!rToUse.empty() || !tToUse.empty()) {
writeClassResult(xml, *c[k], rToUse, tToUse); writeClassResult(xml, *c[k], rToUse, tToUse);
@ -2778,9 +2779,9 @@ void IOF30Interface::writeClass(xmlparser &xml, const oClass &c) {
xml.write("Name", c.getName()); xml.write("Name", c.getName());
oClass::ClassStatus stat = c.getClassStatus(); oClass::ClassStatus stat = c.getClassStatus();
if (stat == oClass::Invalid) if (stat == oClass::ClassStatus::Invalid)
xml.write("Status", L"Invalidated"); xml.write("Status", L"Invalidated");
else if (stat == oClass::InvalidRefund) else if (stat == oClass::ClassStatus::InvalidRefund)
xml.write("Status", L"InvalidatedNoFee"); xml.write("Status", L"InvalidatedNoFee");
xml.endTag(); xml.endTag();
@ -2990,7 +2991,8 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
int tleg = r.getLegNumber() >= 0 ? r.getLegNumber() : 0; int tleg = r.getLegNumber() >= 0 ? r.getLegNumber() : 0;
if (stat == StatusOK && hasTiming) { if (stat == StatusOK && hasTiming) {
int after = r.getTotalRunningTime() - r.getClassRef(true)->getTotalLegLeaderTime(tleg, true, true); int after = r.getTotalRunningTime() -
r.getClassRef(true)->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
if (after >= 0) if (after >= 0)
xml.write("TimeBehind", after); xml.write("TimeBehind", after);
} }
@ -3284,13 +3286,14 @@ void IOF30Interface::writeStartList(xmlparser &xml, const set<int> &classes, boo
vector<pClass> c; vector<pClass> c;
oe.getClasses(c, false); oe.getClasses(c, false);
for (size_t k = 0; k < c.size(); k++) {
if (classes.empty() || classes.count(c[k]->getId())) {
vector<pRunner> rToUse; vector<pRunner> rToUse;
vector<pTeam> tToUse; vector<pTeam> tToUse;
for (size_t k = 0; k < c.size(); k++) {
if (classes.empty() || classes.count(c[k]->getId())) {
getRunnersToUse(c[k], rToUse, tToUse, -1, true); getRunnersToUse(c[k], rToUse, tToUse, -1, true);
oe.sortRunners(SortOrder::ClassStartTime, rToUse);
oe.sortTeams(SortOrder::ClassStartTime, 0, false, tToUse);
if (!rToUse.empty() || !tToUse.empty()) { if (!rToUse.empty() || !tToUse.empty()) {
writeClassStartList(xml, *c[k], rToUse, tToUse); writeClassStartList(xml, *c[k], rToUse, tToUse);
} }
@ -3793,7 +3796,24 @@ pCourse IOF30Interface::readCourse(const xmlobject &xcrs) {
if (!xcrs) if (!xcrs)
return 0; return 0;
int cid = xcrs.getObjectInt("Id"); string sId;
xcrs.getObjectString("Id", sId);
int cid = 0;
if (sId.length() > 0) {
sId = trim(sId);
if (isNumber(sId))
cid = atoi(sId.c_str());
else {
// Handle non-numeric id. Hash. Uniqeness ensured below.
for (size_t j = 0; j < sId.length(); j++)
cid = 31 * cid + sId.at(j);
cid = cid & 0xFFFFFFF;
}
}
if (!readCrsIds.insert(cid).second)
cid = 0; // Ignore for duplicates
wstring name = constructCourseName(xcrs); wstring name = constructCourseName(xcrs);
/*, family; /*, family;
@ -3867,6 +3887,8 @@ pCourse IOF30Interface::readCourse(const xmlobject &xcrs) {
pc = oe.getCourse(name); pc = oe.getCourse(name);
if (pc == 0) if (pc == 0)
pc = oe.addCourse(name); pc = oe.addCourse(name);
readCrsIds.insert(pc->getId());
} }
if (pc) { if (pc) {

View File

@ -271,6 +271,8 @@ class IOF30Interface {
void readId(const xmlobject &person, int &pid, __int64 &extId) const; void readId(const xmlobject &person, int &pid, __int64 &extId) const;
set<int> readCrsIds;
public: public:
IOF30Interface(oEvent *oe, bool forceSplitFee); IOF30Interface(oEvent *oe, bool forceSplitFee);
virtual ~IOF30Interface() {} virtual ~IOF30Interface() {}

View File

@ -310,6 +310,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
lang.get().addLangResource(L"Dansk", L"106"); lang.get().addLangResource(L"Dansk", L"106");
lang.get().addLangResource(L"Český", L"108"); lang.get().addLangResource(L"Český", L"108");
lang.get().addLangResource(L"Français", L"110"); lang.get().addLangResource(L"Français", L"110");
lang.get().addLangResource(L"Español", L"111");
lang.get().addLangResource(L"Russian", L"107"); lang.get().addLangResource(L"Russian", L"107");
if (fileExist(L"extra.lng")) { if (fileExist(L"extra.lng")) {
@ -424,8 +425,23 @@ int APIENTRY WinMain(HINSTANCE hInstance,
else else
return ANSI; return ANSI;
}*/ }*/
int defSize = 0;
gdi_main->setFont(gEvent->getPropertyInt("TextSize", 0), {
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
// Get the size of screen to the variable desktop
GetWindowRect(hDesktop, &desktop);
int d = max(desktop.right, desktop.bottom);
if (d <= 1024)
defSize = 0;
else if (d <= 2000)
defSize = 1;
else if (d <= 2500)
defSize = 2;
else
defSize = 3;
}
gdi_main->setFont(gEvent->getPropertyInt("TextSize", defSize),
gEvent->getPropertyString("TextFont", L"Arial")); gEvent->getPropertyString("TextFont", L"Arial"));
if (hSplash != nullptr) { if (hSplash != nullptr) {
@ -765,8 +781,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
int xp = gEvent->getPropertyInt("xpos", 50); int xp = gEvent->getPropertyInt("xpos", 50);
int yp = gEvent->getPropertyInt("ypos", 20); int yp = gEvent->getPropertyInt("ypos", 20);
int xs = gEvent->getPropertyInt("xsize", max(850, min(int(rc.right)-yp, 1124))); int xs = gEvent->getPropertyInt("xsize", max(850, min<int>(int(rc.right)-yp, (rc.right*9)/10)));
int ys = gEvent->getPropertyInt("ysize", max(650, min(int(rc.bottom)-yp-40, 800))); int ys = gEvent->getPropertyInt("ysize", max(650, min<int>(int(rc.bottom)-yp-40, (rc.bottom*8)/10)));
gEvent->setProperty("ypos", yp + 16); gEvent->setProperty("ypos", yp + 16);
gEvent->setProperty("xpos", xp + 32); gEvent->setProperty("xpos", xp + 32);

View File

@ -165,14 +165,14 @@ BEGIN
BEGIN BEGIN
BLOCK "041d04b0" BLOCK "041d04b0"
BEGIN BEGIN
VALUE "CompanyName", " " VALUE "CompanyName", "Melin Software HB"
VALUE "FileDescription", "meos" VALUE "FileDescription", "meos"
VALUE "FileVersion", "3.3.0.1" VALUE "FileVersion", "3.7.0.1"
VALUE "InternalName", "meos" VALUE "InternalName", "meos"
VALUE "LegalCopyright", "Copyright © 2007-2020" VALUE "LegalCopyright", "Copyright © 2007-2020"
VALUE "OriginalFilename", "meos.exe" VALUE "OriginalFilename", "meos.exe"
VALUE "ProductName", " meos" VALUE "ProductName", " meos"
VALUE "ProductVersion", "3.4.0.1" VALUE "ProductVersion", "3.7.0.1"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -1633,7 +1633,7 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
r.Removed = row["Removed"]; r.Removed = row["Removed"];
r.sqlUpdated = row["Modified"]; r.sqlUpdated = row["Modified"];
r.counter = row["Counter"]; r.counter = row["Counter"];
int oldHeat = r.getDCI().getInt("Heat");
storeData(r.getDI(), row, oe->dataRevision); storeData(r.getDI(), row, oe->dataRevision);
if (oldSno != r.StartNo || oldBib != r.getBib()) if (oldSno != r.StartNo || oldBib != r.getBib())
@ -1683,7 +1683,7 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
} }
else r.Class=0; else r.Class=0;
if (oldClass != r.Class) if (oldClass != r.Class || oldHeat != r.getDCI().getInt("Heat"))
oe->classIdToRunnerHash.reset(); oe->classIdToRunnerHash.reset();
if (int(row["Club"])!=0){ if (int(row["Club"])!=0){

View File

@ -48,8 +48,6 @@ using namespace std;
#include "../oEvent.h" #include "../oEvent.h"
#include "../Localizer.h" #include "../Localizer.h"
#include <typeinfo.h>
#ifdef BUILD_DB_DLL #ifdef BUILD_DB_DLL
HINSTANCE hInst=0; HINSTANCE hInst=0;
Localizer lang; Localizer lang;

View File

@ -6,6 +6,7 @@
#define IDR_3006 108 #define IDR_3006 108
#define IDR_3007 109 #define IDR_3007 109
#define IDR_3008 110 #define IDR_3008 110
#define IDR_3011 111
IDR_3001 300 DISCARDABLE "swedish.lng" IDR_3001 300 DISCARDABLE "swedish.lng"
IDR_3002 300 DISCARDABLE "english.lng" IDR_3002 300 DISCARDABLE "english.lng"
@ -14,5 +15,6 @@ IDR_3004 300 DISCARDABLE "danish.lng"
IDR_3005 300 DISCARDABLE "russian.lng" IDR_3005 300 DISCARDABLE "russian.lng"
IDR_3006 300 DISCARDABLE "czech.lng" IDR_3006 300 DISCARDABLE "czech.lng"
IDR_3008 300 DISCARDABLE "french.lng" IDR_3008 300 DISCARDABLE "french.lng"
IDR_3011 300 DISCARDABLE "spanish.lng"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View File

@ -30,18 +30,18 @@
//V35: abcdef //V35: abcdef
//V36: abcdef //V36: abcdef
int getMeosBuild() { int getMeosBuild() {
string revision("$Rev: 1004 $"); string revision("$Rev: 1014 $");
return 174 + atoi(revision.substr(5, string::npos).c_str()); return 174 + atoi(revision.substr(5, string::npos).c_str());
} }
//V37: a //V37: a
wstring getMeosDate() { wstring getMeosDate() {
wstring date(L"$Date: 2020-02-25 21:05:03 +0100 (ti, 25 feb 2020) $"); wstring date(L"$Date: 2020-05-01 16:22:46 +0200 (fr, 01 maj 2020) $");
return date.substr(7,10); return date.substr(7,10);
} }
wstring getBuildType() { wstring getBuildType() {
return L"RC1"; // No parantheses (...) return L"RC2"; // No parantheses (...)
} }
wstring getMajorVersion() { wstring getMajorVersion() {
@ -145,6 +145,7 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
supp.emplace_back(L"Nyköpings OK"); supp.emplace_back(L"Nyköpings OK");
supp.emplace_back(L"Thomas Engberg, VK Uvarna"); supp.emplace_back(L"Thomas Engberg, VK Uvarna");
supp.emplace_back(L"LG Axmalm, Sävedalens AIK"); supp.emplace_back(L"LG Axmalm, Sävedalens AIK");
supp.emplace_back(L"Falköpings AIK OK");
reverse(supp.begin(), supp.end()); reverse(supp.begin(), supp.end());
} }

View File

@ -2845,6 +2845,16 @@ void MetaListContainer::getGeneralResults(vector<DynamicResultRef> &rmAll) {
} }
} }
void MetaListContainer::getFreeResultModules(vector<pair<string, shared_ptr<DynamicResult>>> &res) const {
for (auto &r : freeResultModules) {
auto dynRes = dynamic_pointer_cast<DynamicResult, GeneralResult>(r.second.ptr);
if (dynRes) {
res.emplace_back(r.first, dynRes);
}
}
}
wstring DynamicResultRef::getAnnotation() const { wstring DynamicResultRef::getAnnotation() const {
if (ctr) if (ctr)
return ctr->getListName(); return ctr->getListName();

View File

@ -364,6 +364,9 @@ public:
virtual ~MetaListContainer(); virtual ~MetaListContainer();
void getFreeResultModules(vector<pair<string, shared_ptr<DynamicResult>>> &res) const;
string getUniqueId(EStdListType code) const; string getUniqueId(EStdListType code) const;
EStdListType getCodeFromUnqiueId(const string &id) const; EStdListType getCodeFromUnqiueId(const string &id) const;
wstring makeUniqueParamName(const wstring &nameIn) const; wstring makeUniqueParamName(const wstring &nameIn) const;

View File

@ -573,6 +573,27 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
currentResult->prepareCalculations(*rr[k], false); currentResult->prepareCalculations(*rr[k], false);
int rt = 0, pt = 0; int rt = 0, pt = 0;
RunnerStatus st = StatusUnknown; RunnerStatus st = StatusUnknown;
{
wstring err;
wstring str;
try {
rt = currentResult->deduceTime(*rr[k], rr[k]->getStartTime());
str = formatTime(rt);
}
catch (meosException &ex) {
err = ex.wwhat();
errors.insert(ex.wwhat());
str = L"Error";
}
TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi] - diff);
if (!err.empty()) {
ti.setColor(colorRed);
gdi.addToolTip("", err, 0, &ti.textRect);
}
txp += w[wi++];
}
{ {
wstring err; wstring err;
wstring str; wstring str;
@ -593,25 +614,6 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
} }
txp += w[wi++]; txp += w[wi++];
} }
{
wstring err;
wstring str;
try {
rt = currentResult->deduceTime(*rr[k], rr[k]->getStartTime());
str = formatTime(rt);
}
catch (meosException &ex) {
err = ex.wwhat();
errors.insert(ex.wwhat());
str = L"Error";
}
TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff);
if (!err.empty()) {
ti.setColor(colorRed);
gdi.addToolTip("", err, 0, &ti.textRect);
}
txp += w[wi++];
}
{ {
wstring err; wstring err;
@ -679,27 +681,28 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
wstring err; wstring err;
wstring str; wstring str;
try { try {
st = currentResult->deduceStatus(*tr[k]); rt = currentResult->deduceTime(*tr[k]);
str = oe->formatStatus(st, false); str = formatTime(rt);
} }
catch (meosException &ex) { catch (meosException &ex) {
err = ex.wwhat(); err = ex.wwhat();
errors.insert(ex.wwhat()); errors.insert(ex.wwhat());
str = L"Error"; str = L"Error";
} }
TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi] - diff);
if (!err.empty()) { if (!err.empty()) {
ti.setColor(colorRed); ti.setColor(colorRed);
gdi.addToolTip("", err, 0, &ti.textRect); gdi.addToolTip("", err, 0, &ti.textRect);
} }
txp += w[wi++]; txp += w[wi++];
} }
{ {
wstring err; wstring err;
wstring str; wstring str;
try { try {
rt = currentResult->deduceTime(*tr[k]); st = currentResult->deduceStatus(*tr[k]);
str = formatTime(rt); str = oe->formatStatus(st, false);
} }
catch (meosException &ex) { catch (meosException &ex) {
err = ex.wwhat(); err = ex.wwhat();
@ -1009,6 +1012,18 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
int rt = 0, pt = 0; int rt = 0, pt = 0;
RunnerStatus st = StatusUnknown; RunnerStatus st = StatusUnknown;
gdi.dropLine(); gdi.dropLine();
try {
rt = currentResult->deduceTime(r, r.getStartTime());
gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen);
}
catch (meosException &ex) {
wstring err = lang.tl(ex.wwhat());
gdi.addString("", 0, L"Time Calculation Failed: X#" + err).setColor(colorRed);
}
if (currentResult->hasMethod(DynamicResult::MDeduceRTime))
currentResult->debugDumpVariables(gdi, false);
try { try {
st = currentResult->deduceStatus(r); st = currentResult->deduceStatus(r);
currentResult->debugDumpVariables(gdi, true); currentResult->debugDumpVariables(gdi, true);
@ -1023,17 +1038,6 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
if (currentResult->hasMethod(DynamicResult::MDeduceRStatus)) if (currentResult->hasMethod(DynamicResult::MDeduceRStatus))
currentResult->debugDumpVariables(gdi, false); currentResult->debugDumpVariables(gdi, false);
try {
rt = currentResult->deduceTime(r, r.getStartTime());
gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen);
}
catch (meosException &ex) {
wstring err = lang.tl(ex.wwhat());
gdi.addString("", 0, L"Time Calculation Failed: X#" + err).setColor(colorRed);
}
if (currentResult->hasMethod(DynamicResult::MDeduceRTime))
currentResult->debugDumpVariables(gdi, false);
try { try {
pt = currentResult->deducePoints(r); pt = currentResult->deducePoints(r);
gdi.addStringUT(1, "ComputedPoints: " + itos(pt)).setColor(colorGreen); gdi.addStringUT(1, "ComputedPoints: " + itos(pt)).setColor(colorGreen);
@ -1065,6 +1069,17 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
int rt = 0, pt = 0; int rt = 0, pt = 0;
RunnerStatus st = StatusUnknown; RunnerStatus st = StatusUnknown;
gdi.dropLine(); gdi.dropLine();
try {
rt = currentResult->deduceTime(t);
gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen);
}
catch (meosException &ex) {
wstring err = lang.tl(ex.wwhat());
gdi.addString("", 0, L"Time Calculation Failed: X#" + err).setColor(colorRed);
}
if (currentResult->hasMethod(DynamicResult::MDeduceRTime))
currentResult->debugDumpVariables(gdi, false);
try { try {
st = currentResult->deduceStatus(t); st = currentResult->deduceStatus(t);
currentResult->debugDumpVariables(gdi, true); currentResult->debugDumpVariables(gdi, true);
@ -1079,17 +1094,6 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
if (currentResult->hasMethod(DynamicResult::MDeduceTStatus)) if (currentResult->hasMethod(DynamicResult::MDeduceTStatus))
currentResult->debugDumpVariables(gdi, false); currentResult->debugDumpVariables(gdi, false);
try {
rt = currentResult->deduceTime(t);
gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen);
}
catch (meosException &ex) {
wstring err = lang.tl(ex.wwhat());
gdi.addString("", 0, L"Time Calculation Failed: X#" + err).setColor(colorRed);
}
if (currentResult->hasMethod(DynamicResult::MDeduceRTime))
currentResult->debugDumpVariables(gdi, false);
try { try {
pt = currentResult->deducePoints(t); pt = currentResult->deducePoints(t);
gdi.addStringUT(1, "ComputedPoints: " + itos(pt)).setColor(colorGreen); gdi.addStringUT(1, "ComputedPoints: " + itos(pt)).setColor(colorGreen);

View File

@ -1714,11 +1714,12 @@ int oClass::getNumDistinctRunnersMinimal() const
return max(ndist, 1); return max(ndist, 1);
} }
void oClass::resetLeaderTime() { void oClass::resetLeaderTime() const {
for (size_t k = 0; k<tLeaderTime.size(); k++) for (size_t k = 0; k<tLeaderTime.size(); k++)
tLeaderTime[k].reset(); tLeaderTime[k].reset();
tBestTimePerCourse.clear(); tBestTimePerCourse.clear();
leaderTimeVersion = -1;
} }
bool oClass::hasCoursePool() const bool oClass::hasCoursePool() const
@ -1839,7 +1840,10 @@ void oClass::updateChangedCoursePool() {
tCoursesChanged = false; tCoursesChanged = false;
} }
oClass::LeaderInfo &oClass::getLeaderInfo(int leg) const { oClass::LeaderInfo &oClass::getLeaderInfo(AllowRecompute recompute, int leg) const {
if (recompute == AllowRecompute::Yes && leaderTimeVersion != oe->dataRevision)
updateLeaderTimes();
leg = mapLeg(leg); leg = mapLeg(leg);
if (leg < 0) if (leg < 0)
throw meosException(); throw meosException();
@ -1849,23 +1853,75 @@ oClass::LeaderInfo &oClass::getLeaderInfo(int leg) const {
return tLeaderTime[leg]; return tLeaderTime[leg];
} }
void oClass::LeaderInfo::updateComputed(int rt, Type t) { bool oClass::LeaderInfo::updateComputed(int rt, Type t) {
bool update = false;
switch (t) { switch (t) {
case Type::Leg: case Type::Leg:
if (bestTimeOnLegComputed == 0 || bestTimeOnLegComputed > rt) if (bestTimeOnLegComputed <= 0 || bestTimeOnLegComputed > rt)
bestTimeOnLegComputed = rt; bestTimeOnLegComputed = rt, update = true;
break; break;
case Type::Total: case Type::Total:
if (totalLeaderTimeComputed == 0 || totalLeaderTimeComputed > rt) if (totalLeaderTimeComputed <= 0 || totalLeaderTimeComputed > rt)
totalLeaderTimeComputed = rt; totalLeaderTimeComputed = rt, update = true;
break; break;
case Type::TotalInput: case Type::TotalInput:
if (totalLeaderTimeInputComputed == 0 || totalLeaderTimeInputComputed > rt) if (totalLeaderTimeInputComputed <= 0 || totalLeaderTimeInputComputed > rt)
totalLeaderTimeInputComputed = rt; totalLeaderTimeInputComputed = rt, update = true;
break; break;
default:
assert(false);
} }
return update;
}
bool oClass::LeaderInfo::update(int rt, Type t) {
bool update = false;
switch (t) {
case Type::Leg:
if (rt >= 0 && (bestTimeOnLeg < 0 || bestTimeOnLeg > rt))
bestTimeOnLeg = rt, update = true;
break;
case Type::Total:
if (rt >= 0 && (totalLeaderTime < 0 || totalLeaderTime > rt))
totalLeaderTime = rt, update = true;
break;
case Type::TotalInput:
if (rt >= 0 && (totalLeaderTimeInput < 0 || totalLeaderTimeInput > rt))
totalLeaderTimeInput = rt, update = true;
break;
case Type::Input:
if (rt >= 0 && (inputTime < 0 || inputTime > rt))
inputTime = rt, update = true;
break;
default:
assert(false);
}
return update;
}
void oClass::updateLeaderTimes() const {
resetLeaderTime();
vector<pRunner> runners;
oe->getRunners(Id, 0, runners, false);
bool needupdate = true;
int leg = 0;
while (needupdate) {
needupdate = false;
for (auto r : runners) {
if (r->tLeg == leg)
r->storeTimes();
else if (r->tLeg > leg)
needupdate = true;
}
leg++;
}
leaderTimeVersion = oe->dataRevision;
} }
void oClass::LeaderInfo::resetComputed(Type t) { void oClass::LeaderInfo::resetComputed(Type t) {
@ -1908,14 +1964,22 @@ int oClass::LeaderInfo::getLeader(Type t, bool computed) const {
return 0; return 0;
} }
int oClass::getBestLegTime(int leg, bool computedTime) const { int oClass::getBestLegTime(AllowRecompute recompute, int leg, bool computedTime) const {
leg = mapLeg(leg); leg = mapLeg(leg);
if (unsigned(leg) >= tLeaderTime.size()) if (unsigned(leg) >= tLeaderTime.size())
return 0; return 0;
return getLeaderInfo(leg).getLeader(LeaderInfo::Type::Leg, computedTime); int bt = getLeaderInfo(recompute, leg).getLeader(LeaderInfo::Type::Leg, computedTime);
if (bt == -1 && recompute == AllowRecompute::Yes) {
updateLeaderTimes();
bt = tLeaderTime[leg].getInputTime();
}
return bt;
} }
int oClass::getBestTimeCourse(int courseId) const { int oClass::getBestTimeCourse(AllowRecompute recompute, int courseId) const {
if (recompute == AllowRecompute::Yes && leaderTimeVersion != oe->dataRevision)
updateLeaderTimes();
map<int, int>::const_iterator res = tBestTimePerCourse.find(courseId); map<int, int>::const_iterator res = tBestTimePerCourse.find(courseId);
if (res == tBestTimePerCourse.end()) if (res == tBestTimePerCourse.end())
return 0; return 0;
@ -1923,24 +1987,40 @@ int oClass::getBestTimeCourse(int courseId) const {
return res->second; return res->second;
} }
int oClass::getBestInputTime(int leg) const { int oClass::getBestInputTime(AllowRecompute recompute, int leg) const {
leg = mapLeg(leg); leg = mapLeg(leg);
if (unsigned(leg)>=tLeaderTime.size()) if (unsigned(leg)>=tLeaderTime.size())
return 0; return 0;
else else {
return tLeaderTime[leg].inputTime; int it = getLeaderInfo(recompute, leg).getInputTime();
if (it == -1 && recompute == AllowRecompute::Yes) {
updateLeaderTimes();
it = getLeaderInfo(AllowRecompute::No, leg).getInputTime();
}
return -1;
}
} }
int oClass::getTotalLegLeaderTime(int leg, bool computedTime, bool includeInput) const { int oClass::getTotalLegLeaderTime(AllowRecompute recompute, int leg, bool computedTime, bool includeInput) const {
leg = mapLeg(leg); leg = mapLeg(leg);
if (unsigned(leg)>=tLeaderTime.size()) if (unsigned(leg) >= tLeaderTime.size())
return 0; return 0;
int res = -1;
int iter = -1;
while (res == -1 && ++iter<2) {
if (includeInput) if (includeInput)
return getLeaderInfo(leg).getLeader(LeaderInfo::Type::TotalInput, computedTime); res = getLeaderInfo(recompute, leg).getLeader(LeaderInfo::Type::TotalInput, computedTime);
else else
return getLeaderInfo(leg).getLeader(LeaderInfo::Type::Total, computedTime); res = getLeaderInfo(recompute, leg).getLeader(LeaderInfo::Type::Total, computedTime);
if (res == -1 && recompute == AllowRecompute::Yes) {
recompute = AllowRecompute::No;
updateLeaderTimes();
}
}
return res;
} }
void oClass::mergeClass(int classIdSec) { void oClass::mergeClass(int classIdSec) {
@ -3619,11 +3699,11 @@ oClass::ClassStatus oClass::getClassStatus() const {
if (tStatusRevision != oe->dataRevision) { if (tStatusRevision != oe->dataRevision) {
wstring s = getDCI().getString("Status"); wstring s = getDCI().getString("Status");
if (s == L"I") if (s == L"I")
tStatus = Invalid; tStatus = ClassStatus::Invalid;
else if (s == L"IR") else if (s == L"IR")
tStatus = InvalidRefund; tStatus = ClassStatus::InvalidRefund;
else else
tStatus = Normal; tStatus = ClassStatus::Normal;
tStatusRevision = oe->dataRevision; tStatusRevision = oe->dataRevision;
} }

View File

@ -153,7 +153,8 @@ class Table;
class oClass : public oBase class oClass : public oBase
{ {
public: public:
enum ClassStatus {Normal, Invalid, InvalidRefund}; enum class ClassStatus {Normal, Invalid, InvalidRefund};
enum class AllowRecompute {Yes, No };
static void getSplitMethods(vector< pair<wstring, size_t> > &methods); static void getSplitMethods(vector< pair<wstring, size_t> > &methods);
static void getSeedingMethods(vector< pair<wstring, size_t> > &methods); static void getSeedingMethods(vector< pair<wstring, size_t> > &methods);
@ -168,21 +169,7 @@ protected:
//First: best time on leg //First: best time on leg
//Second: Total leader time (total leader) //Second: Total leader time (total leader)
struct LeaderInfo { struct LeaderInfo {
LeaderInfo() { private:
reset();
}
void reset() {
bestTimeOnLeg = 0;
bestTimeOnLegComputed = 0;
totalLeaderTime = 0;
totalLeaderTimeComputed = 0;
inputTime = 0;
totalLeaderTimeInput = 0;
totalLeaderTimeInputComputed = 0;
}
int bestTimeOnLeg; int bestTimeOnLeg;
int bestTimeOnLegComputed; // Computed be default result module int bestTimeOnLegComputed; // Computed be default result module
@ -193,21 +180,48 @@ protected:
int totalLeaderTimeInputComputed; //Team total including input int totalLeaderTimeInputComputed; //Team total including input
int inputTime; int inputTime;
public:
LeaderInfo() {
reset();
}
void reset() {
bestTimeOnLeg = -1;
bestTimeOnLegComputed = -1;
totalLeaderTime = -1;
totalLeaderTimeComputed = -1;
inputTime = -1;
totalLeaderTimeInput = -1;
totalLeaderTimeInputComputed = -1;
}
enum class Type { enum class Type {
Leg, Leg,
Total, Total,
TotalInput TotalInput,
Input,
}; };
int getInputTime() const {
return inputTime;
}
void resetComputed(Type t); void resetComputed(Type t);
void updateComputed(int rt, Type t);
bool update(int rt, Type t);
bool updateComputed(int rt, Type t);
int getLeader(Type t, bool computed) const; int getLeader(Type t, bool computed) const;
}; };
LeaderInfo &getLeaderInfo(int leg) const; void updateLeaderTimes() const;
LeaderInfo &getLeaderInfo(AllowRecompute recompute, int leg) const;
mutable int leaderTimeVersion = -1;
mutable vector<LeaderInfo> tLeaderTime; mutable vector<LeaderInfo> tLeaderTime;
map<int, int> tBestTimePerCourse; mutable map<int, int> tBestTimePerCourse;
int tSplitRevision; int tSplitRevision;
map<int, vector<int> > tSplitAnalysisData; map<int, vector<int> > tSplitAnalysisData;
@ -288,7 +302,7 @@ protected:
/** Map to correct leg number for diff class/runner class (for example qual/final)*/ /** Map to correct leg number for diff class/runner class (for example qual/final)*/
int mapLeg(int inputLeg) const { int mapLeg(int inputLeg) const {
if (inputLeg > 0 && legInfo.size() == 1) if (inputLeg > 0 && legInfo.size() <= 1)
return 0; // The case with different class for team/runner. Leg is an index in another class. return 0; // The case with different class for team/runner. Leg is an index in another class.
return inputLeg; return inputLeg;
} }
@ -475,11 +489,11 @@ public:
void getStatistics(const set<int> &feeLock, int &entries, int &started) const; void getStatistics(const set<int> &feeLock, int &entries, int &started) const;
int getBestInputTime(int leg) const; int getBestInputTime(AllowRecompute recompute, int leg) const;
int getBestLegTime(int leg, bool computedTime) const; int getBestLegTime(AllowRecompute recompute, int leg, bool computedTime) const;
int getBestTimeCourse(int courseId) const; int getBestTimeCourse(AllowRecompute recompute, int courseId) const;
int getTotalLegLeaderTime(int leg, bool computedTime, bool includeInput) const; int getTotalLegLeaderTime(AllowRecompute recompute, int leg, bool computedTime, bool includeInput) const;
wstring getInfo() const; wstring getInfo() const;
// Returns true if the class has a pool of courses // Returns true if the class has a pool of courses
@ -491,7 +505,8 @@ public:
// Update changed course pool // Update changed course pool
void updateChangedCoursePool(); void updateChangedCoursePool();
void resetLeaderTime(); /** Reset cache of leader times */
void resetLeaderTime() const;
ClassType getClassType() const; ClassType getClassType() const;

View File

@ -540,7 +540,7 @@ void oClub::addRunnerInvoiceLine(const pRunner r, bool inTeam,
if (res != definedPayModes.end()) if (res != definedPayModes.end())
payMode = ", " + res->second; payMode = ", " + res->second;
*/ */
if (r->getClassRef(false) && r->getClassRef(false)->getClassStatus() == oClass::InvalidRefund) { if (r->getClassRef(false) && r->getClassRef(false)->getClassStatus() == oClass::ClassStatus::InvalidRefund) {
fee = 0; fee = 0;
card = 0; card = 0;
} }
@ -587,7 +587,7 @@ void oClub::addTeamInvoiceLine(const pTeam t, const map<int, wstring> &definedPa
} }
if (t->getClassRef(false) && t->getClassRef(false)->getClassStatus() == oClass::InvalidRefund) { if (t->getClassRef(false) && t->getClassRef(false)->getClassStatus() == oClass::ClassStatus::InvalidRefund) {
fee = 0; fee = 0;
} }
@ -1013,7 +1013,7 @@ void oEvent::setupClubInfoData() {
int id = r.Club->Id; int id = r.Club->Id;
++runners[id]; ++runners[id];
oDataConstInterface di = r.getDCI(); oDataConstInterface di = r.getDCI();
bool skip = r.Class && r.Class->getClassStatus() == oClass::InvalidRefund; bool skip = r.Class && r.Class->getClassStatus() == oClass::ClassStatus::InvalidRefund;
if (!skip) { if (!skip) {
int cardFee = di.getInt("CardFee"); int cardFee = di.getInt("CardFee");
@ -1033,7 +1033,7 @@ void oEvent::setupClubInfoData() {
if (t.Club) { if (t.Club) {
int id = t.Club->Id; int id = t.Club->Id;
oDataConstInterface di = t.getDCI(); oDataConstInterface di = t.getDCI();
bool skip = t.Class && t.Class->getClassStatus() == oClass::InvalidRefund; bool skip = t.Class && t.Class->getClassStatus() == oClass::ClassStatus::InvalidRefund;
if (!skip) { if (!skip) {
fee[id] += di.getInt("Fee"); fee[id] += di.getInt("Fee");

View File

@ -485,7 +485,7 @@ oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
oClassData->addVariableInt("Unordered", oDataContainer::oIS8U, "Oordnade parallella"); oClassData->addVariableInt("Unordered", oDataContainer::oIS8U, "Oordnade parallella");
oClassData->addVariableInt("Heat", oDataContainer::oIS8U, "Heat"); oClassData->addVariableInt("Heat", oDataContainer::oIS8U, "Heat");
oClassData->addVariableInt("Locked", oDataContainer::oIS8U, "Låst gaffling", make_shared<DataBoolean>("Locked")); oClassData->addVariableInt("Locked", oDataContainer::oIS8U, "Låst gaffling", make_shared<DataBoolean>("Locked"));
oClassData->addVariableString("Qualification", "Kvalschema"); oClassData->addVariableString("Qualification", "Kvalschema", make_shared<DataHider>());
oClassData->addVariableInt("NumberMaps", oDataContainer::oIS16, "Kartor"); oClassData->addVariableInt("NumberMaps", oDataContainer::oIS16, "Kartor");
oClassData->addVariableString("Result", 24, "Result module", make_shared<ResultModuleFormatter>()); oClassData->addVariableString("Result", 24, "Result module", make_shared<ResultModuleFormatter>());
oClassData->addVariableInt("TransferFlags", oDataContainer::oIS32, "Överföring", make_shared<DataHider>()); oClassData->addVariableInt("TransferFlags", oDataContainer::oIS32, "Överföring", make_shared<DataHider>());
@ -541,7 +541,6 @@ oEvent::~oEvent()
} }
void oEvent::initProperties() { void oEvent::initProperties() {
setProperty("TextSize", getPropertyString("TextSize", L"0"));
setProperty("Language", getPropertyString("Language", L"103")); setProperty("Language", getPropertyString("Language", L"103"));
setProperty("Interactive", getPropertyString("Interactive", L"1")); setProperty("Interactive", getPropertyString("Interactive", L"1"));
@ -1532,7 +1531,6 @@ pRunner oEvent::dbLookUpByName(const wstring &name, int clubId, int classId, int
if (dbr) { if (dbr) {
sRunner.init(*dbr, false); sRunner.init(*dbr, false);
sRunner.setExtIdentifier(int(dbr->getExtId()));
return &sRunner; return &sRunner;
} }
@ -1561,15 +1559,15 @@ bool oEvent::saveRunnerDatabase(const wchar_t *filename, bool onlyLocal)
void oEvent::updateRunnerDatabase() void oEvent::updateRunnerDatabase()
{ {
if (Name==L"!TESTTÄVLING") if (Name == L"!TESTTÄVLING")
return; return;
if (useRunnerDb()) { if (useRunnerDb()) {
oRunnerList::iterator it; oRunnerList::iterator it;
map<int, int> clubIdMap; map<int, int> clubIdMap;
for (it=Runners.begin(); it != Runners.end(); ++it){ for (it = Runners.begin(); it != Runners.end(); ++it) {
if (it->Card && it->Card->cardNo == it->cardNumber && if (it->Card && it->Card->cardNo == it->cardNumber &&
it->getDI().getInt("CardFee")==0 && it->Card->getNumPunches()>5) it->getDI().getInt("CardFee") == 0 && it->Card->getNumPunches() > 5)
updateRunnerDatabase(&*it, clubIdMap); updateRunnerDatabase(&*it, clubIdMap);
} }
runnerDB->refreshTables(); runnerDB->refreshTables();
@ -1585,6 +1583,16 @@ void oEvent::updateRunnerDatabase()
ml.save(file, this); ml.save(file, this);
} }
} }
}vector<pair<string, shared_ptr<DynamicResult>>> freeMod;
listContainer->getFreeResultModules(freeMod);
for (size_t k = 0; k < freeMod.size(); k++) {
wstring uid = gdibase.widen(freeMod[k].first) + L".rules";
wchar_t file[260];
getUserFile(file, uid.c_str());
if (!fileExist(file)) {
freeMod[k].second->save(file);
}
} }
} }
} }
@ -3755,6 +3763,9 @@ void oEvent::reEvaluateCourse(int CourseId, bool doSync)
void oEvent::reEvaluateAll(const set<int> &cls, bool doSync) void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
{ {
if (disableRecalculate)
return;
if (doSync) if (doSync)
autoSynchronizeLists(false); autoSynchronizeLists(false);
@ -3776,7 +3787,17 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
} }
oRunnerList::iterator it; oRunnerList::iterator it;
for (it=Runners.begin(); it != Runners.end(); ++it) { if (cls.size() < 5) {
vector<pRunner> runners;
getRunners(cls, runners);
for (pRunner it : runners) {
if (!it->tInTeam || it->Class != it->tInTeam->Class || (it->Class && it->Class->isQualificationFinalBaseClass())) {
it->apply(ChangeType::Quiet, nullptr);
}
}
}
else {
for (it = Runners.begin(); it != Runners.end(); ++it) {
if (!cls.empty() && cls.count(it->getClassId(true)) == 0) if (!cls.empty() && cls.count(it->getClassId(true)) == 0)
continue; continue;
@ -3784,6 +3805,7 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
it->apply(ChangeType::Quiet, nullptr); it->apply(ChangeType::Quiet, nullptr);
} }
} }
}
vector<int> mp; vector<int> mp;
bool needupdate = true; bool needupdate = true;
@ -3942,6 +3964,20 @@ void oEvent::reCalculateLeaderTimes(int classId)
{ {
if (disableRecalculate) if (disableRecalculate)
return; return;
if (classId) {
pClass cls = getClass(classId);
if (cls)
cls->resetLeaderTime();
}
else {
for (auto &c : Classes) {
if (!c.isRemoved())
c.resetLeaderTime();
}
}
/*
#ifdef _DEBUG #ifdef _DEBUG
wchar_t bf[128]; wchar_t bf[128];
swprintf_s(bf, L"Calculate leader times %d\n", classId); swprintf_s(bf, L"Calculate leader times %d\n", classId);
@ -3964,7 +4000,7 @@ void oEvent::reCalculateLeaderTimes(int classId)
} }
} }
leg++; leg++;
} }*/
} }
@ -5678,7 +5714,7 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
for (oClassList::iterator it = Classes.begin(); it != Classes.end(); ++it) { for (oClassList::iterator it = Classes.begin(); it != Classes.end(); ++it) {
if (it->isRemoved()) if (it->isRemoved())
continue; continue;
if (it->getClassStatus() != oClass::Normal) if (it->getClassStatus() != oClass::ClassStatus::Normal)
continue; continue;
if (onlyThisClass > 0 && it->getId() != onlyThisClass) if (onlyThisClass > 0 && it->getId() != onlyThisClass)

View File

@ -70,7 +70,7 @@ template<typename T, typename Apply> void calculatePlace(vector<ResultCalcData<T
cScore = 0; cScore = 0;
pClass cls = it.dst->getClassRef(true); pClass cls = it.dst->getClassRef(true);
useResults = true;// cls ? cls->getNoTiming() == false : true; useResults = true;// cls ? cls->getNoTiming() == false : true;
invalidClass = cls ? cls->getClassStatus() != oClass::Normal : false; invalidClass = cls ? cls->getClassStatus() != oClass::ClassStatus::Normal : false;
} }
if (invalidClass) { if (invalidClass) {
@ -151,10 +151,10 @@ void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo) {
cTime=it->tempRT; cTime=it->tempRT;
it->tPlace.update(*this, vPlace); // XXX User other result container it->tPlace.update(*this, vPlace, false); // XXX User other result container
} }
else else
it->tPlace.update(*this, 0); it->tPlace.update(*this, 0, false);
} }
} }
@ -263,7 +263,7 @@ void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bo
for (auto &cls : Classes) { for (auto &cls : Classes) {
if (!cls.isRemoved() && (all || classes.count(cls.getId()))) { if (!cls.isRemoved() && (all || classes.count(cls.getId()))) {
for (unsigned leg = 0; leg < cls.getNumStages(); leg++) for (unsigned leg = 0; leg < cls.getNumStages(); leg++)
cls.getLeaderInfo(leg).resetComputed(oClass::LeaderInfo::Type::Leg); cls.getLeaderInfo(oClass::AllowRecompute::No,leg).resetComputed(oClass::LeaderInfo::Type::Leg);
} }
} }
@ -288,13 +288,12 @@ void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bo
ge->calculateIndividualResults(resCalc.second, true, oListInfo::ResultType::Classwise, false, 0); ge->calculateIndividualResults(resCalc.second, true, oListInfo::ResultType::Classwise, false, 0);
for (pRunner r : resCalc.second) { for (pRunner r : resCalc.second) {
r->tComputedTime = r->getTempResult().getRunningTime(); r->updateComputedResultFromTemp();
r->tComputedPoints = r->getTempResult().getPoints(); r->tPlace.update(*oe, r->getTempResult().getPlace(), false);
r->tComputedStatus = r->getTempResult().getStatus();
r->tPlace.update(*oe, r->getTempResult().getPlace());
if (r->tComputedStatus == StatusOK && r->tComputedTime>0) { if (r->tComputedStatus == StatusOK && r->tComputedTime>0) {
pClass cls = r->getClassRef(true); pClass cls = r->getClassRef(true);
cls->getLeaderInfo(cls->mapLeg(r->getLegNumber())).updateComputed(r->tComputedTime, oClass::LeaderInfo::Type::Leg); cls->getLeaderInfo(oClass::AllowRecompute::No,
cls->mapLeg(r->getLegNumber())).updateComputed(r->tComputedTime, oClass::LeaderInfo::Type::Leg);
} }
} }
} }
@ -367,14 +366,16 @@ void oEvent::calculateRunnerResults(ResultType resultType,
resData.emplace_back(groupId, score, it); resData.emplace_back(groupId, score, it);
} }
bool useStdResultCtr = resultType == ResultType::ClassResultDefault || resultType == ResultType::TotalResultDefault;
if (courseResults) if (courseResults)
calculatePlace(resData, [this](DT &res, int value) {res.dst->tCoursePlace.update(*this, value); }); calculatePlace(resData, [this, useStdResultCtr](DT &res, int value) {res.dst->tCoursePlace.update(*this, value, useStdResultCtr); });
else if (classCourseResults) else if (classCourseResults)
calculatePlace(resData, [this](DT &res, int value) {res.dst->tCourseClassPlace.update(*this, value); }); calculatePlace(resData, [this, useStdResultCtr](DT &res, int value) {res.dst->tCourseClassPlace.update(*this, value, useStdResultCtr); });
else if (totalResults) else if (totalResults)
calculatePlace(resData, [this](DT &res, int value) {res.dst->tTotalPlace.update(*this, value); }); calculatePlace(resData, [this, useStdResultCtr](DT &res, int value) {res.dst->tTotalPlace.update(*this, value, useStdResultCtr); });
else else
calculatePlace(resData, [this](DT &res, int value) {res.dst->tPlace.update(*this, value); }); calculatePlace(resData, [this, useStdResultCtr](DT &res, int value) {res.dst->tPlace.update(*this, value, useStdResultCtr); });
} }
bool oEvent::calculateTeamResults(vector<const oTeam*> &teams, int leg, ResultType resType) { bool oEvent::calculateTeamResults(vector<const oTeam*> &teams, int leg, ResultType resType) {
@ -405,7 +406,7 @@ bool oEvent::calculateTeamResults(vector<const oTeam*> &teams, int leg, ResultTy
cPlace = 0; cPlace = 0;
vPlace = 0; vPlace = 0;
cTime = 0; cTime = 0;
invalidClass = it->Class->getClassStatus() != oClass::Normal; invalidClass = it->Class->getClassStatus() != oClass::ClassStatus::Normal;
} }
int sleg; int sleg;
@ -435,11 +436,13 @@ bool oEvent::calculateTeamResults(vector<const oTeam*> &teams, int leg, ResultTy
p = 0; p = 0;
} }
if (resType == ResultType::TotalResult) bool tmpDefaultResult = resType == ResultType::ClassResultDefault || resType == ResultType::TotalResultDefault;
it->getTeamPlace(sleg).totalP.update(*this, p); if (resType == ResultType::TotalResult || resType == ResultType::TotalResultDefault) {
it->getTeamPlace(sleg).totalP.update(*this, p, tmpDefaultResult);
}
else { else {
it->getTeamPlace(sleg).p.update(*this, p); it->getTeamPlace(sleg).p.update(*this, p, tmpDefaultResult);
res.version = dataRevision; res.version = tmpDefaultResult ? -1 : dataRevision;
res.status = it->_cachedStatus; res.status = it->_cachedStatus;
res.time = it->_sortTime; res.time = it->_sortTime;
it->setComputedResult(sleg, res); it->setComputedResult(sleg, res);
@ -560,8 +563,8 @@ void oEvent::calculateModuleTeamResults(const set<int> &cls, vector<oTeam *> &te
if (c->isRogaining()) if (c->isRogaining())
rgClasses.insert(id); rgClasses.insert(id);
for (unsigned leg = 0; leg < c->getNumStages(); leg++) { for (unsigned leg = 0; leg < c->getNumStages(); leg++) {
c->getLeaderInfo(leg).resetComputed(oClass::LeaderInfo::Type::Total); c->getLeaderInfo(oClass::AllowRecompute::No, leg).resetComputed(oClass::LeaderInfo::Type::Total);
c->getLeaderInfo(leg).resetComputed(oClass::LeaderInfo::Type::TotalInput); c->getLeaderInfo(oClass::AllowRecompute::No, leg).resetComputed(oClass::LeaderInfo::Type::TotalInput);
} }
cls2Mod[c->Id] = c->getResultModuleTag(); cls2Mod[c->Id] = c->getResultModuleTag();
@ -605,8 +608,8 @@ void oEvent::calculateModuleTeamResults(const set<int> &cls, vector<oTeam *> &te
resData.emplace_back(clsId, totScore, t); resData.emplace_back(clsId, totScore, t);
for (int i = 0; i < t->getNumRunners(); i++) { for (int i = 0; i < t->getNumRunners(); i++) {
t->getTeamPlace(i).p.update(*this, t->getTempResult().getPlace()); t->getTeamPlace(i).p.update(*this, t->getTempResult().getPlace(), false);
t->getTeamPlace(i).totalP.update(*this, t->getTempResult().getPlace()); t->getTeamPlace(i).totalP.update(*this, t->getTempResult().getPlace(), false);
oTeam::ComputedLegResult res; oTeam::ComputedLegResult res;
res.version = dataRevision; res.version = dataRevision;
int legTime = 0; int legTime = 0;
@ -624,7 +627,7 @@ void oEvent::calculateModuleTeamResults(const set<int> &cls, vector<oTeam *> &te
else if (lt != LTIgnore && lt != LTExtra) else if (lt != LTIgnore && lt != LTExtra)
timePar = res.time; timePar = res.time;
teamClass->getLeaderInfo(i).updateComputed(res.time, oClass::LeaderInfo::Type::Leg); teamClass->getLeaderInfo(oClass::AllowRecompute::No, i).updateComputed(res.time, oClass::LeaderInfo::Type::Leg);
} }
else { else {
ok = false; ok = false;
@ -635,8 +638,8 @@ void oEvent::calculateModuleTeamResults(const set<int> &cls, vector<oTeam *> &te
legTime = t->tComputedTime; legTime = t->tComputedTime;
else else
legTime = timeAcc + timePar; legTime = timeAcc + timePar;
teamClass->getLeaderInfo(i).updateComputed(legTime, oClass::LeaderInfo::Type::Total); teamClass->getLeaderInfo(oClass::AllowRecompute::No, i).updateComputed(legTime, oClass::LeaderInfo::Type::Total);
teamClass->getLeaderInfo(i).updateComputed(t->getInputTime() + legTime, oClass::LeaderInfo::Type::TotalInput); teamClass->getLeaderInfo(oClass::AllowRecompute::No, i).updateComputed(t->getInputTime() + legTime, oClass::LeaderInfo::Type::TotalInput);
} }
auto ltNext = teamClass->getLegType(i + 1); auto ltNext = teamClass->getLegType(i + 1);
@ -680,13 +683,13 @@ void oEvent::calculateModuleTeamResults(const set<int> &cls, vector<oTeam *> &te
} }
calculatePlace(legResultsData, [this](DR &res, int value) { calculatePlace(legResultsData, [this](DR &res, int value) {
res.dst->tPlace.update(*this, value); res.dst->tPlace.update(*this, value, false);
res.dst->tTotalPlace.update(*this, value); }); res.dst->tTotalPlace.update(*this, value, false); });
// Calculate and store total result // Calculate and store total result
calculatePlace(resData, [this](DT &res, int value) { calculatePlace(resData, [this](DT &res, int value) {
for (int i = 0; i < res.dst->getNumRunners(); i++) { for (int i = 0; i < res.dst->getNumRunners(); i++) {
res.dst->getTeamPlace(i).totalP.update(*this, value); res.dst->getTeamPlace(i).totalP.update(*this, value, false);
}}); }});
} }
} }

View File

@ -636,7 +636,7 @@ const wstring &oEvent::formatPunchStringAux(const oPrintPost &pp, const oListPar
const wstring *wsptr = 0; const wstring *wsptr = 0;
bfw[0] = 0; bfw[0] = 0;
pClass pc = r ? r->getClassRef(true) : 0; pClass pc = r ? r->getClassRef(true) : 0;
bool invalidClass = pc && pc->getClassStatus() != oClass::Normal; bool invalidClass = pc && pc->getClassStatus() != oClass::ClassStatus::Normal;
oCounter counter(counterIn); oCounter counter(counterIn);
static bool reentrantLock = false; static bool reentrantLock = false;
@ -1014,7 +1014,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
auto noTimingTeam = [&]() { auto noTimingTeam = [&]() {
return (pc ? pc->getNoTiming() : false) || (t ? t->getStatusComputed() == StatusNoTiming : false); return (pc ? pc->getNoTiming() : false) || (t ? t->getStatusComputed() == StatusNoTiming : false);
}; };
bool invalidClass = pc && pc->getClassStatus() != oClass::Normal; bool invalidClass = pc && pc->getClassStatus() != oClass::ClassStatus::Normal;
int legIndex = pp.legIndex; int legIndex = pp.legIndex;
if(pc && pp.type != lResultModuleNumber && pp.type != lResultModuleNumberTeam if(pc && pp.type != lResultModuleNumber && pp.type != lResultModuleNumberTeam
&& pp.type != lResultModuleTime && pp.type != lResultModuleTimeTeam) && pp.type != lResultModuleTime && pp.type != lResultModuleTimeTeam)
@ -1363,7 +1363,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
int tleg = r->tLeg >= 0 ? r->tLeg:0; int tleg = r->tLeg >= 0 ? r->tLeg:0;
if (r->getTotalStatus()==StatusOK) { if (r->getTotalStatus()==StatusOK) {
if ( (t && t->getNumShortening(tleg) == 0) || (!t && r->getNumShortening() == 0)) { if ( (t && t->getNumShortening(tleg) == 0) || (!t && r->getNumShortening() == 0)) {
int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true, true); int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
if (after > 0) if (after > 0)
swprintf_s(wbf, L"+%d:%02d", after/60, after%60); swprintf_s(wbf, L"+%d:%02d", after/60, after%60);
} }
@ -1376,7 +1376,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
int tleg=r->tLeg>=0 ? r->tLeg:0; int tleg=r->tLeg>=0 ? r->tLeg:0;
if (r->tStatus==StatusOK && pc && !noTimingRunner()) { if (r->tStatus==StatusOK && pc && !noTimingRunner()) {
if (r->getNumShortening() == 0) { if (r->getNumShortening() == 0) {
int after = r->getRunningTime(true) - pc->getBestLegTime(tleg, true); int after = r->getRunningTime(true) - pc->getBestLegTime(oClass::AllowRecompute::Yes, tleg, true);
if (after > 0) if (after > 0)
swprintf_s(wbf, L"+%d:%02d", after/60, after%60); swprintf_s(wbf, L"+%d:%02d", after/60, after%60);
} }
@ -1528,8 +1528,8 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
if (r && pc && !invalidClass) { if (r && pc && !invalidClass) {
int tleg = r->tLeg >= 0 ? r->tLeg:0; int tleg = r->tLeg >= 0 ? r->tLeg:0;
if (r->getTotalStatus() == StatusOK && pc && !noTimingRunner()) { if (r->getTotalStatus() == StatusOK && pc && !noTimingRunner()) {
int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true, true); int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
int afterOld = r->inputTime - pc->getBestInputTime(tleg); int afterOld = r->inputTime - pc->getBestInputTime(oClass::AllowRecompute::Yes, tleg);
int ad = after - afterOld; int ad = after - afterOld;
if (ad > 0) if (ad > 0)
swprintf_s(wbf, L"+%d:%02d", ad / 60, ad % 60); swprintf_s(wbf, L"+%d:%02d", ad / 60, ad % 60);
@ -1600,7 +1600,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
int after = 0; int after = 0;
if (pp.resultModuleIndex == -1) { if (pp.resultModuleIndex == -1) {
int tleg=r->tLeg>=0 ? r->tLeg:0; int tleg=r->tLeg>=0 ? r->tLeg:0;
int brt = pc->getBestLegTime(tleg, true); int brt = pc->getBestLegTime(oClass::AllowRecompute::Yes, tleg, true);
if (r->prelStatusOK(true, true) && brt > 0) { if (r->prelStatusOK(true, true) && brt > 0) {
after=r->getRunningTime(true) - brt; after=r->getRunningTime(true) - brt;
} }
@ -1623,7 +1623,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
int tleg = r->tLeg >= 0 ? r->tLeg:0; int tleg = r->tLeg >= 0 ? r->tLeg:0;
if (r->getTotalStatus()==StatusOK && pc && !noTimingRunner()) { if (r->getTotalStatus()==StatusOK && pc && !noTimingRunner()) {
if ( (t && t->getNumShortening(tleg) == 0) || (!t && r->getNumShortening() == 0)) { if ( (t && t->getNumShortening(tleg) == 0) || (!t && r->getNumShortening() == 0)) {
int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true, true); int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
if (after > 0) if (after > 0)
swprintf_s(wbf, L"+%d:%02d", after/60, after%60); swprintf_s(wbf, L"+%d:%02d", after/60, after%60);
} }
@ -1637,7 +1637,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
if (r && pc && !invalidClass) { if (r && pc && !invalidClass) {
pCourse crs = r->getCourse(false); pCourse crs = r->getCourse(false);
if (crs && r->tStatus==StatusOK && !noTimingRunner()) { if (crs && r->tStatus==StatusOK && !noTimingRunner()) {
int after = r->getRunningTime(true) - pc->getBestTimeCourse(crs->getId()); int after = r->getRunningTime(true) - pc->getBestTimeCourse(oClass::AllowRecompute::Yes, crs->getId());
if (after > 0) if (after > 0)
swprintf_s(wbf, L"+%d:%02d", after/60, after%60); swprintf_s(wbf, L"+%d:%02d", after/60, after%60);
} }
@ -1836,7 +1836,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
break; break;
case lTeamGrossTime: case lTeamGrossTime:
if (t && !invalidClass) { if (t && !invalidClass) {
int tm = t->getLegRunningTimeUnadjusted(legIndex, false); int tm = t->getLegRunningTimeUnadjusted(legIndex, false, false);
wsptr = &formatTime(tm); wsptr = &formatTime(tm);
} }
break; break;
@ -2050,7 +2050,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
if (t && pc && !invalidClass) { if (t && pc && !invalidClass) {
int tleg = t->getNumRunners() - 1; int tleg = t->getNumRunners() - 1;
if (t->getTotalStatus()==StatusOK && pc && !noTimingTeam()) { if (t->getTotalStatus()==StatusOK && pc && !noTimingTeam()) {
int after = t->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true, true); int after = t->getTotalRunningTime() - pc->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
if (after > 0) if (after > 0)
swprintf_s(wbf, L"+%d:%02d", after/60, after%60); swprintf_s(wbf, L"+%d:%02d", after/60, after%60);
} }
@ -2060,8 +2060,8 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
if (t && pc && !invalidClass) { if (t && pc && !invalidClass) {
int tleg = t->getNumRunners() - 1; int tleg = t->getNumRunners() - 1;
if (t->getTotalStatus()==StatusOK && pc && !noTimingTeam()) { if (t->getTotalStatus()==StatusOK && pc && !noTimingTeam()) {
int after = t->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true, true); int after = t->getTotalRunningTime() - pc->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
int afterOld = t->inputTime - pc->getBestInputTime(tleg); int afterOld = t->inputTime - pc->getBestInputTime(oClass::AllowRecompute::Yes, tleg);
int ad = after - afterOld; int ad = after - afterOld;
if (ad > 0) if (ad > 0)
swprintf_s(wbf, L"+%d:%02d", ad/60, ad%60); swprintf_s(wbf, L"+%d:%02d", ad/60, ad%60);

View File

@ -54,9 +54,27 @@ bool oAbstractRunner::DynamicValue::isOld(const oEvent &oe) const {
return oe.dataRevision != dataRevision; return oe.dataRevision != dataRevision;
} }
void oAbstractRunner::DynamicValue::update(const oEvent &oe, int v) { oAbstractRunner::DynamicValue &oAbstractRunner::DynamicValue::update(const oEvent &oe, int v, bool preferStd) {
if (preferStd)
valueStd = v; // A temporary result for "default" when computing with result modules (internal calculation)
else {
value = v; value = v;
dataRevision = oe.dataRevision; dataRevision = oe.dataRevision;
}
return *this;
}
int oAbstractRunner::DynamicValue::get(bool preferStd) const {
if (preferStd && valueStd >= 0)
return valueStd;
return value;
}
void oAbstractRunner::DynamicValue::reset() {
value = -1;
valueStd = -1;
dataRevision = -1;
} }
const wstring &oAbstractRunner::encodeStatus(RunnerStatus st, bool allowError) { const wstring &oAbstractRunner::encodeStatus(RunnerStatus st, bool allowError) {
@ -1611,19 +1629,19 @@ bool oRunner::evaluateCard(bool doApply, vector<int> & MissingPunches,
if (clz && changeType == ChangeType::Update) { if (clz && changeType == ChangeType::Update) {
bool update = false; bool update = false;
if (tInTeam) { if (tInTeam) {
int t1 = clz->getTotalLegLeaderTime(tLeg, false, false); int t1 = clz->getTotalLegLeaderTime(oClass::AllowRecompute::No, tLeg, false, false);
int t2 = tInTeam->getLegRunningTime(tLeg, false, false); int t2 = tInTeam->getLegRunningTime(tLeg, false, false);
if (t2<=t1 && t2>0) if (t2<=t1 && t2>0)
update = true; update = true;
int t3 = clz->getTotalLegLeaderTime(tLeg, false, true); int t3 = clz->getTotalLegLeaderTime(oClass::AllowRecompute::No, tLeg, false, true);
int t4 = tInTeam->getLegRunningTime(tLeg, false, true); int t4 = tInTeam->getLegRunningTime(tLeg, false, true);
if (t4<=t3 && t4>0) if (t4<=t3 && t4>0)
update = true; update = true;
} }
if (!update) { if (!update) {
int t1 = clz->getBestLegTime(tLeg, false); int t1 = clz->getBestLegTime(oClass::AllowRecompute::No, tLeg, false);
int t2 = getRunningTime(false); int t2 = getRunningTime(false);
if (t2<=t1 && t2>0) if (t2<=t1 && t2>0)
update = true; update = true;
@ -1741,17 +1759,27 @@ bool oRunner::storeTimesAux(pClass targetClass) {
for (int leg = firstLeg; leg<lastLeg; leg++) { for (int leg = firstLeg; leg<lastLeg; leg++) {
if (tStatus==StatusOK) { if (tStatus==StatusOK) {
int &bt=targetClass->tLeaderTime[leg].bestTimeOnLeg; //int &bt=targetClass->tLeaderTime[leg].bestTimeOnLeg;
int rt=getRunningTime(false); int rt=getRunningTime(false);
if (rt > 0 && (bt == 0 || rt < bt)) { if (targetClass->tLeaderTime[leg].update(rt, oClass::LeaderInfo::Type::Leg))
updated = true;
/*if (rt > 0 && (bt == 0 || rt < bt)) {
bt=rt; bt=rt;
updated = true; updated = true;
}*/
} }
if (getStatusComputed() == StatusOK) {
int rt = getRunningTime(true);
if (targetClass->tLeaderTime[leg].updateComputed(rt, oClass::LeaderInfo::Type::Leg))
updated = true;
} }
} }
bool updateTotal = true; bool updateTotal = true;
bool updateTotalInput = true; bool updateTotalInput = true;
bool updateTotalC = true;
bool updateTotalInputC = true;
int basePLeg = firstLeg; int basePLeg = firstLeg;
while (basePLeg > 0 && targetClass->legInfo[basePLeg].isParallel()) while (basePLeg > 0 && targetClass->legInfo[basePLeg].isParallel())
@ -1761,6 +1789,9 @@ bool oRunner::storeTimesAux(pClass targetClass) {
while (ix < nleg && (ix == basePLeg || targetClass->legInfo[ix].isParallel()) ) { while (ix < nleg && (ix == basePLeg || targetClass->legInfo[ix].isParallel()) ) {
updateTotal = updateTotal && tInTeam->getLegStatus(ix, false, false)==StatusOK; updateTotal = updateTotal && tInTeam->getLegStatus(ix, false, false)==StatusOK;
updateTotalInput = updateTotalInput && tInTeam->getLegStatus(ix, false, true)==StatusOK; updateTotalInput = updateTotalInput && tInTeam->getLegStatus(ix, false, true)==StatusOK;
updateTotalC = updateTotalC && tInTeam->getLegStatus(ix, true, false) == StatusOK;
updateTotalInputC = updateTotalInputC && tInTeam->getLegStatus(ix, true, true) == StatusOK;
ix++; ix++;
} }
@ -1773,12 +1804,26 @@ bool oRunner::storeTimesAux(pClass targetClass) {
} }
for (int leg = firstLeg; leg<lastLeg; leg++) { for (int leg = firstLeg; leg<lastLeg; leg++) {
int &bt=targetClass->tLeaderTime[leg].totalLeaderTime; /*int &bt=targetClass->tLeaderTime[leg].totalLeaderTime;
if (rt > 0 && (bt == 0 || rt < bt)) { if (rt > 0 && (bt == 0 || rt < bt)) {
bt=rt; bt=rt;
updated = true; updated = true;
}*/
if (targetClass->tLeaderTime[leg].update(rt, oClass::LeaderInfo::Type::Total))
updated = true;
} }
} }
if (updateTotalC) {
int rt = 0;
int ix = basePLeg;
while (ix < nleg && (ix == basePLeg || targetClass->legInfo[ix].isParallel())) {
rt = max(rt, tInTeam->getLegRunningTime(ix, true, false));
ix++;
}
for (int leg = firstLeg; leg<lastLeg; leg++) {
if (targetClass->tLeaderTime[leg].updateComputed(rt, oClass::LeaderInfo::Type::Total))
updated = true;
}
} }
if (updateTotalInput) { if (updateTotalInput) {
//int rt=tInTeam->getLegRunningTime(tLeg, true); //int rt=tInTeam->getLegRunningTime(tLeg, true);
@ -1789,12 +1834,26 @@ bool oRunner::storeTimesAux(pClass targetClass) {
ix++; ix++;
} }
for (int leg = firstLeg; leg<lastLeg; leg++) { for (int leg = firstLeg; leg<lastLeg; leg++) {
int &bt=targetClass->tLeaderTime[leg].totalLeaderTimeInput; /*int &bt=targetClass->tLeaderTime[leg].totalLeaderTimeInput;
if (rt > 0 && (bt == 0 || rt < bt)) { if (rt > 0 && (bt <= 0 || rt < bt)) {
bt=rt; bt=rt;
updated = true; updated = true;
}*/
if (targetClass->tLeaderTime[leg].update(rt, oClass::LeaderInfo::Type::TotalInput))
updated = true;
} }
} }
if (updateTotalInputC) {
int rt = 0;
int ix = basePLeg;
while (ix < nleg && (ix == basePLeg || targetClass->legInfo[ix].isParallel())) {
rt = max(rt, tInTeam->getLegRunningTime(ix, true, true));
ix++;
}
for (int leg = firstLeg; leg<lastLeg; leg++) {
if (targetClass->tLeaderTime[leg].updateComputed(rt, oClass::LeaderInfo::Type::TotalInput))
updated = true;
}
} }
} }
} }
@ -1802,35 +1861,56 @@ bool oRunner::storeTimesAux(pClass targetClass) {
size_t dupLeg = targetClass->mapLeg(tDuplicateLeg); size_t dupLeg = targetClass->mapLeg(tDuplicateLeg);
if (targetClass && dupLeg < targetClass->tLeaderTime.size()) { if (targetClass && dupLeg < targetClass->tLeaderTime.size()) {
if (tStatus == StatusOK) { if (tStatus == StatusOK) {
int &bt = targetClass->tLeaderTime[dupLeg].bestTimeOnLeg;
int rt = getRunningTime(false); int rt = getRunningTime(false);
if (rt > 0 && (bt == 0 || rt < bt)) { /*int &bt = targetClass->tLeaderTime[dupLeg].bestTimeOnLeg;
if (rt > 0 && (bt <= 0 || rt < bt)) {
bt = rt; bt = rt;
updated = true; updated = true;
}*/
if (targetClass->tLeaderTime[dupLeg].update(rt, oClass::LeaderInfo::Type::Leg))
updated = true;
} }
if (getStatusComputed() == StatusOK) {
int rt = getRunningTime(true);
if (targetClass->tLeaderTime[dupLeg].updateComputed(rt, oClass::LeaderInfo::Type::Leg))
updated = true;
} }
int &bt = targetClass->tLeaderTime[dupLeg].totalLeaderTime;
int rt = getRaceRunningTime(dupLeg); int rt = getRaceRunningTime(false, dupLeg);
if (rt > 0 && (bt == 0 || rt < bt)) { if (targetClass->tLeaderTime[dupLeg].update(rt, oClass::LeaderInfo::Type::Total))
updated = true;
rt = getRaceRunningTime(true, dupLeg);
if (targetClass->tLeaderTime[dupLeg].updateComputed(rt, oClass::LeaderInfo::Type::Total))
updated = true;
/*int &bt = targetClass->tLeaderTime[dupLeg].totalLeaderTime;
if (rt > 0 && (bt <= 0 || rt < bt)) {
bt = rt; bt = rt;
updated = true; updated = true;
targetClass->tLeaderTime[dupLeg].totalLeaderTimeInput = rt; targetClass->tLeaderTime[dupLeg].totalLeaderTimeInput = rt;
} }*/
} }
} }
size_t mappedLeg = targetClass->mapLeg(tLeg); size_t mappedLeg = targetClass->mapLeg(tLeg);
// Best input time // Best input time
if (mappedLeg<targetClass->tLeaderTime.size()) { if (mappedLeg<targetClass->tLeaderTime.size()) {
int &it = targetClass->tLeaderTime[mappedLeg].inputTime; /*int &it = targetClass->tLeaderTime[mappedLeg].inputTime;
if (inputTime > 0 && inputStatus == StatusOK && (it == 0 || inputTime < it) ) { if (inputTime > 0 && inputStatus == StatusOK && (it <= 0 || inputTime < it) ) {
it = inputTime; it = inputTime;
updated = true; updated = true;
}*/
if (inputStatus == StatusOK) {
if (targetClass->tLeaderTime[mappedLeg].update(inputTime, oClass::LeaderInfo::Type::Input))
updated = true;
} }
} }
if (targetClass && tStatus==StatusOK) { if (targetClass && tStatus==StatusOK) {
int rt = getRunningTime(false); int rt = getRunningTime(true);
pCourse pCrs = getCourse(false); pCourse pCrs = getCourse(false);
if (pCrs && rt > 0) { if (pCrs && rt > 0) {
map<int, int>::iterator res = targetClass->tBestTimePerCourse.find(pCrs->getId()); map<int, int>::iterator res = targetClass->tBestTimePerCourse.find(pCrs->getId());
@ -1847,17 +1927,16 @@ bool oRunner::storeTimesAux(pClass targetClass) {
return updated; return updated;
} }
int oRunner::getRaceRunningTime(int leg) const int oRunner::getRaceRunningTime(bool computedTime, int leg) const {
{
if (tParentRunner) if (tParentRunner)
return tParentRunner->getRaceRunningTime(leg); return tParentRunner->getRaceRunningTime(computedTime, leg);
if (leg==-1) if (leg == -1)
leg=multiRunner.size()-1; leg = multiRunner.size() - 1;
if (leg==0) { if (leg == 0) { /// XXX This code is buggy
if (getTotalStatus() == StatusOK) if (getTotalStatus() == StatusOK)
return getRunningTime(false) + inputTime; return getRunningTime(computedTime) + inputTime;
else return 0; else return 0;
} }
leg--; leg--;
@ -1870,23 +1949,24 @@ int oRunner::getRaceRunningTime(int leg) const
switch(lt) { switch(lt) {
case LTNormal: case LTNormal:
if (r->statusOK(false)) { if (r->statusOK(computedTime)) {
int dt=leg>0 ? r->getRaceRunningTime(leg)+r->getRunningTime(false):0; int dt=leg>0 ? r->getRaceRunningTime(computedTime, leg)+r->getRunningTime(computedTime):0;
return max(r->getFinishTime()-tStartTime, dt); // ### Luckor, jaktstart??? return max(r->getFinishTime()-tStartTime, dt); // ### Luckor, jaktstart???
} }
else return 0; else return 0;
break; break;
case LTSum: case LTSum:
if (r->statusOK(false)) if (r->statusOK(computedTime))
return r->getRunningTime(false)+getRaceRunningTime(leg); return r->getRunningTime(computedTime)+getRaceRunningTime(computedTime, leg);
else return 0; else return 0;
default: default:
return 0; return 0;
} }
} }
else return getRunningTime(false); else
return getRunningTime(computedTime);
} }
return 0; return 0;
} }
@ -1915,7 +1995,7 @@ bool oRunner::operator<(const oRunner &c) const {
const oClass * cClass = c.getClassRef(true); const oClass * cClass = c.getClassRef(true);
if (!myClass || !cClass) if (!myClass || !cClass)
return size_t(myClass) < size_t(cClass); return size_t(myClass) < size_t(cClass);
else if (Class == cClass && Class->getClassStatus() != oClass::Normal) else if (Class == cClass && Class->getClassStatus() != oClass::ClassStatus::Normal)
return CompareString(LOCALE_USER_DEFAULT, 0, return CompareString(LOCALE_USER_DEFAULT, 0,
tRealName.c_str(), tRealName.length(), tRealName.c_str(), tRealName.length(),
c.tRealName.c_str(), c.tRealName.length()) == CSTR_LESS_THAN; c.tRealName.c_str(), c.tRealName.length()) == CSTR_LESS_THAN;
@ -2416,14 +2496,14 @@ void oRunner::updateStartNo(int no) {
} }
} }
int oRunner::getPlace() const { int oRunner::getPlace(bool allowUpdate) const {
if (tPlace.isOld(*oe)) { if (allowUpdate && tPlace.isOld(*oe)) {
if (Class) { if (Class) {
oEvent::ResultType rt = oEvent::ResultType::ClassResult; oEvent::ResultType rt = oEvent::ResultType::ClassResult;
oe->calculateResults({ getClassId(true) }, rt, false); oe->calculateResults({ getClassId(true) }, rt, false);
} }
} }
return tPlace.value; return tPlace.get(!allowUpdate);
} }
int oRunner::getCoursePlace(bool perClass) const { int oRunner::getCoursePlace(bool perClass) const {
@ -2432,7 +2512,7 @@ int oRunner::getCoursePlace(bool perClass) const {
oEvent::ResultType rt = oEvent::ResultType::ClassCourseResult; oEvent::ResultType rt = oEvent::ResultType::ClassCourseResult;
oe->calculateResults({ getClassId(true) }, rt, false); oe->calculateResults({ getClassId(true) }, rt, false);
} }
return tCourseClassPlace.value; return tCourseClassPlace.get(false);
} }
else { else {
@ -2440,20 +2520,19 @@ int oRunner::getCoursePlace(bool perClass) const {
oEvent::ResultType rt = oEvent::ResultType::CourseResult; oEvent::ResultType rt = oEvent::ResultType::CourseResult;
oe->calculateResults({ getClassId(true) }, rt, false); oe->calculateResults({ getClassId(true) }, rt, false);
} }
return tCoursePlace.value; return tCoursePlace.get(false);
} }
} }
int oRunner::getTotalPlace() const int oRunner::getTotalPlace(bool allowUpdate) const {
{
if (tInTeam) if (tInTeam)
return tInTeam->getLegPlace(getParResultLeg(), true); return tInTeam->getLegPlace(getParResultLeg(), true, allowUpdate);
else { else {
if (tTotalPlace.isOld(*oe) && Class) { if (allowUpdate && tTotalPlace.isOld(*oe) && Class) {
oEvent::ResultType rt = oEvent::ResultType::TotalResult; oEvent::ResultType rt = oEvent::ResultType::TotalResult;
oe->calculateResults({ getClassId(true) }, rt, false); oe->calculateResults({ getClassId(true) }, rt, false);
} }
return tTotalPlace.value; return tTotalPlace.get(!allowUpdate);
} }
} }
@ -3489,7 +3568,8 @@ void oRunner::apply(ChangeType changeType, pRunner src) {
if (st == STTime) { if (st == STTime) {
pCourse crs = getCourse(false); pCourse crs = getCourse(false);
int startType = crs ? crs->getStartPunchType() : oPunch::PunchStart; int startType = crs ? crs->getStartPunchType() : oPunch::PunchStart;
if (!Card || Card->getPunchByType(startType) == 0 || !pc->hasFreeStart()) { bool hasStartPunch = Card && Card->getPunchByType(startType) != nullptr;
if (!hasStartPunch || pc->ignoreStartPunch()) {
setStartTime(pc->getStartData(tDuplicateLeg), false, changeType); setStartTime(pc->getStartData(tDuplicateLeg), false, changeType);
tUseStartPunch = false; tUseStartPunch = false;
} }
@ -3514,8 +3594,8 @@ void oRunner::apply(ChangeType changeType, pRunner src) {
int lastStart = 0; int lastStart = 0;
if (r && r->FinishTime > 0 && r->statusOK(false)) { if (r && r->FinishTime > 0 && r->statusOK(false)) {
int rt = r->getRaceRunningTime(tDuplicateLeg - 1); int rt = r->getRaceRunningTime(false, tDuplicateLeg - 1);
int timeAfter = rt - pc->getTotalLegLeaderTime(r->tDuplicateLeg, false, true); int timeAfter = rt - pc->getTotalLegLeaderTime(oClass::AllowRecompute::No, r->tDuplicateLeg, false, true);
if (rt > 0 && timeAfter >= 0) if (rt > 0 && timeAfter >= 0)
lastStart = pc->getStartData(tDuplicateLeg) + timeAfter; lastStart = pc->getStartData(tDuplicateLeg) + timeAfter;
} }
@ -4282,12 +4362,12 @@ int oRunner::getTimeAfter(int leg) const
if (!Class || Class->tLeaderTime.size()<=unsigned(leg)) if (!Class || Class->tLeaderTime.size()<=unsigned(leg))
return -1; return -1;
int t=getRaceRunningTime(leg); int t=getRaceRunningTime(true, leg);
if (t<=0) if (t<=0)
return -1; return -1;
return t-Class->getTotalLegLeaderTime(leg, true, true); return t-Class->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, leg, true, true);
} }
int oRunner::getTimeAfter() const { int oRunner::getTimeAfter() const {
@ -4305,7 +4385,7 @@ int oRunner::getTimeAfter() const {
if (t<=0) if (t<=0)
return -1; return -1;
return t - Class->getBestLegTime(leg, true); return t - Class->getBestLegTime(oClass::AllowRecompute::Yes, leg, true);
} }
int oRunner::getTimeAfterCourse() const int oRunner::getTimeAfterCourse() const
@ -4322,7 +4402,7 @@ int oRunner::getTimeAfterCourse() const
if (t<=0) if (t<=0)
return -1; return -1;
int bt = Class->getBestTimeCourse(crs->getId()); int bt = Class->getBestTimeCourse(oClass::AllowRecompute::Yes, crs->getId());
if (bt <= 0) if (bt <= 0)
return -1; return -1;
@ -5882,7 +5962,7 @@ void oRunner::setInputData(const oRunner &r) {
inputStatus = r.tInTeam->getTotalStatus(); inputStatus = r.tInTeam->getTotalStatus();
} }
inputPoints = r.getRogainingPoints(true, true); inputPoints = r.getRogainingPoints(true, true);
inputPlace = r.tTotalPlace.value; inputPlace = r.tTotalPlace.get(false);
} }
else { else {
// Copy input // Copy input
@ -6212,6 +6292,12 @@ void oAbstractRunner::setTempResultZero(const TempResult &tr) {
tmpResult = tr; tmpResult = tr;
} }
void oAbstractRunner::updateComputedResultFromTemp() {
tComputedTime = tmpResult.getRunningTime();
tComputedPoints = tmpResult.getPoints();
tComputedStatus = tmpResult.getStatus();
}
const wstring &oAbstractRunner::TempResult::getStatusS(RunnerStatus inputStatus) const { const wstring &oAbstractRunner::TempResult::getStatusS(RunnerStatus inputStatus) const {
if (inputStatus == StatusOK) if (inputStatus == StatusOK)
return oEvent::formatStatus(getStatus(), true); return oEvent::formatStatus(getStatus(), true);
@ -6618,7 +6704,7 @@ const pair<wstring, int> oRunner::getRaceInfo() {
res.first = lang.tl("Placering: ") + itow(p) + L"."; res.first = lang.tl("Placering: ") + itow(p) + L".";
} }
else { else {
if (ok && rtComp != rtActual || pointsActual != pointsComp) { if (ok) {
res.first += lang.tl("Resultat: "); res.first += lang.tl("Resultat: ");
if (compStatus != baseStatus) if (compStatus != baseStatus)
res.first = oe->formatStatus(compStatus, true) + L", "; res.first = oe->formatStatus(compStatus, true) + L", ";

View File

@ -272,6 +272,9 @@ public:
void setTempResultZero(const TempResult &tr); void setTempResultZero(const TempResult &tr);
/** Set the class computed result from tmp result.*/
void updateComputedResultFromTemp();
// Time // Time
void setInputTime(const wstring &time); void setInputTime(const wstring &time);
wstring getInputTimeS() const; wstring getInputTimeS() const;
@ -378,14 +381,17 @@ public:
virtual int getPrelRunningTime() const; virtual int getPrelRunningTime() const;
virtual const pair<wstring, int> getRaceInfo() = 0;
wstring getPlaceS() const; wstring getPlaceS() const;
wstring getPrintPlaceS(bool withDot) const; wstring getPrintPlaceS(bool withDot) const;
wstring getTotalPlaceS() const; wstring getTotalPlaceS() const;
wstring getPrintTotalPlaceS(bool withDot) const; wstring getPrintTotalPlaceS(bool withDot) const;
virtual int getPlace() const = 0; virtual int getPlace(bool allowUpdate = true) const = 0;
virtual int getTotalPlace() const = 0; virtual int getTotalPlace(bool allowUpdate = true) const = 0;
RunnerStatus getStatusComputed() const { return tComputedStatus != StatusUnknown ? tComputedStatus : tStatus; } RunnerStatus getStatusComputed() const { return tComputedStatus != StatusUnknown ? tComputedStatus : tStatus; }
virtual RunnerStatus getStatus() const { return tStatus;} virtual RunnerStatus getStatus() const { return tStatus;}
@ -444,10 +450,16 @@ public:
virtual ~oAbstractRunner() {}; virtual ~oAbstractRunner() {};
struct DynamicValue { struct DynamicValue {
int dataRevision; private:
int value; int dataRevision = -1;
int value = -1;
int valueStd = -1; // Value without result module
public:
void reset();
bool isOld(const oEvent &oe) const; bool isOld(const oEvent &oe) const;
void update(const oEvent &oe, int v); DynamicValue &update(const oEvent &oe, int v, bool setStd);
void invalidate(bool invalid) { if (invalid) dataRevision = -1; }
int get(bool preferStd) const;
}; };
friend class oListInfo; friend class oListInfo;
@ -741,7 +753,7 @@ public:
int getTotalRunningTime() const override; int getTotalRunningTime() const override;
//Get total running time after leg //Get total running time after leg
int getRaceRunningTime(int leg) const; int getRaceRunningTime(bool computedTime, int leg) const;
// Get the complete name, including team and club. // Get the complete name, including team and club.
wstring getCompleteIdentification(bool includeExtra = true) const; wstring getCompleteIdentification(bool includeExtra = true) const;
@ -758,7 +770,7 @@ public:
int getRogainingOvertime(bool computed) const override; int getRogainingOvertime(bool computed) const override;
const wstring &getProblemDescription() const {return tProblemDescription;} const wstring &getProblemDescription() const {return tProblemDescription;}
const pair<wstring, int> getRaceInfo(); const pair<wstring, int> getRaceInfo() override;
// Leg statistics access methods // Leg statistics access methods
wstring getMissedTimeS() const; wstring getMissedTimeS() const;
wstring getMissedTimeS(int ctrlNo) const; wstring getMissedTimeS(int ctrlNo) const;
@ -842,9 +854,9 @@ public:
oSpeakerObject &spk) const; oSpeakerObject &spk) const;
bool needNoCard() const; bool needNoCard() const;
int getPlace() const; int getPlace(bool allowUpdate = true) const override;
int getCoursePlace(bool perClass) const; int getCoursePlace(bool perClass) const;
int getTotalPlace() const; int getTotalPlace(bool allowUpdate = true) const override;
// Normalized = true means permuted to the unlooped version of the course // Normalized = true means permuted to the unlooped version of the course
const vector<SplitData> &getSplitTimes(bool normalized) const; const vector<SplitData> &getSplitTimes(bool normalized) const;

View File

@ -444,6 +444,7 @@ int oTeam::getRunningTime(bool computedTime) const {
int oTeam::getLegRunningTime(int leg, bool computedTime, bool multidayTotal) const { int oTeam::getLegRunningTime(int leg, bool computedTime, bool multidayTotal) const {
if (computedTime) { if (computedTime) {
leg = getLegToUse(leg);
auto &cr = getComputedResult(leg); auto &cr = getComputedResult(leg);
int addon = 0; int addon = 0;
@ -458,10 +459,10 @@ int oTeam::getLegRunningTime(int leg, bool computedTime, bool multidayTotal) con
} }
} }
return getLegRunningTimeUnadjusted(leg, multidayTotal) + getTimeAdjustment(); return getLegRunningTimeUnadjusted(leg, multidayTotal, false) + getTimeAdjustment();
} }
int oTeam::getLegRestingTime(int leg) const { int oTeam::getLegRestingTime(int leg, bool useComputedRunnerTime) const {
if (!Class) if (!Class)
return 0; return 0;
@ -471,7 +472,7 @@ int oTeam::getLegRestingTime(int leg) const {
if (Class->getStartType(k) == STHunting && !Class->isParallel(k) && if (Class->getStartType(k) == STHunting && !Class->isParallel(k) &&
Runners[k] && Runners[k-1]) { Runners[k] && Runners[k-1]) {
int ft = getLegRunningTimeUnadjusted(k-1, false) + tStartTime; int ft = getLegRunningTimeUnadjusted(k-1, false, useComputedRunnerTime) + tStartTime;
int st = Runners[k]->getStartTime(); int st = Runners[k]->getStartTime();
if (ft > 0 && st > 0) if (ft > 0 && st > 0)
@ -482,7 +483,7 @@ int oTeam::getLegRestingTime(int leg) const {
} }
int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const { int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal, bool useComputedRunnerTime) const {
leg = getLegToUse(leg); leg = getLegToUse(leg);
int addon = 0; int addon = 0;
@ -500,18 +501,19 @@ int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const {
switch(lt) { switch(lt) {
case LTNormal: case LTNormal:
if (Runners[leg]->prelStatusOK(false, true)) { if (Runners[leg]->prelStatusOK(useComputedRunnerTime, true)) {
int dt = leg>0 ? getLegRunningTimeUnadjusted(leg-1, false)+Runners[leg]->getRunningTime(false):0; int dt = leg>0 ? getLegRunningTimeUnadjusted(leg-1, false, useComputedRunnerTime)+Runners[leg]->getRunningTime(useComputedRunnerTime):0;
return addon + max(Runners[leg]->getFinishTimeAdjusted()-(tStartTime + getLegRestingTime(leg)), dt); return addon + max(Runners[leg]->getFinishTimeAdjusted() -
(tStartTime + getLegRestingTime(leg, useComputedRunnerTime)), dt);
} }
else return 0; else return 0;
break; break;
case LTParallelOptional: case LTParallelOptional:
case LTParallel: //Take the longest time of this runner and the previous case LTParallel: //Take the longest time of this runner and the previous
if (Runners[leg]->prelStatusOK(false, false)) { if (Runners[leg]->prelStatusOK(useComputedRunnerTime, false)) {
int pt=leg>0 ? getLegRunningTimeUnadjusted(leg-1, false) : 0; int pt=leg>0 ? getLegRunningTimeUnadjusted(leg-1, false, useComputedRunnerTime) : 0;
int rest = getLegRestingTime(leg); int rest = getLegRestingTime(leg, useComputedRunnerTime);
int finishT = Runners[leg]->getFinishTimeAdjusted(); int finishT = Runners[leg]->getFinishTimeAdjusted();
return addon + max(finishT-(tStartTime + rest), pt); return addon + max(finishT-(tStartTime + rest), pt);
} }
@ -527,7 +529,7 @@ int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const {
baseLeg--; baseLeg--;
int baseTime = 0; int baseTime = 0;
if (baseLeg > 0) if (baseLeg > 0)
baseTime = getLegRunningTimeUnadjusted(baseLeg-1, multidayTotal); baseTime = getLegRunningTimeUnadjusted(baseLeg-1, multidayTotal, useComputedRunnerTime);
else else
baseTime = addon; baseTime = addon;
@ -536,9 +538,9 @@ int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const {
bool bad = false; bool bad = false;
do { do {
if (Runners[cLeg] && Runners[cLeg]->getFinishTime() > 0) { if (Runners[cLeg] && Runners[cLeg]->getFinishTime() > 0) {
int rt = Runners[cLeg]->getRunningTime(false); int rt = Runners[cLeg]->getRunningTime(useComputedRunnerTime);
if (legTime == 0 || rt < legTime) { if (legTime == 0 || rt < legTime) {
bad = !Runners[cLeg]->prelStatusOK(false, false); bad = !Runners[cLeg]->prelStatusOK(useComputedRunnerTime, false);
legTime = rt; legTime = rt;
} }
} }
@ -554,15 +556,15 @@ int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const {
break; break;
case LTSum: case LTSum:
if (Runners[leg]->prelStatusOK(false, false)) { if (Runners[leg]->prelStatusOK(useComputedRunnerTime, false)) {
if (leg==0) if (leg==0)
return addon + Runners[leg]->getRunningTime(false); return addon + Runners[leg]->getRunningTime(useComputedRunnerTime);
else { else {
int prev = getLegRunningTimeUnadjusted(leg-1, multidayTotal); int prev = getLegRunningTimeUnadjusted(leg-1, multidayTotal, useComputedRunnerTime);
if (prev == 0) if (prev == 0)
return 0; return 0;
else else
return Runners[leg]->getRunningTime(false) + prev; return Runners[leg]->getRunningTime(useComputedRunnerTime) + prev;
} }
} }
else return 0; else return 0;
@ -571,7 +573,7 @@ int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const {
if (leg==0) if (leg==0)
return 0; return 0;
else else
return getLegRunningTimeUnadjusted(leg-1, multidayTotal); return getLegRunningTimeUnadjusted(leg-1, multidayTotal, useComputedRunnerTime);
break; break;
@ -579,9 +581,9 @@ int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const {
if (Class->getResultModuleTag().empty()) if (Class->getResultModuleTag().empty())
return 0; return 0;
else { else {
int dt = Runners[leg]->getRunningTime(false); int dt = Runners[leg]->getRunningTime(useComputedRunnerTime);
if (leg > 0) if (leg > 0)
dt += getLegRunningTimeUnadjusted(leg - 1, multidayTotal); dt += getLegRunningTimeUnadjusted(leg - 1, multidayTotal, useComputedRunnerTime);
return dt; return dt;
} }
} }
@ -590,8 +592,9 @@ int oTeam::getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const {
int dt=addon + max(Runners[leg]->getFinishTime()-tStartTime, 0); int dt=addon + max(Runners[leg]->getFinishTime()-tStartTime, 0);
int dt2=0; int dt2=0;
if (leg>0) if (leg > 0)
dt2=getLegRunningTimeUnadjusted(leg-1, multidayTotal)+Runners[leg]->getRunningTime(false); dt2 = getLegRunningTimeUnadjusted(leg - 1, multidayTotal, useComputedRunnerTime) +
Runners[leg]->getRunningTime(useComputedRunnerTime);
return max(dt, dt2); return max(dt, dt2);
} }
@ -688,12 +691,72 @@ RunnerStatus oTeam::getLegStatus(int leg, bool computed, bool multidayTotal) con
return RunnerStatus(s); return RunnerStatus(s);
} }
RunnerStatus oTeam::deduceComputedStatus() const {
int leg = Runners.size() - 1;
leg = getLegToUse(leg); // Ignore optional runners
int s = 0;
if (!Class)
return StatusUnknown;
while (leg>0 && Class->getLegType(leg) == LTIgnore)
leg--;
for (int i = 0; i <= leg; i++) {
// Ignore runners to be ignored
while (i<leg && Class->getLegType(i) == LTIgnore)
i++;
int st = Runners[i] ? Runners[i]->getStatusComputed() : StatusDNS;
int bestTime = Runners[i] ? Runners[i]->getFinishTime() : 0;
//When Type Extra is used, the runner with the best time
//is used for change. Then the status of this runner
//should be carried forward.
if (Class) while ((i + 1) < int(Runners.size()) && Class->getLegType(i + 1) == LTExtra) {
i++;
if (Runners[i]) {
if (bestTime == 0 || (Runners[i]->getFinishTime()>0 &&
Runners[i]->getFinishTime()<bestTime)) {
st = Runners[i]->getStatusComputed();
bestTime = Runners[i]->getFinishTime();
}
}
}
if (st == 0)
return RunnerStatus(s == StatusOK ? 0 : s);
s = max(s, st);
}
// Allow global status DNS
if (s == StatusUnknown && tStatus == StatusDNS)
return tStatus;
return RunnerStatus(s);
}
int oTeam::deduceComputedRunningTime() const {
return getLegRunningTimeUnadjusted(Runners.size() - 1, false, true) + getTimeAdjustment();
}
int oTeam::deduceComputedPoints() const {
int pt = 0;
for (size_t k = 0; k < Runners.size(); k++) {
if (Runners[k])
pt += Runners[k]->getRogainingPoints(true, false);
}
pt = max(0, pt + getPointAdjustment());
return pt;
}
const wstring &oTeam::getLegStatusS(int leg, bool computed, bool multidayTotal) const const wstring &oTeam::getLegStatusS(int leg, bool computed, bool multidayTotal) const
{ {
return oe->formatStatus(getLegStatus(leg, computed, multidayTotal), true); return oe->formatStatus(getLegStatus(leg, computed, multidayTotal), true);
} }
int oTeam::getLegPlace(int leg, bool multidayTotal) const { int oTeam::getLegPlace(int leg, bool multidayTotal, bool allowUpdate) const {
if (leg == -1) if (leg == -1)
leg = Runners.size() - 1; leg = Runners.size() - 1;
@ -703,16 +766,16 @@ int oTeam::getLegPlace(int leg, bool multidayTotal) const {
} }
auto &p = getTeamPlace(leg); auto &p = getTeamPlace(leg);
if (!multidayTotal) { if (!multidayTotal) {
if (Class && p.p.isOld(*oe)) { if (Class && allowUpdate && p.p.isOld(*oe)) {
oe->calculateTeamResults({getClassId(true)}, oEvent::ResultType::ClassResult); oe->calculateTeamResults({getClassId(true)}, oEvent::ResultType::ClassResult);
} }
return p.p.value; return p.p.get(!allowUpdate);
} }
else { else {
if (Class && p.totalP.isOld(*oe)) { if (Class && allowUpdate && p.totalP.isOld(*oe)) {
oe->calculateTeamResults({ getClassId(true) }, oEvent::ResultType::TotalResult); oe->calculateTeamResults({ getClassId(true) }, oEvent::ResultType::TotalResult);
} }
return p.totalP.value; return p.totalP.get(!allowUpdate);
} }
} }
@ -1146,11 +1209,11 @@ void oTeam::apply(ChangeType changeType, pRunner source) {
bool setStart = false; bool setStart = false;
if (i>0 && Runners[i-1]) { if (i>0 && Runners[i-1]) {
if (lt == LTNormal || lt == LTSum || availableStartTimes.empty()) { if (lt == LTNormal || lt == LTSum || availableStartTimes.empty()) {
int rt = getLegRunningTimeUnadjusted(i-1, false); int rt = getLegRunningTimeUnadjusted(i-1, false, false);
if (rt>0) if (rt>0)
setStart = true; setStart = true;
int leaderTime = pc->getTotalLegLeaderTime(i-1, false, false); int leaderTime = pc->getTotalLegLeaderTime(oClass::AllowRecompute::No, i-1, false, false);
int timeAfter = leaderTime > 0 ? rt - leaderTime : 0; int timeAfter = leaderTime > 0 ? rt - leaderTime : 0;
if (rt>0 && timeAfter>=0) if (rt>0 && timeAfter>=0)
@ -1587,7 +1650,7 @@ int oTeam::getTimeAfter(int leg) const {
if (t<=0) if (t<=0)
return -1; return -1;
return t-Class->getTotalLegLeaderTime(leg, true, false); return t-Class->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, leg, true, false);
} }
int oTeam::getLegStartTime(int leg) const int oTeam::getLegStartTime(int leg) const
@ -1786,7 +1849,7 @@ void oTeam::setInputData(const oTeam &t) {
inputTime = t.getTotalRunningTime(); inputTime = t.getTotalRunningTime();
inputStatus = t.getTotalStatus(); inputStatus = t.getTotalStatus();
inputPoints = t.getRogainingPoints(true, true); inputPoints = t.getRogainingPoints(true, true);
int tp = t.getTotalPlace(); int tp = t.getTotalPlace(true);
inputPlace = tp; inputPlace = tp;
oDataInterface dest = getDI(); oDataInterface dest = getDI();
@ -2391,8 +2454,72 @@ oTeam::TeamPlace &oTeam::getTeamPlace(int leg) const {
bool oTeam::isResultUpdated(bool totalResult) const { bool oTeam::isResultUpdated(bool totalResult) const {
auto &p = getTeamPlace(Runners.size() - 1); auto &p = getTeamPlace(Runners.size() - 1);
if (totalResult) if (!totalResult)
return !p.p.isOld(*oe); return !p.p.isOld(*oe);
else else
return !p.totalP.isOld(*oe); return !p.totalP.isOld(*oe);
} }
const pair<wstring, int> oTeam::getRaceInfo() {
pair<wstring, int> res;
RunnerStatus baseStatus = getStatus();
int rtActual = getRunningTime(false);
if (isResultStatus(baseStatus) || (isPossibleResultStatus(baseStatus) && rtActual>0)) {
int p = getPlace(true);
int rtComp = getRunningTime(true);
int pointsActual = getRogainingPoints(false, false);
int pointsComp = getRogainingPoints(true, false);
RunnerStatus compStatus = getStatusComputed();
bool ok = compStatus == StatusOK || compStatus == StatusOutOfCompetition
|| compStatus == StatusNoTiming;
res.second = ok ? 1 : -1;
if (compStatus == baseStatus && rtComp == rtActual && pointsComp == pointsActual) {
if (ok && p > 0)
res.first = lang.tl("Placering: ") + itow(p) + L".";
}
else {
if (ok) {
res.first += lang.tl("Resultat: ");
if (compStatus != baseStatus)
res.first = oe->formatStatus(compStatus, true) + L", ";
if (pointsActual != pointsComp)
res.first += itow(pointsComp) + L", ";
res.first += formatTime(rtComp);
if (p > 0)
res.first += L" (" + itow(p) + L")";
}
else if (!ok && compStatus != baseStatus) {
res.first = lang.tl("Resultat: ") + oe->formatStatus(compStatus, true);
}
/*
if (ok && getRogainingReduction(true) > 0) {
tProblemDescription = L"Tidsavdrag: X poäng.#" + itow(getRogainingReduction(true));
}
if (!getProblemDescription().empty()) {
if (!res.first.empty()) {
if (res.first.back() != ')')
res.first += L", ";
else
res.first += L" ";
}
res.first += lang.tl(getProblemDescription());
}*/
}
}
else {
vector<oFreePunch*> pl;
oe->synchronizeList(oListId::oLPunchId);
oe->getPunchesForRunner(Id, true, pl);
if (!pl.empty()) {
res.first = lang.tl(L"Senast sedd: X vid Y.#" +
oe->getAbsTime(pl.back()->Time) +
L"#" + pl.back()->getType());
}
}
return res;
}

View File

@ -44,9 +44,9 @@ public:
}; };
private: private:
int getLegRunningTimeUnadjusted(int leg, bool multidayTotal) const; int getLegRunningTimeUnadjusted(int leg, bool multidayTotal, bool useComputedRunnerTime) const;
/** Return the total time the team has been resting (pursuit start etc.) up to the specified leg */ /** Return the total time the team has been resting (pursuit start etc.) up to the specified leg */
int getLegRestingTime(int leg) const; int getLegRestingTime(int leg, bool useComputedRunnerTime) const;
void speakerLegInfo(int leg, int specifiedLeg, int courseControlId, void speakerLegInfo(int leg, int specifiedLeg, int courseControlId,
int &missingLeg, int &totalLeg, int &missingLeg, int &totalLeg,
@ -138,6 +138,13 @@ protected:
public: public:
/** Deduce from computed runner times.*/
RunnerStatus deduceComputedStatus() const;
int deduceComputedRunningTime() const;
int deduceComputedPoints() const;
const pair<wstring, int> getRaceInfo() override;
static const shared_ptr<Table> &getTable(oEvent *oe); static const shared_ptr<Table> &getTable(oEvent *oe);
/** Check the the main leg is set if any parallel is set. Returns true if corrections where made.*/ /** Check the the main leg is set if any parallel is set. Returns true if corrections where made.*/
@ -224,8 +231,8 @@ public:
void importRunners(const vector<int> &rns); void importRunners(const vector<int> &rns);
void importRunners(const vector<pRunner> &rns); void importRunners(const vector<pRunner> &rns);
int getPlace() const {return getLegPlace(-1, false);} int getPlace(bool allowUpdate = true) const override {return getLegPlace(-1, false, allowUpdate);}
int getTotalPlace() const {return getLegPlace(-1, true);} int getTotalPlace(bool allowUpdate = true) const override {return getLegPlace(-1, true, allowUpdate);}
int getNumShortening() const; int getNumShortening() const;
// Number of shortenings up to and including a leg // Number of shortenings up to and including a leg
@ -255,7 +262,7 @@ public:
wstring getLegPlaceS(int leg, bool multidayTotal) const; wstring getLegPlaceS(int leg, bool multidayTotal) const;
wstring getLegPrintPlaceS(int leg, bool multidayTotal, bool withDot) const; wstring getLegPrintPlaceS(int leg, bool multidayTotal, bool withDot) const;
int getLegPlace(int leg, bool multidayTotal) const; int getLegPlace(int leg, bool multidayTotal, bool allowUpdate = true) const;
bool isResultUpdated(bool totalResult) const override; bool isResultUpdated(bool totalResult) const override;

View File

@ -2473,7 +2473,7 @@ Result module = Resultatmodul
ask:usecourseinclass = Banan används inte av någon annan deltagare i klassen.\n\nVill du använda den i alla fall? ask:usecourseinclass = Banan används inte av någon annan deltagare i klassen.\n\nVill du använda den i alla fall?
Inkludera bana = Inkludera bana Inkludera bana = Inkludera bana
Rogaining points before automatic reduction = Poäng före tidsavdrag Rogaining points before automatic reduction = Poäng före tidsavdrag
Runner/team earlier stage places = Deltagare/lag: plarcering på etapper Runner/team earlier stage places = Deltagare/lag: placering på etapper
Runner/team earlier stage points = Deltagare/lag: poäng på etapper Runner/team earlier stage points = Deltagare/lag: poäng på etapper
Runner/team earlier stage running times = Deltagare/lag: tid på etapper Runner/team earlier stage running times = Deltagare/lag: tid på etapper
Runner/team earlier stage statuses = Deltagare/lag: status på etapper Runner/team earlier stage statuses = Deltagare/lag: status på etapper
@ -2500,3 +2500,4 @@ Först = Först
Lottat = Lottat Lottat = Lottat
Sist = Sist Sist = Sist
Fakturadatum = Fakturadatum Fakturadatum = Fakturadatum
Youth Cup X = Ungdomscup X