diff --git a/code/HTMLWriter.cpp b/code/HTMLWriter.cpp
index 02338e1..db326a1 100644
--- a/code/HTMLWriter.cpp
+++ b/code/HTMLWriter.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/HTMLWriter.h b/code/HTMLWriter.h
index e85ffdd..eaecad5 100644
--- a/code/HTMLWriter.h
+++ b/code/HTMLWriter.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/MeOSFeatures.cpp b/code/MeOSFeatures.cpp
index 47b0747..9a5d4f1 100644
--- a/code/MeOSFeatures.cpp
+++ b/code/MeOSFeatures.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/MeOSFeatures.h b/code/MeOSFeatures.h
index 9f92607..fa52890 100644
--- a/code/MeOSFeatures.h
+++ b/code/MeOSFeatures.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/Printer.h b/code/Printer.h
index 896e768..a52d506 100644
--- a/code/Printer.h
+++ b/code/Printer.h
@@ -4,7 +4,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/RestService.cpp b/code/RestService.cpp
index c776932..80dd277 100644
--- a/code/RestService.cpp
+++ b/code/RestService.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/RestService.h b/code/RestService.h
index af987f2..6f6d6c7 100644
--- a/code/RestService.h
+++ b/code/RestService.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
-Copyright (C) 2009-2019 Melin Software HB
+Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/RunnerDB.cpp b/code/RunnerDB.cpp
index 6e3890b..224318f 100644
--- a/code/RunnerDB.cpp
+++ b/code/RunnerDB.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1194,19 +1194,13 @@ void RunnerDB::refreshTables() {
}
void RunnerDB::releaseTables() {
- if (runnerTable)
- runnerTable->releaseOwnership();
- runnerTable = 0;
-
- if (clubTable)
- clubTable->releaseOwnership();
- clubTable = 0;
+ runnerTable.reset();
+ clubTable.reset();
}
-Table *RunnerDB::getRunnerTB()//Table mode
-{
- if (runnerTable == 0) {
- Table *table=new Table(oe, 20, L"Löpardatabasen", "runnerdb");
+const shared_ptr
&RunnerDB::getRunnerTB() {
+ if (!runnerTable) {
+ auto table = make_shared(oe, 20, L"Löpardatabasen", "runnerdb");
table->addColumn("Index", 70, true, true);
table->addColumn("Id", 70, true, true);
@@ -1220,7 +1214,6 @@ Table *RunnerDB::getRunnerTB()//Table mode
table->setTableProp(Table::CAN_INSERT|Table::CAN_DELETE|Table::CAN_PASTE);
table->setClearOnHide(false);
- table->addOwnership();
runnerTable = table;
}
int nr = 0;
@@ -1284,18 +1277,17 @@ void RunnerDB::refreshRunnerTableData(Table &table) {
}
}
-Table *RunnerDB::getClubTB()//Table mode
-{
+const shared_ptr &RunnerDB::getClubTB() {
bool canEdit = !oe->isClient();
- if (clubTable == 0) {
- Table *table = new Table(oe, 20, L"Klubbdatabasen", "clubdb");
+ if (!clubTable) {
+ auto table = make_shared(oe, 20, L"Klubbdatabasen", "clubdb");
table->addColumn("Id", 70, true, true);
table->addColumn("Ändrad", 70, false);
table->addColumn("Namn", 200, false);
- oClub::buildTableCol(oe, table);
+ oClub::buildTableCol(oe, table.get());
if (canEdit)
table->setTableProp(Table::CAN_DELETE|Table::CAN_INSERT|Table::CAN_PASTE);
@@ -1303,7 +1295,6 @@ Table *RunnerDB::getClubTB()//Table mode
table->setTableProp(0);
table->setClearOnHide(false);
- table->addOwnership();
clubTable = table;
}
@@ -1318,7 +1309,6 @@ Table *RunnerDB::getClubTB()//Table mode
return clubTable;
}
-
void oDBRunnerEntry::addTableRow(Table &table) const {
bool canEdit = !oe->isClient();
@@ -1377,8 +1367,8 @@ const RunnerDBEntry &oDBRunnerEntry::getRunner() const {
return db->rdb[index];
}
-bool oDBRunnerEntry::inputData(int id, const wstring &input,
- int inputId, wstring &output, bool noUpdate)
+pair oDBRunnerEntry::inputData(int id, const wstring &input,
+ int inputId, wstring &output, bool noUpdate)
{
if (!db)
throw meosException("Not initialized");
@@ -1392,7 +1382,7 @@ bool oDBRunnerEntry::inputData(int id, const wstring &input,
db->nhash.clear();
db->runnerHash.clear();
db->runnerHashByClub.clear();
- return true;
+ break;
case TID_CARD:
db->rhash.remove(rd.cardNo);
rd.cardNo = _wtoi(input.c_str());
@@ -1401,7 +1391,7 @@ bool oDBRunnerEntry::inputData(int id, const wstring &input,
output = itow(rd.cardNo);
else
output = L"";
- return true;
+ break;
case TID_NATIONAL:
if (input.empty()) {
rd.national[0] = 0;
@@ -1429,7 +1419,7 @@ bool oDBRunnerEntry::inputData(int id, const wstring &input,
output = input;
break;
}
- return false;
+ return make_pair(0, false);
}
void oDBRunnerEntry::fillInput(int id, vector< pair > &out, size_t &selected)
diff --git a/code/RunnerDB.h b/code/RunnerDB.h
index c6fcc4a..ec6d8bd 100644
--- a/code/RunnerDB.h
+++ b/code/RunnerDB.h
@@ -11,7 +11,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -161,8 +161,8 @@ class RunnerDB {
private:
oEvent *oe;
- Table *runnerTable;
- Table *clubTable;
+ shared_ptr runnerTable;
+ shared_ptr clubTable;
static int cellEntryIndex;
@@ -286,8 +286,8 @@ public:
void refreshClubTableData(Table &table);
void refreshTables();
- Table *getRunnerTB();
- Table *getClubTB();
+ const shared_ptr &getRunnerTB();
+ const shared_ptr &getClubTB();
void hasEnteredCompetition(__int64 extId);
@@ -368,9 +368,9 @@ public:
const RunnerDBEntry &getRunner() const;
void addTableRow(Table &table) const;
- bool inputData(int id, const wstring &input,
- int inputId, wstring &output, bool noUpdate);
- void fillInput(int id, vector< pair > &out, size_t &selected);
+ pair inputData(int id, const wstring &input,
+ int inputId, wstring &output, bool noUpdate) override;
+ void fillInput(int id, vector< pair > &out, size_t &selected) override;
oDBRunnerEntry(oEvent *oe);
virtual ~oDBRunnerEntry();
diff --git a/code/SportIdent.cpp b/code/SportIdent.cpp
index 0e31efc..20d4d3c 100644
--- a/code/SportIdent.cpp
+++ b/code/SportIdent.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/SportIdent.h b/code/SportIdent.h
index fd0369d..2ec6571 100644
--- a/code/SportIdent.h
+++ b/code/SportIdent.h
@@ -13,7 +13,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabAuto.cpp b/code/TabAuto.cpp
index 508f56f..c276fe3 100644
--- a/code/TabAuto.cpp
+++ b/code/TabAuto.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -291,7 +291,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.setInputStatus("ExportScript", stat);
gdi.setInputStatus("BrowseFile", stat);
gdi.setInputStatus("BrowseScript", stat);
- if (gdi.hasField("HTMLRefresh")) {
+ if (gdi.hasWidget("HTMLRefresh")) {
gdi.setInputStatus("HTMLRefresh", stat);
gdi.setInputStatus("StructuredExport", stat);
}
diff --git a/code/TabAuto.h b/code/TabAuto.h
index d6098bd..71c968e 100644
--- a/code/TabAuto.h
+++ b/code/TabAuto.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabBase.cpp b/code/TabBase.cpp
index 0ae479a..a5d376e 100644
--- a/code/TabBase.cpp
+++ b/code/TabBase.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabBase.h b/code/TabBase.h
index 887ddcf..8dce07c 100644
--- a/code/TabBase.h
+++ b/code/TabBase.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabClass.cpp b/code/TabClass.cpp
index 0243516..2f40c2b 100644
--- a/code/TabClass.cpp
+++ b/code/TabClass.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
#include
#include "oEvent.h"
+#include "metalist.h"
#include "xmlparser.h"
#include "gdioutput.h"
#include "csvparser.h"
@@ -37,12 +38,15 @@
#include "meos_util.h"
#include "oListInfo.h"
#include "TabClass.h"
+#include "TabList.h"
+#include "methodeditor.h"
#include "ClassConfigInfo.h"
#include "meosException.h"
#include "gdifonts.h"
#include "oEventDraw.h"
#include "MeOSFeatures.h"
#include "qualification_final.h"
+#include "generalresult.h"
extern pEvent gEvent;
const char *visualDrawWindow = "visualdraw";
@@ -70,6 +74,7 @@ TabClass::TabClass(oEvent *poe):TabBase(poe)
}
void TabClass::clearCompetitionData() {
+ currentResultModuleTags.clear();
pSettings.clear();
pSavedDepth = 3600;
pFirstRestart = 3600;
@@ -460,15 +465,15 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
save(gdi, false); //Clears and reloads
- if (gdi.hasField("Courses")) {
+ if (gdi.hasWidget("Courses")) {
gdi.selectItemByData("Courses", -2);
gdi.disableInput("Courses");
}
oe->setupRelay(*pc, newType, nstages, st);
- if (gdi.hasField("MAdd")) {
+ if (gdi.hasWidget("MAdd")) {
for (const char *s : {"MCourses", "StageCourses", "MAdd", "MRemove", "MUp", "MDown"}) {
- if (gdi.hasField(s)) {
+ if (gdi.hasWidget(s)) {
gdi.enableInput(s);
}
}
@@ -481,7 +486,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
pc->synchronize();
gdi.restore();
gdi.enableInput("MultiCourse", true);
- if (gdi.hasField("Courses"))
+ if (gdi.hasWidget("Courses"))
gdi.enableInput("Courses");
oe->adjustTeamMultiRunners(pc);
}
@@ -705,6 +710,18 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
tableMode=!tableMode;
loadPage(gdi);
}
+ else if (bi.id == "EditModule") {
+ save(gdi, true);
+
+ size_t ix = gdi.getSelectedItem("Module").first;
+ if (ix < currentResultModuleTags.size()) {
+ TabList &tc = dynamic_cast(*gdi.getTabs().get(TListTab));
+ tc.getMethodEditor().show(this, gdi);
+ const string &mtag = currentResultModuleTags[ix];
+ tc.getMethodEditor().load(gdi, mtag, false);
+ gdi.refresh();
+ }
+ }
else if (bi.id=="Restart") {
save(gdi, true);
clearPage(gdi, true);
@@ -842,56 +859,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
}
DrawSettingsCSV::write(gdi, *oe, fn, res);
-
- /*csvparser writer;
- writer.openOutput(fn.c_str());
- vector header;
-
- writer.outputRow(header);
- header.emplace_back("ClassId");
- header.emplace_back("Class");
- header.emplace_back("Competitors");
- header.emplace_back("Course");
- header.emplace_back("First Control");
-
- header.emplace_back("First Start");
- header.emplace_back("Interval");
- header.emplace_back("Vacant");
-
- writer.outputRow(header);
- vector line;
-
- for (size_t k = 0; kgetId()));
- line.push_back(gdi.toUTF8(ci.pc->getName()));
- line.push_back(itos(ci.pc->getNumRunners(1, false, false)));
- pCourse crs = ci.pc->getCourse();
- pControl ctrl = nullptr;
- if (crs) {
- line.push_back(gdi.toUTF8(crs->getName()));
- ctrl = crs->getControl(0);
- }
- else line.emplace_back("");
-
- if (ctrl) {
- line.push_back(itos(ctrl->getId()));
- }
- else line.emplace_back("");
-
- // Save settings with class
-
- line.push_back(gdi.narrow(oe->getAbsTime(drawInfo.firstStart + drawInfo.baseInterval * ci.firstStart)));
- line.push_back(gdi.narrow(formatTime(ci.interval * drawInfo.baseInterval)));
- line.push_back(itos(ci.nVacant));
- writer.outputRow(line);
- }
- }*/
}
else if (bi.id == "ImportDrawSettings") {
-
wstring fn = gdi.browseForOpen({ make_pair(lang.tl("Kalkylblad/csv"), L"*.csv") }, L"csv");
if (fn.empty())
@@ -1030,7 +999,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
prepareForDrawing(gdi);
}
else if (bi.id == "DrawMode") {
- if (gdi.hasField("Name"))
+ if (gdi.hasWidget("Name"))
save(gdi, false);
ClassId = 0;
@@ -1120,7 +1089,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oListParam par;
for (int k = 0; k < oe->getNumClasses(); k++) {
- if (!gdi.hasField("PLUse" + itos(k)))
+ if (!gdi.hasWidget("PLUse" + itos(k)))
continue;
BaseInfo *biu = gdi.setText("PLUse" + itos(k), L"", false);
if (biu) {
@@ -1188,7 +1157,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oe->setProperty("DrawInterlace", allowNeighbourSameCourse ? 1 : 0);
int pairSize = 1;
- if (gdi.hasField("PairSize")) {
+ if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
@@ -1269,7 +1238,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
wstring firstStart = oe->getAbsTime(3600);
wstring minInterval = L"2:00";
wstring vacances = getDefaultVacant();
- if (gdi.hasField("Vacances")) {
+ if (gdi.hasWidget("Vacances")) {
vacances = gdi.getText("Vacances");
setDefaultVacant(vacances);
}
@@ -1277,7 +1246,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
int maxNumControl = 1;
int pairSize = 1;
- if (gdi.hasField("AllowNeighbours")) {
+ if (gdi.hasWidget("AllowNeighbours")) {
bool allowNeighbourSameCourse = gdi.isChecked("AllowNeighbours");
oe->setProperty("DrawInterlace", allowNeighbourSameCourse ? 1 : 0);
}
@@ -1296,7 +1265,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
minInterval = gdi.getText("MinInterval");
vacances = gdi.getText("Vacances");
//pairwise = gdi.isChecked("Pairwise");
- if (gdi.hasField("PairSize")) {
+ if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
}
@@ -1480,15 +1449,15 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oEvent::DrawMethod method = oEvent::DrawMethod(gdi.getSelectedItem("Method").first);
int interval = 0;
- if (gdi.hasField("Interval"))
+ if (gdi.hasWidget("Interval"))
interval = convertAbsoluteTimeMS(gdi.getText("Interval"));
int vacanses = 0;
- if (gdi.hasField("Vacanses"))
+ if (gdi.hasWidget("Vacanses"))
vacanses = gdi.getTextNo("Vacanses");
int leg = 0;
- if (gdi.hasField("Leg")) {
+ if (gdi.hasWidget("Leg")) {
leg = gdi.getSelectedItem("Leg").first;
}
else if (pc && pc->getParentClass() != 0)
@@ -1497,7 +1466,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
wstring bib;
bool doBibs = false;
- if (gdi.hasField("Bib")) {
+ if (gdi.hasWidget("Bib")) {
bib = gdi.getText("Bib");
doBibs = gdi.isChecked("HandleBibs");
}
@@ -1520,23 +1489,23 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
}
//bool pairwise = false;
-// if (gdi.hasField("Pairwise"))
+// if (gdi.hasWidget("Pairwise"))
// pairwise = gdi.isChecked("Pairwise");
int pairSize = 1;
- if (gdi.hasField("PairSize")) {
+ if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
int maxTime = 0, restartTime = 0;
double scaleFactor = 1.0;
- if (gdi.hasField("TimeRestart"))
+ if (gdi.hasWidget("TimeRestart"))
restartTime = oe->getRelativeTime(gdi.getText("TimeRestart"));
- if (gdi.hasField("MaxAfter"))
+ if (gdi.hasWidget("MaxAfter"))
maxTime = convertAbsoluteTimeMS(gdi.getText("MaxAfter"));
- if (gdi.hasField("ScaleFactor"))
+ if (gdi.hasWidget("ScaleFactor"))
scaleFactor = _wtof(gdi.getText("ScaleFactor").c_str());
if (method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::MeOS) {
@@ -1623,7 +1592,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
return 0;
int leg = 0;
- if (gdi.hasField("Leg")) {
+ if (gdi.hasWidget("Leg")) {
leg = gdi.getSelectedItem("Leg").first;
}
vector spec;
@@ -1836,8 +1805,23 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oListParam par;
par.selection.insert(cid);
oListInfo info;
- par.listCode = EStdStartList;
- par.setLegNumberCoded(leg);
+ ClassConfigInfo cc;
+ if (pc->getNumDistinctRunnersMinimal() == 1) {
+ par.listCode = EStdStartList;
+ par.setLegNumberCoded(leg);
+ }
+ else {
+ if (pc->getClassType() == ClassType::oClassPatrol) {
+ par.listCode = oe->getListContainer().getType("patrolstart");
+ }
+ else if (leg >= 0) {
+ par.listCode = EStdTeamStartListLeg;
+ par.setLegNumberCoded(leg);
+ }
+ else {
+ par.listCode = EStdStartList;
+ }
+ }
oe->generateListInfo(par, gdi.getLineHeight(), info);
oe->generateList(gdi, false, info, true);
@@ -2146,6 +2130,13 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
int num = bi.data;
updateSplitDistribution(gdi, num, bi.getExtraInt());
}
+ else if (bi.id == "Module") {
+ size_t ix = gdi.getSelectedItem("Module").first;
+ if (ix < currentResultModuleTags.size()) {
+ const string &mtag = currentResultModuleTags[ix];
+ gdi.hideWidget("EditModule", mtag.empty());
+ }
+ }
else if (bi.id=="Courses")
EditChanged=true;
else if (bi.id == "BibSettings") {
@@ -2496,7 +2487,7 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
if (cid==0) {
gdi.restore("", true);
gdi.disableInput("MultiCourse", true);
- if (gdi.hasField("Courses"))
+ if (gdi.hasWidget("Courses"))
gdi.enableInput("Courses");
gdi.enableEditControls(false);
gdi.setText("Name", L"");
@@ -2504,19 +2495,19 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
gdi.check("AllowQuickEntry", true);
gdi.setText("NumberMaps", L"");
- if (gdi.hasField("FreeStart"))
+ if (gdi.hasWidget("FreeStart"))
gdi.check("FreeStart", false);
- if (gdi.hasField("IgnoreStart"))
+ if (gdi.hasWidget("IgnoreStart"))
gdi.check("IgnoreStart", false);
- if (gdi.hasField("DirectResult"))
+ if (gdi.hasWidget("DirectResult"))
gdi.check("DirectResult", false);
- if (gdi.hasField("LockStartList")) {
+ if (gdi.hasWidget("LockStartList")) {
gdi.check("LockStartList", false);
gdi.setInputStatus("LockStartList", false);
}
- if (gdi.hasField("NoTiming"))
+ if (gdi.hasWidget("NoTiming"))
gdi.check("NoTiming", false);
ClassId=cid;
@@ -2549,28 +2540,30 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
else
gdi.selectItemByData("StartBlock", -1);
- if (gdi.hasField("Status")) {
+ if (gdi.hasWidget("Status")) {
vector< pair > out;
size_t selected = 0;
pc->getDCI().fillInput("Status", out, selected);
gdi.addItem("Status", out);
gdi.selectItemByData("Status", selected);
+
+ fillResultModules(gdi, pc);
}
gdi.check("AllowQuickEntry", pc->getAllowQuickEntry());
- if (gdi.hasField("NoTiming"))
+ if (gdi.hasWidget("NoTiming"))
gdi.check("NoTiming", pc->getNoTiming());
- if (gdi.hasField("FreeStart"))
+ if (gdi.hasWidget("FreeStart"))
gdi.check("FreeStart", pc->hasFreeStart());
- if (gdi.hasField("IgnoreStart"))
+ if (gdi.hasWidget("IgnoreStart"))
gdi.check("IgnoreStart", pc->ignoreStartPunch());
- if (gdi.hasField("DirectResult"))
+ if (gdi.hasWidget("DirectResult"))
gdi.check("DirectResult", pc->hasDirectResult());
- if (gdi.hasField("LockStartList")) {
+ if (gdi.hasWidget("LockStartList")) {
bool active = pc->getParentClass() != 0;
gdi.setInputStatus("LockStartList", active);
gdi.check("LockStartList", active && pc->lockedClassAssignment());
@@ -2581,7 +2574,7 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
gdi.restore("", false);
gdi.enableInput("MultiCourse", false);
- if (gdi.hasField("Courses")) {
+ if (gdi.hasWidget("Courses")) {
gdi.enableInput("Courses");
pCourse pcourse = pc->getCourse();
gdi.selectItemByData("Courses", pcourse ? pcourse->getId() : -2);
@@ -2611,22 +2604,22 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
multiCourse(gdi, pc->getNumStages());
gdi.refresh();
- if (gdi.hasField("Courses")) {
+ if (gdi.hasWidget("Courses")) {
gdi.addItem("Courses", lang.tl("Flera banor"), -3);
gdi.selectItemByData("Courses", -3);
gdi.disableInput("Courses");
gdi.check("CoursePool", pc->hasCoursePool());
}
- if (gdi.hasField("Unordered"))
+ if (gdi.hasWidget("Unordered"))
gdi.check("Unordered", pc->hasUnorderedLegs());
- if (gdi.hasField("LockForking")) {
+ if (gdi.hasWidget("LockForking")) {
gdi.check("LockForking", pc->lockedForking());
setLockForkingState(gdi, pc->hasCoursePool(), pc->lockedForking());
}
- if (gdi.hasField("MCourses")) {
+ if (gdi.hasWidget("MCourses")) {
oe->fillCourses(gdi, "MCourses", true);
string strId = "StageCourses_label";
gdi.setTextTranslate(strId, getCourseLabel(pc->hasCoursePool()), true);
@@ -2659,11 +2652,11 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
gdi.setInputStatus(string("Restart")+legno, !pc->restartIgnored(k), true);
gdi.setInputStatus(string("RestartRope")+legno, !pc->restartIgnored(k), true);
- if (gdi.hasField(string("Restart")+legno))
+ if (gdi.hasWidget(string("Restart")+legno))
gdi.setText(string("Restart")+legno, pc->getRestartTimeS(k));
- if (gdi.hasField(string("RestartRope")+legno))
+ if (gdi.hasWidget(string("RestartRope")+legno))
gdi.setText(string("RestartRope")+legno, pc->getRopeTimeS(k));
- if (gdi.hasField(string("MultiR")+legno))
+ if (gdi.hasWidget(string("MultiR")+legno))
gdi.selectItemByData((string("MultiR")+legno).c_str(), pc->getLegRunner(k));
}
}
@@ -2671,13 +2664,13 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
else {
gdi.restore("", true);
gdi.enableInput("MultiCourse", true);
- if (gdi.hasField("Courses")) {
+ if (gdi.hasWidget("Courses")) {
gdi.enableInput("Courses");
pCourse pcourse = pc->getCourse();
gdi.selectItemByData("Courses", pcourse ? pcourse->getId() : -2);
}
}
- if (gdi.hasField("QualificationFinal"))
+ if (gdi.hasWidget("QualificationFinal"))
gdi.setInputStatus("QualificationFinal", pc->getParentClass() == 0);
gdi.selectItemByData("Classes", cid);
@@ -2966,44 +2959,44 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
ClassId=pc->getId();
- pc->setName(name);
- if (gdi.hasField("NumberMaps")) {
+ pc->setName(name, true);
+ if (gdi.hasWidget("NumberMaps")) {
pc->setNumberMaps(gdi.getTextNo("NumberMaps"));
}
- if (gdi.hasField("StartName"))
+ if (gdi.hasWidget("StartName"))
pc->setStart(gdi.getText("StartName"));
- if (gdi.hasField("ClassType"))
+ if (gdi.hasWidget("ClassType"))
pc->setType(gdi.getText("ClassType"));
- if (gdi.hasField("StartBlock"))
+ if (gdi.hasWidget("StartBlock"))
pc->setBlock(gdi.getTextNo("StartBlock"));
- if (gdi.hasField("Status")) {
+ if (gdi.hasWidget("Status")) {
pc->getDI().setEnum("Status", gdi.getSelectedItem("Status").first);
}
- if (gdi.hasField("CoursePool"))
+ if (gdi.hasWidget("CoursePool"))
pc->setCoursePool(gdi.isChecked("CoursePool"));
- if (gdi.hasField("Unordered"))
+ if (gdi.hasWidget("Unordered"))
pc->setUnorderedLegs(gdi.isChecked("Unordered"));
- if (gdi.hasField("LockForking"))
+ if (gdi.hasWidget("LockForking"))
pc->lockedForking(gdi.isChecked("LockForking"));
pc->setAllowQuickEntry(gdi.isChecked("AllowQuickEntry"));
- if (gdi.hasField("NoTiming"))
+ if (gdi.hasWidget("NoTiming"))
pc->setNoTiming(gdi.isChecked("NoTiming"));
- if (gdi.hasField("FreeStart"))
+ if (gdi.hasWidget("FreeStart"))
pc->setFreeStart(gdi.isChecked("FreeStart"));
- if (gdi.hasField("IgnoreStart"))
+ if (gdi.hasWidget("IgnoreStart"))
pc->setIgnoreStartPunch(gdi.isChecked("IgnoreStart"));
- if (gdi.hasField("DirectResult")) {
+ if (gdi.hasWidget("DirectResult")) {
bool withDirect = gdi.isChecked("DirectResult");
if (withDirect && !pc->hasDirectResult() && !hasWarnedDirect &&
@@ -3017,13 +3010,13 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
pc->setDirectResult(withDirect);
}
- if (gdi.hasField("LockStartList")) {
+ if (gdi.hasWidget("LockStartList")) {
bool locked = gdi.isChecked("LockStartList");
if (pc->getParentClass())
pc->lockedClassAssignment(locked);
}
- if (gdi.hasField("Courses")) {
+ if (gdi.hasWidget("Courses")) {
int crs = gdi.getSelectedItem("Courses").first;
if (crs == 0) {
@@ -3039,8 +3032,15 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
pc->setCourse(oe->getCourse(crs));
}
- if (pc->hasMultiCourse()) {
+ if (gdi.hasWidget("Module")) {
+ size_t ix = gdi.getSelectedItem("Module").first;
+ if (ix < currentResultModuleTags.size()) {
+ const string &mtag = currentResultModuleTags[ix];
+ pc->setResultModule(mtag);
+ }
+ }
+ if (pc->hasMultiCourse()) {
if (gdi.hasData("SimpleMulti")) {
bool sim = gdi.isChecked("CommonStart");
if (sim) {
@@ -3059,7 +3059,7 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
char legno[10];
sprintf_s(legno, "%d", k);
- if (!gdi.hasField(string("LegType")+legno))
+ if (!gdi.hasWidget(string("LegType")+legno))
continue;
pc->setLegType(k, LegTypes(gdi.getSelectedItem(string("LegType")+legno).first));
@@ -3079,16 +3079,16 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
string key;
key = string("Restart")+legno;
- if (gdi.hasField(key))
+ if (gdi.hasWidget(key))
pc->setRestartTime(k, gdi.getText(key));
key = string("RestartRope")+legno;
- if (gdi.hasField(key))
+ if (gdi.hasWidget(key))
pc->setRopeTime(k, gdi.getText(key));
key = string("MultiR")+legno;
- if (gdi.hasField(key)) {
+ if (gdi.hasWidget(key)) {
int mr = gdi.getSelectedItem(key).first;
if (pc->getLegRunner(k) != mr)
@@ -3143,6 +3143,14 @@ bool TabClass::loadPage(gdioutput &gdi)
oe->checkDB();
oe->checkNecessaryFeatures();
gdi.selectTab(tabId);
+
+ TabList &tc = dynamic_cast(*gdi.getTabs().get(TListTab));
+ if (tc.getMethodEditor().isShown(this)) {
+ tc.getMethodEditor().show(this, gdi);
+ gdi.refresh();
+ return true;
+ }
+
clearPage(gdi, false);
int xp = gdi.getCX();
@@ -3153,8 +3161,7 @@ bool TabClass::loadPage(gdioutput &gdi)
ClassesCB, "Välj vy", false, false).fixedCorner();
if (tableMode) {
- Table *tbl = oe->getClassTB();
- gdi.addTable(tbl, xp, 30);
+ gdi.addTable(oClass::getTable(oe), xp, gdi.scaleLength(30));
return true;
}
@@ -3235,7 +3242,23 @@ bool TabClass::loadPage(gdioutput &gdi)
gdi.popX();
gdi.dropLine(3);
- gdi.addSelection("Status", 200, 300, 0, L"Status:");
+ gdi.addSelection("Status", 100, 300, 0, L"Status:");
+ vector> statusClass;
+ oClass::fillClassStatus(statusClass);
+ vector< pair > st;
+ for (auto &sc : statusClass)
+ st.emplace_back(lang.tl(sc.second), st.size());
+ gdi.addItem("Status", st);
+ gdi.autoGrow("Status");
+
+ gdi.popX();
+ gdi.dropLine(3);
+ gdi.addSelection("Module", 100, 400, ClassesCB, L"Resultatuträkning:");
+ fillResultModules(gdi, nullptr);
+ gdi.dropLine(0.9);
+ gdi.addButton("EditModule", "Redigera", ClassesCB);
+ gdi.hideWidget("EditModule");
+ gdi.dropLine(-0.9);
}
gdi.popX();
@@ -3454,7 +3477,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi) {
saveClassSettingsTable(gdi, modifiedFee, modifiedBib);
oe->synchronize(true);
- if (gdi.hasField("BibGap")) {
+ if (gdi.hasWidget("BibGap")) {
int gap = gdi.getTextNo("BibGap");
if (oe->getBibClassGap() != gap) {
oe->setBibClassGap(gap);
@@ -3544,17 +3567,17 @@ void TabClass::drawDialog(gdioutput &gdi, oEvent::DrawMethod method, const oClas
int pairSize = lastPairSize;
- if (gdi.hasField("FirstStart"))
+ if (gdi.hasWidget("FirstStart"))
firstStart = oe->getRelativeTime(gdi.getText("FirstStart"));
else if (!lastFirstStart.empty())
firstStart = oe->getRelativeTime(lastFirstStart);
- if (gdi.hasField("Interval"))
+ if (gdi.hasWidget("Interval"))
interval = convertAbsoluteTimeMS(gdi.getText("Interval"));
else if (!lastInterval.empty())
interval = convertAbsoluteTimeMS(lastInterval);
- if (gdi.hasField("PairSize")) {
+ if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
gdi.restore("MultiDayDraw", false);
@@ -3698,10 +3721,10 @@ void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMetho
gdi.selectItemByData("Method", int(defaultMethod));
- if (gdi.hasField("Vacanses")) {
+ if (gdi.hasWidget("Vacanses")) {
gdi.setInputStatus("Vacanses", !hasMulti);
}
- if (gdi.hasField("HandleBibs")) {
+ if (gdi.hasWidget("HandleBibs")) {
gdi.setInputStatus("HandleBibs", !hasMulti);
if (hasMulti) {
@@ -3710,7 +3733,7 @@ void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMetho
}
}
- if (gdi.hasField("DoDrawBefore")) {
+ if (gdi.hasWidget("DoDrawBefore")) {
gdi.setInputStatus("DoDrawBefore", !hasMulti);
gdi.setInputStatus("DoDrawAfter", !hasMulti);
}
@@ -3869,7 +3892,7 @@ void TabClass::showClassSelection(gdioutput &gdi, int &bx, int &by, GUICALLBACK
}
void TabClass::enableLoadSettings(gdioutput &gdi) {
- if (!gdi.hasField("LoadSettings"))
+ if (!gdi.hasWidget("LoadSettings"))
return;
set sel;
gdi.getSelection("Classes", sel);
@@ -3982,21 +4005,18 @@ void TabClass::selectCourses(gdioutput &gdi, int legNo) {
}
void TabClass::updateFairForking(gdioutput &gdi, pClass pc) const {
- if (!gdi.hasField("FairForking"))
+ if (!gdi.hasWidget("FairForking"))
return;
vector< vector > forks;
vector< vector > forksC;
set< pair > unfairLegs;
-
+ BaseInfo *bi = gdi.setText("FairForking", gdi.getText("FairForking"), false);
+ TextInfo &text = dynamic_cast(*bi);
if (pc->checkForking(forksC, forks, unfairLegs)) {
- BaseInfo *bi = gdi.setText("FairForking", gdi.getText("FairForking"), false);
- TextInfo &text = dynamic_cast(*bi);
text.setColor(colorGreen);
gdi.setText("FairForking", lang.tl("The forking is fair."), true);
}
else {
- BaseInfo *bi = gdi.setText("FairForking", gdi.getText("FairForking"), false);
- TextInfo &text = dynamic_cast(*bi);
text.setColor(colorRed);
gdi.setText("FairForking", lang.tl("The forking is not fair."), true);
}
@@ -4215,7 +4235,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set &classModifiedFee
int block = gdi.getTextNo("Blck"+id);
int sort = gdi.getTextNo("Sort"+id);
- if (gdi.hasField("Fee" + id)) {
+ if (gdi.hasWidget("Fee" + id)) {
int fee = oe->interpretCurrency(gdi.getText("Fee"+id));
int latefee = oe->interpretCurrency(gdi.getText("LateFee"+id));
int feered = oe->interpretCurrency(gdi.getText("RedFee"+id));
@@ -4236,7 +4256,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set &classModifiedFee
it->getDI().setInt("HighClassFeeRed", latefeered);
}
- if (gdi.hasField("Bib" + id)) {
+ if (gdi.hasWidget("Bib" + id)) {
ListBoxInfo lbi;
bool mod = false;
if (gdi.getSelectedItem("Bib" + id, lbi)) {
@@ -4248,7 +4268,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set &classModifiedFee
}
modifiedBib |= mod;
- if (gdi.hasField("BibTeam" + id)) {
+ if (gdi.hasWidget("BibTeam" + id)) {
ListBoxInfo lbi_bib;
if (gdi.getSelectedItem("BibTeam" + id, lbi_bib)) {
if (it->getBibMode() != lbi_bib.data)
@@ -4270,6 +4290,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set &classModifiedFee
it->setCourse(oe->getCourse(courseId));
it->getDI().setInt("SortIndex", sort);
it->setAllowQuickEntry(direct);
+ it->synchronize(true);
}
}
@@ -4293,7 +4314,7 @@ void TabClass::updateStartData(gdioutput &gdi, pClass pc, int leg, bool updateDe
if (st == STChange) {
if (typeid(sdataBase) != typeid(ListBoxInfo)) {
InputInfo sdII = dynamic_cast(sdataBase);
- gdi.removeControl(sdKey);
+ gdi.removeWidget(sdKey);
gdi.addSelection(sdII.getX(), sdII.getY(), sdKey, sdII.getWidth(), 200, MultiCB);
setParallelOptions(sdKey, gdi, pc, leg);
}
@@ -4304,7 +4325,7 @@ void TabClass::updateStartData(gdioutput &gdi, pClass pc, int leg, bool updateDe
else {
if (typeid(sdataBase) != typeid(InputInfo)) {
ListBoxInfo sdLBI = dynamic_cast(sdataBase);
- gdi.removeControl(sdKey);
+ gdi.removeWidget(sdKey);
string val = "-";
gdi.addInput(sdLBI.getX(), sdLBI.getY(), sdKey, pc->getStartDataS(leg), 8, MultiCB);
}
@@ -4452,19 +4473,19 @@ void TabClass::setLockForkingState(gdioutput &gdi, const oClass &c) {
}
void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockState) {
- if (gdi.hasField("DefineForking"))
+ if (gdi.hasWidget("DefineForking"))
gdi.setInputStatus("DefineForking", !lockState && !poolState);
- if (gdi.hasField("LockForking"))
+ if (gdi.hasWidget("LockForking"))
gdi.setInputStatus("LockForking", !poolState);
int legno = 0;
- while (gdi.hasField("@Course" + itos(legno))) {
+ while (gdi.hasWidget("@Course" + itos(legno))) {
gdi.setInputStatus("@Course" + itos(legno++), !lockState || poolState);
}
for (string s : {"MCourses", "StageCourses", "MAdd", "MRemove"}) {
- if (gdi.hasField(s)) {
+ if (gdi.hasWidget(s)) {
gdi.setInputStatus(s, !lockState || poolState);
}
}
@@ -4472,7 +4493,7 @@ void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockStat
bool moveUp = false;
bool moveDown = false;
- if (gdi.hasField("MCourses")) {
+ if (gdi.hasWidget("MCourses")) {
ListBoxInfo lbi;
if (gdi.getSelectedItem("StageCourses", lbi)) {
if (lbi.index > 0)
@@ -4483,10 +4504,10 @@ void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockStat
}
}
- if (gdi.hasField("MUp")) {
+ if (gdi.hasWidget("MUp")) {
gdi.setInputStatus("MUp", (!lockState || poolState) && moveUp);
}
- if (gdi.hasField("MDown")) {
+ if (gdi.hasWidget("MDown")) {
gdi.setInputStatus("MDown", (!lockState || poolState) && moveDown);
}
}
@@ -4780,3 +4801,28 @@ void TabClass::setDefaultVacant(const wstring &v) {
if (val >= 0 && val <= 100)
oe->setProperty("VacantPercent", val);
}
+void TabClass::fillResultModules(gdioutput &gdi, pClass pc) {
+ string tag;
+ if (pc)
+ tag = pc->getResultModuleTag();
+
+ vector< pair > st;
+ vector< pair > > mol;
+ oe->loadGeneralResults(false, true);
+ oe->getGeneralResults(false, mol, true);
+ currentResultModuleTags.clear();
+ st.emplace_back(lang.tl("Standard"), 0);
+ currentResultModuleTags.emplace_back("");
+ int current = 0;
+ for (size_t k = 0; k < mol.size(); k++) {
+ st.emplace_back(mol[k].second.second, k+1);
+ if (tag == mol[k].second.first)
+ current = k+1;
+
+ currentResultModuleTags.push_back(mol[k].second.first);
+ }
+ gdi.addItem("Module", st);
+ gdi.autoGrow("Module");
+ gdi.selectItemByData("Module", current);
+ gdi.hideWidget("EditModule", current == 0);
+}
diff --git a/code/TabClass.h b/code/TabClass.h
index d568516..8cf1c33 100644
--- a/code/TabClass.h
+++ b/code/TabClass.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -159,6 +159,9 @@ class TabClass :
wstring getDefaultVacant();
void setDefaultVacant(const wstring &val);
+
+ vector currentResultModuleTags;
+ void fillResultModules(gdioutput &gdi, pClass pc);
public:
void clearCompetitionData();
diff --git a/code/TabClub.cpp b/code/TabClub.cpp
index 5210669..718fc41 100644
--- a/code/TabClub.cpp
+++ b/code/TabClub.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -132,10 +132,11 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
pClub pc=oe->getClub(lbi.data);
if (pc) {
gdi.clearPage(true);
- oe->calculateTeamResults(false);
- oe->sortTeams(ClassStartTime, 0, true);
oe->calculateResults({}, oEvent::ResultType::ClassResult);
oe->sortRunners(ClassStartTime);
+ oe->calculateTeamResults(set({}), oEvent::ResultType::ClassResult);
+ oe->sortTeams(ClassStartTime, 0, true);
+
int pay, paid;
{
map ppm;
@@ -581,7 +582,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
else if (type == GUI_LINK) {
TextInfo *ti = static_cast(data);
if (ti->id == "CmpSettings") {
- if (gdi.hasField("SaveSettings"))
+ if (gdi.hasWidget("SaveSettings"))
gdi.sendCtrlMessage("SaveSettings");
TabCompetition &tc = dynamic_cast(*gdi.getTabs().get(TCmpTab));
tc.loadPage(gdi);
@@ -592,7 +593,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
}
else if (type == GUI_CLEAR) {
if (gdi.isInputChanged("")) {
- if (gdi.hasField("SaveSettings")) {
+ if (gdi.hasWidget("SaveSettings")) {
gdi.sendCtrlMessage("SaveSettings");
}
}
@@ -664,8 +665,7 @@ bool TabClub::loadPage(gdioutput &gdi)
gdi.dropLine(2);
gdi.addString("", 10, "help:29758");
gdi.dropLine(1);
- Table *tbl=oe->getClubsTB();
- gdi.addTable(tbl, gdi.getCX(), gdi.getCY());
+ gdi.addTable(oClub::getTable(oe), gdi.getCX(), gdi.getCY());
gdi.refresh();
return true;
}
diff --git a/code/TabClub.h b/code/TabClub.h
index 6657102..a6bf1ce 100644
--- a/code/TabClub.h
+++ b/code/TabClub.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabCompetition.cpp b/code/TabCompetition.cpp
index 8f650ba..2ba5af1 100644
--- a/code/TabCompetition.cpp
+++ b/code/TabCompetition.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -60,6 +60,7 @@
#include
#include
#include
+#include "generalresult.h"
void Setup(bool overwrite, bool overWriteall);
void exportSetup();
@@ -132,11 +133,11 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
oe->updateStartTimes(delta);
}
- oe->setDate(date);
+ oe->setDate(date, true);
oe->useLongTimes(longTimes);
- oe->setName(gdi.getText("Name"));
+ oe->setName(gdi.getText("Name"), true);
oe->setAnnotation(gdi.getText("Annotation"));
- oe->setZeroTime(zt);
+ oe->setZeroTime(zt, true);
oe->synchronize();
@@ -872,7 +873,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.disableInput("ExpandTResults", true);
gdi.disableInput("SelectAll", true);
gdi.disableInput("SelectNone", true);
- if (gdi.hasField("ClassNewEntries")) {
+ if (gdi.hasWidget("ClassNewEntries")) {
gdi.getSelection("ClassNewEntries", allTransfer);
transferNoCompet = gdi.isChecked("TransferEconomy");
}
@@ -977,7 +978,6 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.addButton("MultiEvent", "Återgå", CompetitionCB);
gdi.scrollToBottom();
gdi.refresh();
-
}
else
throw std::exception("Kunde inte lokalisera nästa etapp");
@@ -1406,7 +1406,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
ci = &events[eventIndex];
bool removeRemoved = true;
- if (gdi.hasField("RemoveRemoved"))
+ if (gdi.hasWidget("RemoveRemoved"))
removeRemoved = gdi.isChecked("RemoveRemoved");
wstring course = gdi.getText("FileName", true);
@@ -1431,7 +1431,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
lastEntry = gdi.getText("LastEntryDate");
}
- if (gdi.hasField("EventorImport")) {
+ if (gdi.hasWidget("EventorImport")) {
gdi.disableInput("EventorImport");
gdi.disableInput("FileName");
gdi.disableInput("FirstStart");
@@ -1504,7 +1504,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.addString("", 1, "Skapar ny tävling");
oe->newCompetition(L"New");
oe->importXML_EntryData(gdi, tEvent, false, false, noFilter, noType);
- oe->setZeroTime(formatTimeHMS(zeroTime));
+ oe->setZeroTime(formatTimeHMS(zeroTime), false);
oe->getDI().setDate("OrdinaryEntry", lastEntry);
if (ci) {
if (!ci->account.empty())
@@ -1598,7 +1598,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
}
gdi.scrollToBottom();
gdi.dropLine();
- if (gdi.hasField("Cancel"))
+ if (gdi.hasWidget("Cancel"))
gdi.disableInput("Cancel"); // Disable "cancel" above
gdi.fillRight();
if (id > 0)
@@ -1740,10 +1740,10 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (save.empty())
throw meosException("Filnamn kan inte vara tomt");
- bool individual = !gdi.hasField("ExportTeam") || gdi.isChecked("ExportTeam");
+ bool individual = !gdi.hasWidget("ExportTeam") || gdi.isChecked("ExportTeam");
bool includeStage = true;
- if (gdi.hasField("IncludeRaceNumber"))
+ if (gdi.hasWidget("IncludeRaceNumber"))
includeStage = gdi.isChecked("IncludeRaceNumber");
gdi.getSelection("ClassNewEntries", allTransfer);
@@ -1784,7 +1784,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (save.empty())
throw meosException("Filnamn kan inte vara tomt");
- //bool individual = !gdi.hasField("ExportTeam") || gdi.isChecked("ExportTeam");
+ //bool individual = !gdi.hasWidget("ExportTeam") || gdi.isChecked("ExportTeam");
gdi.getSelection("ClassNewEntries", allTransfer);
checkReadyForResultExport(gdi, allTransfer);
@@ -1795,7 +1795,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
bool unroll = gdi.isChecked("UnrollLoops"); // If not applicable, field does not exist.
bool includeStage = true;
- if (gdi.hasField("IncludeRaceNumber"))
+ if (gdi.hasWidget("IncludeRaceNumber"))
includeStage = gdi.isChecked("IncludeRaceNumber");
gdi.setWaitCursor(true);
@@ -2259,7 +2259,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
}
else if (type==GUI_CLEAR) {
if (gdi.isInputChanged("")) {
- if (gdi.hasField("SaveSettings")) {
+ if (gdi.hasWidget("SaveSettings")) {
gdi.sendCtrlMessage("SaveSettings");
}
else {
@@ -2310,7 +2310,7 @@ int TabCompetition::restoreCB(gdioutput &gdi, int type, void *data) {
else {
const wstring &name = oe->getName();
if (name.find_last_of(L"}") != name.length()-1)
- oe->setName(name + L" {" + lang.tl(L"återställd") + L"}");
+ oe->setName(name + L" {" + lang.tl(L"återställd") + L"}", false);
oe->restoreBackup();
@@ -2357,7 +2357,7 @@ void TabCompetition::copyrightLine(gdioutput &gdi) const
gdi.dropLine(0.4);
gdi.fillDown();
- gdi.addString("", 0, makeDash(L"#Copyright © 2007-2019 Melin Software HB"));
+ gdi.addString("", 0, makeDash(L"#Copyright © 2007-2020 Melin Software HB"));
gdi.dropLine(1);
gdi.popX();
@@ -2387,7 +2387,7 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
gdi.dropLine(1.5);
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
- gdi.addStringUT(1, makeDash(L"Copyright © 2007-2019 Melin Software HB"));
+ gdi.addStringUT(1, makeDash(L"Copyright © 2007-2020 Melin Software HB"));
gdi.dropLine();
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
"(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB,"
@@ -3210,14 +3210,14 @@ void TabCompetition::loadRunnerDB(gdioutput &gdi, int tableToShow, bool updateTa
if (tableToShow == 1) {
oe->updateRunnerDatabase();
- Table *tb = oe->getRunnerDatabase().getRunnerTB();
- gdi.addTable(tb, 40, gdi.getCY());
+ auto tb = oe->getRunnerDatabase().getRunnerTB();
+ gdi.addTable(tb, gdi.scaleLength(40), gdi.getCY());
gdi.registerEvent("CellAction", CompetitionCB);
}
else if (tableToShow == 2) {
oe->updateRunnerDatabase();
- Table *tb = oe->getRunnerDatabase().getClubTB();
- gdi.addTable(tb, 40, gdi.getCY());
+ auto tb = oe->getRunnerDatabase().getClubTB();
+ gdi.addTable(tb, gdi.scaleLength(40), gdi.getCY());
}
gdi.refresh();
@@ -3646,17 +3646,17 @@ TabCompetition::FlowOperation TabCompetition::checkStageFilter(gdioutput & gdi,
gdi.scrollToBottom();
gdi.refresh();
gdi.runSubCommand();
- while (gdi.hasField("OK_Stage") && gdi.getExtraInt("OK_Stage") == 0 && gdi.getExtraInt("Cancel_Stage") == 0) {
+ while (gdi.hasWidget("OK_Stage") && gdi.getExtraInt("OK_Stage") == 0 && gdi.getExtraInt("Cancel_Stage") == 0) {
mainMessageLoop(0, 10);
}
bool ok = false, cancel = false;
- if (gdi.hasField("OK_Stage")) {
+ if (gdi.hasWidget("OK_Stage")) {
ok = gdi.getExtraInt("OK_Stage") != 0;
cancel = gdi.getExtraInt("Cancel_Stage") != 0;
- gdi.removeControl("OK_Stage");
- gdi.removeControl("Cancel_Stage");
+ gdi.removeWidget("OK_Stage");
+ gdi.removeWidget("Cancel_Stage");
if (stageFilter)
gdi.disableInput("Stage");
if (idtype)
@@ -3827,20 +3827,20 @@ void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
}
void TabCompetition::setExportOptionsStatus(gdioutput &gdi, int format) const {
- if (gdi.hasField("LegType")) {
+ if (gdi.hasWidget("LegType")) {
gdi.setInputStatus("LegType", format == ImportFormats::IOF30 || format == ImportFormats::IOF203); // Enable on IOF-XML
}
- if (gdi.hasField("ExportTeam")) {
+ if (gdi.hasWidget("ExportTeam")) {
gdi.setInputStatus("ExportTeam", format == ImportFormats::IOF30); // Enable on IOF-XML
}
- if (gdi.hasField("ExportSplitTimes")) {
+ if (gdi.hasWidget("ExportSplitTimes")) {
gdi.setInputStatus("ExportSplitTimes", format == ImportFormats::OE);
if (format == ImportFormats::IOF203 || format == ImportFormats::IOF30)
gdi.check("ExportSplitTimes", true);
}
- if (gdi.hasField("IncludeRaceNumber")) {
+ if (gdi.hasWidget("IncludeRaceNumber")) {
gdi.setInputStatus("IncludeRaceNumber", format == ImportFormats::IOF30); // Enable on IOF-XML
}
@@ -4047,7 +4047,7 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
oe->getPayModes(modes);
for (size_t k = 0; k < modes.size(); k++) {
string field = "M"+itos(k);
- if (gdi.hasField(field)) {
+ if (gdi.hasWidget(field)) {
wstring mode = gdi.getText("M"+itos(k));
int id = gdi.getBaseInfo(field.c_str()).getExtraInt();
oe->setPayMode(id, mode);
diff --git a/code/TabCompetition.h b/code/TabCompetition.h
index 57d5784..8689d70 100644
--- a/code/TabCompetition.h
+++ b/code/TabCompetition.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabControl.cpp b/code/TabControl.cpp
index 4b2a485..deacbaf 100644
--- a/code/TabControl.cpp
+++ b/code/TabControl.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -96,7 +96,7 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
gdi.setText("Name", pc->getName());
gdi.setText("TimeAdjust", pc->getTimeAdjustS());
gdi.setText("MinTime", pc->getMinTimeS());
- if (gdi.hasField("Point"))
+ if (gdi.hasWidget("Point"))
gdi.setText("Point", pc->getRogainingPointsS());
controlId = pc->getId();
@@ -114,7 +114,7 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
if (st == oControl::StatusNoTiming)
gdi.disableInput("TimeAdjust");
- if (gdi.hasField("Point") && st != oControl::StatusRogaining)
+ if (gdi.hasWidget("Point") && st != oControl::StatusRogaining)
gdi.disableInput("Point");
}
}
@@ -127,7 +127,7 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
gdi.setText("ControlID", makeDash(L"-"), true);
gdi.setText("TimeAdjust", L"00:00");
- if (gdi.hasField("Point"))
+ if (gdi.hasWidget("Point"))
gdi.setText("Point", L"");
gdi.disableInput("Remove");
@@ -169,7 +169,7 @@ void TabControl::save(gdioutput &gdi)
pc->setRogainingPoints(0);
}
else {
- if (gdi.hasField("Point")) {
+ if (gdi.hasWidget("Point")) {
pc->setMinTime(0);
pc->setRogainingPoints(gdi.getTextNo("Point"));
}
@@ -355,7 +355,7 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="Visitors") {
save(gdi);
- Table *table=new Table(oe, 20, L"Kontroll X#" + itow(controlId), "controlvisitor");
+ shared_ptr table=make_shared(oe, 20, L"Kontroll X#" + itow(controlId), "controlvisitor");
table->addColumn("Id", 70, true, true);
table->addColumn("Ändrad", 70, false);
@@ -375,11 +375,11 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
int xp=gdi.getCX();
gdi.fillDown();
gdi.addButton("Show", "Återgå", ControlsCB);
- gdi.addTable(table, xp, gdi.getCY());
+ gdi.addTable(table, xp, gdi.getCY());
gdi.refresh();
}
else if (bi.id=="Courses") {
- Table *table=new Table(oe, 20, L"Kontroll X#" + itow(controlId), "controlcourse");
+ auto table=make_shared(oe, 20, L"Kontroll X#" + itow(controlId), "controlcourse");
table->addColumn("Id", 70, true, true);
table->addColumn("Ändrad", 70, false);
@@ -395,7 +395,7 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
int xp=gdi.getCX();
gdi.fillDown();
gdi.addButton("Show", "Återgå", ControlsCB);
- gdi.addTable(table, xp, gdi.getCY());
+ gdi.addTable(table, xp, gdi.getCY());
gdi.refresh();
}
else if (bi.id=="Show") {
@@ -445,8 +445,7 @@ bool TabControl::loadPage(gdioutput &gdi)
ControlsCB, "Välj vy", false, false).fixedCorner();
if (tableMode) {
- Table *tbl=oe->getControlTB();
- gdi.addTable(tbl, xp, 30);
+ gdi.addTable(oControl::getTable(oe), xp, gdi.scaleLength(30));
return true;
}
diff --git a/code/TabControl.h b/code/TabControl.h
index 8a92d2e..aeb8dd6 100644
--- a/code/TabControl.h
+++ b/code/TabControl.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabCourse.cpp b/code/TabCourse.cpp
index 8cb4d12..67bc4e4 100644
--- a/code/TabCourse.cpp
+++ b/code/TabCourse.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@ void LoadClassPage(gdioutput &gdi);
void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
{
- if (gdi.hasField("Rogaining")) {
+ if (gdi.hasWidget("Rogaining")) {
gdi.setText("TimeLimit", L"");
gdi.disableInput("TimeLimit");
gdi.setText("PointLimit", L"");
@@ -77,7 +77,8 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
wstring uis = pc->getControlsUI();
gdi.setText("Controls", uis);
- gdi.setText("CourseExpanded", encodeCourse(uis, pc->useFirstAsStart(), pc->useLastAsFinish()), true);
+ gdi.setText("CourseExpanded", encodeCourse(uis, pc->getMaximumRogainingTime() > 0,
+ pc->useFirstAsStart(), pc->useLastAsFinish()), true);
gdi.setText("Name", pc->getName());
@@ -88,7 +89,7 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
gdi.check("FirstAsStart", pc->useFirstAsStart());
gdi.check("LastAsFinish", pc->useLastAsFinish());
- if (gdi.hasField("Rogaining")) {
+ if (gdi.hasWidget("Rogaining")) {
int rt = pc->getMaximumRogainingTime();
int rp = pc->getMinimumRogainingPoints();
@@ -215,20 +216,20 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
gdi.setInputStatus("DrawCourse", pc != 0);
}
-int CourseCB(gdioutput *gdi, int type, void *data)
-{
+int CourseCB(gdioutput *gdi, int type, void *data) {
TabCourse &tc = dynamic_cast(*gdi->getTabs().get(TCourseTab));
-
return tc.courseCB(*gdi, type, data);
}
-void TabCourse::save(gdioutput &gdi, int canSwitchViewMode)
-{
+void TabCourse::save(gdioutput &gdi, int canSwitchViewMode) {
DWORD cid = courseId;
pCourse pc;
wstring name=gdi.getText("Name");
+ if (cid == 0 && name.empty())
+ return;
+
if (name.empty()) {
gdi.alert("Banan måste ha ett namn.");
return;
@@ -292,7 +293,7 @@ void TabCourse::save(gdioutput &gdi, int canSwitchViewMode)
else
pc->setShorterVersion(false, 0);
- if (gdi.hasField("Rogaining")) {
+ if (gdi.hasWidget("Rogaining")) {
string t;
pc->setMaximumRogainingTime(convertAbsoluteTimeMS(gdi.getText("TimeLimit")));
pc->setMinimumRogainingPoints(_wtoi(gdi.getText("PointLimit").c_str()));
@@ -338,6 +339,12 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
if (bi.id=="Save") {
save(gdi, 1);
}
+ else if (bi.id == "SwitchMode") {
+ if (!tableMode)
+ save(gdi, true);
+ tableMode = !tableMode;
+ loadPage(gdi);
+ }
else if (bi.id == "LegLengths") {
save(gdi, 2);
@@ -723,9 +730,22 @@ bool TabCourse::loadPage(gdioutput &gdi) {
gdi.getData("RunnerID", RunnerID);
gdi.clearPage(false);
+ int xp = gdi.getCX();
gdi.setData("ClassID", ClassID);
gdi.setData("RunnerID", RunnerID);
+
+ string switchMode;
+ const int button_w = gdi.scaleLength(90);
+ switchMode = tableMode ? "Formulärläge" : "Tabelläge";
+ gdi.addButton(2, 2, button_w, "SwitchMode", switchMode,
+ CourseCB, "Välj vy", false, false).fixedCorner();
+
+ if (tableMode) {
+ gdi.addTable(oCourse::getTable(oe), xp, gdi.scaleLength(30));
+ return true;
+ }
+
gdi.addString("", boldLarge, "Banor");
gdi.pushY();
@@ -1125,17 +1145,21 @@ oEvent::DrawMethod TabCourse::getDefaultMethod() const {
void TabCourse::clearCompetitionData() {
courseId = 0;
addedCourse = false;
+ tableMode = false;
}
void TabCourse::refreshCourse(const wstring &text, gdioutput &gdi) {
bool firstAsStart = gdi.isChecked("FirstAsStart");
bool lastAsFinish = gdi.isChecked("LastAsFinish");
- wstring controls = encodeCourse(text, firstAsStart, lastAsFinish);
+ bool rogaining = gdi.hasWidget("Rogaining") && gdi.getSelectedItem("Rogaining").first == 1;
+
+ wstring controls = encodeCourse(text, rogaining, firstAsStart, lastAsFinish);
+
if (controls != gdi.getText("CourseExpanded"))
gdi.setText("CourseExpanded", controls, true);
}
-wstring TabCourse::encodeCourse(const wstring &in, bool firstStart, bool lastFinish) {
+wstring TabCourse::encodeCourse(const wstring &in, bool rogaining, bool firstStart, bool lastFinish) {
vector newC;
string ins;
wide2String(in, ins);
@@ -1144,35 +1168,53 @@ wstring TabCourse::encodeCourse(const wstring &in, bool firstStart, bool lastFin
wstring out;
out.reserve(in.length() * 2);
wstring bf;
- for (size_t i = 0; i < newC.size(); ++i) {
- if (i == 0 && (newC.size() > 1 || firstStart)) {
- out += lang.tl("Start");
- if (firstStart)
- out += L"(" + itow(newC[i]) + L")";
- else
- out += dash + formatControl(newC[i], bf);
- if (newC.size() == 1) {
- out += dash + lang.tl("MÃ¥l");
- break;
- }
- continue;
- }
- else
- out += dash;
+ if (!rogaining) {
+ for (size_t i = 0; i < newC.size(); ++i) {
+ if (i == 0 && (newC.size() > 1 || firstStart)) {
+ out += lang.tl("Start");
+ if (firstStart)
+ out += L"(" + itow(newC[i]) + L")";
+ else
+ out += dash + formatControl(newC[i], bf);
- if (i+1 == newC.size()) {
- if (i == 0) {
- out = lang.tl("Start") + dash;
+ if (newC.size() == 1) {
+ out += dash + lang.tl("MÃ¥l");
+ break;
+ }
+ continue;
}
- if (lastFinish)
- out += lang.tl("MÃ¥l") + L"(" + itow(newC[i]) + L")";
else
- out += formatControl(newC[i], bf) + dash + lang.tl("MÃ¥l");
+ out += dash;
+
+ if (i + 1 == newC.size()) {
+ if (i == 0) {
+ out = lang.tl("Start") + dash;
+ }
+ if (lastFinish)
+ out += lang.tl("MÃ¥l") + L"(" + itow(newC[i]) + L")";
+ else
+ out += formatControl(newC[i], bf) + dash + lang.tl("MÃ¥l");
+ }
+ else {
+ out += formatControl(newC[i], bf);
+ }
}
- else {
+ }
+ else {
+ int pcnt = 0;
+ for (size_t i = 0; i < newC.size(); ++i) {
+ if (i > 0)
+ out += L"; ";
+ auto pc = oe->getControl(newC[i]);
+ if (pc)
+ pcnt += pc->getRogainingPoints();
+
out += formatControl(newC[i], bf);
}
+
+ if (pcnt > 0)
+ out += L" = " + itow(pcnt) + L"p";
}
return out;
}
diff --git a/code/TabCourse.h b/code/TabCourse.h
index 1339ec5..863c658 100644
--- a/code/TabCourse.h
+++ b/code/TabCourse.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,6 +38,8 @@ class TabCourse :
wstring point_limit;
wstring point_reduction;
+ bool tableMode = false;
+
void fillCourseControls(gdioutput &gdi, const wstring &ctrl);
void fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops);
@@ -47,7 +49,7 @@ class TabCourse :
oEvent::DrawMethod getDefaultMethod() const;
- wstring encodeCourse(const wstring &in, bool firstStart, bool lastFinish);
+ wstring encodeCourse(const wstring &in, bool rogaining, bool firstStart, bool lastFinish);
void refreshCourse(const wstring &text, gdioutput &gdi);
const wstring &formatControl(int id, wstring &bf) const;
diff --git a/code/TabList.cpp b/code/TabList.cpp
index b7f678f..f27d06f 100644
--- a/code/TabList.cpp
+++ b/code/TabList.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -52,12 +52,14 @@
#include "animationdata.h"
#include
#include "HTMLWriter.h"
+#include "generalresult.h"
const static int CUSTOM_OFFSET = 10;
const static int NUMTEXTSAMPLE = 13;
const static int ForcePageBreak = 1024;
const static int IgnoreLimitPer = 512;
+const static int AddTeamRogaining = 5;
const static int AddTeamClasses = 4;
const static int AddPatrolClasses = 3;
const static int AddRogainingClasses = 2;
@@ -65,20 +67,12 @@ const static int AddAllClasses = 1;
TabList::TabList(oEvent *poe):TabBase(poe)
{
- listEditor = 0;
- methodEditor = 0;
-
lastHtmlTarget = poe->getPropertyString("LastExportTarget", L"");
clearCompetitionData();
}
TabList::~TabList(void)
{
- delete listEditor;
- delete methodEditor;
- listEditor = 0;
- methodEditor = 0;
-
for (size_t k = 0; k < liveResults.size(); k++) {
delete liveResults[k];
liveResults[k] = 0;
@@ -140,7 +134,7 @@ int NoStartRunnerCB(gdioutput *gdi, int type, void *data)
pRunner p = tc.getEvent()->getRunner(id, 0);
if (p) {
- p->setStatus(StatusDNS, true, false);
+ p->setStatus(StatusDNS, true, oBase::ChangeType::Update);
p->synchronize();
ti->callBack=0;
ti->highlight=false;
@@ -368,7 +362,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (bi.id == "ClassSelection") {
gdioutput *gdi_settings = getExtraWindow("list_class", true);
if (!gdi_settings) {
- gdi_settings = createExtraWindow("list_class", lang.tl("Klassval"), gdi.scaleLength(350), gdi.scaleLength(600), true);
+ gdi_settings = createExtraWindow("list_class", lang.tl("Klassval"), gdi.scaleLength(350), gdi.scaleLength(650), true);
}
if (gdi_settings) {
loadClassSettings(*gdi_settings, gdi.getTag());
@@ -560,7 +554,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
lst.insert(-1);
gdi.setSelection("ListSelection", lst);
- if (gdi.hasField("ResultType")) {
+ if (gdi.hasWidget("ResultType")) {
ListBoxInfo entry;
gdi.getSelectedItem("ResultType", entry);
gdi.setInputStatus("Generate", int(entry.data) >= 0);
@@ -569,7 +563,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="SelectNone") {
set lst;
gdi.setSelection("ListSelection", lst);
- if (gdi.hasField("ResultType")) {
+ if (gdi.hasWidget("ResultType")) {
gdi.setInputStatus("Generate", false);
}
}
@@ -580,18 +574,18 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
const char *ctype = (char *)gdi.getData("Type");
saveExtraLines(*oe, ctype, gdi);
- if (gdi.hasField("SplitAnalysis")) {
+ if (gdi.hasWidget("SplitAnalysis")) {
int aflag = (gdi.isChecked("SplitAnalysis") ? 0 : 1) + (gdi.isChecked("Speed") ? 0 : 2)
+ (gdi.isChecked("Results") ? 0 : 4);
oe->getDI().setInt("Analysis", aflag);
}
- if (gdi.hasField("WideFormat")) {
+ if (gdi.hasWidget("WideFormat")) {
bool wide = gdi.isChecked("WideFormat");
oe->setProperty("WideSplitFormat", wide);
- if (wide && gdi.hasField("NumPerPage")) {
+ if (wide && gdi.hasWidget("NumPerPage")) {
pair res = gdi.getSelectedItem("NumPerPage");
if (res.second)
oe->setProperty("NumSplitsOnePage", res.first);
@@ -665,19 +659,12 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
loadGeneralList(gdi);
}
else if (bi.id == "EditList") {
- if (!listEditor)
- listEditor = new ListEditor(oe);
-
gdi.clearPage(false);
- listEditor->show(gdi);
+ getListEditor().show(this, gdi);
gdi.refresh();
}
else if (bi.id == "EditMethod") {
- if (!methodEditor)
- methodEditor = new MethodEditor(oe);
-
- gdi.clearPage(false);
- methodEditor->show(gdi);
+ getMethodEditor().show(this, gdi);
gdi.refresh();
}
else if (bi.id=="ResultIndividual") {
@@ -686,7 +673,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
getResultIndividual(par, cnf);
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, false);
readSettings(gdi, par, true);
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
@@ -698,7 +685,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oListParam par;
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, false);
par.listCode = EStdResultList;
readSettings(gdi, par, true);
@@ -901,7 +888,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
par.back().listCode = EIndCourseList;
par.back().showInterTitle = false;
par.back().setLegNumberCoded(-1);
- cnf.getIndividual(par.back().selection);
+ cnf.getIndividual(par.back().selection, true);
}
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
@@ -923,7 +910,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
oListParam par;
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, false);
par.listCode = EIndPriceList;
par.showHeader = gdi.isChecked("ShowHeader");
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
@@ -956,6 +943,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
bool isStartList = bi.id.substr(0, 7) == "StartL:";
bool allClasses = baseType == AddAllClasses;
bool rogaining = baseType == AddRogainingClasses;
+ bool rogainingTeam = baseType == AddTeamRogaining;
bool patrol = baseType == AddPatrolClasses;
bool team = baseType == AddTeamClasses;
oe->sanityCheck(gdi, bi.id.substr(0, 7) == "Result:");
@@ -979,6 +967,11 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oe->getClassConfigurationInfo(cnf);
cnf.getRogaining(par.selection);
}
+ else if (rogainingTeam) {
+ ClassConfigInfo cnf;
+ oe->getClassConfigurationInfo(cnf);
+ cnf.getRogaining(par.selection);
+ }
else if (team) {
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
@@ -987,7 +980,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (!isReport && !allClasses) {
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, isStartList);
cnf.getPatrol(par.selection);
}
@@ -1044,7 +1037,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oListInfo::EBaseType type = oe->getListContainer().getList(index).getListType();
if (oListInfo::addRunners(type))
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, true);
if (oListInfo::addPatrols(type))
cnf.getPatrol(par.selection);
if (oListInfo::addTeams(type))
@@ -1186,7 +1179,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
}
else if (lbi.id == "ListSelection") {
gdi.getSelection(lbi.id, lastClassSelection);
- if (gdi.hasField("ResultType")) {
+ if (gdi.hasWidget("ResultType")) {
ListBoxInfo entry;
gdi.getSelectedItem("ResultType", entry);
gdi.setInputStatus("Generate", !lastClassSelection.empty() && int(entry.data) >= 0);
@@ -1225,7 +1218,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oe->synchronize(false);
oe->getListContainer().load(MetaListContainer::ExternalList, xlist, false);
oe->synchronize(true);
- oe->loadGeneralResults(true);
+ oe->loadGeneralResults(true, false);
}
ButtonInfo bi;
bi.id = "ImportCustom";
@@ -1261,10 +1254,10 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (ti.id == "EditInstalled") {
int ix = ti.getExtraInt();
if (!listEditor)
- listEditor = new ListEditor(oe);
+ listEditor = make_shared(oe);
gdi.clearPage(false);
listEditor->load(oe->getListContainer(), ix);
- listEditor->show(gdi);
+ listEditor->show(this, gdi);
gdi.refresh();
}
}
@@ -1646,7 +1639,7 @@ void TabList::handleRememberSettings(gdioutput &gdi, BaseInfo &info, GuiEventTyp
}
oe->synchronize(true);
- dest_gdi.removeControl("Remember");
+ dest_gdi.removeWidget("Remember");
gdi.closeWindow();
}
else if (bi.id == "DoMerge") {
@@ -1876,13 +1869,13 @@ void TabList::handleListSettings(gdioutput &gdi, BaseInfo &info, GuiEventType ty
addAnimationSettings(gdi, tmpSettingsParam);
}
else {
- if (gdi.hasField("Time"))
+ if (gdi.hasWidget("Time"))
saveAnimationSettings(gdi, tmpSettingsParam);
- gdi.removeControl("Time");
- gdi.removeControl("NPage");
- gdi.removeControl("Margin");
- gdi.removeControl("Animate");
+ gdi.removeWidget("Time");
+ gdi.removeWidget("NPage");
+ gdi.removeWidget("Margin");
+ gdi.removeWidget("Animate");
}
gdi.refresh();
}
@@ -2000,7 +1993,7 @@ void TabList::handleHTMLSettings(gdioutput &gdi, BaseInfo &info, GuiEventType ty
int time_ms = 0;
double scale = 0;
- if (gdi.hasField("Margin")) {
+ if (gdi.hasWidget("Margin")) {
margin = gdi.getTextNo("Margin");
if (gdi.isChecked("UseRows"))
rows = gdi.getTextNo("Rows");
@@ -2129,6 +2122,14 @@ void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
gdi.dropLine(2.5);
gdi.fillDown();
+ gdi.addSelection("AgeFilter", 200, 150, nullptr, L"Ã…ldersfiltrering:");
+ vector> ages;
+ ages.emplace_back(L"Alla", size_t(oListParam::AgeFilter::All));
+ ages.emplace_back(L"Ungdom", size_t(oListParam::AgeFilter::OnlyYouth));
+ ages.emplace_back(L"Vuxna", size_t(oListParam::AgeFilter::ExludeYouth));
+ gdi.addItem("AgeFilter", ages);
+ gdi.selectItemByData("AgeFilter", int(currentList.getParam().ageFilter));
+
gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, currentList.getParam().pageBreak).setHandler(&settingsClassSelection);
gdi.addCheckbox("ShowHeader", "Visa rubrik", 0, currentList.getParam().showHeader).setHandler(&settingsClassSelection);
@@ -2141,12 +2142,6 @@ void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
gdi.addButton("Cancel", "Avbryt").setCancel().setHandler(&settingsClassSelection);
gdi.dropLine(2.5);
gdi.popX();
- //
- // int ey = gdi.getCY() + gdi.scaleLength(4);
-// int ex = gdi.getWidth();
-// RECT rc = { sx, sy, ex, ey };
-// gdi.addRectangle(rc, colorLightBlue);
-
gdi.refresh();
}
@@ -2159,6 +2154,9 @@ void TabList::handleClassSettings(gdioutput &gdi, BaseInfo &info, GuiEventType t
oListParam ¶m = currentList.getParam();
param.lockUpdate = true;
gdi.getSelection("ListSelection", param.selection);
+
+ auto filter = gdi.getSelectedItem("AgeFilter");
+ param.ageFilter = oListParam::AgeFilter(filter.first);
bool pb = gdi.isChecked("PageBreak");
param.pageBreak = pb;
@@ -2347,6 +2345,19 @@ bool TabList::loadPage(gdioutput &gdi)
oe->checkDB();
oe->synchronize();
gdi.selectTab(tabId);
+
+ if (getMethodEditor().isShown(this)) {
+ getMethodEditor().show(this, gdi);
+ gdi.refresh();
+ return true;
+ }
+
+ if (getListEditor().isShown(this)) {
+ getListEditor().show(this, gdi);
+ gdi.refresh();
+ return true;
+ }
+
noReEvaluate = false;
gdi.clearPage(false);
if (SelectedList!="") {
@@ -2402,6 +2413,11 @@ bool TabList::loadPage(gdioutput &gdi)
}
}
+ if (cnf.hasRogainingTeam()) {
+ checkWidth(gdi);
+ gdi.addButton("StartL:teamstartlist", "Rogaining", ListsCB).setExtra(AddRogainingClasses);
+ }
+
checkWidth(gdi);
gdi.addButton("MinuteStartList", "Minutstartlista", ListsCB);
@@ -2496,6 +2512,11 @@ bool TabList::loadPage(gdioutput &gdi)
gdi.addButton("Result:rogainingind", "Rogaining", ListsCB).setExtra(AddRogainingClasses);
}
+ if (cnf.hasRogainingTeam()) {
+ checkWidth(gdi);
+ gdi.addButton("Result:teamrogainingresult", "Rogaining", ListsCB).setExtra(AddTeamRogaining);
+ }
+
checkWidth(gdi);
gdi.addButton("ResultList", "Avancerat...", ListsCB);
@@ -2680,7 +2701,7 @@ bool TabList::loadPage(gdioutput &gdi)
}
void TabList::enableWideFormat(gdioutput &gdi, bool wide) {
- if (gdi.hasField("NumPerPage")) {
+ if (gdi.hasWidget("NumPerPage")) {
gdi.setInputStatus("NumPerPage", wide);
bool needTime = gdi.getSelectedItem("NumPerPage").first != 1;
@@ -2982,10 +3003,8 @@ void TabList::clearCompetitionData() {
lastLeg = 0;
lastFilledResultClassType = -1;
- delete listEditor;
- delete methodEditor;
- listEditor = 0;
- methodEditor = 0;
+ listEditor.reset();
+ methodEditor.reset();
}
void TabList::setAnimationMode(gdioutput &gdi) {
@@ -2997,7 +3016,7 @@ void TabList::setAnimationMode(gdioutput &gdi) {
void TabList::getStartIndividual(oListParam &par, ClassConfigInfo &cnf){
par.listCode = EStdStartList;
par.setLegNumberCoded(-1);
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, true);
}
void TabList::getStartClub(oListParam &par) {
@@ -3006,7 +3025,7 @@ void TabList::getStartClub(oListParam &par) {
}
void TabList::getResultIndividual(oListParam &par, ClassConfigInfo &cnf) {
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, false);
par.listCode = EStdResultList;
par.showInterTimes = true;
par.setLegNumberCoded(-1);
@@ -3015,7 +3034,7 @@ void TabList::getResultIndividual(oListParam &par, ClassConfigInfo &cnf) {
void TabList::getResultClub(oListParam &par, ClassConfigInfo &cnf) {
par.listCode = EStdClubResultList;
par.setLegNumberCoded(-1);
- cnf.getIndividual(par.selection);
+ cnf.getIndividual(par.selection, true);
cnf.getPatrol(par.selection);
}
@@ -3124,3 +3143,20 @@ void TabList::readSettings(gdioutput &gdi, oListParam &par, bool forResult) {
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
}
}
+
+MethodEditor &TabList::getMethodEditor() {
+ if (!methodEditor)
+ methodEditor = make_shared(oe);
+
+ return *methodEditor;
+}
+
+ListEditor &TabList::getListEditor() {
+ if (!listEditor)
+ listEditor = make_shared(oe);
+ return *listEditor;
+}
+
+ListEditor *TabList::getListEditorPtr() const {
+ return listEditor.get();
+}
diff --git a/code/TabList.h b/code/TabList.h
index 835980e..49624e1 100644
--- a/code/TabList.h
+++ b/code/TabList.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -67,8 +67,8 @@ protected:
bool hideButtons;
bool ownWindow;
- ListEditor *listEditor;
- MethodEditor *methodEditor;
+ shared_ptr listEditor;
+ shared_ptr methodEditor;
bool noReEvaluate;
@@ -112,6 +112,8 @@ public:
/** Returns a collection of public lists. */
void static getPublicLists(oEvent &oe, vector &lists);
+ MethodEditor &getMethodEditor();
+
bool loadPage(gdioutput &gdi);
bool loadPage(gdioutput &gdi, const string &command);
@@ -149,7 +151,8 @@ public:
static void saveExtraLines(oEvent &oe, const char *dataField, gdioutput &gdi);
static void enableWideFormat(gdioutput &gdi, bool wide);
- ListEditor *getListeditor() const {return listEditor;}
+ ListEditor &getListEditor();
+ ListEditor *getListEditorPtr() const;
const char * getTypeStr() const {return "TListTab";}
TabType getType() const {return TListTab;}
diff --git a/code/TabMulti.cpp b/code/TabMulti.cpp
index 95d9a6b..340fd2e 100644
--- a/code/TabMulti.cpp
+++ b/code/TabMulti.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabMulti.h b/code/TabMulti.h
index f9270ca..acf0aab 100644
--- a/code/TabMulti.h
+++ b/code/TabMulti.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabRunner.cpp b/code/TabRunner.cpp
index 9ede707..6e2efb6 100644
--- a/code/TabRunner.cpp
+++ b/code/TabRunner.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -131,7 +131,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.selectItemByData("Runners", -1);
gdi.setInputFocus("Name", true);
- if (gdi.hasField("MultiR")) {
+ if (gdi.hasWidget("MultiR")) {
gdi.clearList("MultiR");
gdi.disableInput("MultiR");
}
@@ -139,18 +139,18 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
enableControlButtons(gdi, false, false);
disablePunchCourse(gdi);
- if (gdi.hasField("EditTeam"))
+ if (gdi.hasWidget("EditTeam"))
gdi.disableInput("EditTeam");
gdi.setText("RunnerInfo", L"", true);
gdi.setText("TimeAdjust", makeDash(L"-"));
gdi.setText("PointAdjust", L"");
- if (gdi.hasField("StatusIn")) {
+ if (gdi.hasWidget("StatusIn")) {
gdi.selectFirstItem("StatusIn");
gdi.setText("PlaceIn", L"");
gdi.setText("TimeIn", makeDash(L"-"));
- if (gdi.hasField("PointIn"))
+ if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", L"");
}
@@ -163,9 +163,8 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
pRunner parent = r->getMultiRunner(0);
r->synchronizeAll();
- //r->apply(false);
vector mp;
- r->evaluateCard(true, mp, 0, false);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
gdi.selectItemByData("Runners", parent->getId());
@@ -174,7 +173,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.setText("Name", r->getNameRaw());
wstring bib = r->getBib();
- if (gdi.hasField("Bib")) {
+ if (gdi.hasWidget("Bib")) {
gdi.setText("Bib", bib);
bool controlBib = r->getTeam() == 0 || (r->getClassRef(true) && r->getClassRef(true)->getBibMode() == BibFree);
gdi.setInputStatus("Bib", controlBib);
@@ -188,7 +187,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.addItem("RClass", lang.tl("Ingen klass"), 0);
gdi.selectItemByData("RClass", r->getClassId(true));
- if (gdi.hasField("EditTeam")) {
+ if (gdi.hasWidget("EditTeam")) {
gdi.setInputStatus("EditTeam", r->getTeam() != 0);
if (r->getTeam()) {
@@ -239,7 +238,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.refresh();
#endif
- if (gdi.hasField("MultiR")) {
+ if (gdi.hasWidget("MultiR")) {
int numMulti = parent->getNumMulti();
if (numMulti == 0) {
gdi.clearList("MultiR");
@@ -268,7 +267,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
warnDuplicateCard(gdi, cno, r);
gdi.check("RentCard", r->isHiredCard());
- bool hasFee = gdi.hasField("Fee");
+ bool hasFee = gdi.hasWidget("Fee");
if (hasFee)
gdi.setText("Fee", oe->formatCurrency(parent->getDI().getInt("Fee")));
@@ -282,24 +281,25 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
if (hasFee)
gdi.setInputStatus("Fee", parent == r);
- if(gdi.hasField("Club"))
+ if(gdi.hasWidget("Club"))
gdi.setInputStatus("Club", parent == r);
enableControlButtons(gdi, true, r->isVacant());
- gdi.setText("Start", r->getStartTimeS());
+ //gdi.setText("Start", r->getStartTimeS());
gdi.setInputStatus("Start", canSetStart(r));
- gdi.setText("Finish", r->getFinishTimeS());
+ //gdi.setText("Finish", r->getFinishTimeS());
gdi.setInputStatus("Finish", canSetFinish(r));
- gdi.setText("Time", r->getRunningTimeS());
- gdi.setText("Points", itow(r->getRogainingPoints(false)));
+ //gdi.setText("Time", r->getRunningTimeS(true));
+ //gdi.setText("Points", itow(r->getRogainingPoints(false)));
- gdi.selectItemByData("Status", r->getStatus());
- gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
+ //gdi.selectItemByData("Status", r->getStatus());
+ //gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
+ updateStatus(gdi, r);
- if (gdi.hasField("StatusIn")) {
+ if (gdi.hasWidget("StatusIn")) {
gdi.selectItemByData("StatusIn", r->getInputStatus());
int ip = r->getInputPlace();
if (ip > 0)
@@ -308,7 +308,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.setText("PlaceIn", makeDash(L"-"));
gdi.setText("TimeIn", r->getInputTimeS());
- if (gdi.hasField("PointIn"))
+ if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", r->getInputPoints());
}
@@ -554,7 +554,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->getCard()->getCardNo() != cardNo && r->getCardNo() != cardNo) {
if (gdi.ask(L"Vill du koppla isär X från inläst bricka Y?#" + r->getName() +
L"#" + r->getCard()->getCardNoString())) {
- r->setStatus(StatusUnknown, true, false, false);
+ r->setStatus(StatusUnknown, true, oBase::ChangeType::Update, false);
r->setCard(0);
r->setFinishTime(0);
r->synchronize(true);
@@ -581,7 +581,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->getDI().setInt("CardFee", 0);
}
- if (gdi.hasField("Fee"))
+ if (gdi.hasWidget("Fee"))
r->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee")));
gdioutput *gdi_settings = getExtraWindow("ecosettings", false);
@@ -593,16 +593,16 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->setStartTimeS(gdi.getText("Start"));
r->setFinishTimeS(gdi.getText("Finish"));
- if (gdi.hasField("NumShort")) {
+ if (gdi.hasWidget("NumShort")) {
r->setNumShortening(gdi.getSelectedItem("NumShort").first);
}
- if (gdi.hasField("TimeAdjust")) {
+ if (gdi.hasWidget("TimeAdjust")) {
int t = convertAbsoluteTimeMS(gdi.getText("TimeAdjust"));
if (t != NOTIME)
r->setTimeAdjustment(t);
}
- if (gdi.hasField("PointAdjust")) {
+ if (gdi.hasWidget("PointAdjust")) {
r->setPointAdjustment(-gdi.getTextNo("PointAdjust"));
}
@@ -635,25 +635,56 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->setClassId(classId, true);
- if (gdi.hasField("Bib")) {
+ if (gdi.hasWidget("Bib")) {
const wstring &bib = gdi.getText("Bib");
wchar_t pat[32];
int num = oClass::extractBibPattern(bib, pat);
bool lockedForking = r->getClassRef(true) && r->getClassRef(true)->lockedForking();
- r->setBib(bib, num, num>0 && !lockedForking, false);
+ r->setBib(bib, num, num>0 && !lockedForking);
}
- r->setCourseId(gdi.getSelectedItem("RCourse").first);
+ int crsId = gdi.getSelectedItem("RCourse").first;
+ if (crsId > 0 && r->getCourseId() != -1) {
+ pClass cls = r->getClassRef(true);
+ pCourse crs = oe->getCourse(crsId);
+ vector courses;
+ if (cls && crs) {
+ cls->getCourses(r->getLegNumber(), courses);
+ set crsIds;
+ for (auto c : courses)
+ crsIds.insert(c->getId());
+
+ if (crsIds.count(crsId) == 0) {
+ vector clsRunner;
+ oe->getRunners(cls->getId(), -1, clsRunner, false);
+ bool ok = clsRunner.size() < 2;
+ for (auto cr : clsRunner) {
+ if (cr->getCourseId() > 0 && !crsIds.count(cr->getCourseId())) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (!ok) {
+ if (!gdi.ask(L"ask:usecourseinclass"))
+ crsId = 0;
+ }
+ }
+ }
+ }
+
+
+ r->setCourseId(crsId);
RunnerStatus sIn = (RunnerStatus)gdi.getSelectedItem("Status").first;
bool checkStatus = sIn != originalStatus;
if (r->getStatus() != sIn && !noSetStatus) {
- r->setStatus(sIn, true, false);
+ r->setStatus(sIn, true, oBase::ChangeType::Update);
}
r->addClassDefaultFee(false);
vector mp;
- r->evaluateCard(true, mp, 0, true);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
if (r->getClassId(true) != classId && r->getClassId(false) != classId) {
gdi.alert("Deltagarens klass styrs av laget.");
@@ -662,16 +693,16 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
if (checkStatus && sIn != r->getStatus())
gdi.alert("Status matchar inte data i löparbrickan.");
- if (gdi.hasField("StatusIn") && readStatusIn) {
+ if (gdi.hasWidget("StatusIn") && readStatusIn) {
r->setInputStatus(RunnerStatus(gdi.getSelectedItem("StatusIn").first));
r->setInputPlace(gdi.getTextNo("PlaceIn"));
r->setInputTime(gdi.getText("TimeIn"));
- if (gdi.hasField("PointIn"))
+ if (gdi.hasWidget("PointIn"))
r->setInputPoints(gdi.getTextNo("PointIn"));
}
r->synchronizeAll();
-
+
if (r->getClassRef(false) && r->getClassRef(false)->hasClassGlobalDependence()) {
set cls;
cls.insert(r->getClassId(false));
@@ -827,7 +858,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="SetDNS") {
for (size_t k=0; kgetStatus()==StatusUnknown) {
- unknown[k]->setStatus(StatusDNS, true, false);
+ unknown[k]->setStatus(StatusDNS, true, oBase::ChangeType::Update);
unknown[k]->setFlag(oAbstractRunner::FlagAutoDNS, true);
unknown[k]->synchronize(true);
}
@@ -842,7 +873,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
oe->getRunners(0, 0, runners, true);
for (pRunner r : runners) {
if (r->getStatus() == StatusDNS && r->hasFlag(oAbstractRunner::FlagAutoDNS)) {
- r->setStatus(StatusUnknown, true, false);
+ r->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
r->setFlag(oAbstractRunner::FlagAutoDNS, false);
r->synchronize(true);
}
@@ -855,7 +886,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="SetUnknown") {
for (size_t k=0; kgetStatus()==StatusDNS) {
- known_dns[k]->setStatus(StatusUnknown, true, false);
+ known_dns[k]->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
known_dns[k]->synchronize(true);
}
}
@@ -984,7 +1015,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
if (r->getStartTime()>0) {
pRunner newRunner = oe->addRunnerVacant(r->getClassId(true));
newRunner->cloneStartTime(r);
- newRunner->setStartNo(r->getStartNo(), false);
+ newRunner->setStartNo(r->getStartNo(), oBase::ChangeType::Update);
if (r->getCourseId())
newRunner->setCourseId(r->getCourseId());
newRunner->synchronizeAll();
@@ -993,9 +1024,9 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
for (int k=0;kgetNumMulti()+1; k++) {
pRunner rr = r->getMultiRunner(k);
if (rr) {
- rr->setStartTime(0, true, false);
+ rr->setStartTime(0, true, oBase::ChangeType::Update);
//rr->setStartNo(0, false);
- rr->setStatus(StatusCANCEL, true, false);
+ rr->setStatus(StatusCANCEL, true, oBase::ChangeType::Update);
rr->setCardNo(0, false);
}
}
@@ -1047,11 +1078,11 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
card->synchronize();
//Update runner
vector mp;
- r->evaluateCard(true, mp, 0, true);
-
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
+ r->synchronize();
card->fillPunches(gdi, "Punches", r->getCourse(true));
- gdi.setText("Time", r->getRunningTimeS());
+ gdi.setText("Time", r->getRunningTimeS(true));
gdi.selectItemByData("Status", r->getStatus());
}
else if (bi.id=="Check") {
@@ -1314,19 +1345,19 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
oRunner temp(oe, 0);
temp.setTemporary();
- temp.setBib(r->getBib(), 0, false, false);
- temp.setStartNo(r->getStartNo(), false);
+ temp.setBib(r->getBib(), 0, false);
+ temp.setStartNo(r->getStartNo(), oBase::ChangeType::Update);
temp.setClassId(r->getClassId(true), true);
- temp.apply(false, 0, false);
+ temp.apply(oBase::ChangeType::Update, nullptr);
temp.cloneStartTime(r);
r->setClassId(vacancy->getClassId(true), true);
// Remove or create multi runners
r->createMultiRunner(true, true);
- r->apply(false, 0, false);
+ r->apply(oBase::ChangeType::Quiet, nullptr);
r->cloneStartTime(vacancy);
- r->setBib(vacancy->getBib(), 0, false, false);
- r->setStartNo(vacancy->getStartNo(), false);
+ r->setBib(vacancy->getBib(), 0, false);
+ r->setStartNo(vacancy->getStartNo(), oBase::ChangeType::Update);
if (oe->hasPrevStage()) {
if (gdi.ask(L"Vill du sätta resultatet från tidigare etapper till ?"))
@@ -1336,10 +1367,10 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
vacancy->setClassId(temp.getClassId(true), true);
// Remove or create multi runners
vacancy->createMultiRunner(true, true);
- vacancy->apply(false, 0, false);
+ vacancy->apply(oBase::ChangeType::Update, nullptr);
vacancy->cloneStartTime(&temp);
- vacancy->setBib(temp.getBib(), 0, false, false);
- vacancy->setStartNo(temp.getStartNo(), false);
+ vacancy->setBib(temp.getBib(), 0, false);
+ vacancy->setStartNo(temp.getStartNo(), oBase::ChangeType::Update);
r->synchronizeAll();
vacancy->synchronizeAll();
@@ -1361,8 +1392,7 @@ void TabRunner::showCardsList(gdioutput &gdi)
addToolbar(gdi);
gdi.dropLine();
cardModeStartY=gdi.getCY();
- Table *t=oe->getCardsTB();
- gdi.addTable(t,gdi.getCX(),gdi.getCY()+15);
+ gdi.addTable(oCard::getTable(oe), gdi.getCX(), gdi.getCY() + gdi.scaleLength(15));
gdi.registerEvent("CellAction", RunnerCB);
gdi.refresh();
}
@@ -1410,7 +1440,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
wstring club;
int birthYear = 0;
- if (gdi.hasField("Club")) {
+ if (gdi.hasWidget("Club")) {
club = gdi.getText("Club");
pClub pc = oe->getClubCreate(0, club);
if (pc)
@@ -1422,7 +1452,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
r->setClub(club);
int fee = 0;
- if (gdi.hasField("Fee")) {
+ if (gdi.hasWidget("Fee")) {
ListBoxInfo lbi;
if (gdi.getSelectedItem("Fee", lbi) && lbi.data == -1) {
lastFee = L"@";
@@ -1454,7 +1484,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
TabSI::writePayMode(gdi, fee + cardFee, *r);
- if (gdi.hasField("AllStages")) {
+ if (gdi.hasWidget("AllStages")) {
r->setFlag(oRunner::FlagTransferSpecified, true);
r->setFlag(oRunner::FlagTransferNew, gdi.isChecked("AllStages"));
}
@@ -1506,7 +1536,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
tsi.storedInfo.allStages = gdi.isChecked("AllStages");
tsi.storedInfo.rentState = gdi.isChecked("RentCard");
tsi.storedInfo.hasPaid = gdi.isChecked("Paid");
- tsi.storedInfo.payMode = gdi.hasField("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
+ tsi.storedInfo.payMode = gdi.hasWidget("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
return 1;
}
return 0;
@@ -1595,7 +1625,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi) {
runnerReport(oe, gdi, runnersToReport[k].first, runnersToReport[k].second);
}
else {
- oe.calculateTeamResults(false);
+ oe.calculateTeamResults(clsSet, oEvent::ResultType::ClassResult);
set selectedRunners;
bool selHasRes = false;
@@ -1607,13 +1637,13 @@ void TabRunner::showRunnerReport(gdioutput &gdi) {
}
wstring tInfo = t->getName();
- if (t->statusOK()) {
- tInfo += L", " + t->getRunningTimeS() + lang.tl(".S Placering: ") + t->getPlaceS();
+ if (t->statusOK(true)) {
+ tInfo += L", " + t->getRunningTimeS(true) + lang.tl(", Placering: ") + t->getPlaceS();
if (t->getTimeAfter(-1) > 0)
tInfo += L", +" + formatTime(t->getTimeAfter(-1));
}
- else if (t->getStatus() != StatusUnknown) {
- tInfo += L" " + t->getStatusS(true);
+ else if (t->getStatusComputed() != StatusUnknown) {
+ tInfo += L" " + t->getStatusS(true, true);
}
gdi.addStringUT(fontMediumPlus, t->getClass(true));
@@ -1676,7 +1706,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
gdi.dropLine(0.3);
- if (r->statusOK()) {
+ if (r->statusOK(true)) {
int total, finished, dns;
r->getClassRef(true)->getNumResults(r->getLegNumber(), total, finished, dns);
@@ -1693,7 +1723,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
}
}
}
- else if (r->getStatus() != StatusUnknown) {
+ else if (r->getStatusComputed() != StatusUnknown) {
gdi.addStringUT(fontMediumPlus, str).setColor(colorRed);
}
@@ -2125,7 +2155,7 @@ void TabRunner::listRunners(gdioutput &gdi, const vector &r, bool filte
gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, "(" + itos(c) + ")", 190);
}
else {
- TextInfo &ti = gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, L"(" + itow(c) + lang.tl(", reused card") + L")", gdi.scaleLength(100));
+ TextInfo &ti = gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, L"(" + itow(c) + lang.tl(", reused card") + L")", gdi.scaleLength(150));
wstring tt;
for (size_t j = 0; j < out.size(); j++) {
if (out[j] == r[k]->getMultiRunner(0))
@@ -2219,15 +2249,27 @@ void disablePunchCourse(gdioutput &gdi)
disablePunchCourseChange(gdi);
}
-void UpdateStatus(gdioutput &gdi, pRunner r)
-{
+void TabRunner::updateStatus(gdioutput &gdi, pRunner r) {
if (!r) return;
gdi.setText("Start", r->getStartTimeS());
gdi.setText("Finish", r->getFinishTimeS());
- gdi.setText("Time", r->getRunningTimeS());
+ gdi.setText("Time", r->getRunningTimeS(false));
+ gdi.setText("Points", itow(r->getRogainingPoints(false, false)));
+
gdi.selectItemByData("Status", r->getStatus());
- gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
+ auto ri = r->getRaceInfo();
+ BaseInfo *bi = gdi.setText("RunnerInfo", ri.first, true);
+ TextInfo *ti = dynamic_cast(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);
+ }
}
int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
@@ -2313,7 +2355,8 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
if (bi.id == "AddC") {
vector mp;
- r->evaluateCard(true, mp);
+ r->synchronize();
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
pCourse pc = r->getCourse(true);
@@ -2330,30 +2373,30 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
vector nmp;
if (oc->getStatus() == oControl::StatusRogaining) {
- r->evaluateCard(true, nmp, oc->getFirstNumber()); //Add this punch
+ r->evaluateCard(true, nmp, oc->getFirstNumber(), oBase::ChangeType::Update); //Add this punch
}
else {
for (size_t k = 0; k < mp.size(); k++) {
if (oc->hasNumber(mp[k]))
- r->evaluateCard(true, nmp, mp[k]); //Add this punch
+ r->evaluateCard(true, nmp, mp[k], oBase::ChangeType::Update); //Add this punch
}
}
//synchronize SQL
card->synchronize();
- r->synchronize(true);
- r->evaluateCard(true, mp);
+ r->synchronizeAll(true);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->hasManuallyUpdatedTimeStatus();
card->fillPunches(gdi, "Punches", pc);
- UpdateStatus(gdi, r);
+ updateStatus(gdi, r);
}
else if (bi.id == "AddAllC") {
vector mp;
- r->evaluateCard(true, mp);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
vector::iterator it = mp.begin();
while (it != mp.end()) {
vector nmp;
- r->evaluateCard(true, nmp, *it); //Add this punch
+ r->evaluateCard(true, nmp, *it, oBase::ChangeType::Update); //Add this punch
++it;
if (nmp.empty())
break;
@@ -2361,11 +2404,11 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
//synchronize SQL
card->synchronize();
- r->synchronize(true);
- r->evaluateCard(true, mp);
+ r->synchronizeAll(true);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
card->fillPunches(gdi, "Punches", r->getCourse(true));
r->hasManuallyUpdatedTimeStatus();
- UpdateStatus(gdi, r);
+ updateStatus(gdi, r);
}
else if (bi.id == "SaveC") {
if (!savePunchTime(r, gdi))
@@ -2392,10 +2435,10 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
card->synchronize();*/
vector mp;
r->synchronize();
- r->evaluateCard(true, mp);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->hasManuallyUpdatedTimeStatus();
card->fillPunches(gdi, "Punches", r->getCourse(true));
- UpdateStatus(gdi, r);
+ updateStatus(gdi, r);
gdi.selectItemByData("Punches", lbi.data);
}
}
@@ -2419,10 +2462,11 @@ bool TabRunner::savePunchTime(pRunner r, gdioutput &gdi) {
card->setPunchTime(pp, gdi.getText("PTime"));
vector mp;
- r->evaluateCard(true, mp);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
//synchronize SQL
card->synchronize();
+ r->synchronizeAll();
return true;
}
@@ -2440,10 +2484,9 @@ bool TabRunner::loadPage(gdioutput &gdi)
int basex = gdi.getCX();
if (currentMode == 1) {
- Table *tbl = oe->getRunnersTB();
addToolbar(gdi);
gdi.dropLine(1);
- gdi.addTable(tbl, basex, gdi.getCY());
+ gdi.addTable(oRunner::getTable(oe), basex, gdi.getCY());
return true;
}
else if (currentMode == 2) {
@@ -2625,8 +2668,8 @@ bool TabRunner::loadPage(gdioutput &gdi)
gdi.popX();
gdi.selectItemByData("Status", 0);
- gdi.addString("RunnerInfo", 1, "").setColor(colorRed);
-
+ gdi.addString("RunnerInfo", 0, "").setColor(colorRed);
+ gdi.dropLine(0.4);
const bool multiDay = oe->hasPrevStage();
if (multiDay) {
@@ -2714,13 +2757,13 @@ bool TabRunner::loadPage(gdioutput &gdi)
gdi.dropLine(0.2);
gdi.fillRight();
gdi.addButton(gdi.getCX(), gdi.getCY(), gdi.scaleLength(120), "SplitPrint",
- "Skriv ut sträcktider", RunnerCB, "", false, false).isEdit(true).setExtra(0);
+ "Sträcktider", RunnerCB, "", false, false).isEdit(true).setExtra(0);
gdi.addButton("PrintSettings", "...", RunnerCB, "Inställningar").isEdit(true).setExtra(0);
gdi.dropLine(2.5);
gdi.setCX(contX);
gdi.addButton(gdi.getCX(), gdi.getCY(), gdi.scaleLength(120), "SplitPrint",
- "Skriv ut startbevis", RunnerCB, "", false, false).isEdit(true).setExtra(1);
+ "Startbevis", RunnerCB, "", false, false).isEdit(true).setExtra(1);
gdi.addButton("PrintSettings", "...", RunnerCB, "Inställningar").isEdit(true).setExtra(1);
gdi.pushY();
@@ -2908,7 +2951,7 @@ int TabRunner::numShorteningLevels() const {
}
void TabRunner::updateNumShort(gdioutput &gdi, pCourse crs, pRunner r) {
- if (gdi.hasField("NumShort")) {
+ if (gdi.hasWidget("NumShort")) {
if (crs && crs->getShorterVersion().first) {
gdi.enableInput("NumShort");
if (r)
@@ -3086,12 +3129,12 @@ void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
auto &db = oe->getRunnerDatabase();
auto runner = db.getRunnerByIndex(ix);
- if (runner && gdi.hasField("Club") && gdi.getText("Club").empty()) {
+ if (runner && gdi.hasWidget("Club") && gdi.getText("Club").empty()) {
pClub club = db.getClub(runner->dbe().clubNo);
if (club)
gdi.setText("Club", club->getName());
}
- if (runner && runner->dbe().cardNo > 0 && gdi.hasField("CardNo") && gdi.getText("CardNo").empty()) {
+ if (runner && runner->dbe().cardNo > 0 && gdi.hasWidget("CardNo") && gdi.getText("CardNo").empty()) {
gdi.setText("CardNo", runner->dbe().cardNo);
}
}
@@ -3102,7 +3145,7 @@ void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
pClub TabRunner::extractClub(oEvent *oe, gdioutput &gdi) {
oClub *dbClub = nullptr;
- if (gdi.hasField("Club")) {
+ if (gdi.hasWidget("Club")) {
auto &db = oe->getRunnerDatabase();
int clubId = gdi.getExtraInt("Club");
if (clubId >= 0) {
diff --git a/code/TabRunner.h b/code/TabRunner.h
index 309d721..4acad7a 100644
--- a/code/TabRunner.h
+++ b/code/TabRunner.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -90,7 +90,7 @@ private:
int numShorteningLevels() const;
void updateNumShort(gdioutput &gdi, pCourse crs, pRunner r);
-
+ static void updateStatus(gdioutput &gdi, pRunner r);
static void autoGrowCourse(gdioutput &gdi);
void loadEconomy(gdioutput &gdi, oRunner &r);
diff --git a/code/TabSI.cpp b/code/TabSI.cpp
index 68288de..6eb9974 100644
--- a/code/TabSI.cpp
+++ b/code/TabSI.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -67,8 +67,7 @@ TabSI::TabSI(oEvent *poe):TabBase(poe), activeSIC(ConvertedTimeStatus::Unknown)
lastClubId=0;
lastClassId=0;
- logger = 0;
-
+
minRunnerId = 0;
inputId = 0;
printErrorShown = false;
@@ -77,9 +76,6 @@ TabSI::TabSI(oEvent *poe):TabBase(poe), activeSIC(ConvertedTimeStatus::Unknown)
TabSI::~TabSI(void)
{
- if (logger!=0)
- delete logger;
- logger = 0;
}
@@ -93,8 +89,8 @@ static void entryTips(gdioutput &gdi) {
void TabSI::logCard(gdioutput &gdi, const SICard &card)
{
- if (logger == 0) {
- logger = new csvparser;
+ if (!logger) {
+ logger = make_shared();
wstring readlog = L"sireadlog_" + getLocalTimeFileName() + L".csv";
wchar_t file[260];
wstring subfolder = makeValidFileName(oe->getName(), true);
@@ -124,6 +120,20 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (type == GUI_BUTTON) {
ButtonInfo bi = *(ButtonInfo *)data;
+ if (bi.id == "LockFunction") {
+ lockedFunction = true;
+ loadPage(gdi);
+ }
+ else if (bi.id == "UnlockFunction") {
+ lockedFunction = false;
+ loadPage(gdi);
+ }
+ else if (bi.id == "AllowStart")
+ allowStart = gdi.isChecked(bi.id);
+ else if (bi.id == "AllowControl")
+ allowControl = gdi.isChecked(bi.id);
+ else if (bi.id == "AllowFinish")
+ allowFinish = gdi.isChecked(bi.id);
if (bi.id == "ClearMemory") {
if (gdi.ask(L"Do you want to clear the card memory?")) {
savedCards.clear();
@@ -675,7 +685,9 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
int year = 0;
pRunner r = gEvent->addRunner(gdi.getText("Runners"), club,
classes[0]->getId(), activeSIC.CardNumber, year, true);
-
+ if (oe->isHiredCard(activeSIC.CardNumber)) {
+ r->getDI().setInt("CardFee", oe->getBaseCardFee());
+ }
gdi.setData("RunnerId", r->getId());
gdi.restore();
@@ -742,6 +754,10 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
int year = 0;
pRunner r = gEvent->addRunner(gdi.getText("Runners"), club,
lbi.data, activeSIC.CardNumber, year, true);
+
+ if (activeSIC.CardNumber > 0 && oe->isHiredCard(activeSIC.CardNumber)) {
+ r->getDI().setInt("CardFee", oe->getBaseCardFee());
+ }
r->setStartTimeS(gdi.getText("StartTime"));
r->setCardNo(activeSIC.CardNumber, false);
@@ -777,7 +793,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
oe->getClass(1)->getNumRunners(false, false, false) == 0) {
pclass = oe->getClass(1);
pclass->setType(L"");
- pclass->setName(gdi.getText("ClassName"));
+ pclass->setName(gdi.getText("ClassName"), true);
pc = pclass->getCourse();
if (pc)
pc->setName(gdi.getText("ClassName"));
@@ -798,6 +814,9 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pRunner r = gEvent->addRunner(gdi.getText("Runners"), gdi.getText("Club", true),
pclass->getId(), activeSIC.CardNumber, year, true);
+ if (activeSIC.CardNumber > 0 && oe->isHiredCard(activeSIC.CardNumber)) {
+ r->getDI().setInt("CardFee", oe->getBaseCardFee());
+ }
r->setStartTimeS(gdi.getText("StartTime"));
r->setCardNo(activeSIC.CardNumber, false);
gdi.restore();
@@ -925,7 +944,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
di.setString("Phone", gdi.getText("Phone"));
- r->setFlag(oRunner::FlagTransferSpecified, gdi.hasField("AllStages"));
+ r->setFlag(oRunner::FlagTransferSpecified, gdi.hasWidget("AllStages"));
r->setFlag(oRunner::FlagTransferNew, gdi.isChecked("AllStages"));
r->setStartTimeS(gdi.getText("StartTime"));
@@ -943,7 +962,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
}
}
else {
- r->setBib(bibIn, 0, false, false);
+ r->setBib(bibIn, 0, false);
bib = L", " + lang.tl(L"Nummerlapp: ") + r->getBib();
}
r->synchronize();
@@ -1178,7 +1197,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pRunner r = gEvent->getRunner(bi.data, 0);
if (r) {
gdi.setData("RunnerId", bi.data);
- if (gdi.hasField("Club"))
+ if (gdi.hasWidget("Club"))
gdi.setText("Club", r->getClub());
gdi.setText("FindMatch", lang.tl("Press Enter to continue"), true);
}
@@ -1203,7 +1222,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.restore("SIPageLoaded");
mode = SIMode(bi.data);
gdi.setInputStatus("StartInfo", mode == ModeEntry);
-
+
if (mode==ModeAssignCards || mode==ModeEntry) {
if (mode==ModeAssignCards) {
gdi.dropLine(1);
@@ -1231,6 +1250,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
showManualInput(gdi);
}
else if (mode == ModeCardData) {
+ numSavedCardsOnCmpOpen = savedCards.size();
showModeCardData(gdi);
}
else if (mode == ModeCheckCards) {
@@ -1239,6 +1259,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
else if (mode == ModeRegisterCards) {
showRegisterHiredCards(gdi);
}
+ updateReadoutFunction(gdi);
gdi.refresh();
}
else if (bi.id=="Fee") {
@@ -1282,7 +1303,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (!db_r && lastClubId)
db_r = oe->dbLookUpByName(bi.text, lastClubId, 0, 0);
- if (db_r && gdi.hasField("Club")) {
+ if (db_r && gdi.hasWidget("Club")) {
gdi.setText("Club", db_r->getClub());
}
}
@@ -1325,7 +1346,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.setInputFocus("OK1");
gdi.setText("Runners", r->getName());
gdi.setData("RunnerId", runnerMatchedId);
- if (gdi.hasField("Club"))
+ if (gdi.hasWidget("Club"))
gdi.setText("Club", r->getClub());
inputId = -1;
gdi.setText("FindMatch", lang.tl("Press Enter to continue"), true);
@@ -1530,7 +1551,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
storedInfo.clear();
storedInfo.storedName = gdi.getText("Name");
storedInfo.storedCardNo = gdi.getText("CardNo");
- storedInfo.storedClub = gdi.hasField("Club") ? gdi.getText("Club") : L"";
+ storedInfo.storedClub = gdi.hasWidget("Club") ? gdi.getText("Club") : L"";
storedInfo.storedFee = gdi.getText("Fee", true);
ListBoxInfo lbi;
@@ -1542,7 +1563,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
storedInfo.allStages = gdi.isChecked("AllStages");
storedInfo.rentState = gdi.isChecked("RentCard");
storedInfo.hasPaid = gdi.isChecked("Paid");
- storedInfo.payMode = gdi.hasField("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
+ storedInfo.payMode = gdi.hasWidget("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
}
return 1;
}
@@ -1748,18 +1769,38 @@ bool TabSI::loadPage(gdioutput &gdi) {
if (!oe->empty()) {
gdi.setCX(xb + gdi.scaleLength(10));
gdi.setCY(yb + gdi.scaleLength(10));
- gdi.addString("", fontMediumPlus, "Funktion:");
- gdi.addSelection("ReadType", 200, 200, SportIdentCB);
- gdi.addItem("ReadType", lang.tl("Avläsning/radiotider"), ModeReadOut);
- gdi.addItem("ReadType", lang.tl("Tilldela hyrbrickor"), ModeAssignCards);
- gdi.addItem("ReadType", lang.tl("Avstämning hyrbrickor"), ModeCheckCards);
- gdi.addItem("ReadType", lang.tl("Registrera hyrbrickor"), ModeRegisterCards);
- gdi.addItem("ReadType", lang.tl("Anmälningsläge"), ModeEntry);
- gdi.addItem("ReadType", lang.tl("Print card data"), ModeCardData);
+
+ if (!lockedFunction) {
+ gdi.addString("", fontMediumPlus, "Funktion:");
+ gdi.addSelection("ReadType", 200, 200, SportIdentCB);
+ gdi.addItem("ReadType", lang.tl("Avläsning/radiotider"), ModeReadOut);
+ gdi.addItem("ReadType", lang.tl("Tilldela hyrbrickor"), ModeAssignCards);
+ gdi.addItem("ReadType", lang.tl("Avstämning hyrbrickor"), ModeCheckCards);
+ gdi.addItem("ReadType", lang.tl("Registrera hyrbrickor"), ModeRegisterCards);
+ gdi.addItem("ReadType", lang.tl("Anmälningsläge"), ModeEntry);
+ gdi.addItem("ReadType", lang.tl("Print card data"), ModeCardData);
+ gdi.selectItemByData("ReadType", mode);
- gdi.selectItemByData("ReadType", mode);
- gdi.dropLine(2.5);
- gdi.setCX(xb + gdi.scaleLength(10));
+ gdi.dropLine(-0.1);
+ gdi.addButton("LockFunction", "LÃ¥s funktion...", SportIdentCB);
+ readoutFunctionX = gdi.getCX();
+ readoutFunctionY = gdi.getCY();
+ gdi.dropLine(0.3);
+
+ gdi.addString("Allow", 0, "Tillåt:");
+ gdi.addCheckbox("AllowStart", "Start", SportIdentCB, allowStart);
+ gdi.addCheckbox("AllowControl", "Radio", SportIdentCB, allowControl);
+ gdi.addCheckbox("AllowFinish", "MÃ¥l", SportIdentCB, allowFinish);
+
+ updateReadoutFunction(gdi);
+
+ gdi.dropLine(2.5);
+ gdi.setCX(xb + gdi.scaleLength(10));
+ }
+ else {
+ gdi.addButton("UnlockFunction", "LÃ¥s upp", SportIdentCB);
+ gdi.dropLine(0.2);
+ }
}
else {
mode = ModeCardData;
@@ -1831,6 +1872,14 @@ bool TabSI::loadPage(gdioutput &gdi) {
return true;
}
+void TabSI::updateReadoutFunction(gdioutput &gdi) {
+ bool hide = mode != SIMode::ModeReadOut;
+ gdi.hideWidget("Allow", hide);
+ gdi.hideWidget("AllowStart", hide);
+ gdi.hideWidget("AllowControl", hide);
+ gdi.hideWidget("AllowFinish", hide);
+}
+
void InsertSICard(gdioutput &gdi, SICard &sic)
{
TabSI &tsi = dynamic_cast(*gdi.getTabs().get(TSITab));
@@ -1856,6 +1905,10 @@ pRunner TabSI::autoMatch(const SICard &sic, pRunner db_r)
if (classes.size()==1 && dist>=-1 && dist<=1) { //Almost perfect match found. Assume it is it!
r = gEvent->addRunnerFromDB(db_r, classes[0]->getId(), true);
r->setCardNo(sic.CardNumber, false);
+
+ if (oe->isHiredCard(sic.CardNumber)) {
+ r->getDI().setInt("CardFee", oe->getBaseCardFee());
+ }
}
else r=0; //Do not assume too much...
}
@@ -1968,6 +2021,11 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
else
sic.analyseHour12Time(zt2);
}
+
+ // Write read card to log
+ logCard(gdi, sic);
+
+ bool first = savedCards.size() == numSavedCardsOnCmpOpen;
savedCards.push_back(make_pair(savedCardUniqueId++, sic));
if (printSplits) {
@@ -1980,11 +2038,15 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
if (pageLoaded) {
gdi.enableInput("CreateCompetition", true);
- printCard(gdi, savedCards.back().first, false);
+ printCard(gdi, savedCards.back().first, nullptr, false);
gdi.dropLine();
gdi.refreshFast();
gdi.scrollToBottom();
}
+
+ if (first && !oe->empty())
+ gdi.alert(L"warn:printmodeonly");
+
return;
}
gEvent->synchronizeList({ oListId::oLCardId, oListId::oLRunnerId });
@@ -2209,7 +2271,7 @@ void TabSI::startInteractive(gdioutput &gdi, const SICard &sic, pRunner r, pRunn
if (db_r)
gdi.setText("Club", db_r->getClub()); //Data from DB
}
- if (gdi.getText("Runners").empty() || !gdi.hasField("Club"))
+ if (gdi.getText("Runners").empty() || !gdi.hasWidget("Club"))
gdi.setInputFocus("Runners");
else
gdi.setInputFocus("Club");
@@ -2444,7 +2506,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
if (pcourse)
pcourse->synchronize();
else if (pclass && pclass->hasDirectResult())
- runner->setStatus(StatusOK, true, false, false);
+ runner->setStatus(StatusOK, true, oBase::ChangeType::Update, false);
//silent=true;
SICard sic(csic);
wstring info, warnings, cardno;
@@ -2502,20 +2564,21 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
runner->setCard(0);
if (csic.statusOK) {
- runner->setStatus(StatusOK, true, false);
+ runner->setStatus(StatusOK, true, oBase::ChangeType::Update);
runner->setFinishTime(csic.relativeFinishTime);
}
else if (csic.statusDNF) {
- runner->setStatus(StatusDNF, true, false);
+ runner->setStatus(StatusDNF, true, oBase::ChangeType::Update);
runner->setFinishTime(0);
}
else {
- runner->setStatus(StatusMP, true, false);
+ runner->setStatus(StatusMP, true, oBase::ChangeType::Update);
runner->setFinishTime(csic.relativeFinishTime);
}
cardno = makeDash(L"-");
- runner->evaluateCard(true, MP, false, false);
+ runner->evaluateCard(true, MP, 0, oBase::ChangeType::Update);
+ runner->synchronizeAll(true);
runner->hasManuallyUpdatedTimeStatus();
}
@@ -2531,13 +2594,14 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
if (!warnings.empty())
rc.bottom+=gdi.getLineHeight();
- if (runner->getStatus()==StatusOK) {
- set clsSet;
- if (runner->getClassId(false))
- clsSet.insert(runner->getClassId(true));
- gEvent->calculateResults(clsSet, oEvent::ResultType::ClassResult);
- if (runner->getTeam())
- gEvent->calculateTeamResults(runner->getLegNumber(), false);
+ set clsSet;
+ if (runner->getClassId(false))
+ clsSet.insert(runner->getClassId(true));
+ gEvent->calculateResults(clsSet, oEvent::ResultType::ClassResult);
+ if (runner->getTeam())
+ gEvent->calculateTeamResults(clsSet, oEvent::ResultType::ClassResult);
+
+ if (runner->getStatusComputed()==StatusOK || isPossibleResultStatus(runner->getStatusComputed())) {
bool qfClass = runner->getClassId(false) != runner->getClassId(true);
wstring placeS = (runner->getTeam() && !qfClass) ?
runner->getTeam()->getLegPlaceS(runner->getLegNumber(), false) :
@@ -2553,27 +2617,27 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
gdi.addStringUT(rc.top+6+2*lh, rc.left+20, 0, warnings);
wstring statusline = lang.tl(L"Status OK, ") +
- lang.tl(L"Tid: ") + runner->getRunningTimeS() +
- lang.tl(L", Prel. placering: ") + placeS;
-
+ lang.tl(L"Tid: ") + runner->getRunningTimeS(true);
+ if (!placeS.empty())
+ statusline += lang.tl(L", Prel. placering: ") + placeS;
statusline += lang.tl(L", Prel. bomtid: ") + runner->getMissedTimeS();
gdi.addStringUT(rc.top+6+lh, rc.left+20, 0, statusline);
- if (runner->isHiredCard())
+ if (runner->isHiredCard() || oe->isHiredCard(sic.CardNumber))
rentCardInfo(gdi, rc.right-rc.left);
gdi.scrollToBottom();
}
else {
wstring msg = L"#" + runner->getName() + L" (" + cardno + L")\n"+
runner->getClub() + L". " + runner->getClass(true) +
- L"\n" + lang.tl("Tid: ") + runner->getRunningTimeS() + lang.tl(L", Plats ") + placeS;
+ L"\n" + lang.tl("Tid: ") + runner->getRunningTimeS(true) + lang.tl(L", Plats ") + placeS;
gdi.addInfoBox("SIINFO", msg, 10000);
}
}
else {
- wstring msg=lang.tl(L"Status: ") + runner->getStatusS(true);
+ wstring msg=lang.tl(L"Status: ") + runner->getStatusS(true, true);
if (!MP.empty()) {
msg=msg + L", (";
@@ -2625,20 +2689,32 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
void TabSI::processPunchOnly(gdioutput &gdi, const SICard &csic)
{
- SICard sic=csic;
+ SICard sic = csic;
DWORD loaded;
gEvent->convertTimes(nullptr, sic);
- oFreePunch *ofp=0;
-
- if (sic.nPunch==1)
- ofp=gEvent->addFreePunch(sic.Punch[0].Time, sic.Punch[0].Code, sic.CardNumber, true);
- else if (sic.FinishPunch.Time > 0)
- ofp=gEvent->addFreePunch(sic.FinishPunch.Time, oPunch::PunchFinish, sic.CardNumber, true);
- else if (sic.StartPunch.Time > 0)
- ofp=gEvent->addFreePunch(sic.StartPunch.Time, oPunch::PunchStart, sic.CardNumber, true);
- else
- ofp=gEvent->addFreePunch(sic.CheckPunch.Time, oPunch::PunchCheck, sic.CardNumber, true);
-
+ oFreePunch *ofp = 0;
+ wstring accessError;
+ if (sic.nPunch == 1) {
+ if (allowControl)
+ ofp = gEvent->addFreePunch(sic.Punch[0].Time, sic.Punch[0].Code, sic.CardNumber, true);
+ else
+ accessError = L"Radio tillåts inte (X)#" + itow(sic.CardNumber);
+ }
+ else if (sic.FinishPunch.Time > 0) {
+ if (allowFinish)
+ ofp = gEvent->addFreePunch(sic.FinishPunch.Time, oPunch::PunchFinish, sic.CardNumber, true);
+ else
+ accessError = L"Målstämpling tillåts inte (X)#" + itow(sic.CardNumber);
+ }
+ else if (sic.StartPunch.Time > 0) {
+ if (allowStart)
+ ofp = gEvent->addFreePunch(sic.StartPunch.Time, oPunch::PunchStart, sic.CardNumber, true);
+ else
+ accessError = L"Startstämpling tillåts inte (X)#" + itow(sic.CardNumber);
+ }
+ else {
+ ofp = gEvent->addFreePunch(sic.CheckPunch.Time, oPunch::PunchCheck, sic.CardNumber, true);
+ }
if (ofp) {
pRunner r = ofp->getTiedRunner();
if (gdi.getData("SIPageLoaded", loaded)){
@@ -2650,7 +2726,7 @@ void TabSI::processPunchOnly(gdioutput &gdi, const SICard &csic)
gdi.dropLine();
}
else {
- wstring str=L"SI " + itow(sic.CardNumber) + lang.tl(" (okänd) stämplade vid ") + ofp->getSimpleString();
+ wstring str= itow(sic.CardNumber) + lang.tl(" (okänd) stämplade vid ") + ofp->getSimpleString();
gdi.addStringUT(0, str);
gdi.dropLine(0.3);
}
@@ -2659,14 +2735,21 @@ void TabSI::processPunchOnly(gdioutput &gdi, const SICard &csic)
tabForceSync(gdi, gEvent);
gdi.makeEvent("DataUpdate", "sireadout", r ? r->getId() : 0, 0, true);
-
+ }
+ else if (!accessError.empty()) {
+ if (gdi.getData("SIPageLoaded", loaded)) {
+ gdi.addString("", 0, accessError).setColor(colorDarkRed);
+ gdi.dropLine(0.3);
+ gdi.scrollToBottom();
+ }
+ else
+ gdi.addInfoBox("Access", accessError);
}
checkMoreCardsInQueue(gdi);
return;
}
-
void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
{
gdi.setText("CardNo", sic.CardNumber);
@@ -2692,10 +2775,10 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
name=wstring(sic.lastName) + L", " + wstring(sic.firstName);
gdi.setText("Name", name);
- if (gdi.hasField("Club") && !club.empty())
+ if (gdi.hasWidget("Club") && !club.empty())
gdi.setText("Club", club);
- if (club.empty() && gdi.hasField("Club"))
+ if (club.empty() && gdi.hasWidget("Club"))
gdi.setInputFocus("Club");
else if (name.empty())
gdi.setInputFocus("Name");
@@ -2863,27 +2946,27 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r) {
gdi.setText("CardNo", r->getCardNo());
gdi.setText("Name", r->getNameRaw());
- if (gdi.hasField("Club")) {
+ if (gdi.hasWidget("Club")) {
gdi.selectItemByData("Club", r->getClubId());
}
gdi.selectItemByData("Class", r->getClassId(true));
oDataConstInterface dci = r->getDCI();
- if (gdi.hasField("Fee"))
+ if (gdi.hasWidget("Fee"))
gdi.setText("Fee", oe->formatCurrency(dci.getInt("Fee")));
gdi.setText("Phone", dci.getString("Phone"));
gdi.setText("Bib", r->getBib());
gdi.check("RentCard", dci.getInt("CardFee") != 0);
- if (gdi.hasField("Paid"))
+ if (gdi.hasWidget("Paid"))
gdi.check("Paid", dci.getInt("Paid")>0);
- else if (gdi.hasField("PayMode")) {
+ else if (gdi.hasWidget("PayMode")) {
int paidId = dci.getInt("Paid") > 0 ? r->getPaymentMode() : 1000;
gdi.selectItemByData("PayMode", paidId);
}
- if (gdi.hasField("AllStages")) {
+ if (gdi.hasWidget("AllStages")) {
gdi.check("AllStages", r->hasFlag(oRunner::FlagTransferNew));
}
}
@@ -2926,7 +3009,7 @@ void TabSI::updateEntryInfo(gdioutput &gdi)
wstring method;
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy)) {
bool invoice = true;
- if (gdi.hasField("PayMode")) {
+ if (gdi.hasWidget("PayMode")) {
invoice = gdi.getSelectedItem("PayMode").first == 1000;
}
else
@@ -2956,7 +3039,7 @@ void TabSI::generateSplits(const pRunner r, gdioutput &gdi)
else {
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
vector mp;
- r->evaluateCard(true, mp);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->printSplits(gdiprint);
printProtected(gdi, gdiprint);
//gdiprint.print(splitPrinter, oe, false, true);
@@ -3217,7 +3300,7 @@ void TabSI::showModeCardData(gdioutput &gdi) {
gdi.dropLine(3);
gdi.popX();
bool first = true;
- for (list >::iterator it = savedCards.begin(); it != savedCards.end(); ++it) {
+ for (auto it = savedCards.begin(); it != savedCards.end(); ++it) {
gdi.dropLine(0.5);
if (!first) {
RECT rc = {30, gdi.getCY(), gdi.scaleLength(250), gdi.getCY() + 3};
@@ -3225,7 +3308,7 @@ void TabSI::showModeCardData(gdioutput &gdi) {
}
first = false;
- printCard(gdi, it->first, false);
+ printCard(gdi, it->first, &it->second, false);
}
}
@@ -3235,10 +3318,10 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
int cardId = ti.getExtraInt();
SICard &card = tabSI->getCard(cardId);
ti.id = "card" + itos(cardId);
- gdi.removeControl("CardName");
- gdi.removeControl("ClubName");
- gdi.removeControl("OKCard");
- gdi.removeControl("CancelCard");
+ gdi.removeWidget("CardName");
+ gdi.removeWidget("ClubName");
+ gdi.removeWidget("OKCard");
+ gdi.removeWidget("CancelCard");
wstring name, club;
if (card.firstName[0])
@@ -3283,10 +3366,10 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
gdi.setText("card" + itos(cardId), s, true);
}
- gdi.removeControl("CardName");
- gdi.removeControl("ClubName");
- gdi.removeControl("OKCard");
- gdi.removeControl("CancelCard");
+ gdi.removeWidget("CardName");
+ gdi.removeWidget("ClubName");
+ gdi.removeWidget("OKCard");
+ gdi.removeWidget("CancelCard");
}
else if (type == GUI_FOCUS) {
InputInfo &ii = dynamic_cast(info);
@@ -3297,8 +3380,11 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
}
}
-void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
- SICard &c = getCard(cardId);
+void TabSI::printCard(gdioutput &gdi, int cardId, SICard *crdRef, bool forPrinter) const {
+ if (crdRef == nullptr)
+ crdRef = &getCard(cardId);
+
+ SICard &c = *crdRef;
if (c.readOutTime[0] == 0)
strcpy_s(c.readOutTime, getLocalTimeN().c_str());
@@ -3421,7 +3507,7 @@ int TabSI::analyzePunch(SIPunch &p, int &start, int &accTime, int &days) {
void TabSI::generateSplits(int cardId, gdioutput &gdi) {
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
- printCard(gdiprint, cardId, true);
+ printCard(gdiprint, cardId, nullptr, true);
printProtected(gdi, gdiprint);
}
@@ -3511,7 +3597,7 @@ void TabSI::createCompetitionFromCards(gdioutput &gdi) {
if (zeroTime < 0)
zeroTime += 3600 * 24;
zeroTime -= zeroTime % 1800;
- oe->setZeroTime(formatTime(zeroTime));
+ oe->setZeroTime(formatTime(zeroTime), false);
// Add competitors
for (size_t k = 0; k < cards.size(); k++) {
@@ -3578,6 +3664,17 @@ void TabSI::clearCompetitionData() {
checkedCardFlags.clear();
currentAssignIndex = 0;
warnedClassOutOfMaps.clear();
+
+ lockedFunction = false;
+ allowControl = true;
+ allowFinish = true;
+ allowStart = false;
+
+ if (mode == ModeCardData)
+ mode = SIMode::ModeReadOut;
+
+ logger.reset();
+ numSavedCardsOnCmpOpen = savedCards.size();
}
SICard &TabSI::getCard(int id) const {
@@ -3761,7 +3858,7 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
wstring cp = r[k]->getCompleteIdentification();
if (r[k]->getStatus() != StatusUnknown)
- cp += L" " + r[k]->getStatusS(true);
+ cp += L" " + r[k]->getStatusS(true, true);
else
cp += makeDash(L" -");
@@ -3889,7 +3986,7 @@ bool TabSI::writePayMode(gdioutput &gdi, int amount, oRunner &r) {
int paid = 0;
bool hasPaid = false;
- if (gdi.hasField("PayMode"))
+ if (gdi.hasWidget("PayMode"))
hasPaid = gdi.getSelectedItem("PayMode").first != 1000;
bool fixPay = gdi.isChecked("Paid");
@@ -3928,7 +4025,7 @@ bool TabSI::checkpPrintQueue(gdioutput &gdi) {
printPunchRunnerIdQueue.pop_front();
pRunner r = oe->getRunner(rid, 0);
if (r) {
- r->evaluateCard(true, mp);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->printSplits(gdiprint);
}
gdiprint.dropLine(4);
@@ -3950,7 +4047,7 @@ void TabSI::printSIInfo(gdioutput &gdi, const wstring &port) const {
oClub *TabSI::extractClub(gdioutput &gdi) const {
auto &db = oe->getRunnerDatabase();
oClub *dbClub = nullptr;
- if (gdi.hasField("Club")) {
+ if (gdi.hasWidget("Club")) {
int clubId = gdi.getExtraInt("Club");
if (clubId > 0) {
dbClub = db.getClub(clubId-1);
@@ -4128,14 +4225,14 @@ void TabSI::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
}
}
if (r) {
- if (gdi.hasField("Club") && r->dbe().clubNo) {
+ if (gdi.hasWidget("Club") && r->dbe().clubNo) {
if (gdi.getText("Club").empty()) {
auto pclub = oe->getRunnerDatabase().getClub(r->dbe().clubNo);
if (pclub)
gdi.setText("Club", pclub->getName());
}
}
- if (gdi.hasField("CardNo") && r->dbe().cardNo) {
+ if (gdi.hasWidget("CardNo") && r->dbe().cardNo) {
if (gdi.getText("CardNo").empty())
gdi.setText("CardNo", r->dbe().cardNo);
}
diff --git a/code/TabSI.h b/code/TabSI.h
index 0f58a4d..9f8a299 100644
--- a/code/TabSI.h
+++ b/code/TabSI.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -81,8 +81,13 @@ private:
bool printErrorShown;
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
- //Interactive card assign
+ //Operation mode
SIMode mode;
+ bool lockedFunction = false;
+ bool allowControl = true;
+ bool allowFinish = true;
+ bool allowStart = false;
+
int currentAssignIndex;
void printSIInfo(gdioutput &gdi, const wstring &port) const;
@@ -96,7 +101,7 @@ private:
int lastClubId;
wstring lastFee;
int inputId;
-
+ int numSavedCardsOnCmpOpen = 0;
void showCheckCardStatus(gdioutput &gdi, const string &cmd);
void showRegisterHiredCards(gdioutput &gdi);
@@ -142,7 +147,7 @@ private:
void generateSplits(const pRunner r, gdioutput &gdi);
int logcounter;
- csvparser *logger;
+ shared_ptr logger;
string insertCardNumberField;
@@ -159,7 +164,7 @@ private:
void showModeCardData(gdioutput &gdi);
- void printCard(gdioutput &gdi, int cardId, bool forPrinter) const;
+ void printCard(gdioutput &gdi, int cardId, SICard *crdRef, bool forPrinter) const;
void generateSplits(int cardId, gdioutput &gdi);
static int analyzePunch(SIPunch &p, int &start, int &accTime, int &days);
@@ -197,6 +202,10 @@ private:
oClub *extractClub(gdioutput &gdi) const;
RunnerWDBEntry *extractRunner(gdioutput &gdi) const;
+ void updateReadoutFunction(gdioutput &gdi);
+ int readoutFunctionX = 0;
+ int readoutFunctionY = 0;
+
protected:
void clearCompetitionData();
diff --git a/code/TabSpeaker.cpp b/code/TabSpeaker.cpp
index b41a9c1..40d3638 100644
--- a/code/TabSpeaker.cpp
+++ b/code/TabSpeaker.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -214,7 +214,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.clearPage(false);
gdi.addButton("Cancel", "Stäng", tabSpeakerCB);
gdi.dropLine();
- gdi.addTable(oe->getPunchesTB(), gdi.getCX(), gdi.getCY());
+ gdi.addTable(oFreePunch::getTable(oe), gdi.getCX(), gdi.getCY());
gdi.refresh();
}
else if (bu.id == "Report") {
@@ -745,7 +745,7 @@ void TabSpeaker::generateControlList(gdioutput &gdi, int classId)
return;
bool keepLegs = false;
- if (gdi.hasField("Leg")) {
+ if (gdi.hasWidget("Leg")) {
DWORD clsSel = 0;
if (gdi.getData("ClassSelection", clsSel) && clsSel == pc->getId()) {
gdi.restore("LegSelection", true);
@@ -1125,17 +1125,17 @@ bool TabSpeaker::loadPage(gdioutput &gdi) {
if (classId == -1) {
string btn = "Events";
- if (gdi.hasField(btn))
+ if (gdi.hasWidget(btn))
gdi.sendCtrlMessage(btn);
}
else if (classId == -2) {
string btn = "Report";
- if (gdi.hasField(btn))
+ if (gdi.hasWidget(btn))
gdi.sendCtrlMessage(btn);
}
else if (classId > 0) {
string btn = "cid" + itos(classId);
- if (gdi.hasField(btn))
+ if (gdi.hasWidget(btn))
gdi.sendCtrlMessage(btn);
}
@@ -1265,7 +1265,7 @@ void TabSpeaker::savePriorityClass(gdioutput &gdi) {
pRunner r = oe->getRunner(runnersToSet[k], 0);
if (r) {
int id = runnersToSet[k];
- if (!gdi.hasField("A" + itos(id))) {
+ if (!gdi.hasWidget("A" + itos(id))) {
runnersToSet.clear(); //Page not loaded. Abort.
return;
}
diff --git a/code/TabSpeaker.h b/code/TabSpeaker.h
index 433d9bc..ab66693 100644
--- a/code/TabSpeaker.h
+++ b/code/TabSpeaker.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/TabTeam.cpp b/code/TabTeam.cpp
index 804918c..36f6cb9 100644
--- a/code/TabTeam.cpp
+++ b/code/TabTeam.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -179,7 +179,7 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
{
if (t){
t->synchronize();
- t->evaluate(false);
+ t->evaluate(oBase::ChangeType::Quiet);
teamId=t->getId();
@@ -192,7 +192,7 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.selectItemByData("RClass", t->getClassId(false));
gdi.selectItemByData("Teams", t->getId());
- if (gdi.hasField("StatusIn")) {
+ if (gdi.hasWidget("StatusIn")) {
gdi.selectItemByData("StatusIn", t->getInputStatus());
int ip = t->getInputPlace();
if (ip > 0)
@@ -201,11 +201,11 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.setText("PlaceIn", makeDash(L"-"));
gdi.setText("TimeIn", t->getInputTimeS());
- if (gdi.hasField("PointIn"))
+ if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", t->getInputPoints());
}
- if (gdi.hasField("NoRestart")) {
+ if (gdi.hasWidget("NoRestart")) {
gdi.check("NoRestart", t->preventRestart());
}
@@ -224,11 +224,11 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.selectItemByData("Teams", -1);
- if (gdi.hasField("StatusIn")) {
+ if (gdi.hasWidget("StatusIn")) {
gdi.selectFirstItem("StatusIn");
gdi.setText("PlaceIn", L"");
gdi.setText("TimeIn", makeDash(L"-"));
- if (gdi.hasField("PointIn"))
+ if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", L"");
}
@@ -243,11 +243,11 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
{
if (!t) {
gdi.setText("Name", L"");
- if (gdi.hasField("StartNo"))
+ if (gdi.hasWidget("StartNo"))
gdi.setText("StartNo", L"");
- if (gdi.hasField("Club"))
+ if (gdi.hasWidget("Club"))
gdi.setText("Club", L"");
- bool hasFee = gdi.hasField("Fee");
+ bool hasFee = gdi.hasWidget("Fee");
if (hasFee) {
gdi.setText("Fee", L"");
}
@@ -262,19 +262,19 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
}
gdi.setText("Name", t->getName());
- if (gdi.hasField("StartNo"))
+ if (gdi.hasWidget("StartNo"))
gdi.setText("StartNo", t->getBib());
- if (gdi.hasField("Club"))
+ if (gdi.hasWidget("Club"))
gdi.setText("Club", t->getClub());
- bool hasFee = gdi.hasField("Fee");
+ bool hasFee = gdi.hasWidget("Fee");
if (hasFee) {
gdi.setText("Fee", oe->formatCurrency(t->getDI().getInt("Fee")));
}
gdi.setText("Start", t->getStartTimeS());
gdi.setText("Finish",t->getFinishTimeS());
- gdi.setText("Time", t->getRunningTimeS());
+ gdi.setText("Time", t->getRunningTimeS(true));
gdi.setText("TimeAdjust", getTimeMS(t->getTimeAdjustment()));
gdi.setText("PointAdjust", -t->getPointAdjustment());
gdi.selectItemByData("Status", t->getStatus());
@@ -305,13 +305,13 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
bool bibModified = false;
if (t) {
t->setName(name, true);
- if (gdi.hasField("StartNo")) {
+ if (gdi.hasWidget("StartNo")) {
const wstring &bib = gdi.getText("StartNo");
if (bib != t->getBib()) {
bibModified = true;
wchar_t pat[32];
int no = oClass::extractBibPattern(bib, pat);
- t->setBib(bib, no, no > 0, false);
+ t->setBib(bib, no, no > 0);
}
}
wstring start = gdi.getText("Start");
@@ -321,16 +321,16 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
t->setFinishTimeS(gdi.getText("Finish"));
- if (gdi.hasField("Fee"))
+ if (gdi.hasWidget("Fee"))
t->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee")));
- if (gdi.hasField("NoRestart"))
+ if (gdi.hasWidget("NoRestart"))
t->preventRestart(gdi.isChecked("NoRestart"));
- t->apply(false, 0, false);
+ t->apply(oBase::ChangeType::Quiet, nullptr);
- if (gdi.hasField("Club")) {
+ if (gdi.hasWidget("Club")) {
ListBoxInfo lbi;
gdi.getSelectedItem("Club", lbi);
@@ -351,13 +351,13 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
RunnerStatus sIn = (RunnerStatus)lbi.data;
// Must be done AFTER all runners are set. But setting runner can modify status, so decide here.
- bool setDNS = (sIn == StatusDNS || sIn == StatusCANCEL) && (t->getStatus() != sIn);
+ bool setTeamStatus = (!oAbstractRunner::isResultStatus(sIn) || sIn == StatusOK) && (t->getStatus() != sIn);
bool checkStatus = (sIn != t->getStatus());
- if (sIn == StatusUnknown && (t->getStatus() == StatusDNS || t->getStatus() == StatusCANCEL))
- t->setTeamNoStart(false, StatusDNS);
+ if (sIn == StatusUnknown && !oAbstractRunner::isResultStatus(t->getStatus()))
+ t->setTeamMemberStatus(StatusUnknown);
else if ((RunnerStatus)lbi.data != t->getStatus())
- t->setStatus((RunnerStatus)lbi.data, true, false);
+ t->setStatus((RunnerStatus)lbi.data, true, oBase::ChangeType::Update);
gdi.getSelectedItem("RClass", lbi);
@@ -384,27 +384,27 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
if (pc) {
pair snoBib = pc->getNextBib();
if (snoBib.first > 0) {
- t->setBib(snoBib.second, snoBib.first, true, false);
+ t->setBib(snoBib.second, snoBib.first, true);
}
}
}
t->setClassId(classId, true);
- if (gdi.hasField("TimeAdjust")) {
+ if (gdi.hasWidget("TimeAdjust")) {
int time = convertAbsoluteTimeMS(gdi.getText("TimeAdjust"));
if (time != NOTIME)
t->setTimeAdjustment(time);
}
- if (gdi.hasField("PointAdjust")) {
+ if (gdi.hasWidget("PointAdjust")) {
t->setPointAdjustment(-gdi.getTextNo("PointAdjust"));
}
- if (gdi.hasField("StatusIn") && readStatusIn) {
+ if (gdi.hasWidget("StatusIn") && readStatusIn) {
t->setInputStatus(RunnerStatus(gdi.getSelectedItem("StatusIn").first));
t->setInputPlace(gdi.getTextNo("PlaceIn"));
t->setInputTime(gdi.getText("TimeIn"));
- if (gdi.hasField("PointIn"))
+ if (gdi.hasWidget("PointIn"))
t->setInputPoints(gdi.getTextNo("PointIn"));
}
@@ -416,7 +416,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
for (unsigned i=0;igetNumStages(); i++) {
char bf[16];
sprintf_s(bf, "R%d", i);
- if (!gdi.hasField("SI" + itos(i))) // Skip if field not loaded in page
+ if (!gdi.hasWidget("SI" + itos(i))) // Skip if field not loaded in page
continue;
if (pc->getLegRunner(i)==i) {
@@ -474,10 +474,10 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
}
}
}
-
}
- if (setDNS)
- t->setTeamNoStart(true, sIn);
+
+ if (setTeamStatus)
+ t->setTeamMemberStatus(sIn);
if (t->checkValdParSetup()) {
gdi.alert("Laguppställningen hade fel, som har rättats");
@@ -486,7 +486,8 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
if (t->getRunner(0))
t->getRunner(0)->setStartTimeS(start);
- t->evaluate(true);
+ t->applyBibs();
+ t->evaluate(oBase::ChangeType::Update);
if (globalDep)
oe->reEvaluateAll(classes, false);
@@ -660,7 +661,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
else {
oldR->setClassId(0, true);
vector mp;
- oldR->evaluateCard(true, mp, 0, true);
+ oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
oldR->synchronize(true);
t->setRunner(leg, r, true);
t->checkValdParSetup();
@@ -731,17 +732,9 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
int currentKey = max(newSno-1, 0) % nf;
if (currentKey == lbi.data) {
- t->setStartNo(newSno, false);
- t->apply(false, 0, false);
+ t->setStartNo(newSno, oBase::ChangeType::Update);
t->synchronize(true);
- for (int i = 0; i < t->getNumRunners(); i++) {
- pRunner r = t->getRunner(i);
- if (r) {
- vector mp;
- r->evaluateCard(true, mp);
- r->synchronize(true);
- }
- }
+ t->evaluate(oBase::ChangeType::Update);
selectTeam(gdi, t);
return 0;
}
@@ -921,11 +914,12 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
if (pc) {
pair snoBib = pc->getNextBib();
if (snoBib.first > 0) {
- t->setBib(snoBib.second, snoBib.first, true, false);
+ t->setBib(snoBib.second, snoBib.first, true);
}
}
t->setClassId(clsId, true);
+ t->synchronize();
fillTeamList(gdi);
//oe->fillTeams(gdi, "Teams");
@@ -993,7 +987,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
if (gdi.isInputChanged("")) {
pTeam t = oe->getTeam(teamId);
bool newName = t && t->getName() != gdi.getText("Name");
- bool newBib = gdi.hasField("StartNo") && t && t->getBib() != gdi.getText("StartNo");
+ bool newBib = gdi.hasWidget("StartNo") && t && t->getBib() != gdi.getText("StartNo");
save(gdi, true);
if (newName || newBib) {
@@ -1272,13 +1266,13 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
gdi.check("RENT" + itos(i), r->getDCI().getInt("CardFee") != 0);
}
string sid = "STATUS"+itos(i);
- if (r->statusOK()) {
- TextInfo * ti = (TextInfo *)gdi.setText(sid, L"OK, " + r->getRunningTimeS(), false);
+ if (r->statusOK(true)) {
+ TextInfo * ti = (TextInfo *)gdi.setText(sid, L"OK, " + r->getRunningTimeS(true), false);
if (ti)
ti->setColor(colorGreen);
}
- else if (r->getStatus() != StatusUnknown) {
- TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS(false) + L", " + r->getRunningTimeS(), false);
+ else if (r->getStatusComputed() != StatusUnknown) {
+ TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS(false, true) + L", " + r->getRunningTimeS(true), false);
if (ti)
ti->setColor(colorRed);
}
@@ -1344,10 +1338,9 @@ bool TabTeam::loadPage(gdioutput &gdi)
gdi.clearPage(false);
if (currentMode == 1) {
- Table *tbl=oe->getTeamsTB();
addToolbar(gdi);
gdi.dropLine(1);
- gdi.addTable(tbl, gdi.getCX(), gdi.getCY());
+ gdi.addTable(oTeam::getTable(oe), gdi.getCX(), gdi.getCY());
return true;
}
@@ -1790,7 +1783,7 @@ void TabTeam::doAddTeamMembers(gdioutput &gdi) {
}
}
if (ch) {
- mt->apply(false, 0, false);
+ mt->apply(oBase::ChangeType::Update, nullptr);
mt->synchronize();
for (int j = 0; j < mt->getNumRunners(); j++) {
if (mt->getRunner(j) != 0) {
@@ -1905,9 +1898,9 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
int otherLeg = r->getLegNumber();
otherTeam->setRunner(otherLeg, oldR, true);
if (oldR)
- oldR->evaluateCard(true, mp, 0, true);
+ oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
otherTeam->checkValdParSetup();
- otherTeam->apply(true, 0, false);
+ otherTeam->apply(oBase::ChangeType::Update, nullptr);
otherTeam->synchronize(true);
}
else if (oldR) {
@@ -1918,14 +1911,14 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
else
oldR->setClassId(r->getClassId(false), true);
removeAnnonumousTeamMember = oldR->isAnnonumousTeamMember();
- oldR->evaluateCard(true, mp, 0, true);
+ oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
oldR->synchronize(true);
}
t->setRunner(leg, r, true);
- r->evaluateCard(true, mp, 0, true);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
t->checkValdParSetup();
- t->apply(true, 0, false);
+ t->apply(oBase::ChangeType::Update, nullptr);
t->synchronize(true);
if (removeAnnonumousTeamMember)
@@ -1981,12 +1974,12 @@ void TabTeam::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
auto &db = oe->getRunnerDatabase();
auto runner = db.getRunnerByIndex(ix);
- if (runner && gdi.hasField("Club") && gdi.getText("Club").empty()) {
+ if (runner && gdi.hasWidget("Club") && gdi.getText("Club").empty()) {
pClub club = db.getClub(runner->dbe().clubNo);
if (club)
gdi.setText("Club", club->getName());
}
- if (runner && runner->dbe().cardNo > 0 && gdi.hasField("DirCard") && gdi.getText("DirCard").empty()) {
+ if (runner && runner->dbe().cardNo > 0 && gdi.hasWidget("DirCard") && gdi.getText("DirCard").empty()) {
gdi.setText("DirCard", runner->dbe().cardNo);
}
}
diff --git a/code/TabTeam.h b/code/TabTeam.h
index 231ccaa..a584f90 100644
--- a/code/TabTeam.h
+++ b/code/TabTeam.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/Table.cpp b/code/Table.cpp
index 364638a..fe4c017 100644
--- a/code/Table.cpp
+++ b/code/Table.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -72,7 +72,6 @@ Table::Table(oEvent *oe_, int rowH,
partialCell = false;
startSelect = false;
- ownerCounter = 0;
clearCellSelection(0);
tableProp = -1;
dataPointer = -1;
@@ -86,18 +85,10 @@ Table::Table(oEvent *oe_, int rowH,
Table::~Table(void)
{
- assert(ownerCounter == 0);
if (hEdit)
DestroyWindow(hEdit);
}
-
-void Table::releaseOwnership() {
- ownerCounter--;
- if (ownerCounter == 0)
- delete this;
-}
-
void Table::clearCellSelection(gdioutput *gdi) {
upperRow = -1;
lowerRow = -1;
@@ -111,8 +102,12 @@ void Table::clearCellSelection(gdioutput *gdi) {
}
int Table::addColumn(const string &Title, int width, bool isnum, bool formatRight) {
+ return addColumn(lang.tl(Title).c_str(), width, isnum, formatRight);
+}
+
+int Table::addColumn(const wstring &translatedTitle, int width, bool isnum, bool formatRight) {
ColInfo ri;
- wcscpy_s(ri.name, lang.tl(Title).c_str());
+ wcscpy_s(ri.name, translatedTitle.c_str());
ri.baseWidth = width;
ri.width = 0;
ri.padWidthZeroSort = 0;
@@ -121,7 +116,7 @@ int Table::addColumn(const string &Title, int width, bool isnum, bool formatRigh
Titles.push_back(ri);
columns.push_back(nTitles);
nTitles++;
- return Titles.size()-1;
+ return Titles.size() - 1;
}
int Table::addColumnPaddedSort(const string &title, int width, int padding, bool formatRight) {
@@ -440,26 +435,21 @@ void Table::sort(int col)
}
}
-int TablesCB(gdioutput *gdi, int type, void *data)
-{
+int TablesCB(gdioutput *gdi, int type, void *data) {
if (type!=GUI_LINK || gdi->Tables.empty())
return 0;
TableInfo &tai=gdi->Tables.front();
- Table *t=tai.table;
+ auto &t = tai.table;
TextInfo *ti=(TextInfo *)data;
-
if (ti->id.substr(0,4)=="sort"){
int col=atoi(ti->id.substr(4).c_str());
t->sort(col);
}
gdi->refresh();
- //gdi->Restore();
- //t->Render(*gdi);
-//*/
return 0;
}
@@ -720,17 +710,26 @@ int tblSelectionCB(gdioutput *gdi, int type, void *data)
}
void Table::selection(gdioutput &gdi, const wstring &text, int data) {
- if (size_t(selectionRow) >= Data.size() || size_t(selectionCol) >= Titles.size())
- throw std::exception("Index out of bounds.");
+ if (size_t(selectionRow) >= Data.size() || size_t(selectionCol) >= Titles.size())
+ throw std::exception("Index out of bounds.");
- TableCell &cell = Data[selectionRow].cells[selectionCol];
- int id = Data[selectionRow].id;
- if (cell.hasOwner())
- cell.getOwner()->inputData(cell.id, text, data, cell.contents, false);
- reloadRow(id);
- RECT rc;
- getRowRect(selectionRow, rc);
- InvalidateRect(gdi.getHWNDTarget(), &rc, false);
+ TableCell &cell = Data[selectionRow].cells[selectionCol];
+ int id = Data[selectionRow].id;
+ pair res;
+ if (cell.hasOwner())
+ res = cell.getOwner()->inputData(cell.id, text, data, cell.contents, false);
+ if (res.second) {
+ update();
+ gdi.refresh();
+ }
+ else {
+ reloadRow(id);
+ if (res.first)
+ reloadRow(res.first);
+ //RECT rc;
+ //getRowRect(selectionRow, rc);
+ InvalidateRect(gdi.getHWNDTarget(), nullptr, false);
+ }
}
#ifndef MEOSDB
@@ -838,7 +837,7 @@ bool Table::destroyEditControl(gdioutput &gdi) {
hEdit=0;
}
}
- gdi.removeControl(tId);
+ gdi.removeWidget(tId);
if (drawFilterLabel) {
drawFilterLabel=false;
@@ -1643,7 +1642,7 @@ bool Table::enter(gdioutput &gdi)
}
}
}
- else if (gdi.hasField(tId)) {
+ else if (gdi.hasWidget(tId)) {
ListBoxInfo lbi;
gdi.getSelectedItem(tId, lbi);
@@ -1662,7 +1661,7 @@ void Table::escape(gdioutput &gdi)
DestroyWindow(hEdit);
hEdit = 0;
}
- gdi.removeControl(tId);
+ gdi.removeWidget(tId);
drawFilterLabel=false;
gdi.refresh();
}
@@ -2279,7 +2278,7 @@ void Table::autoSelectColumns() {
for (size_t r = 2; r 1000
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/animationdata.cpp b/code/animationdata.cpp
index 2958d3e..cc0d8d0 100644
--- a/code/animationdata.cpp
+++ b/code/animationdata.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
-Copyright (C) 2009-2019 Melin Software HB
+Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/animationdata.h b/code/animationdata.h
index fc8bba9..d4df7b0 100644
--- a/code/animationdata.h
+++ b/code/animationdata.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
-Copyright (C) 2009-2019 Melin Software HB
+Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/autocomplete.cpp b/code/autocomplete.cpp
index a4625d4..d2c95b1 100644
--- a/code/autocomplete.cpp
+++ b/code/autocomplete.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
-Copyright (C) 2009-2019 Melin Software HB
+Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/autocomplete.h b/code/autocomplete.h
index 0d2adae..8a47993 100644
--- a/code/autocomplete.h
+++ b/code/autocomplete.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/autocompletehandler.h b/code/autocompletehandler.h
index 8a30ae4..81c4c18 100644
--- a/code/autocompletehandler.h
+++ b/code/autocompletehandler.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/autotask.cpp b/code/autotask.cpp
index 5349390..de385ae 100644
--- a/code/autotask.cpp
+++ b/code/autotask.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/autotask.h b/code/autotask.h
index 610f7b1..7189065 100644
--- a/code/autotask.h
+++ b/code/autotask.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/classconfiginfo.cpp b/code/classconfiginfo.cpp
index 43f220f..02c00fc 100644
--- a/code/classconfiginfo.cpp
+++ b/code/classconfiginfo.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -48,11 +48,15 @@ void ClassConfigInfo::clear() {
}
bool ClassConfigInfo::empty() const {
- return individual.empty() && relay.empty() && patrol.empty() && raceNStart.empty();
+ return individual.empty() && rogainingClasses.empty()
+ && relay.empty() && patrol.empty()
+ && raceNStart.empty() && rogainingTeam.empty();
}
-void ClassConfigInfo::getIndividual(set &sel) const {
+void ClassConfigInfo::getIndividual(set &sel, bool forStartList) const {
sel.insert(individual.begin(), individual.end());
+ if (forStartList)
+ sel.insert(rogainingClasses.begin(), rogainingClasses.end());
}
void ClassConfigInfo::getRelay(set &sel) const {
@@ -79,6 +83,9 @@ void ClassConfigInfo::getRogaining(set &sel) const {
sel.insert(rogainingClasses.begin(), rogainingClasses.end());
}
+void ClassConfigInfo::getRogainingTeam(set &sel) const {
+ sel.insert(rogainingTeam.begin(), rogainingTeam.end());
+}
void ClassConfigInfo::getRaceNStart(int race, set &sel) const {
if (size_t(race) < raceNStart.size() && !raceNStart[race].empty())
@@ -124,8 +131,6 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
cnf.maximumLegNumber = max(cnf.maximumLegNumber, it->getNumStages());
ClassType ct = it->getClassType();
- if (it->isRogaining())
- cnf.rogainingClasses.push_back(it->getId());
if (it->getCourse() == 0)
cnf.classWithoutCourse.push_back(it->getName()); //MultiCourse not analysed...
@@ -187,12 +192,20 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
cnf.hasMultiCourse = true;
}
}
+
if (ct == oClassIndividual) {
- cnf.individual.push_back(it->getId());
+ if (it->isRogaining())
+ cnf.rogainingClasses.push_back(it->getId());
+ else
+ cnf.individual.push_back(it->getId());
+
if (cnf.timeStart.empty())
cnf.timeStart.resize(1);
cnf.timeStart[0].push_back(it->getId());
}
+ else if ((ct == oClassPatrol || ct == oClassRelay) && it->isRogaining()) {
+ cnf.rogainingTeam.push_back(it->getId());
+ }
else if (ct == oClassPatrol)
cnf.patrol.push_back(it->getId());
else if (ct == oClassRelay) {
diff --git a/code/classconfiginfo.h b/code/classconfiginfo.h
index 96cfdad..b198bed 100644
--- a/code/classconfiginfo.h
+++ b/code/classconfiginfo.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,6 +35,7 @@ public:
vector individual;
vector relay;
vector patrol;
+ vector rogainingTeam;
vector< vector > legNStart;
vector< vector > raceNStart;
@@ -65,15 +66,18 @@ public:
bool hasRelay() const {return relay.size()>0;}
bool hasPatrol() const {return patrol.size()>0;}
bool hasRogaining() const {return rogainingClasses.size()>0;}
+ bool hasRogainingTeam() const { return rogainingTeam.size()>0; }
+
bool empty() const;
// Return true of this is an event in a sequence of events.
bool isMultiStageEvent() const {return hasMultiEvent;}
- void getIndividual(set &sel) const;
+ void getIndividual(set &sel, bool forStartList) const;
void getRelay(set &sel) const;
void getPatrol(set &sel) const;
void getTeamClass(set &sel) const;
void getRogaining(set &sel) const;
+ void getRogainingTeam(set &sel) const;
bool hasTeamClass() const;
diff --git a/code/csvparser.cpp b/code/csvparser.cpp
index 09c9d3b..f86ac13 100644
--- a/code/csvparser.cpp
+++ b/code/csvparser.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -165,18 +165,18 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
pTeam team=event.addTeam(sp[OSclub] + L" " + sp[OSdesc], ClubId, ClassId);
team->setEntrySource(externalSourceId);
- team->setStartNo(wtoi(sp[OSstno]), false);
+ team->setStartNo(wtoi(sp[OSstno]), oBase::ChangeType::Update);
if (sp[12].length()>0)
- team->setStatus( ConvertOEStatus( wtoi(sp[OSstatus]) ), true, false);
+ team->setStatus( ConvertOEStatus( wtoi(sp[OSstatus]) ), true, oBase::ChangeType::Update);
- team->setStartTime(event.convertAbsoluteTime(sp[OSstart]), true, false);
+ team->setStartTime(event.convertAbsoluteTime(sp[OSstart]), true, oBase::ChangeType::Update);
if (sp[OStime].length()>0)
team->setFinishTime( event.convertAbsoluteTime(sp[OSstart])+event.convertAbsoluteTime(sp[OStime])-event.getZeroTimeNum() );
if (team->getStatus()==StatusOK && team->getFinishTime()==0)
- team->setStatus(StatusUnknown, true, false);
+ team->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
unsigned rindex=Offset;
@@ -204,14 +204,14 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
DI.setInt("CardFee", event.getDCI().getInt("CardFee"));
//r->setCardNo(atoi(sp[rindex+OSRcard]), false);
- r->setStartTime(event.convertAbsoluteTime(sp[rindex+OSRstart]), true, false);
+ r->setStartTime(event.convertAbsoluteTime(sp[rindex+OSRstart]), true, oBase::ChangeType::Update);
r->setFinishTime( event.convertAbsoluteTime(sp[rindex+OSRfinish]) );
if (sp[rindex+OSRstatus].length()>0)
- r->setStatus( ConvertOEStatus( wtoi(sp[rindex+OSRstatus]) ), true, false, false);
+ r->setStatus( ConvertOEStatus( wtoi(sp[rindex+OSRstatus]) ), true, oBase::ChangeType::Update, false);
- if (r->getStatus()==StatusOK && r->getRunningTime()==0)
- r->setStatus(StatusUnknown, true, false, false);
+ if (r->getStatus()==StatusOK && r->getRunningTime(false)==0)
+ r->setStatus(StatusUnknown, true, oBase::ChangeType::Update, false);
r->addClassDefaultFee(false);
@@ -225,7 +225,7 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
if (pc && runner>(int)pc->getNumStages())
pc->setNumStages(runner);
- team->apply(true, 0, false);
+ team->evaluate(oBase::ChangeType::Update);
}
}
fin.close();
@@ -324,14 +324,14 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
pr->setClubId(pclub ? pclub->getId():0);
pr->setCardNo( wtoi(sp[OEcard]), false );
- pr->setStartTime(event.convertAbsoluteTime(sp[OEstart]), true, false);
+ pr->setStartTime(event.convertAbsoluteTime(sp[OEstart]), true, oBase::ChangeType::Update);
pr->setFinishTime(event.convertAbsoluteTime(sp[OEfinish]));
if (sp[OEstatus].length()>0)
- pr->setStatus( ConvertOEStatus( wtoi(sp[OEstatus]) ), true, false);
+ pr->setStatus( ConvertOEStatus( wtoi(sp[OEstatus]) ), true, oBase::ChangeType::Update);
- if (pr->getStatus()==StatusOK && pr->getRunningTime()==0)
- pr->setStatus(StatusUnknown, true, false);
+ if (pr->getStatus()==StatusOK && pr->getRunningTime(false)==0)
+ pr->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
//Autocreate class if it does not exist...
int classId=wtoi(sp[OEclassno]);
@@ -350,9 +350,9 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
if (needSno || newEntry) {
if (stno>0)
- pr->setStartNo(stno, false);
+ pr->setStartNo(stno, oBase::ChangeType::Update);
else
- pr->setStartNo(nimport, false);
+ pr->setStartNo(nimport, oBase::ChangeType::Update);
}
oDataInterface DI=pr->getDI();
@@ -361,7 +361,7 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
DI.setString("Nationality", sp[OEnat]);
if (sp.size()>OEbib && needBib)
- pr->setBib(sp[OEbib], 0, false, false);
+ pr->setBib(sp[OEbib], 0, false);
if (sp.size()>=38) {//ECO
DI.setInt("Fee", wtoi(sp[OEfee]));
@@ -682,7 +682,7 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
//Club is autocreated...
pTeam team=event.addTeam(sp[RAIDteam], ClubId, ClassId);
- team->setStartNo(wtoi(sp[RAIDid]), false);
+ team->setStartNo(wtoi(sp[RAIDid]), oBase::ChangeType::Update);
if (sp.size()>8)
team->getDI().setInt("SortIndex", wtoi(sp[RAIDcanoe]));
oDataInterface teamDI=team->getDI();
@@ -703,7 +703,7 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
pRunner r2=event.addRunner(sp[RAIDrunner2], ClubId, ClassId, 0, 0, false);
team->setRunner(1, r2, false);
- team->apply(true, 0, false);
+ team->evaluate(oBase::ChangeType::Update);
}
}
fin.close();
diff --git a/code/csvparser.h b/code/csvparser.h
index 8d2805c..ec4bf7e 100644
--- a/code/csvparser.h
+++ b/code/csvparser.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/download.cpp b/code/download.cpp
index 833abd0..201b581 100644
--- a/code/download.cpp
+++ b/code/download.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/download.h b/code/download.h
index 630c5bc..c3540a1 100644
--- a/code/download.h
+++ b/code/download.h
@@ -7,7 +7,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/english.lng b/code/english.lng
index 0e14a6b..542a635 100644
--- a/code/english.lng
+++ b/code/english.lng
@@ -1421,8 +1421,8 @@ xml-data = xml data
Ändrad = Modified
Ändrade avgift för X deltagare = Modified fee for X competitor(s)
Ã…ldersfilter = Age filter
-Åldersgräns ungdom = Age limit, low
-Åldersgräns äldre = Age limit, high
+Åldersgräns ungdom = Age limit, low (youth)
+Åldersgräns äldre = Age limit, high (pensioner)
Åldersgränser, reducerad anmälningsavgift = Age Limits, Fee Reduction
Ã…ngra = Undo
Återansluten mot databasen, tävlingen synkroniserad = Reconnected to database, competition synchronized
@@ -1871,7 +1871,7 @@ Byt till rätt klass (behåll eventuell starttid) = Switch to the right class (k
Byt till vakansplats i rätt klass (om möjligt) = Switch to a vacant position in the right class (if possible)
Tillåt ny klass, behåll resultat från annan klass = Allow new class and keep results from other class
Tillåt ny klass, inget totalresultat = Allow new class but without total result
-tooltip_explain_status = - = Unknown Status (No result yet)\nOK = Valid result\nDNS = Did Not Start\nCancelled = Cancelled entry (shown in start list)\nMP = Missing Punch\nDNF = Did Not Finish\nDISQ = Disqualified\nOMT = Over Maximum Time\nNTP = Not Taking Part
+tooltip_explain_status = - = Unknown Status (No result yet)\nOK = Valid result\nDNS = Did Not Start\nCancelled = Cancelled entry (shown in start list)\nMP = Missing Punch\nDNF = Did Not Finish\nDISQ = Disqualified\nOMT = Over Maximum Time\nOOC = Out-of-competition\nNTP = Not Taking Part
Placering = Place
Resultat från tidigare etapper = Results from Earlier Stages
Input Results = Input Results
@@ -2106,7 +2106,7 @@ prefsMaximumSpeakerDelay = Maximum delay in announcer's view update
prefsOrganizer = Organizer
prefsPort = MySQL network port
prefsRentCard = Rent card
-prefsSeniorAge = Upper age limit
+prefsSeniorAge = Upper (pensioner) age limit
prefsServer = Default network server
prefsSpeakerShortNames = Use initials in names
prefsStreet = Organizer street address
@@ -2435,4 +2435,43 @@ Runner check time = Runner check time
ClassNumEntries = Number of entries in class
Flera lopp i valfri ordning = Several races in any order
Knockout sammanställning = Knock-out summary
+Utom tävlan = OOC
+Status code for running out-of-competition = Status code for running out-of-competition (OOC)
X anmälda = X entries
+LÃ¥s funktion = Lock function
+LÃ¥s upp = Unlock
+Målstämpling tillåts inte (X) = Finish punch disallowed (X)
+Radio = Radio
+Radio tillåts inte (X) = Radio controls disallowed (X)
+Startstämpling tillåts inte (X) = Start punch disallowed (X)
+Tillåt = Allow
+warn:printmodeonly = Note that you will only generate a printout of the card contents.\n\nTo save a result to the competition you need to select function readout/radio.
+There is no result module with X as identifier = There is no result module with X as identifier
+Senast sedd: X vid Y = Last seen: X at Y
+Referens = Reference
+Poäng E[stageno] = Points S
+Status E[stageno] = Status S
+Tid E[stageno] = Time S
+Plac. E[stageno] = Pl. S
+Från första = From first
+Kartor = Maps
+Poängreduktion = Reduction
+Stigning = Climb
+Till sista = To last
+Heat = Heat
+Kvalschema = Qualification scheme
+LÃ¥st gaffling = Locked forking
+Result module = Result module
+ask:usecourseinclass = The course is not used by any other competitor in this class.\n\nWould you like to use it anyway?
+Inkludera bana = Include course
+Rogaining points before automatic reduction = Rogaining points before automatic reduction
+Runner/team earlier stage places = Runner/team earlier stage places
+Runner/team earlier stage points = Runner/team earlier stage points
+Runner/team earlier stage running times = Runner/team earlier stage running times
+Runner/team earlier stage statuses = Runner/team earlier stage statuses
+Status code for cancelled entry = Status code for cancelled entry
+Ã…ldersfiltrering = Age filter
+Age (on last day of current year) = Age (on last day of current year)
+Age above or equal implies senior/pensioner = Age above or equal implies senior/pensioner
+Age below or equal implies youth = Age below or equal implies youth
+Status code for not no timing = Status code for not no timing
diff --git a/code/gdiconstants.h b/code/gdiconstants.h
index 7ded93a..4b19a3c 100644
--- a/code/gdiconstants.h
+++ b/code/gdiconstants.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/gdifonts.h b/code/gdifonts.h
index 1d8fc02..e7b2cb8 100644
--- a/code/gdifonts.h
+++ b/code/gdifonts.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -60,25 +60,28 @@ const int timerIgnoreSign = 1<<15;
const int Capitalize = 1<<16;
const int absolutePosition = 1 << 17;
const int skipBoundingBox = 1 << 18;
+const int hiddenText = 1 << 19;
-enum GDICOLOR {colorBlack = RGB(0,0,0),
- colorRed = RGB(128,0,0),
- colorGreen = RGB(0,128,0),
- colorDarkGrey = RGB(40,40,40),
- colorDarkRed = RGB(64,0,0),
- colorGreyBlue = RGB(92,92,128),
- colorDarkBlue = RGB(0,0,92),
- colorDarkGreen = RGB(0,64,0),
- colorYellow = RGB(255, 230, 0),
- colorLightBlue = RGB(240,240,255),
- colorLightRed = RGB(255,230,230),
- colorLightGreen = RGB(180, 255, 180),
- colorLightYellow = RGB(255, 255, 200),
- colorLightCyan = RGB(200, 255, 255),
- colorLightMagenta = RGB(255, 200, 255),
- colorMediumRed = RGB(255,200,200),
- colorMediumDarkRed = RGB(240,120,120),
- colorWindowBar = -2,
- colorDefault = -1,
- colorTransparent = -3};
+enum GDICOLOR {
+ colorBlack = RGB(0, 0, 0),
+ colorRed = RGB(128, 0, 0),
+ colorGreen = RGB(0, 128, 0),
+ colorDarkGrey = RGB(40, 40, 40),
+ colorDarkRed = RGB(64, 0, 0),
+ colorGreyBlue = RGB(92, 92, 128),
+ colorDarkBlue = RGB(0, 0, 92),
+ colorDarkGreen = RGB(0, 64, 0),
+ colorYellow = RGB(255, 230, 0),
+ colorLightBlue = RGB(235, 238, 254),
+ colorLightRed = RGB(255, 230, 230),
+ colorLightGreen = RGB(219, 247, 209),
+ colorLightYellow = RGB(248, 248, 216),
+ colorLightCyan = RGB(220, 249, 245),//RGB(200, 255, 255),
+ colorLightMagenta = RGB(240, 207, 244),//RGB(255, 200, 255),
+ colorMediumRed = RGB(255, 200, 200),
+ colorMediumDarkRed = RGB(240, 120, 120),
+ colorWindowBar = -2,
+ colorDefault = -1,
+ colorTransparent = -3
+};
diff --git a/code/gdiimpl.h b/code/gdiimpl.h
index 8405472..c42e44c 100644
--- a/code/gdiimpl.h
+++ b/code/gdiimpl.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/gdioutput.cpp b/code/gdioutput.cpp
index 3a5fc3f..480782c 100644
--- a/code/gdioutput.cpp
+++ b/code/gdioutput.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -100,10 +100,11 @@ EventInfo::EventInfo() : callBack(0), keyEvent(KC_NONE) {}
/** Return true if rendering text should be skipped for
this format. */
bool gdioutput::skipTextRender(int format) {
- format &= 0xFF;
+ format &= 0xFF | hiddenText;
return format == pageNewPage ||
format == pagePageInfo ||
- format == pageNewChapter;
+ format == pageNewChapter ||
+ (format & hiddenText) == hiddenText;
}
#ifndef MEOSDB
@@ -376,11 +377,8 @@ gdioutput::~gdioutput()
if (toolbar)
delete toolbar;
toolbar = 0;
- //delete table;
- while(!Tables.empty()){
- Tables.front().table->releaseOwnership();
- Tables.pop_front();
- }
+
+ Tables.clear();
if (tabs) {
delete tabs;
@@ -507,7 +505,7 @@ void gdioutput::drawBackground(HDC hDC, RECT &rc)
SelectObject(hDC, GetStockObject(ANSI_FIXED_FONT));
DeleteObject(hInfo);
}
-
+/*
DWORD c=GetSysColor(COLOR_3DFACE);
double red = double(GetRValue(c)) *0.9;
double green = double(GetGValue(c)) * 0.85;
@@ -523,7 +521,15 @@ void gdioutput::drawBackground(HDC hDC, RECT &rc)
double blue1=min(255., blue*1.3);
double green1=min(255., green*1.3);
double red1=min(255., red*1.3);
+ */
+ double red = 242.0;
+ double green = 247.0;
+ double blue = 254.0;
+
+ double blue1 = 250.0;
+ double green1 = 232.0;
+ double red1 = 223.0;
TRIVERTEX vert[2];
if (hideBG) {
@@ -661,8 +667,10 @@ void gdioutput::draw(HDC hDC, RECT &rc, RECT &drawArea)
}
void gdioutput::renderRectangle(HDC hDC, RECT *clipRegion, const RectangleInfo &ri) {
- if (ri.drawBorder)
- SelectObject(hDC, GetStockObject(BLACK_PEN));
+ if (ri.drawBorder) {
+ SelectObject(hDC, GetStockObject(DC_PEN));
+ SetDCPenColor(hDC, RGB(40,40,60));
+ }
else
SelectObject(hDC, GetStockObject(NULL_PEN));
@@ -1213,7 +1221,8 @@ void gdioutput::enableCheckBoxLink(TextInfo &ti, bool enable) {
else {
needRefresh = ti.callBack != 0;
ti.callBack = 0;
- ti.setColor(colorDarkGrey);
+ DWORD c = GetSysColor(COLOR_GRAYTEXT);
+ ti.setColor(GDICOLOR(c));
}
if (needRefresh)
InvalidateRect(hWndTarget, &ti.textRect, true);
@@ -2980,12 +2989,12 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
lockUpDown = false;
hasAnyTimer = false;
enableTables();
- #ifndef MEOSDB
- if (toolbar && !keepToolbar)
- toolbar->hide();
- #endif
+#ifndef MEOSDB
+ if (toolbar && !keepToolbar)
+ toolbar->hide();
+#endif
- while(!timers.empty()) {
+ while (!timers.empty()) {
KillTimer(hWndTarget, (UINT_PTR)&timers.back());
timers.back().setWnd = 0;
timers.back().parent = 0;
@@ -2994,11 +3003,11 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
restorePoints.clear();
shownStrings.clear();
- onClear=0;
+ onClear = 0;
FocusList.clear();
currentFocus = 0;
TL.clear();
- itTL=TL.end();
+ itTL = TL.end();
listDescription.clear();
if (hWndTarget && autoRefresh)
@@ -3010,14 +3019,14 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
for (ToolList::iterator it = toolTips.begin(); it != toolTips.end(); ++it) {
if (hWndToolTip) {
- SendMessage(hWndToolTip, TTM_DELTOOL, 0, (LPARAM) &it->ti);
+ SendMessage(hWndToolTip, TTM_DELTOOL, 0, (LPARAM)&it->ti);
}
}
toolTips.clear();
{
list::iterator it;
- for(it=BI.begin(); it != BI.end(); ++it) {
+ for (it = BI.begin(); it != BI.end(); ++it) {
it->callBack = 0;
it->setHandler(0);
DestroyWindow(it->hWnd);
@@ -3027,7 +3036,7 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
}
{
list::iterator it;
- for(it=II.begin(); it != II.end(); ++it) {
+ for (it = II.begin(); it != II.end(); ++it) {
it->callBack = 0;
it->setHandler(0);
DestroyWindow(it->hWnd);
@@ -3038,7 +3047,7 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
{
list::iterator it;
- for(it=LBI.begin(); it != LBI.end(); ++it) {
+ for (it = LBI.begin(); it != LBI.end(); ++it) {
it->callBack = 0;
it->setHandler(0);
DestroyWindow(it->hWnd);
@@ -3049,14 +3058,10 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
LBI.clear();
}
- //delete table;
- //table=0;
- while(!Tables.empty()){
- Table *t=Tables.front().table;
- Tables.front().table=0;
+ while (!Tables.empty()) {
+ auto t = Tables.front().table;
Tables.pop_front();
t->hide(*this);
- t->releaseOwnership();
}
DataInfo.clear();
@@ -3065,16 +3070,16 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
Rectangles.clear();
- MaxX=40;
- MaxY=100;
+ MaxX = scaleLength(60);
+ MaxY = scaleLength(100);
- CurrentX=40;
- CurrentY=START_YP;
+ CurrentX = scaleLength(40);
+ CurrentY = scaleLength(START_YP);
- OffsetX=0;
- OffsetY=0;
+ OffsetX = 0;
+ OffsetY = 0;
- renderOptimize=true;
+ renderOptimize = true;
backgroundColor1 = -1;
backgroundColor2 = -1;
@@ -3097,7 +3102,7 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
wstring msg = ex.wwhat();
alert(msg);
}
- catch(const std::exception &ex) {
+ catch (const std::exception &ex) {
if (isTestMode)
throw ex;
string msg(ex.what());
@@ -3105,7 +3110,7 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
}
postClear = 0;
- manualUpdate=!autoRefresh;
+ manualUpdate = !autoRefresh;
}
void gdioutput::getWindowText(HWND hWnd, wstring &text)
@@ -3208,7 +3213,7 @@ const wstring &gdioutput::getText(const char *id, bool acceptMissing) const
return _EmptyWString;
}
-bool gdioutput::hasField(const string &id) const
+bool gdioutput::hasWidget(const string &id) const
{
for(list::const_iterator it=II.begin();
it != II.end(); ++it){
@@ -3602,8 +3607,8 @@ void gdioutput::setTabStops(const string &Name, int t1, int t2)
int n=1;
LONG bu=GetDialogBaseUnits();
int baseunitX=LOWORD(bu);
- array[0]=(t1 * 4) / baseunitX ;
- array[1]=(t2 * 4) / baseunitX ;
+ array[0]=int(t1 * 4.2) / baseunitX ;
+ array[1]=int(t2 * 4.2) / baseunitX ;
int lastTabStop = 0;
if (t2>0) {
n=2;
@@ -3989,7 +3994,6 @@ void gdioutput::removeString(string id)
for (it=TL.begin(); it != TL.end(); ++it) {
if (it->id==id) {
HDC hDC=GetDC(hWndTarget);
- //TextOut(
RECT rc;
rc.left=it->xp;
rc.top=it->yp;
@@ -4213,12 +4217,12 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC)
ti.textRect.bottom+=ti.yp+dx;
if (ti.format == 10) {
- DWORD c=GetSysColor(COLOR_INFOBK);
+ DWORD c = colorLightYellow;// GetSysColor(COLOR_INFOBK);
double red=GetRValue(c);
double green=GetGValue(c);
double blue=GetBValue(c);
- double blue1=min(255., blue*0.8);
+ double blue1=min(255., blue*1.05);
double green1=min(255., green*1.05);
double red1=min(255., red*1.05);
@@ -4273,7 +4277,7 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC)
rc.bottom+=ti.yp+dx-OffsetY;
rc.right=ti.xp+dx+width-OffsetX;
- SetTextColor(hDC, GetSysColor(COLOR_INFOTEXT));
+ SetTextColor(hDC, 0);
DrawText(hDC, ti.text.c_str(), ti.text.length(), &rc, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
}
@@ -4787,7 +4791,7 @@ void gdioutput::CheckInterfaceTimeouts(DWORD T)
}
}
-bool gdioutput::removeControl(const string &id)
+bool gdioutput::removeWidget(const string &id)
{
list::iterator it=BI.begin();
@@ -4834,13 +4838,15 @@ bool gdioutput::removeControl(const string &id)
return false;
}
-bool gdioutput::hideControl(const string &id)
-{
+bool gdioutput::hideWidget(const string &id, bool hide) {
list::iterator it=BI.begin();
while (it!=BI.end()) {
- if (it->id==id) {
- ShowWindow(it->hWnd, SW_HIDE);
+ if (it->id == id) {
+ ShowWindow(it->hWnd, hide ? SW_HIDE : SW_SHOW);
+ if (it->isCheckbox) {
+ hideWidget("T" + id, hide);
+ }
return true;
}
++it;
@@ -4850,7 +4856,7 @@ bool gdioutput::hideControl(const string &id)
while (lit!=LBI.end()) {
if (lit->id==id) {
- ShowWindow(lit->hWnd, SW_HIDE);
+ ShowWindow(lit->hWnd, hide ? SW_HIDE : SW_SHOW);
return true;
}
++lit;
@@ -4860,15 +4866,25 @@ bool gdioutput::hideControl(const string &id)
while (iit!=II.end()) {
if (iit->id==id) {
- ShowWindow(iit->hWnd, SW_HIDE);
+ ShowWindow(iit->hWnd, hide ? SW_HIDE : SW_SHOW);
return true;
}
++iit;
}
+
+ for (auto &ti : TL) {
+ if (ti.id == id) {
+ if (hide)
+ ti.format |= hiddenText;
+ else
+ ti.format &= ~hiddenText;
+
+ return true;
+ }
+ }
return false;
}
-
void gdioutput::setRestorePoint()
{
setRestorePoint("");
@@ -4974,11 +4990,9 @@ void gdioutput::restoreInternal(const RestoreInfo &ri)
}
while(Tables.size() > unsigned(ri.nTables)){
- Table *t=Tables.back().table;
- Tables.back().table=0;
+ auto t=Tables.back().table;
Tables.pop_back();
t->hide(*this);
- t->releaseOwnership();
}
int dataRemove=DataInfo.size()-ri.nData;
@@ -5656,7 +5670,7 @@ Table &gdioutput::getTable() const {
if (Tables.empty())
throw std::exception("No table defined");
- return *const_cast(Tables.back().table);
+ return *const_cast(Tables.back().table.get());
}
static int gdiTableCB(gdioutput *gdi, int type, void *data)
@@ -5774,16 +5788,10 @@ void gdioutput::enableTables()
useTables=true;
#ifndef MEOSDB
if (!Tables.empty()) {
- Table *t = Tables.front().table;
+ auto &t = Tables.front().table;
if (toolbar == 0)
toolbar = new Toolbar(*this);
-/* RECT rc;
- rc.top = 10;
- rc.bottom = 100;
- rc.left = 100;
- rc.right = 200;
- addToolTip("Hej hopp!", 0, &rc);
-*/
+
toolbar->setData(t);
string tname = string("table") + itos(t->canDelete()) + itos(t->canInsert()) + itos(t->canPaste());
@@ -5809,19 +5817,18 @@ void gdioutput::enableTables()
#endif
}
-void gdioutput::processToolbarMessage(const string &id, void *data) {
+void gdioutput::processToolbarMessage(const string &id, Table *tbl) {
if (hasCommandLock())
return;
wstring msg;
string cmd;
if (getRecorder().recording()) {
- Table *tbl = (Table *)data;
cmd = "tableCmd(\"" + id + "\"); //" + narrow(tbl->getTableName());
}
try {
ButtonInfo bi;
bi.id = id;
- tableCB(bi, (Table *)data);
+ tableCB(bi, tbl);
getRecorder().record(cmd);
}
catch (meosException &ex) {
@@ -5879,7 +5886,7 @@ void gdioutput::disableTables()
if (bit->id.substr(0, 3)=="tbl" && bit->getExtra()!=0) {
string id = bit->id;
++bit;
- removeControl(id);
+ removeWidget(id);
}
else
++bit;
@@ -5887,7 +5894,7 @@ void gdioutput::disableTables()
}
-void gdioutput::addTable(Table *t, int x, int y)
+void gdioutput::addTable(const shared_ptr &t, int x, int y)
{
TableInfo ti;
ti.table = t;
@@ -5899,7 +5906,6 @@ void gdioutput::addTable(Table *t, int x, int y)
t->autoSelectColumns();
t->autoAdjust(*this);
- ti.table->addOwnership();
Tables.push_back(ti);
//updatePos(x, y, dx + TableXMargin, dy + TableYMargin);
diff --git a/code/gdioutput.h b/code/gdioutput.h
index ee8f4fb..601cdfe 100644
--- a/code/gdioutput.h
+++ b/code/gdioutput.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -371,7 +371,7 @@ public:
bool hasToolbar() const;
void activateToolbar(bool active);
- void processToolbarMessage(const string &id, void *data);
+ void processToolbarMessage(const string &id, Table *data);
void synchronizeListScroll(const string &id1, const string &id2);
@@ -424,7 +424,7 @@ public:
void selectTab(int Id);
- void addTable(Table *table, int x, int y);
+ void addTable(const shared_ptr &table, int x, int y);
Table &getTable() const; //Get the (last) table. If needed, add support for named tables...
@@ -468,8 +468,8 @@ public:
void setRestorePoint();
void setRestorePoint(const string &id);
- bool removeControl(const string &id);
- bool hideControl(const string &id);
+ bool removeWidget(const string &id);
+ bool hideWidget(const string &id, bool hide = true);
void CheckInterfaceTimeouts(DWORD T);
bool RemoveFirstInfoBox(const string &id);
@@ -597,7 +597,7 @@ public:
bool clearList(const string &id);
- bool hasField(const string &id) const;
+ bool hasWidget(const string &id) const;
const wstring &getText(const char *id, bool acceptMissing = false) const;
diff --git a/code/gdistructures.h b/code/gdistructures.h
index d8a10e2..b3307e9 100644
--- a/code/gdistructures.h
+++ b/code/gdistructures.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -131,7 +131,7 @@ public:
TableInfo():xp(0), yp(0), table(0) {}
int xp;
int yp;
- Table *table;
+ shared_ptr table;
HWND getControlWindow() const {throw std::exception("Unsupported");}
};
diff --git a/code/generalresult.cpp b/code/generalresult.cpp
index bfc727c..e847625 100644
--- a/code/generalresult.cpp
+++ b/code/generalresult.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,22 +32,26 @@
extern gdioutput *gdi_main;
-GeneralResultCtr::GeneralResultCtr(const char *tagIn, const wstring &nameIn, GeneralResult *ptrIn) {
+GeneralResultCtr::GeneralResultCtr(const char *tagIn, const wstring &nameIn, const shared_ptr &ptrIn) {
name = nameIn;
tag = tagIn;
ptr = ptrIn;
}
-GeneralResultCtr::GeneralResultCtr(wstring &file, DynamicResult *ptrIn) {
+GeneralResultCtr::GeneralResultCtr(wstring &file, const shared_ptr &ptrIn) {
ptr = ptrIn;
name = ptrIn->getName(false);
tag = ptrIn->getTag();
fileSource = file;
}
+bool GeneralResultCtr::operator<(const GeneralResultCtr &c) const {
+ return CompareString(LOCALE_USER_DEFAULT, 0,
+ name.c_str(), name.length(),
+ c.name.c_str(), c.name.length()) == CSTR_LESS_THAN;
+}
+
GeneralResultCtr::~GeneralResultCtr() {
- delete ptr;
- ptr = 0;
}
GeneralResultCtr::GeneralResultCtr(const GeneralResultCtr &ctr) {
@@ -55,16 +59,15 @@ GeneralResultCtr::GeneralResultCtr(const GeneralResultCtr &ctr) {
name = ctr.name;
tag = ctr.tag;
fileSource = ctr.fileSource;
- ctr.ptr = 0;
}
void GeneralResultCtr::operator=(const GeneralResultCtr &ctr) {
if (this == &ctr)
return;
- delete ptr;
name = ctr.name;
ptr = ctr.ptr;
- ctr.ptr = 0;
+ tag = ctr.tag;
+ fileSource = ctr.fileSource;
}
bool GeneralResultCtr::isDynamic() const {
@@ -87,6 +90,13 @@ void GRINSTANCE() {
gr.sort(b, SortByFinishTime);
}
+const string &GeneralResult::getTimeStamp() const {
+ return gdioutput::narrow(getMeosDate());
+}
+
+bool GeneralResult::isRogaining() const {
+ return false;
+}
void GeneralResult::setContext(const oListParam *contextIn) {
context = contextIn;
@@ -112,7 +122,7 @@ int GeneralResult::getListParamTimeFromControl() const {
struct GRSortInfo {
int principalSort;
- int score;
+ pair score;
oAbstractRunner *tr;
bool operator<(const GRSortInfo &other) const {
@@ -130,72 +140,99 @@ struct GRSortInfo {
}
};
-void GeneralResult::calculateTeamResults(vector &teams, oListInfo::ResultType resType, bool sortTeams, int inputNumber) const {
+void GeneralResult::calculateTeamResults(vector &teams,
+ bool classResult,
+ oListInfo::ResultType resType,
+ bool sortTeams,
+ int inputNumber) const {
if (teams.empty())
return;
- prepareCalculations(*teams[0]->oe, true, inputNumber);
- //bool classSort = resType == oListInfo::Global ? false : true;
- vector teamScore(teams.size());
- for (size_t k = 0; k < teams.size(); k++) {
- if (resType == oListInfo::Classwise) {
- teamScore[k].principalSort = teams[k]->Class ? teams[k]->Class->getSortIndex() * 50000
- + teams[k]->Class->getId() : 0;
+ if (lockPrepare)
+ throw meosException("Bad cyclic call");
+ lockPrepare = true;
+
+ try {
+ set clsId;
+ vector runners;
+ for (pTeam t : teams) {
+ clsId.insert(t->getClassId(true));
+ for (int j = 0; j < t->getNumRunners(); j++) {
+ pRunner r = t->getRunner(j);
+ if (r) {
+ runners.push_back(r);
+ clsId.insert(r->getClassId(true));
+ }
+ }
}
- else
- teamScore[k].principalSort = 0;
+ prepareCalculations(*teams[0]->oe, classResult, clsId, runners, teams, inputNumber);
- prepareCalculations(*teams[k]);
- teams[k]->tmpResult.runningTime = teams[k]->getStartTime(); //XXX
- teams[k]->tmpResult.runningTime = deduceTime(*teams[k]);
- teams[k]->tmpResult.status = deduceStatus(*teams[k]);
- teams[k]->tmpResult.points = deducePoints(*teams[k]);
+ vector teamScore(teams.size());
+ for (size_t k = 0; k < teams.size(); k++) {
+ if (resType == oListInfo::Classwise) {
+ teamScore[k].principalSort = teams[k]->Class ? teams[k]->Class->getSortIndex() * 50000
+ + teams[k]->Class->getId() : 0;
+ }
+ else
+ teamScore[k].principalSort = 0;
- teamScore[k].score = score(*teams[k], teams[k]->tmpResult.status,
- teams[k]->tmpResult.runningTime,
- teams[k]->tmpResult.points);
+ prepareCalculations(*teams[k], classResult);
+ teams[k]->tmpResult.runningTime = teams[k]->getStartTime(); //XXX
+ teams[k]->tmpResult.runningTime = deduceTime(*teams[k]);
+ teams[k]->tmpResult.status = deduceStatus(*teams[k]);
+ teams[k]->tmpResult.points = deducePoints(*teams[k]);
- storeOutput(teams[k]->tmpResult.outputTimes,
- teams[k]->tmpResult.outputNumbers);
+ teamScore[k].score = score(*teams[k], teams[k]->tmpResult.status,
+ teams[k]->tmpResult.runningTime,
+ teams[k]->tmpResult.points);
- teamScore[k].tr = teams[k];
+ storeOutput(teams[k]->tmpResult.outputTimes,
+ teams[k]->tmpResult.outputNumbers);
- }
+ teamScore[k].tr = teams[k];
- ::sort(teamScore.begin(), teamScore.end());
- int place = 1;
- int iPlace = 1;
- int leadtime = 0;
- for (size_t k = 0; k < teamScore.size(); k++) {
- if (k > 0 && teamScore[k - 1].principalSort != teamScore[k].principalSort) {
- place = 1;
- iPlace = 1;
- }
- else if (k > 0 && teamScore[k - 1].score != teamScore[k].score) {
- place = iPlace;
}
- if (teamScore[k].tr->tmpResult.status == StatusOK) {
- teamScore[k].tr->tmpResult.place = place;
- iPlace++;
- if (place == 1) {
- leadtime = teamScore[k].tr->tmpResult.runningTime;
- teamScore[k].tr->tmpResult.timeAfter = 0;
+ ::sort(teamScore.begin(), teamScore.end());
+ int place = 1;
+ int iPlace = 1;
+ int leadtime = 0;
+ for (size_t k = 0; k < teamScore.size(); k++) {
+ if (k > 0 && teamScore[k - 1].principalSort != teamScore[k].principalSort) {
+ place = 1;
+ iPlace = 1;
+ }
+ else if (k > 0 && teamScore[k - 1].score != teamScore[k].score) {
+ place = iPlace;
+ }
+
+ if (teamScore[k].tr->tmpResult.status == StatusOK) {
+ teamScore[k].tr->tmpResult.place = place;
+ iPlace++;
+ if (place == 1) {
+ leadtime = teamScore[k].tr->tmpResult.runningTime;
+ teamScore[k].tr->tmpResult.timeAfter = 0;
+ }
+ else {
+ teamScore[k].tr->tmpResult.timeAfter = teamScore[k].tr->tmpResult.runningTime - leadtime;
+ }
}
else {
- teamScore[k].tr->tmpResult.timeAfter = teamScore[k].tr->tmpResult.runningTime - leadtime;
+ teamScore[k].tr->tmpResult.place = 0;
+ teamScore[k].tr->tmpResult.timeAfter = 0;
}
}
- else {
- teamScore[k].tr->tmpResult.place = 0;
- teamScore[k].tr->tmpResult.timeAfter = 0;
- }
- }
- if (sortTeams) {
- for (size_t k = 0; k < teamScore.size(); k++) {
- teams[k] = (oTeam *)teamScore[k].tr;
+ if (sortTeams) {
+ for (size_t k = 0; k < teamScore.size(); k++) {
+ teams[k] = (oTeam *)teamScore[k].tr;
+ }
}
+ lockPrepare = false;
+ }
+ catch (...) {
+ lockPrepare = false;
+ throw;
}
}
@@ -271,118 +308,138 @@ template void GeneralResult::sort(vector &rt, SortOrder so) const
}
void GeneralResult::calculateIndividualResults(vector &runners,
+ bool classResult,
oListInfo::ResultType resType,
bool sortRunners,
int inputNumber) const {
if (runners.empty())
return;
- prepareCalculations(*runners[0]->oe, false, inputNumber);
- //bool classSort = resType == oListInfo::Global ? false : true;
- vector runnerScore(runners.size());
- for (size_t k = 0; k < runners.size(); k++) {
- const oRunner *r = runners[k];
- if (resType == oListInfo::Classwise) {
- runnerScore[k].principalSort = r->Class ? r->Class->getSortIndex() * 50000
- + r->Class->getId() : 0;
- }
- else if (resType == oListInfo::Legwise) {
- runnerScore[k].principalSort = r->Class ? r->Class->getSortIndex() * 50000
- + r->Class->getId() : 0;
- int ln = r->getLegNumber();
- const oTeam *pt = r->getTeam();
- if (pt) {
- const oClass *tcls = pt->getClassRef(false);
- if (tcls && tcls->getClassType() == oClassRelay) {
- int dummy;
- tcls->splitLegNumberParallel(r->getLegNumber(), ln, dummy);
- }
+ if (lockPrepare)
+ throw meosException("Bad cyclic call");
+ lockPrepare = true;
+
+ try {
+
+ set clsId;
+ for (pRunner r : runners) {
+ clsId.insert(r->getClassId(true));
+ }
+ vector noTeams;
+ prepareCalculations(*runners[0]->oe, classResult, clsId, runners, noTeams, inputNumber);
+ //bool classSort = resType == oListInfo::Global ? false : true;
+ vector runnerScore(runners.size());
+ for (size_t k = 0; k < runners.size(); k++) {
+ const oRunner *r = runners[k];
+ if (resType == oListInfo::Classwise) {
+ runnerScore[k].principalSort = r->Class ? r->Class->getSortIndex() * 50000
+ + r->Class->getId() : 0;
}
- runnerScore[k].principalSort = runnerScore[k].principalSort * 50 + ln;
- }
- else if (resType == oListInfo::Coursewise) {
- pCourse crs = r->getCourse(false);
- runnerScore[k].principalSort = crs ? crs->getId() : 0;
- }
- else
- runnerScore[k].principalSort = 0;
+ else if (resType == oListInfo::Legwise) {
+ runnerScore[k].principalSort = r->Class ? r->Class->getSortIndex() * 50000
+ + r->Class->getId() : 0;
- int from = getListParamTimeFromControl();
- if (from <= 0) {
- runners[k]->tmpResult.startTime = r->getStartTime();
- }
- else {
- int rt;
- RunnerStatus stat;
- runners[k]->getSplitTime(from, stat, rt);
- if (stat == StatusOK)
- runners[k]->tmpResult.startTime = runners[k]->getStartTime() + rt;
+ int ln = r->getLegNumber();
+ const oTeam *pt = r->getTeam();
+ if (pt) {
+ const oClass *tcls = pt->getClassRef(false);
+ if (tcls && tcls->getClassType() == oClassRelay) {
+ int dummy;
+ tcls->splitLegNumberParallel(r->getLegNumber(), ln, dummy);
+ }
+ }
+ runnerScore[k].principalSort = runnerScore[k].principalSort * 50 + ln;
+ }
+ else if (resType == oListInfo::Coursewise) {
+ pCourse crs = r->getCourse(false);
+ runnerScore[k].principalSort = crs ? crs->getId() : 0;
+ }
else
- runners[k]->tmpResult.startTime = runners[k]->getStartTime();
- }
- prepareCalculations(*runners[k]);
- runners[k]->tmpResult.runningTime = deduceTime(*runners[k], runners[k]->tmpResult.startTime);
- runners[k]->tmpResult.status = deduceStatus(*runners[k]);
- runners[k]->tmpResult.points = deducePoints(*runners[k]);
+ runnerScore[k].principalSort = 0;
- runnerScore[k].score = score(*runners[k], runners[k]->tmpResult.status,
- runners[k]->tmpResult.runningTime,
- runners[k]->tmpResult.points, false);
-
- storeOutput(runners[k]->tmpResult.outputTimes,
- runners[k]->tmpResult.outputNumbers);
-
- runnerScore[k].tr = runners[k];
-
- }
-
- ::sort(runnerScore.begin(), runnerScore.end());
- int place = 1;
- int iPlace = 1;
- int leadtime = 0;
- for (size_t k = 0; k < runnerScore.size(); k++) {
- if (k > 0 && runnerScore[k - 1].principalSort != runnerScore[k].principalSort) {
- place = 1;
- iPlace = 1;
- }
- else if (k > 0 && runnerScore[k - 1].score != runnerScore[k].score) {
- place = iPlace;
- }
-
- if (runnerScore[k].tr->tmpResult.status == StatusOK) {
- runnerScore[k].tr->tmpResult.place = place;
- iPlace++;
- if (place == 1) {
- leadtime = runnerScore[k].tr->tmpResult.runningTime;
- runnerScore[k].tr->tmpResult.timeAfter = 0;
+ int from = getListParamTimeFromControl();
+ if (from <= 0) {
+ runners[k]->tmpResult.startTime = r->getStartTime();
}
else {
- runnerScore[k].tr->tmpResult.timeAfter = runnerScore[k].tr->tmpResult.runningTime - leadtime;
+ int rt;
+ RunnerStatus stat;
+ runners[k]->getSplitTime(from, stat, rt);
+ if (stat == StatusOK)
+ runners[k]->tmpResult.startTime = runners[k]->getStartTime() + rt;
+ else
+ runners[k]->tmpResult.startTime = runners[k]->getStartTime();
+ }
+
+ prepareCalculations(*runners[k], classResult);
+ runners[k]->tmpResult.runningTime = deduceTime(*runners[k], runners[k]->tmpResult.startTime);
+ runners[k]->tmpResult.status = deduceStatus(*runners[k]);
+ runners[k]->tmpResult.points = deducePoints(*runners[k]);
+
+ runnerScore[k].score = score(*runners[k], runners[k]->tmpResult.status,
+ runners[k]->tmpResult.runningTime,
+ runners[k]->tmpResult.points, false);
+
+ storeOutput(runners[k]->tmpResult.outputTimes,
+ runners[k]->tmpResult.outputNumbers);
+
+ runnerScore[k].tr = runners[k];
+
+ }
+
+ ::sort(runnerScore.begin(), runnerScore.end());
+ int place = 1;
+ int iPlace = 1;
+ int leadtime = 0;
+ for (size_t k = 0; k < runnerScore.size(); k++) {
+ if (k > 0 && runnerScore[k - 1].principalSort != runnerScore[k].principalSort) {
+ place = 1;
+ iPlace = 1;
+ }
+ else if (k > 0 && runnerScore[k - 1].score != runnerScore[k].score) {
+ place = iPlace;
+ }
+
+ if (runnerScore[k].tr->tmpResult.status == StatusOK) {
+ runnerScore[k].tr->tmpResult.place = place;
+ iPlace++;
+ if (place == 1) {
+ leadtime = runnerScore[k].tr->tmpResult.runningTime;
+ runnerScore[k].tr->tmpResult.timeAfter = 0;
+ }
+ else {
+ runnerScore[k].tr->tmpResult.timeAfter = runnerScore[k].tr->tmpResult.runningTime - leadtime;
+ }
+ }
+ else {
+ runnerScore[k].tr->tmpResult.place = 0;
+ runnerScore[k].tr->tmpResult.timeAfter = 0;
}
}
- else {
- runnerScore[k].tr->tmpResult.place = 0;
- runnerScore[k].tr->tmpResult.timeAfter = 0;
+
+ if (sortRunners) {
+ for (size_t k = 0; k < runnerScore.size(); k++) {
+ runners[k] = (oRunner *)runnerScore[k].tr;
+ }
}
}
-
- if (sortRunners) {
- for (size_t k = 0; k < runnerScore.size(); k++) {
- runners[k] = (oRunner *)runnerScore[k].tr;
- }
+ catch (...) {
+ lockPrepare = false;
+ throw;
}
+ lockPrepare = false;
}
-void GeneralResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const {
+void GeneralResult::prepareCalculations(oEvent &oe, bool classResult, const set &cls, vector &runners, vector &teams, int inputNumber) const {
}
-void GeneralResult::prepareCalculations(oTeam &team) const {
+void GeneralResult::prepareCalculations(oTeam &team, bool classResult) const {
int nr = team.getNumRunners();
for (int j = 0; j < nr; j++) {
pRunner r = team.getRunner(j);
if (r) {
- prepareCalculations(*r);
+ prepareCalculations(*r, classResult);
r->tmpResult.runningTime = deduceTime(*r, r->getStartTime()); //XXX
r->tmpResult.status = deduceStatus(*r);
r->tmpResult.place = 0;//XXX?
@@ -398,7 +455,7 @@ void GeneralResult::prepareCalculations(oTeam &team) const {
}
}
-void GeneralResult::prepareCalculations(oRunner &runner) const {
+void GeneralResult::prepareCalculations(oRunner &runner, bool classResult) const {
int from = getListParamTimeFromControl();
runner.tmpResult.startTime = runner.getStartTime();
@@ -414,8 +471,8 @@ void GeneralResult::prepareCalculations(oRunner &runner) const {
void GeneralResult::storeOutput(vector ×, vector &numbers) const {
}
-int GeneralResult::score(oTeam &team, RunnerStatus st, int rt, int points) const {
- return (100 * RunnerStatusOrderMap[st] + team.getNumShortening()) * 900000 + rt;
+pair GeneralResult::score(oTeam &team, RunnerStatus st, int rt, int points) const {
+ return make_pair((100 * RunnerStatusOrderMap[st] + team.getNumShortening()) * 100000 - points, + rt);
}
RunnerStatus GeneralResult::deduceStatus(oTeam &team) const {
@@ -423,19 +480,20 @@ RunnerStatus GeneralResult::deduceStatus(oTeam &team) const {
}
int GeneralResult::deduceTime(oTeam &team) const {
- return team.getRunningTime();
+ return team.getRunningTime(false);
}
int GeneralResult::deducePoints(oTeam &team) const {
- return team.getRogainingPoints(false);
+ return team.getRogainingPoints(false, false);
}
-int GeneralResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
+pair GeneralResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (asTeamMember) {
- return runner.getLegNumber();
+ return make_pair(runner.getLegNumber(), 0);
+ }
+ else {
+ return make_pair((100 * RunnerStatusOrderMap[st] + runner.getNumShortening()) * 100000 - points, time);
}
- else
- return (RunnerStatusOrderMap[st] * 100 + runner.getNumShortening()) * 900000 + time;
}
RunnerStatus GeneralResult::deduceStatus(oRunner &runner) const {
@@ -443,14 +501,14 @@ RunnerStatus GeneralResult::deduceStatus(oRunner &runner) const {
}
int GeneralResult::deduceTime(oRunner &runner, int startTime) const {
- return runner.getRunningTime();
+ return runner.getRunningTime(false);
}
int GeneralResult::deducePoints(oRunner &runner) const {
- return runner.getRogainingPoints(false);
+ return runner.getRogainingPoints(false, false);
}
-int ResultAtControl::score(oTeam &team, RunnerStatus st, int time, int points) const {
+pair ResultAtControl::score(oTeam &team, RunnerStatus st, int time, int points) const {
return GeneralResult::score(team, st, time, points);
}
@@ -466,14 +524,11 @@ int ResultAtControl::deducePoints(oTeam &team) const {
return GeneralResult::deducePoints(team);
}
-int ResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
+pair ResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (asTeamMember)
- return runner.getLegNumber();
- const int TK = 3600 * 100;
- if (st == StatusOK)
- return time;
- else
- return TK + st;
+ return make_pair(runner.getLegNumber(), 0);
+
+ return make_pair(RunnerStatusOrderMap[st], time);
}
RunnerStatus TotalResultAtControl::deduceStatus(oRunner &runner) const {
@@ -492,7 +547,7 @@ RunnerStatus TotalResultAtControl::deduceStatus(oRunner &runner) const {
while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx)))
legIx--;
if (legIx > 0)
- inputStatus = t->getLegStatus(legIx - 1, true);
+ inputStatus = t->getLegStatus(legIx - 1, false, true);
}
else {
inputStatus = t->getInputStatus();
@@ -522,7 +577,7 @@ int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const {
while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx)))
legIx--;
if (legIx > 0)
- inputTime = t->getLegRunningTime(legIx - 1, true);
+ inputTime = t->getLegRunningTime(legIx - 1, false, true);
}
else {
inputTime = t->getInputTime();
@@ -535,16 +590,16 @@ int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const {
return singleTime + inputTime;
}
-int TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
+pair TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (asTeamMember)
- return runner.getLegNumber();
- const int TK = 3600 * 100;
+ return make_pair(runner.getLegNumber(), 0);
+ const int TK = 3600 * 24 * 7;
RunnerStatus inputStatus = StatusOK;
if (runner.getTeam()) {
const pTeam t = runner.getTeam();
if (runner.getLegNumber() > 0) {
- inputStatus = t->getLegStatus(runner.getLegNumber() - 1, true);
+ inputStatus = t->getLegStatus(runner.getLegNumber() - 1, false, true);
}
else {
inputStatus = t->getInputStatus();
@@ -557,11 +612,7 @@ int TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int
if (st != StatusUnknown)
st = max(inputStatus, st);
- if (st == StatusOK) {
- return time;
- }
- else
- return TK + st;
+ return make_pair(RunnerStatusOrderMap[st], time);
}
RunnerStatus ResultAtControl::deduceStatus(oRunner &runner) const {
@@ -573,7 +624,7 @@ RunnerStatus ResultAtControl::deduceStatus(oRunner &runner) const {
return stat;
}
RunnerStatus st = runner.getStatus();
- if (st == StatusUnknown && runner.getRunningTime() > 0)
+ if (st == StatusUnknown && runner.getRunningTime(false) > 0)
return StatusOK;
return st;
}
@@ -644,6 +695,7 @@ DynamicResult::DynamicResult(const DynamicResult &resIn) {
}
void DynamicResult::operator=(const DynamicResult &resIn) {
+ clear();
isCompiled = false;
name = resIn.name;
tag = resIn.tag;
@@ -718,17 +770,21 @@ RunnerStatus DynamicResult::toStatus(int status) const {
return StatusDQ;
case StatusMAX:
return StatusMAX;
+ case StatusOutOfCompetition:
+ return StatusOutOfCompetition;
+ case StatusNoTiming:
+ return StatusNoTiming;
default:
throw meosException("Unknown status code X#" + itos(status));
}
}
-int DynamicResult::score(oTeam &team, RunnerStatus st, int time, int points) const {
+pair DynamicResult::score(oTeam &team, RunnerStatus st, int time, int points) const {
if (getMethod(MTScore)) {
parser.addSymbol("ComputedTime", time);
parser.addSymbol("ComputedStatus", st);
parser.addSymbol("ComputedPoints", points);
- return getMethod(MTScore)->evaluate(parser);
+ return make_pair(0, getMethod(MTScore)->evaluate(parser));
}
else if (getMethodSource(MTScore).empty())
return GeneralResult::score(team, st, time, points);
@@ -759,12 +815,12 @@ int DynamicResult::deducePoints(oTeam &team) const {
else throw meosException("Syntax error");
}
-int DynamicResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
+pair DynamicResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (getMethod(MRScore)) {
parser.addSymbol("ComputedTime", time);
parser.addSymbol("ComputedStatus", st);
parser.addSymbol("ComputedPoints", points);
- return getMethod(MRScore)->evaluate(parser);
+ return make_pair(0, getMethod(MRScore)->evaluate(parser));
}
else if (getMethodSource(MRScore).empty())
return GeneralResult::score(runner, st, time, points, asTeamMember);
@@ -831,7 +887,7 @@ void DynamicResult::save(xmlparser &xml) const {
void DynamicResult::clear() {
parser.clear();
for (size_t k = 0; k < methods.size(); k++) {
- methods[k].pn = 0;
+ methods[k].pn = nullptr;
methods[k].source.clear();
methods[k].description.clear();
}
@@ -937,6 +993,11 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("InputPlace", "Runner/team input place", false);
parser.declareSymbol("InputPoints", "Runner/team input points", false);
+ parser.declareSymbol("StageStatus", "Runner/team earlier stage statuses", true);
+ parser.declareSymbol("StageTime", "Runner/team earlier stage running times", true);
+ parser.declareSymbol("StagePlace", "Runner/team earlier stage places", true);
+ parser.declareSymbol("StagePoints", "Runner/team earlier stage points", true);
+
parser.declareSymbol("Fee", "Runner/team fee", false);
parser.declareSymbol("ClubId", "Club id number", false);
@@ -963,6 +1024,9 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("LegPlace", "Place on course leg", true);
parser.declareSymbol("Leg", "Leg number in team, zero indexed", false);
parser.declareSymbol("BirthYear", "Year of birth", false);
+ parser.declareSymbol("Age", "Age (on last day of current year)", false);
+ parser.declareSymbol("AgeLowLimit", "Age below or equal implies youth", false);
+ parser.declareSymbol("AgeHighLimit", "Age above or equal implies senior/pensioner", false);
parser.declareSymbol("CheckTime", "Runner check time", false);
}
else {
@@ -997,7 +1061,9 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("StatusCANCEL", "Status code for cancelled entry", false);
parser.declareSymbol("StatusMAX", "Status code for a time over the maximum", false);
parser.declareSymbol("StatusDQ", "Status code for disqualification", false);
+ parser.declareSymbol("StatusOutOfCompetition", "Status code for running out-of-competition", false);
parser.declareSymbol("StatusNotCompetiting", "Status code for not competing", false);
+ parser.declareSymbol("StatusNoTiming", "Status code for not no timing", false);
parser.declareSymbol("ShortestClassTime", "Shortest time in class", false);
@@ -1016,22 +1082,59 @@ void DynamicResult::getSymbolInfo(int ix, wstring &name, wstring &desc) const {
parser.getSymbolInfo(ix, name, desc);
}
-void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const {
+void DynamicResult::prepareCalculations(oEvent &oe,
+ bool classResult,
+ const set &clsSelection,
+ vector &runners,
+ vector &teams,
+ int inputNumber) const {
compile(false);
- oe.calculateResults(set(), oEvent::ResultType::ClassResult);
- oe.calculateResults(set(), oEvent::ResultType::TotalResult);
+
+
+ oDataConstInterface odc = oe.getDCI();
+ lowAgeLimit = odc.getInt("YouthAge");
+ highAgeLimit = odc.getInt("SeniorAge");
+
+ oEvent::ResultType single, total;
+ if (classResult) {
+ single = oEvent::ResultType::ClassResultDefault;
+ total = oEvent::ResultType::TotalResultDefault;
+ }
+ else {
+ single = oEvent::ResultType::ClassResult;
+ total = oEvent::ResultType::TotalResult;
+ }
+ oe.calculateResults(clsSelection, single);
+ oe.calculateResults(clsSelection, total);
+ vector *tPtr = &teams;
+ vector prepTeam;
+ if (teams.empty()) {
+ vector allTeam;
+ oe.getTeams(0, allTeam, false);
+ if (clsSelection.empty())
+ prepTeam.swap(allTeam);
+ else {
+ for (pTeam t : allTeam)
+ if (clsSelection.count(t->getClassId(false))) {
+ prepTeam.push_back(t);
+ }
+ }
+ tPtr = &prepTeam;
+ }
+
+ oe.calculateTeamResults(*tPtr, single);
+ oe.calculateTeamResults(*tPtr, total);
declareSymbols(MRScore, true);
- if (prepareForTeam) {
+ if (teams.size() > 0) {
declareSymbols(MTScore, false);
- vector t;
- oe.getTeams(0, t, false);
- for (size_t k = 0; k < t.size(); k++)
- t[k]->resetResultCalcCache();
+ for (pTeam t : teams)
+ t->resetResultCalcCache();
- oe.calculateTeamResults(false);
- oe.calculateTeamResults(true);
+ oe.calculateTeamResults(teams, single);
+ oe.calculateTeamResults(teams, total);
}
+
parser.addSymbol("StatusUnknown", StatusUnknown);
parser.addSymbol("StatusOK", StatusOK);
parser.addSymbol("StatusMP", StatusMP);
@@ -1040,13 +1143,16 @@ void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inp
parser.addSymbol("StatusDNS", StatusDNS);
parser.addSymbol("StatusMAX", StatusMAX);
parser.addSymbol("StatusDQ", StatusDQ);
+ parser.addSymbol("StatusOutOfCompetition", StatusOutOfCompetition);
+ parser.addSymbol("StatusNoTiming", StatusNoTiming);
parser.addSymbol("StatusNotCompetiting", StatusNotCompetiting);
parser.addSymbol("MaxTime", oe.getMaximalTime());
parser.addSymbol("InputNumber", inputNumber);
}
-void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
+void DynamicResult::prepareCommon(oAbstractRunner &runner, bool classResult) const {
+ bool useComputed = classResult == false;
parser.clearVariables();
int st = runner.getStatus();
int ft = runner.getFinishTime();
@@ -1055,12 +1161,12 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
parser.addSymbol("Status", st);
parser.addSymbol("Start", runner.getStartTime());
parser.addSymbol("Finish", ft);
- parser.addSymbol("Time", runner.getRunningTime());
+ parser.addSymbol("Time", runner.getRunningTime(useComputed));
parser.addSymbol("Place", runner.getPlace());
- parser.addSymbol("Points", runner.getRogainingPoints(false));
- parser.addSymbol("PointReduction", runner.getRogainingReduction());
- parser.addSymbol("PointOvertime", runner.getRogainingOvertime());
- parser.addSymbol("PointGross", runner.getRogainingPointsGross());
+ parser.addSymbol("Points", runner.getRogainingPoints(useComputed, false));
+ parser.addSymbol("PointReduction", runner.getRogainingReduction(useComputed));
+ parser.addSymbol("PointOvertime", runner.getRogainingOvertime(useComputed));
+ parser.addSymbol("PointGross", runner.getRogainingPointsGross(useComputed));
parser.addSymbol("PointAdjustment", runner.getPointAdjustment());
parser.addSymbol("TimeAdjustment", runner.getTimeAdjustment());
@@ -1075,6 +1181,25 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
parser.addSymbol("InputPoints", runner.getInputPoints());
parser.addSymbol("Shorten", runner.getNumShortening());
+ vector inst;
+ vector times;
+ vector points;
+ vector places;
+ vector iinst;
+ runner.getInputResults(inst, times, points, places);
+ for (RunnerStatus s : inst)
+ iinst.push_back(s);
+
+ parser.addSymbol("StageStatus", iinst);
+ parser.addSymbol("StageTime", times);
+ parser.addSymbol("StagePlace", places);
+ parser.addSymbol("StagePoints", points);
+
+ parser.addSymbol("InputStatus", runner.getInputStatus());
+ parser.addSymbol("InputTime", runner.getInputTime());
+ parser.addSymbol("InputPlace", runner.getInputPlace());
+ parser.addSymbol("InputPoints", runner.getInputPoints());
+
parser.addSymbol("Fee", runner.getDCI().getInt("Fee"));
const pClub pc = runner.getClubRef();
@@ -1089,9 +1214,9 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
parser.addSymbol("Bib", _wtoi(runner.getBib().c_str()));
}
-void DynamicResult::prepareCalculations(oTeam &team) const {
- GeneralResult::prepareCalculations(team);
- prepareCommon(team);
+void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
+ GeneralResult::prepareCalculations(team, classResult);
+ prepareCommon(team, classResult);
int nr = team.getNumRunners();
vector status(nr), time(nr), start(nr), finish(nr), points(nr);
vector< vector > runnerOutputTimes(nr);
@@ -1126,7 +1251,8 @@ void DynamicResult::prepareCalculations(oTeam &team) const {
parser.removeSymbol("SplitTimesAccumulated");
parser.removeSymbol("LegTimeDeviation");
parser.removeSymbol("BirthYear");
-
+ parser.removeSymbol("Age");
+
parser.addSymbol("RunnerOutputNumbers", runnerOutputNumbers);
parser.addSymbol("RunnerOutputTimes", runnerOutputTimes);
@@ -1150,13 +1276,13 @@ void DynamicResult::prepareCalculations(oTeam &team) const {
pClass cls = team.getClassRef(true);
if (cls) {
int nl = max(1, cls->getNumStages() - 1);
- parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(nl, false));
+ parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(nl, false, false));
}
}
-void DynamicResult::prepareCalculations(oRunner &runner) const {
- GeneralResult::prepareCalculations(runner);
- prepareCommon(runner);
+void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const {
+ GeneralResult::prepareCalculations(runner, classResult);
+ prepareCommon(runner, classResult);
pCard pc = runner.getCard();
if (pc) {
vector punches;
@@ -1263,7 +1389,7 @@ void DynamicResult::prepareCalculations(oRunner &runner) const {
pClass cls = runner.getClassRef(true);
if (cls) {
int nl = runner.getLegNumber();
- parser.addSymbol("ShortestClassTime", cls->getBestLegTime(nl));
+ parser.addSymbol("ShortestClassTime", cls->getBestLegTime(nl, false));
}
vector delta;
vector place;
@@ -1277,6 +1403,11 @@ void DynamicResult::prepareCalculations(oRunner &runner) const {
parser.addSymbol("LegPlace", place);
parser.addSymbol("Leg", runner.getLegNumber());
parser.addSymbol("BirthYear", runner.getBirthYear());
+ int ba = runner.getBirthAge();
+ parser.addSymbol("Age", ba);
+ parser.addSymbol("AgeLowLimit", lowAgeLimit);
+ parser.addSymbol("AgeHighLimit", highAgeLimit);
+
parser.addSymbol("CheckTime", runner.getCheckTime());
}
@@ -1298,12 +1429,17 @@ long long DynamicResult::getHashCode() const {
string DynamicResult::undecorateTag(const string &inputTag) {
int ix = inputTag.rfind("-v");
- if (ix > 0 && ix != inputTag.npos)
+ int limit = inputTag.length() - 4;
+ if (ix > 0 && ix != inputTag.npos && ix >= limit)
return inputTag.substr(0, ix);
else
return inputTag;
}
+bool DynamicResult::isRogaining() const {
+ return !methods[DynamicMethods::MDeduceRPoints].source.empty();
+}
+
wstring DynamicResult::getName(bool withAnnotation) const {
if (annotation.empty() || !withAnnotation)
return name;
@@ -1346,7 +1482,11 @@ void GeneralResult::calculateIndividualResults(vector &runners,
controlId.first == oPunch::PunchStart) {
if (!totalResults) {
- oe.calculateResults(set(), oEvent::ResultType::ClassResult, true);
+ set clsId;
+ for (pRunner r : runners) {
+ clsId.insert(r->getClassId(true));
+ }
+ oe.calculateResults(clsId, oEvent::ResultType::ClassResult, true);
for (pRunner r : runners) {
ri.status = r->getStatus();
if (ri.status == StatusUnknown) {
@@ -1368,8 +1508,8 @@ void GeneralResult::calculateIndividualResults(vector &runners,
else
ri.place = 0;
- ri.score = r->getRogainingPoints(false);
- ri.time = r->getRunningTime();
+ ri.score = r->getRogainingPoints(true, false);
+ ri.time = r->getRunningTime(true);
ri.src = r;
results.push_back(ri);
}
@@ -1397,7 +1537,7 @@ void GeneralResult::calculateIndividualResults(vector &runners,
else
ri.place = 0;
- ri.score = r->getRogainingPoints(true);
+ ri.score = r->getRogainingPoints(true, true);
ri.time = r->getTotalRunningTime();
ri.src = r;
results.push_back(ri);
@@ -1432,14 +1572,14 @@ void GeneralResult::calculateIndividualResults(vector &runners,
}
else {
wstring srcDMY;
- GeneralResult *gResult = 0;
+ GeneralResult *gResult = nullptr;
shared_ptr specialInstance;
oListParam param;
param.useControlIdResultTo = controlId.second;
param.useControlIdResultFrom = controlId.first;
if (!resTag.empty())
- gResult = &oe.getGeneralResult(resTag, srcDMY);
+ gResult = oe.getGeneralResult(resTag, srcDMY).get();
else {
if (controlId.second == oPunch::PunchFinish &&
controlId.first == oPunch::PunchStart && !totalResults)
@@ -1452,7 +1592,7 @@ void GeneralResult::calculateIndividualResults(vector &runners,
gResult = specialInstance.get();
}
gResult->setContext(¶m);
- gResult->calculateIndividualResults(runners, resType, true, inputNumber);
+ gResult->calculateIndividualResults(runners, false, resType, true, inputNumber);
gResult->clearContext();
map mapHasCourse;
GeneralResultInfo ri;
@@ -1510,7 +1650,7 @@ GeneralResult::calculateTeamResults(vector &teams,
if (resTag.empty()) {
out->useModule = false;
if (controlId.second == oPunch::PunchFinish) {
- oe.calculateTeamResults(false);
+ oe.calculateTeamResults(teams, oEvent::ResultType::ClassResult);
GeneralResultInfo ri;
for (pTeam r : teams) {
ri.status = r->getStatus();
@@ -1524,9 +1664,9 @@ GeneralResult::calculateTeamResults(vector &teams,
else
ri.place = 0;
- ri.score = r->getRogainingPoints(false);
+ ri.score = r->getRogainingPoints(true, false);
ri.status = r->getStatus();
- ri.time = r->getRunningTime();
+ ri.time = r->getRunningTime(true);
ri.src = r;
results.push_back(ri);
}
@@ -1555,7 +1695,7 @@ GeneralResult::calculateTeamResults(vector &teams,
out->useModule = true;
wstring srcDMY;
auto &gResult = oe.getGeneralResult(resTag, srcDMY);
- gResult.calculateTeamResults(teams, resType, true, inputNumber);
+ gResult->calculateTeamResults(teams, false, resType, true, inputNumber);
GeneralResultInfo ri;
for (pTeam r : teams) {
const auto &tmp = r->getTempResult(0);
@@ -1623,9 +1763,9 @@ bool GeneralResult::GeneralResultInfo::getSubResult(const BaseResultContext &con
}
else {
if (context.controlId.second == oPunch::PunchFinish) {
- out.score = r->getRogainingPoints(false);
+ out.score = r->getRogainingPoints(true, false);
out.status = r->getStatus();
- out.time = r->getRunningTime();
+ out.time = r->getRunningTime(true);
}
else {
out.score = 0; // Undefined
diff --git a/code/generalresult.h b/code/generalresult.h
index 7e80ca1..9668275 100644
--- a/code/generalresult.h
+++ b/code/generalresult.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,24 +37,25 @@ class GeneralResult
{
private:
const oListParam *context;
+ mutable bool lockPrepare = false;
protected:
enum PrincipalSort {None, ClassWise, CourseWise};
- virtual int score(oTeam &team, RunnerStatus st, int time, int points) const;
+ virtual pair score(oTeam &team, RunnerStatus st, int time, int points) const;
virtual RunnerStatus deduceStatus(oTeam &team) const;
virtual int deduceTime(oTeam &team) const;
virtual int deducePoints(oTeam &team) const;
- virtual int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
+ virtual pair score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
virtual RunnerStatus deduceStatus(oRunner &runner) const;
virtual int deduceTime(oRunner &runner, int startTime) const;
virtual int deducePoints(oRunner &runner) const;
- virtual void prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const;
- virtual void prepareCalculations(oTeam &team) const;
- virtual void prepareCalculations(oRunner &runner) const;
+ virtual void prepareCalculations(oEvent &oe, bool classResult, const set &clsSelection, vector &runners, vector &teams, int inputNumber) const;
+ virtual void prepareCalculations(oTeam &team, bool classResult) const;
+ virtual void prepareCalculations(oRunner &runner, bool classResult) const;
virtual void storeOutput(vector ×, vector &numbers) const;
int getListParamTimeToControl() const;
@@ -62,6 +63,10 @@ protected:
public:
+ virtual const string &getTimeStamp() const;
+
+ virtual bool isRogaining() const;
+
struct BaseResultContext {
private:
int leg;
@@ -142,10 +147,22 @@ public:
void setContext(const oListParam *context);
void clearContext();
- void calculateTeamResults(vector &teams, oListInfo::ResultType resType, bool sortTeams, int inputNumber) const;
- void calculateIndividualResults(vector &runners, oListInfo::ResultType resType, bool sortRunners, int inputNumber) const;
+ void calculateTeamResults(vector &teams,
+ bool classResult,
+ oListInfo::ResultType resType,
+ bool sortTeams,
+ int inputNumber) const;
+ void calculateIndividualResults(vector &runners,
+ bool classResult,
+ oListInfo::ResultType resType,
+ bool sortRunners,
+ int inputNumber) const;
void sortTeamMembers(vector &runners) const;
+ virtual bool isDynamic() const {
+ return false;
+ }
+
template void sort(vector &rt, SortOrder so) const;
GeneralResult(void);
@@ -154,22 +171,22 @@ public:
class ResultAtControl : public GeneralResult {
protected:
- int score(oTeam &team, RunnerStatus st, int time, int points) const;
- RunnerStatus deduceStatus(oTeam &team) const;
- int deduceTime(oTeam &team) const;
- int deducePoints(oTeam &team) const;
+ pair score(oTeam &team, RunnerStatus st, int time, int points) const override;
+ RunnerStatus deduceStatus(oTeam &team) const override;
+ int deduceTime(oTeam &team) const override;
+ int deducePoints(oTeam &team) const override;
- int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
- RunnerStatus deduceStatus(oRunner &runner) const;
- int deduceTime(oRunner &runner, int startTime) const;
- int deducePoints(oRunner &runner) const;
+ pair score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const override;
+ RunnerStatus deduceStatus(oRunner &runner) const override;
+ int deduceTime(oRunner &runner, int startTime) const override;
+ int deducePoints(oRunner &runner) const override;
};
class TotalResultAtControl : public ResultAtControl {
protected:
- int deduceTime(oRunner &runner, int startTime) const;
- RunnerStatus deduceStatus(oRunner &runner) const;
- int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
+ int deduceTime(oRunner &runner, int startTime) const override;
+ RunnerStatus deduceStatus(oRunner &runner) const override;
+ pair score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const override;
};
class DynamicResult : public GeneralResult {
@@ -189,11 +206,14 @@ public:
};
private:
-
+ bool allowRetag = true;
static map symb2Method;
static map > method2SymbName;
static int instanceCount;
+ mutable int lowAgeLimit = -1;
+ mutable int highAgeLimit = 1000;
+
class MethodInfo {
string source;
mutable ParseNode *pn;
@@ -221,16 +241,24 @@ private:
void addSymbol(DynamicMethods method, const char *symb, const char *name);
RunnerStatus toStatus(int status) const;
- void prepareCommon(oAbstractRunner &runner) const;
+ void prepareCommon(oAbstractRunner &runner, bool classResult) const;
- static string getInternalPath(const string &tag);
public:
+ bool isDynamic() const override {
+ return true;
+ }
+
+ bool retaggable() const { return allowRetag; }
+ void retaggable(bool r) { allowRetag = r; }
+
void setReadOnly() const {readOnly = true;}
bool isReadOnly() const {return readOnly;}
- const string &getTimeStamp() const {return timeStamp;}
+ const string &getTimeStamp() const override {return timeStamp;}
+
+ bool isRogaining() const override;
static string undecorateTag(const string &inputTag);
@@ -241,20 +269,26 @@ public:
void declareSymbols(DynamicMethods m, bool clear) const;
- void prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const;
- void prepareCalculations(oTeam &team) const;
- void prepareCalculations(oRunner &runner) const;
+ void prepareCalculations(oEvent &oe,
+ bool classResult,
+ const set &clsSelection,
+ vector &runners,
+ vector &teams,
+ int inputNumber) const override;
+ void prepareCalculations(oTeam &team, bool classResult) const override;
+ void prepareCalculations(oRunner &runner, bool classResult) const override;
+
void storeOutput(vector ×, vector &numbers) const;
- int score(oTeam &team, RunnerStatus st, int time, int points) const;
- RunnerStatus deduceStatus(oTeam &team) const;
- int deduceTime(oTeam &team) const;
- int deducePoints(oTeam &team) const;
+ pair score(oTeam &team, RunnerStatus st, int time, int points) const override;
+ RunnerStatus deduceStatus(oTeam &team) const override;
+ int deduceTime(oTeam &team) const override;
+ int deducePoints(oTeam &team) const override;
- int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
- RunnerStatus deduceStatus(oRunner &runner) const;
- int deduceTime(oRunner &runner, int startTime) const;
- int deducePoints(oRunner &runner) const;
+ pair score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const override;
+ RunnerStatus deduceStatus(oRunner &runner) const override;
+ int deduceTime(oRunner &runner, int startTime) const override;
+ int deducePoints(oRunner &runner) const override;
DynamicResult();
DynamicResult(const DynamicResult &resIn);
@@ -294,3 +328,25 @@ public:
void clear();
};
+struct GeneralResultCtr {
+ wstring name;
+ string tag;
+ wstring fileSource;
+
+ bool isDynamic() const;
+ bool operator<(const GeneralResultCtr &c) const;
+ shared_ptr ptr;
+
+ // True if implicitly loaded (form list or by class results)
+ bool isImplicit() const {
+ return fileSource == L"*";
+ }
+
+ GeneralResultCtr(const char *tag, const wstring &name, const shared_ptr &ptr);
+ GeneralResultCtr(wstring &file, const shared_ptr &ptr);
+ GeneralResultCtr() {}
+
+ ~GeneralResultCtr();
+ GeneralResultCtr(const GeneralResultCtr &ctr);
+ void operator=(const GeneralResultCtr &ctr);
+};
diff --git a/code/guihandler.h b/code/guihandler.h
index 55bec24..cc50c65 100644
--- a/code/guihandler.h
+++ b/code/guihandler.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/html1.htm b/code/html1.htm
index a2d5f9f..76a685a 100644
--- a/code/html1.htm
+++ b/code/html1.htm
@@ -429,13 +429,16 @@ This query is suitable for auto complete functionality.
card Card number.
-Returns:
-Status.
+Returns:
+Status.
+
+Note: If the card number is registered as a rental card, it will be set as such and
+ hiredCard will be set in the Fee attribute. The returned fee includes any rental card fee.
*Answer>
*Status>OK*/Status>
- *Fee>130*/Fee>
+ *Fee hiredCard="true">130*/Fee>
*Info>Open Long, Rudolf Minowski (OK Tisaren)*/Info>
*/Answer>
@@ -454,7 +457,6 @@ Status.
Returns:
Installed template file with the specified tag.
-
Image
Syntax:
/meos?image=*image>
diff --git a/code/image.cpp b/code/image.cpp
index 2472aef..512b431 100644
--- a/code/image.cpp
+++ b/code/image.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/image.h b/code/image.h
index c390f02..1bdff5c 100644
--- a/code/image.h
+++ b/code/image.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/importformats.cpp b/code/importformats.cpp
index 7ef0b26..2d597ac 100644
--- a/code/importformats.cpp
+++ b/code/importformats.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/infoserver.cpp b/code/infoserver.cpp
index 1d41f41..bb179db 100644
--- a/code/infoserver.cpp
+++ b/code/infoserver.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -488,10 +488,14 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
ch = true;
}
- int s = bc.getStatus();
- int rt = bc.getRunningTime() * 10;
- if (rt > 0 && s == RunnerStatus::StatusUnknown)
- s = RunnerStatus::StatusOK;
+ RunnerStatus s = bc.getStatus();
+ int rt = bc.getRunningTime(true) * 10;
+ if (rt > 0) {
+ if (s == RunnerStatus::StatusUnknown)
+ s = RunnerStatus::StatusOK;
+ }
+ else if (isPossibleResultStatus(s))
+ s = StatusUnknown;
if (status != s) {
status = s;
@@ -547,8 +551,8 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
s = r.getTotalStatusInput();
}
else if (t && !isQF && r.getLegNumber() > 0) {
- legInput = t->getLegRunningTime(r.getLegNumber() - 1, false) * 10;
- s = t->getLegStatus(r.getLegNumber() - 1, false);
+ legInput = t->getLegRunningTime(r.getLegNumber() - 1, true, false) * 10;
+ s = t->getLegStatus(r.getLegNumber() - 1, true, false);
}
if (totalStatus != s) {
@@ -569,9 +573,29 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
bool useTotalResults = cmp.includeTotalResults();
bool inludeCourse = cmp.includeCourse();
-
bool ch = synchronize(useTotalResults, inludeCourse, r);
+ int cno = r.getCardNo();
+ if (cno != cardNo) {
+ cardNo = cno;
+ changeCard = true;
+ ch = true;
+ }
+
+ bool nr;
+ if ((r.getStatus() == StatusUnknown || r.getStatus() == StatusOutOfCompetition || r.getStatus() == StatusNoTiming) && r.getFinishTime() <= 0) {
+ vector pv;
+ r.getEvent()->getPunchesForRunner(r.getId(), false, pv);
+ nr = pv.size() > 0;
+ }
+ else {
+ nr = false;
+ }
+ if (isRunning != nr) {
+ isRunning = nr;
+ ch = true;
+ }
+
vector newRT;
if (r.getClassId(false) > 0) {
const vector &radios = cmp.getControls(r.getClassId(true), r.getLegNumber());
@@ -601,7 +625,16 @@ bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
void InfoCompetitor::serialize(xmlbuffer &xml, bool diffOnly) const {
vector< pair > sprop;
- sprop.push_back(make_pair("id", itow(getId())));
+ sprop.reserve(3);
+ sprop.emplace_back("id", itow(getId()));
+
+ if (changeCard || !diffOnly) {
+ sprop.emplace_back("card", itow(cardNo));
+ changeCard = false;
+ }
+ if (isRunning)
+ sprop.emplace_back("competing", L"true");
+
xmlbuffer &subTag = xml.startTag("cmp", sprop);
InfoBaseCompetitor::serialize(subTag, diffOnly, course);
@@ -627,7 +660,6 @@ void InfoCompetitor::serialize(xmlbuffer &xml, bool diffOnly) const {
xml.endTag();
}
-
bool InfoTeam::synchronize(oTeam &t) {
bool ch = synchronizeBase(t);
diff --git a/code/infoserver.h b/code/infoserver.h
index 5392176..b804aa3 100644
--- a/code/infoserver.h
+++ b/code/infoserver.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -182,9 +182,12 @@ class InfoCompetitor : public InfoBaseCompetitor {
int inputTime;
int totalStatus;
int course;
+ int cardNo = 0;
+ bool isRunning = false;
bool synchronize(const InfoCompetition &cmp, oRunner &c);
bool changeTotalSt;
bool changeRadio;
+ mutable bool changeCard = false;
public:
bool synchronize(bool useTotalResults, bool useCourse, oRunner &c);
void serialize(xmlbuffer &xml, bool diffOnly) const;
diff --git a/code/inthashmap.h b/code/inthashmap.h
index 5b01b25..22c487c 100644
--- a/code/inthashmap.h
+++ b/code/inthashmap.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/intkeymap.hpp b/code/intkeymap.hpp
index 1db8275..07a4982 100644
--- a/code/intkeymap.hpp
+++ b/code/intkeymap.hpp
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/intkeymapimpl.hpp b/code/intkeymapimpl.hpp
index 73c0156..a821069 100644
--- a/code/intkeymapimpl.hpp
+++ b/code/intkeymapimpl.hpp
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/iof30interface.cpp b/code/iof30interface.cpp
index be54c42..69b5fac 100644
--- a/code/iof30interface.cpp
+++ b/code/iof30interface.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1236,7 +1236,8 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
wstring name;
xo.getObjectString("Name", name);
- oe.setName(name);
+ if (!oe.hasFlag(oEvent::TransferFlags::FlagManualName))
+ oe.setName(name, false);
int id = xo.getObjectInt("Id");
if (id>0) {
@@ -1264,11 +1265,13 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
int zt = t - 3600;
if (zt < 0)
zt += 3600*24;
- oe.setZeroTime(formatTimeHMS(zt));
+
+ if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
+ oe.setZeroTime(formatTimeHMS(zt), false);
}
}
-
- oe.setDate(dateStr);
+ if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
+ oe.setDate(dateStr, false);
//oe.setZeroTime(...);
}
@@ -1425,16 +1428,16 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
if (!matchStageFilter(stageFilter, races))
return 0;
- bool newTeam;
- pTeam t = getCreateTeam(gdi, xTeam, newTeam);
-
- if (!t)
- return 0;
-
// Class
map > localTeamClassConfig;
pClass pc = readClass(xTeam.getObject("Class"), localTeamClassConfig);
+ bool newTeam;
+ pTeam t = getCreateTeam(gdi, xTeam, pc ? pc->getId() : 0, newTeam);
+
+ if (!t)
+ return 0;
+
if (pc && (t->getClassId(false) == 0 || !t->hasFlag(oAbstractRunner::FlagUpdateClass)) ) {
t->setClassId(pc->getId(), false);
}
@@ -1443,11 +1446,11 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
wchar_t pat[32];
int no = oClass::extractBibPattern(bib, pat);
if (no > 0 && t->getBib().empty())
- t->setBib(bib, no, true, false);
+ t->setBib(bib, no, true);
else if (newTeam) {
pair autoBib = pc->getNextBib(bibPatterns);
if (autoBib.first > 0) {
- t->setBib(autoBib.second, autoBib.first, true, false);
+ t->setBib(autoBib.second, autoBib.first, true);
}
}
@@ -1486,8 +1489,8 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
for (size_t k = 0; ksynchronize();
+ t->applyBibs();
+ t->evaluate(oBase::ChangeType::Update);
return t;
}
@@ -1495,7 +1498,7 @@ pTeam IOF30Interface::readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
map > &bibPatterns,
const map > &teamClassConfig) {
bool newTeam;
- pTeam t = getCreateTeam(gdi, xTeam, newTeam);
+ pTeam t = getCreateTeam(gdi, xTeam, pc ? pc->getId() : 0, newTeam);
if (!t)
return 0;
@@ -1509,11 +1512,11 @@ pTeam IOF30Interface::readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
wchar_t pat[32];
int no = oClass::extractBibPattern(bib, pat);
if (no > 0 && t->getBib().empty())
- t->setBib(bib, no, true, false);
+ t->setBib(bib, no, true);
else if (newTeam){
pair autoBib = pc->getNextBib(bibPatterns);
if (autoBib.first > 0) {
- t->setBib(autoBib.second, autoBib.first, true, false);
+ t->setBib(autoBib.second, autoBib.first, true);
}
}
xmlList xEntries;
@@ -1522,12 +1525,12 @@ pTeam IOF30Interface::readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
for (size_t k = 0; ksynchronize();
+ t->applyBibs();
+ t->evaluate(oBase::ChangeType::Update);
return t;
}
-pTeam IOF30Interface::getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool &newTeam) {
+pTeam IOF30Interface::getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, int expectedClassId, bool &newTeam) {
newTeam = false;
wstring name;
xTeam.getObjectString("Name", name);
@@ -1542,7 +1545,8 @@ pTeam IOF30Interface::getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool
t = oe.getTeam(id);
else {
t = oe.getTeamByName(name);
- // XXX Check class
+ if (t && expectedClassId > 0 && t->getClassId(false) != expectedClassId)
+ t = nullptr;
}
if (!t) {
if (id > 0) {
@@ -1825,7 +1829,7 @@ pRunner IOF30Interface::readPersonStart(gdioutput &gdi, pClass pc, xmlobject &xo
starts[k].getObjectString("BibNumber", bib);
rRace->getDI().setString("Bib", bib);
- rRace->setStartTime(parseISO8601Time(startTime), true, false);
+ rRace->setStartTime(parseISO8601Time(startTime), true, oBase::ChangeType::Update);
}
}
@@ -2301,14 +2305,15 @@ pClass IOF30Interface::readClass(const xmlobject &xclass,
pc = oe.addClass(name);
oDataInterface DI = pc->getDI();
-
- if (!longName.empty()) {
- pc->setName(name);
- DI.setString("LongName", longName);
- }
- else {
- if (pc->getName() != name && DI.getString("LongName") != name)
- pc->setName(name);
+ if (!pc->hasFlag(oClass::TransferFlags::FlagManualName)) {
+ if (!longName.empty()) {
+ pc->setName(name, false);
+ DI.setString("LongName", longName);
+ }
+ else {
+ if (pc->getName() != name && DI.getString("LongName") != name)
+ pc->setName(name, false);
+ }
}
xmlList legs;
xclass.getObjects("Leg", legs);
@@ -2666,46 +2671,8 @@ void IOF30Interface::writeResultList(xmlparser &xml, const set &classes,
oe.getClasses(c, false);
for (size_t k = 0; k < c.size(); k++) {
-// bool indRel = c[k]->getClassType() == oClassIndividRelay;
if (classes.empty() || classes.count(c[k]->getId())) {
- /* oe.getRunners(c[k]->getId(), r, false);
- vector rToUse;
- rToUse.reserve(r.size());
-
- for (size_t j = 0; j < r.size(); j++) {
- if (leg == -1 || leg == r[j]->getLegNumber()) {
- if (leg == -1 && indRel && r[j]->getLegNumber() != 0)
- continue; // Skip all but leg 0 for individual relay
-
- if (leg == -1 && !indRel && r[j]->getTeam())
- continue; // For teams, skip presonal results, unless individual relay
-
- if (r[j]->getStatus() == StatusUnknown)
- continue;
-
- rToUse.push_back(r[j]);
- }
- }
-
- vector tToUse;
-
- if (leg == -1) {
- oe.getTeams(c[k]->getId(), t, false);
- tToUse.reserve(t.size());
-
- for (size_t j = 0; j < t.size(); j++) {
- for (int n = 0; n < t[j]->getNumRunners(); n++) {
- pRunner tr = t[j]->getRunner(n);
- if (tr && tr->getStatus() != StatusUnknown) {
- tToUse.push_back(t[j]);
- break;
- }
- }
- }
-
- }
- */
vector rToUse;
vector tToUse;
getRunnersToUse(c[k], rToUse, tToUse, leg, false);
@@ -2716,7 +2683,6 @@ void IOF30Interface::writeResultList(xmlparser &xml, const set &classes,
}
}
-
xml.endTag();
}
@@ -2801,8 +2767,11 @@ void IOF30Interface::writeCourseInfo(xmlparser &xml, const oCourse &c) {
}
-wstring formatStatus(RunnerStatus st) {
+wstring formatStatus(RunnerStatus st, bool hasTime) {
switch (st) {
+ case StatusNoTiming:
+ if (!hasTime)
+ break;
case StatusOK:
return L"OK";
case StatusDNS:
@@ -2817,11 +2786,13 @@ wstring formatStatus(RunnerStatus st) {
return L"Disqualified";
case StatusMAX:
return L"OverTime";
+ case StatusOutOfCompetition:
+ if (!hasTime)
+ break;
case StatusNotCompetiting:
return L"NotCompeting";
- default:
- return L"Inactive";
}
+ return L"Inactive";
}
void IOF30Interface::writePersonResult(xmlparser &xml, const oRunner &r,
@@ -2890,6 +2861,8 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (teamMember)
writeLegOrder(xml, rPerson.getClassRef(false), rPerson.getLegNumber());
+ bool patrolResult = r.getTeam() && r.getClassRef(false)->getClassType() == oClassPatrol && !teamsAsIndividual;
+
wstring bib = rPerson.getBib();
if (!bib.empty())
xml.write("BibNumber", bib);
@@ -2897,21 +2870,47 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (r.getStartTime() > 0)
xml.write("StartTime", oe.getAbsDateTimeISO(r.getStartTime(), true, useGMT));
+ int finishTime, runningTime, place, after;
+ RunnerStatus status;
+ if (!patrolResult) {
+ place = r.getPlace();
+ finishTime = r.getFinishTimeAdjusted();
+ runningTime = r.getRunningTime(true);
+ after = r.getTimeAfter();
+ status = r.getStatusComputed();
+ }
+ else {
+ int pl = r.getParResultLeg();
+ place = r.getTeam()->getLegPlace(pl, false);
+ runningTime = r.getTeam()->getLegRunningTime(pl, true, false);
+ if (runningTime > 0)
+ finishTime = r.getStartTime() + runningTime;
+ else
+ finishTime = 0;
+
+ after = r.getTeam()->getTimeAfter(pl);
+ status = r.getTeam()->getLegStatus(pl, true, false);
+ }
+
+ if ((r.getClassRef(false) && r.getClassRef(true)->getNoTiming()) ||
+ r.getStatusComputed() == StatusNoTiming) {
+ after = -1;
+ runningTime = 0;
+ }
+
if (r.getFinishTime() > 0)
- xml.write("FinishTime", oe.getAbsDateTimeISO(r.getFinishTimeAdjusted(), true, useGMT));
+ xml.write("FinishTime", oe.getAbsDateTimeISO(finishTime, true, useGMT));
- if (r.getRunningTime() > 0)
- xml.write("Time", r.getRunningTime());
+ if (runningTime > 0)
+ xml.write("Time", runningTime);
- int after = r.getTimeAfter();
if (after >= 0) {
if (teamMember) {
xml.write("TimeBehind", "type", L"Leg", itow(after));
- after = r.getTimeAfterCourse();
- if (after >= 0)
- xml.write("TimeBehind", "type", L"Course", itow(after));
-
+ int afterCourse = r.getTimeAfterCourse();
+ if (afterCourse >= 0)
+ xml.write("TimeBehind", "type", L"Course", itow(afterCourse));
}
else
xml.write("TimeBehind", after);
@@ -2919,27 +2918,26 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (r.getClassRef(false)) {
- if (r.statusOK() && r.getClassRef(false)->getNoTiming() == false) {
- if (!teamMember && r.getPlace() > 0 && r.getPlace() < 50000) {
- xml.write("Position", r.getPlace());
+ if (r.statusOK(true) && r.getClassRef(false)->getNoTiming() == false) {
+ if (!teamMember && place > 0 && place < 50000) {
+ xml.write("Position", place);
}
else if (teamMember) {
- int pos = r.getPlace();
- if (pos > 0 && pos < 50000)
- xml.write("Position", "type", L"Leg", itow(pos));
+ if (place > 0 && place < 50000)
+ xml.write("Position", "type", L"Leg", itow(place));
- pos = r.getCoursePlace();
- if (pos > 0)
- xml.write("Position", "type", L"Course", itow(pos));
+ int placeCourse = r.getCoursePlace(true);
+ if (placeCourse > 0)
+ xml.write("Position", "type", L"Course", itow(placeCourse));
}
}
- xml.write("Status", formatStatus(r.getStatus()));
+ xml.write("Status", formatStatus(status, r.getFinishTime()>0));
- int rg = r.getRogainingPoints(false);
+ int rg = r.getRogainingPoints(true, false);
if (rg > 0) {
xml.write("Score", "type", L"Score", itow(rg));
- xml.write("Score", "type", L"Penalty", itow(r.getRogainingReduction()));
+ xml.write("Score", "type", L"Penalty", itow(r.getRogainingReduction(true)));
}
if ( (r.getTeam() && r.getClassRef(false)->getClassType() != oClassPatrol && !teamsAsIndividual) || hasInputTime) {
xml.startTag("OverallResult");
@@ -2953,7 +2951,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
int tleg = r.getLegNumber() >= 0 ? r.getLegNumber() : 0;
if (stat == StatusOK && hasTiming) {
- int after = r.getTotalRunningTime() - r.getClassRef(true)->getTotalLegLeaderTime(tleg, true);
+ int after = r.getTotalRunningTime() - r.getClassRef(true)->getTotalLegLeaderTime(tleg, true, true);
if (after >= 0)
xml.write("TimeBehind", after);
}
@@ -2961,7 +2959,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (stat == StatusOK && hasTiming)
xml.write("Position", r.getTotalPlace());
- xml.write("Status", formatStatus(stat));
+ xml.write("Status", formatStatus(stat, r.getFinishTime() > 0));
xml.endTag();
}
@@ -2972,9 +2970,10 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
writeCourse(xml, *crs);
const vector &sp = r.getSplitTimes(doUnroll);
- if (r.getStatus()>0 && r.getStatus() != StatusDNS &&
- r.getStatus() != StatusCANCEL &&
- r.getStatus() != StatusNotCompetiting) {
+ RunnerStatus st = r.getStatusComputed();
+ if (r.getStatus()>0 && st != StatusDNS &&
+ st != StatusCANCEL &&
+ st != StatusNotCompetiting) {
int nc = crs->getNumControls();
bool hasRogaining = crs->hasRogaining();
int firstControl = crs->useFirstAsStart() ? 1 : 0;
@@ -3264,7 +3263,7 @@ void IOF30Interface::getRunnersToUse(const pClass cls, vector &rToUse,
if (leg == -1 && !indRel && r[j]->getTeam())
continue; // For teams, skip presonal results, unless individual relay
- if (!includeUnknown && r[j]->getStatus() == StatusUnknown)
+ if (!includeUnknown && !r[j]->hasResult())
continue;
}
rToUse.push_back(r[j]);
@@ -3281,7 +3280,7 @@ void IOF30Interface::getRunnersToUse(const pClass cls, vector &rToUse,
else {
for (int n = 0; n < t[j]->getNumRunners(); n++) {
pRunner tr = t[j]->getRunner(n);
- if (tr && tr->getStatus() != StatusUnknown) {
+ if (tr && tr->hasResult()) {
tToUse.push_back(t[j]);
break;
}
diff --git a/code/iof30interface.h b/code/iof30interface.h
index 637785e..4f07eda 100644
--- a/code/iof30interface.h
+++ b/code/iof30interface.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -163,7 +163,7 @@ class IOF30Interface {
map > &bibPatterns,
const map > &teamClassConfig);
- pTeam getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool &newTeam);
+ pTeam getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, int expectedClassId, bool &newTeam);
static int getIndexFromLegPos(int leg, int legorder, const vector &setup);
diff --git a/code/license.txt b/code/license.txt
index 5f4e616..6754e03 100644
--- a/code/license.txt
+++ b/code/license.txt
@@ -7,7 +7,7 @@ Third Party Code. Additional copyright notices and license terms applicable to p
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
------------------------------------
-Copyright 2007-2019 Melin Software HB.
+Copyright 2007-2020 Melin Software HB.
------------------------------------
diff --git a/code/listeditor.cpp b/code/listeditor.cpp
index 381c0f1..3697e46 100644
--- a/code/listeditor.cpp
+++ b/code/listeditor.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -34,6 +34,7 @@
#include "oEvent.h"
#include "tabbase.h"
#include "CommDlg.h"
+#include "generalresult.h"
ListEditor::ListEditor(oEvent *oe_) {
oe = oe_;
@@ -42,7 +43,7 @@ ListEditor::ListEditor(oEvent *oe_) {
dirtyExt = false;
dirtyInt = false;
lastSaved = NotSaved;
- oe->loadGeneralResults(false);
+ oe->loadGeneralResults(false, true);
}
ListEditor::~ListEditor() {
@@ -78,6 +79,13 @@ void ListEditor::load(const MetaListContainer &mlc, int index) {
savedFileName.clear();
}
+void ListEditor::show(TabBase *dst, gdioutput &gdi) {
+
+ gdi.clearPage(false);
+ origin = dst;
+ show(gdi);
+}
+
void ListEditor::show(gdioutput &gdi) {
gdi.setRestorePoint("BeginListEdit");
@@ -452,7 +460,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
else
mlp.setLeg(-1);
- if (gdi.hasField("UseResultModule") && gdi.isChecked("UseResultModule"))
+ if (gdi.hasWidget("UseResultModule") && gdi.isChecked("UseResultModule"))
mlp.setResultModule(currentList->getResultModule());
else
mlp.setResultModule("");
@@ -604,7 +612,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
lastSaved = SavedFile;
savedFileName = fileName;
- oe->loadGeneralResults(true);
+ oe->loadGeneralResults(true, true);
makeDirty(gdi, ClearDirty, ClearDirty);
show(gdi);
}
@@ -700,7 +708,12 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
makeDirty(gdi, ClearDirty, ClearDirty);
currentIndex = -1;
savedFileName.clear();
- gdi.getTabs().get(TListTab)->loadPage(gdi);
+
+ if (origin) {
+ auto oc = origin;
+ origin = nullptr;
+ oc->loadPage(gdi);
+ }
return 0;
}
/*else if (bi.id == "BrowseFont") {
@@ -732,9 +745,12 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
if (type == lResultModuleNumber || type == lResultModuleTime ||
type == lResultModuleNumberTeam || type == lResultModuleTimeTeam) {
gdi.check("UseLeg", true);
- gdi.check("UseResultModule", true);
- gdi.disableInput("UseResultModule");
gdi.disableInput("UseLeg");
+
+ if (gdi.hasWidget("UseResultModule")) {
+ gdi.check("UseResultModule", true);
+ gdi.disableInput("UseResultModule");
+ }
gdi.enableInput("Leg");
if (gdi.getText("Leg").empty())
gdi.setText("Leg", L"0");
@@ -887,9 +903,11 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
if (storedType == lResultModuleNumber || storedType == lResultModuleTime || storedType == lResultModuleTimeTeam || storedType == lResultModuleNumberTeam) {
gdi.check("UseLeg", true);
- gdi.check("UseResultModule", true);
- gdi.disableInput("UseResultModule");
gdi.disableInput("UseLeg");
+ if (gdi.hasWidget("UseResultModule")) {
+ gdi.check("UseResultModule", true);
+ gdi.disableInput("UseResultModule");
+ }
}
gdi.dropLine(2);
@@ -1174,11 +1192,11 @@ void ListEditor::makeDirty(gdioutput &gdi, DirtyFlag inside, DirtyFlag outside)
else if (outside == ClearDirty)
dirtyExt = false;
- if (gdi.hasField("SaveInside")) {
+ if (gdi.hasWidget("SaveInside")) {
gdi.setInputStatus("SaveInside", dirtyInt || lastSaved != SavedInside);
}
- if (gdi.hasField("SaveFile")) {
+ if (gdi.hasWidget("SaveFile")) {
gdi.setInputStatus("SaveFile", dirtyExt || lastSaved != SavedFile);
}
}
diff --git a/code/listeditor.h b/code/listeditor.h
index d004258..aeabdb9 100644
--- a/code/listeditor.h
+++ b/code/listeditor.h
@@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +30,8 @@ class BaseInfo;
class ButtonInfo;
class oEvent;
enum EPostType;
+class TabBase;
+
#include
class ListEditor {
@@ -65,6 +67,10 @@ private:
void enableOpen(gdioutput &gdi);
void makeDirty(gdioutput &gdi, DirtyFlag inside, DirtyFlag outside);
+
+ TabBase *origin = nullptr;
+ void show(gdioutput &gdi);
+
public:
ListEditor(oEvent *oe);
virtual ~ListEditor();
@@ -72,7 +78,9 @@ public:
//void load(MetaList *list);
void load(const MetaListContainer &mlc, int index);
- void show(gdioutput &gdi);
+ void show(TabBase *dst, gdioutput &gdi);
+
+ bool isShown(TabBase *tab) const { return origin == tab; }
MetaList *getCurrentList() const {return currentList;};
diff --git a/code/liveresult.cpp b/code/liveresult.cpp
index 50fab00..f77d8d3 100644
--- a/code/liveresult.cpp
+++ b/code/liveresult.cpp
@@ -1,6 +1,6 @@
/********************i****************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -284,7 +284,7 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
pRunner r = oe->getRunner(rToWatch[i], 0);
if (r) {
r->synchronize();
- r->setStartTime(st, true, false, true);
+ r->setStartTime(st, true, oBase::ChangeType::Update, true);
r->synchronize(false);
}
}
diff --git a/code/liveresult.h b/code/liveresult.h
index f20d847..dc88b07 100644
--- a/code/liveresult.h
+++ b/code/liveresult.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/localizer.cpp b/code/localizer.cpp
index a344784..d86c6e4 100644
--- a/code/localizer.cpp
+++ b/code/localizer.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/localizer.h b/code/localizer.h
index 5b00ad8..85aab30 100644
--- a/code/localizer.h
+++ b/code/localizer.h
@@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/code/meos.cpp b/code/meos.cpp
index 63bb34d..4fb53eb 100644
--- a/code/meos.cpp
+++ b/code/meos.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -67,6 +67,7 @@
#include "autocomplete.h"
#include "image.h"
#include "csvparser.h"
+#include "generalresult.h"
int defaultCodePage = 1252;
@@ -221,17 +222,26 @@ int APIENTRY WinMain(HINSTANCE hInstance,
RunnerStatusOrderMap[k] = 0;
}
RunnerStatusOrderMap[StatusOK] = 0;
- RunnerStatusOrderMap[StatusMAX] = 1;
- RunnerStatusOrderMap[StatusMP] = 2;
- RunnerStatusOrderMap[StatusDNF] = 3;
- RunnerStatusOrderMap[StatusDQ] = 4;
- RunnerStatusOrderMap[StatusCANCEL] = 5;
- RunnerStatusOrderMap[StatusDNS] = 6;
- RunnerStatusOrderMap[StatusUnknown] = 7;
- RunnerStatusOrderMap[StatusNotCompetiting] = 8;
+ RunnerStatusOrderMap[StatusNoTiming] = 1;
+ RunnerStatusOrderMap[StatusOutOfCompetition] = 2;
+
+ RunnerStatusOrderMap[StatusMAX] = 3;
+ RunnerStatusOrderMap[StatusMP] = 4;
+ RunnerStatusOrderMap[StatusDNF] = 5;
+ RunnerStatusOrderMap[StatusDQ] = 6;
+ RunnerStatusOrderMap[StatusCANCEL] = 7;
+ RunnerStatusOrderMap[StatusDNS] = 8;
+ RunnerStatusOrderMap[StatusUnknown] = 9;
+ RunnerStatusOrderMap[StatusNotCompetiting] = 10;
lang.init();
StringCache::getInstance().init();
+
+ for (RunnerStatus st : getAllRunnerStatus()) {
+ if (st != StatusOK)
+ assert(RunnerStatusOrderMap[st] > 0);
+ oAbstractRunner::encodeStatus(st);
+ }
GetCurrentDirectory(MAX_PATH, programPath);
bool utfRecode = false;
@@ -469,14 +479,14 @@ int APIENTRY WinMain(HINSTANCE hInstance,
}
}
}
-
+ gdi_main = nullptr;
gdi_extra.clear();
if (gEvent)
gEvent->saveProperties(settings);
delete gEvent;
- gEvent = 0;
+ gEvent = nullptr;
initMySQLCriticalSection(false);
diff --git a/code/meos.rc b/code/meos.rc
index d0cc44d..631bfdf 100644
--- a/code/meos.rc
+++ b/code/meos.rc
@@ -169,7 +169,7 @@ BEGIN
VALUE "FileDescription", "meos"
VALUE "FileVersion", "3.3.0.1"
VALUE "InternalName", "meos"
- VALUE "LegalCopyright", "Copyright © 2007-2019"
+ VALUE "LegalCopyright", "Copyright © 2007-2020"
VALUE "OriginalFilename", "meos.exe"
VALUE "ProductName", " meos"
VALUE "ProductVersion", "3.4.0.1"
diff --git a/code/meos_util.cpp b/code/meos_util.cpp
index 7b28af5..bce3454 100644
--- a/code/meos_util.cpp
+++ b/code/meos_util.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -2212,3 +2212,8 @@ void checkWriteAccess(const wstring &file) {
}
CloseHandle(h);
}
+
+int compareStringIgnoreCase(const wstring &a, const wstring &b) {
+ return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a.c_str(), a.length(),
+ b.c_str(), b.length()) - CSTR_EQUAL;
+}
diff --git a/code/meos_util.h b/code/meos_util.h
index 9b58a2d..4363cc0 100644
--- a/code/meos_util.h
+++ b/code/meos_util.h
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -119,6 +119,9 @@ const vector &split(const string &line, const string &separators, vector
const vector &split(const wstring &line, const wstring &separators, vector &split_vector);
const wstring &unsplit(const vector &split_vector, const wstring &separators, wstring &line);
+// Compare two strings, ignore case. 0 = equal, != zero compares as the integers.
+int compareStringIgnoreCase(const wstring &a, const wstring &b);
+
const wstring &makeDash(const wstring &t);
const wstring &makeDash(const wchar_t *t);
diff --git a/code/meosdb/MeosSQL.cpp b/code/meosdb/MeosSQL.cpp
index 53a3d6a..8a879fd 100644
--- a/code/meosdb/MeosSQL.cpp
+++ b/code/meosdb/MeosSQL.cpp
@@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
- Copyright (C) 2009-2019 Melin Software HB
+ Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@
#include "../metalist.h"
#include "../MeOSFeatures.h"
#include "../meosexception.h"
+#include "../generalresult.h"
using namespace mysqlpp;
@@ -394,7 +395,7 @@ void MeosSQL::upgradeDB(const string &db, oDataContainer const * dc) {
if (!eCol.count("InputTime")) {
string sql = "ALTER TABLE " + db + " ";
sql += "ADD COLUMN " + C_INT("InputTime");
- sql += "ADD COLUMN " + C_INT("InputStatus");
+ sql += "ADD COLUMN InputStatus INT NOT NULL DEFAULT 1, ";
sql += "ADD COLUMN " + C_INT("InputPoints");
sql += "ADD COLUMN " + C_INT("InputPlace");
sql = sql.substr(0, sql.length() - 2);
@@ -715,7 +716,6 @@ OpFailStatus MeosSQL::SyncUpdate(oEvent *oe)
<< " WHERE Id=" << oe->Id;
queryset.execute();
- //syncUpdate(queryset, "oEvent", oe, true);
}
catch (const mysqlpp::Exception& er){
setDefaultDB();
@@ -1126,7 +1126,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
}
pw.setProgress(20);
-
+ oe->sqlClubs.reset();
try {
ResUse res = query.use("SELECT * FROM oClub WHERE Removed=0");
@@ -1139,9 +1139,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
oClub c(oe, row["Id"]);
storeClub(row, c);
oe->addClub(c);
-
- oe->sqlUpdateClubs = max(c.sqlUpdated, oe->sqlUpdateClubs);
- oe->sqlCounterClubs = max(c.counter, oe->sqlCounterClubs);
+ c.update(oe->sqlClubs);
}
}
}
@@ -1154,7 +1152,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
pw.setProgress(30);
- oe->sqlCounterControls=0;
+ oe->sqlControls.reset();
try {
ResUse res = query.use("SELECT * FROM oControl WHERE Removed=0");
@@ -1166,9 +1164,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
oControl c(oe, row["Id"]);
storeControl(row, c);
oe->addControl(c);
-
- oe->sqlUpdateControls = max(c.sqlUpdated, oe->sqlUpdateControls);
- oe->sqlCounterControls = max(c.counter, oe->sqlCounterControls);
+ c.update(oe->sqlControls);
}
}
}
@@ -1179,7 +1175,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
return opStatusFail;
}
- oe->sqlCounterCourses = 0;
+ oe->sqlCourses.reset();
pw.setProgress(40);
try{
@@ -1193,9 +1189,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
oCourse c(oe, row["Id"]);
storeCourse(row, c, tmp, false);
oe->addCourse(c);
-
- oe->sqlUpdateCourses = max(c.sqlUpdated, oe->sqlUpdateCourses);
- oe->sqlCounterCourses = max(c.counter, oe->sqlCounterCourses);
+ c.update(oe->sqlCourses);
}
}
}
@@ -1208,7 +1202,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
pw.setProgress(50);
- oe->sqlCounterClasses = 0;
+ oe->sqlClasses.reset();
try{
ResUse res = query.use("SELECT * FROM oClass WHERE Removed=0");
@@ -1217,13 +1211,9 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
while (row = res.fetch_row()) {
oClass c(oe, row["Id"]);
storeClass(row, c, false, false);
-
c.changed = false;
- c.reChanged = false;
oe->addClass(c);
-
- oe->sqlUpdateClasses = max(c.sqlUpdated, oe->sqlUpdateClasses);
- oe->sqlCounterClasses = max(c.counter, oe->sqlCounterClasses);
+ c.update(oe->sqlClasses);
}
}
}
@@ -1234,7 +1224,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
return opStatusFail;
}
- oe->sqlCounterCards=0;
+ oe->sqlCards.reset();
try{
ResUse res = query.use("SELECT * FROM oCard WHERE Removed=0");
@@ -1250,9 +1240,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
oe->addCard(c);
assert(!c.changed);
- oe->sqlCounterCards = max(c.counter, oe->sqlCounterCards);
- oe->sqlUpdateCards = max(c.sqlUpdated, oe->sqlUpdateCards);
-
+ c.update(oe->sqlCards);
if (++counter % 100 == 50)
pw.setProgress(pStart + (counter * pPart) / nCard);
}
@@ -1266,7 +1254,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
return opStatusFail;
}
- oe->sqlCounterRunners = 0;
+ oe->sqlRunners.reset();
try{
ResUse res = query.use("SELECT * FROM oRunner WHERE Removed=0");
int counter = 0;
@@ -1280,9 +1268,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
storeRunner(row, r, false, false, false, false);
assert(!r.changed);
oe->addRunner(r, false);
-
- oe->sqlUpdateRunners = max(r.sqlUpdated, oe->sqlUpdateRunners);
- oe->sqlCounterRunners = max(r.counter,oe->sqlCounterRunners);
+ r.update(oe->sqlRunners);
if (++counter % 100 == 50)
pw.setProgress(pStart + (counter * pPart) / nRunner);
@@ -1296,7 +1282,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
return opStatusFail;
}
- oe->sqlCounterTeams=0;
+ oe->sqlTeams.reset();
try{
ResUse res = query.use("SELECT * FROM oTeam WHERE Removed=0");
@@ -1314,7 +1300,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
pTeam at = oe->addTeam(t, false);
if (at) {
- at->apply(false, 0, true);
+ at->apply(oBase::ChangeType::Quiet, nullptr);
at->changed = false;
for (size_t k = 0; kRunners.size(); k++) {
if (at->Runners[k]) {
@@ -1323,9 +1309,8 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
}
}
}
- oe->sqlUpdateTeams = max(t.sqlUpdated, oe->sqlUpdateTeams);
- oe->sqlCounterTeams = max(t.counter, oe->sqlCounterTeams);
-
+ t.update(oe->sqlTeams);
+
if (++counter % 100 == 50)
pw.setProgress(pStart + (counter * pPart) / nTeam);
}
@@ -1441,7 +1426,7 @@ void MeosSQL::storeClub(const Row &row, oClub &c)
c.counter = row["Counter"];
c.Removed = row["Removed"];
- c.oe->sqlChangedClubs = true;
+ c.oe->sqlClubs.changed = true;
c.changedObject();
synchronized(c);
@@ -1459,7 +1444,7 @@ void MeosSQL::storeControl(const Row &row, oControl &c)
c.counter = row["Counter"];
c.Removed = row["Removed"];
- c.oe->sqlChangedControls = true;
+ c.oe->sqlControls.changed = true;
if (c.changed || oldStat != c.Status) {
c.oe->dataRevision++;
c.changed = false;
@@ -1487,7 +1472,7 @@ void MeosSQL::storeCard(const Row &row, oCard &c)
}
c.changedObject();
synchronized(c);
- c.oe->sqlChangedCards = true;
+ c.oe->sqlCards.changed = true;
}
void MeosSQL::storePunch(const Row &row, oFreePunch &p, bool rehash)
@@ -1509,7 +1494,7 @@ void MeosSQL::storePunch(const Row &row, oFreePunch &p, bool rehash)
p.changedObject();
synchronized(p);
- p.oe->sqlChangedPunches = true;
+ p.oe->sqlPunches.changed = true;
}
OpFailStatus MeosSQL::storeClass(const Row &row, oClass &c,
@@ -1570,7 +1555,7 @@ OpFailStatus MeosSQL::storeClass(const Row &row, oClass &c,
c.changed = false;
c.changedObject();
- c.oe->sqlChangedClasses = true;
+ c.oe->sqlClasses.changed = true;
synchronized(c);
return success;
}
@@ -1611,7 +1596,7 @@ OpFailStatus MeosSQL::storeCourse(const Row &row, oCourse &c,
c.oe->dataRevision++;
c.changed = false;
c.changedObject();
- c.oe->sqlChangedCourses = true;
+ c.oe->sqlCourses.changed = true;
synchronized(c);
return success;
}
@@ -1633,7 +1618,7 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
const wstring &oldBib = r.getBib();
r.sName = fromUTF((string)row["Name"]);
- oRunner::getRealName(r.sName, r.tRealName);
+ r.getRealName(r.sName, r.tRealName);
r.setCardNo(row["CardNo"], false, true);
r.StartNo = row["StartNo"];
r.tStartTime = r.startTime = row["StartTime"];
@@ -1675,6 +1660,8 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
}
else r.Course=0;
+ pClass oldClass = r.Class;
+
if (int(row["Class"])!=0) {
r.Class=oe->getClass(int(row["Class"]));
@@ -1696,6 +1683,9 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
}
else r.Class=0;
+ if (oldClass != r.Class)
+ oe->classIdToRunnerHash.reset();
+
if (int(row["Club"])!=0){
r.Club = oe->getClub(int(row["Club"]));
@@ -1776,7 +1766,7 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
// Mark new class as changed
r.changedObject();
r.sqlChanged = true;
- r.oe->sqlChangedRunners = true;
+ r.oe->sqlRunners.changed = true;
synchronized(r);
return success;
@@ -1873,7 +1863,7 @@ OpFailStatus MeosSQL::storeTeam(const Row &row, oTeam &t,
if (or.sName.empty()) {
or.sName = L"@AutoCorrection";
- oRunner::getRealName(or.sName, or.tRealName);
+ or.getRealName(or.sName, or.tRealName);
}
if (!or.isRemoved()) {
@@ -1894,7 +1884,7 @@ OpFailStatus MeosSQL::storeTeam(const Row &row, oTeam &t,
t.Class->markSQLChanged(-1,-1);
t.sqlChanged = true;
- t.oe->sqlChangedTeams = true;
+ t.oe->sqlTeams.changed = true;
synchronized(t);
return success;
}
@@ -1951,7 +1941,6 @@ bool MeosSQL::Remove(oBase *ob)
ResNSel res = updateCounter(oTable.c_str(), ob->Id, &query);
ob->Removed = true;
ob->changed = false;
- ob->reChanged = false;
}
catch (const mysqlpp::Exception& er){
alert(string(er.what())+" [REMOVE " +oTable +"]");
@@ -2023,11 +2012,13 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oRunner *r, bool readClassClub, b
if (!r || !con.connected())
return opStatusFail;
- if (!forceRead && !r->existInDB())
- return syncUpdate(r, true);
+ if (!forceRead) {
+ if (!r->existInDB())
+ return syncUpdate(r, true);
- if (!r->changed && skipSynchronize(*r))
- return opStatusOK;
+ if (!r->changed && skipSynchronize(*r))
+ return opStatusOKSkipped;
+ }
try {
Query query = con.query();
@@ -2049,7 +2040,7 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oRunner *r, bool readClassClub, b
r->changed = false;
vector mp;
- r->evaluateCard(true, mp, 0, false);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
//Forget evaluated changes. Not our buisness to update.
r->changed = false;
@@ -2074,9 +2065,8 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oRunner *r, bool readClassClub, b
return syncUpdate(r, false);
vector mp;
- r->evaluateCard(true, mp, 0, false);
+ r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->changed = false;
- r->reChanged = false;
return opStatusOK;
}
@@ -2116,11 +2106,13 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oCard *c)
if (!c || !con.connected())
return opStatusFail;
- if (!forceRead && !c->existInDB())
- return syncUpdate(c, true);
+ if (!forceRead) {
+ if (!c->existInDB())
+ return syncUpdate(c, true);
- if (!c->changed && skipSynchronize(*c))
- return opStatusOK;
+ if (!c->changed && skipSynchronize(*c))
+ return opStatusOKSkipped;
+ }
try{
Query query = con.query();
@@ -2207,13 +2199,15 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oTeam *t, bool readRecursive)
if (!t || !con.connected())
return opStatusFail;
- if (!forceRead && !t->existInDB())
- return syncUpdate(t, true);
+ if (!forceRead) {
+ if (!t->existInDB())
+ return syncUpdate(t, true);
- if (!t->changed && skipSynchronize(*t))
- return opStatusOK;
+ if (!t->changed && skipSynchronize(*t))
+ return opStatusOK;
+ }
- try{
+ try {
Query query = con.query();
query << "SELECT * FROM oTeam WHERE Id=" << t->Id << andWhereOld(t);
Result res = query.store();
@@ -2230,7 +2224,6 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oTeam *t, bool readRecursive)
t->oe->dataRevision++;
t->Modified.update();
t->changed = false;
- t->reChanged = false;
return success;
}
else {
@@ -2252,7 +2245,7 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oTeam *t, bool readRecursive)
return success;
}
- return opStatusOK;
+ return opStatusOK;
}
catch (const mysqlpp::Exception& er){
alert(string(er.what())+" [SYNCREAD oTeam]");
@@ -2319,7 +2312,6 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oClass *c, bool readCourses)
c->oe->dataRevision++;
c->Modified.update();
c->changed = false;
- c->reChanged = false;
return opStatusOK;
}
else {
@@ -2488,17 +2480,21 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oClub *c)
if (!c || !con.connected())
return opStatusFail;
- if (!forceRead && !c->existInDB())
- return syncUpdate(c, true);
+ if (!forceRead) {
+ if (!c->existInDB())
+ return syncUpdate(c, true);
- try{
+ if (!c->changed && skipSynchronize(*c))
+ return opStatusOKSkipped;
+ }
+ try {
Query query = con.query();
query << "SELECT * FROM oClub WHERE Id=" << c->Id;
Result res = query.store();
Row row;
- if (!res.empty()){
- row=res.at(0);
+ if (!res.empty()) {
+ row = res.at(0);
if (!c->changed || isOld(row["Counter"], string(row["Modified"]), c)) {
OpFailStatus success = opStatusOK;
@@ -2508,21 +2504,21 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oClub *c)
storeClub(row, *c);
c->Modified.update();
- c->changed=false;
+ c->changed = false;
return success;
}
- else if (c->changed){
+ else if (c->changed) {
return syncUpdate(c, false);
}
}
- else{
+ else {
//Something is wrong!? Deleted?
return syncUpdate(c, true);
}
return opStatusOK;
}
- catch (const mysqlpp::Exception& er){
- alert(string(er.what())+" [SYNCREAD oClub]");
+ catch (const mysqlpp::Exception& er) {
+ alert(string(er.what()) + " [SYNCREAD oClub]");
return opStatusFail;
}
@@ -2557,8 +2553,13 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oControl *c)
if (!c || !con.connected())
return opStatusFail;
- if (!forceRead && !c->existInDB())
- return syncUpdate(c, true);
+ if (!forceRead) {
+ if (!c->existInDB())
+ return syncUpdate(c, true);
+
+ if (!c->changed && skipSynchronize(*c))
+ return opStatusOKSkipped;
+ }
try{
Query query = con.query();
@@ -2638,11 +2639,13 @@ OpFailStatus MeosSQL::syncReadCourse(bool forceRead, oCourse *c, set &readC
if (isTMP)
return opStatusFail;
- if (!forceRead && !c->existInDB())
- return syncUpdate(c, true);
+ if (!forceRead) {
+ if (!c->existInDB())
+ return syncUpdate(c, true);
- if (!c->changed && skipSynchronize(*c))
- return opStatusOK; // Skipped readout
+ if (!c->changed && skipSynchronize(*c))
+ return opStatusOKSkipped; // Skipped readout
+ }
try{
Query query = con.query();
@@ -2661,7 +2664,6 @@ OpFailStatus MeosSQL::syncReadCourse(bool forceRead, oCourse *c, set &readC
c->oe->dataRevision++;
c->Modified.update();
c->changed=false;
- c->reChanged=false;
return success;
}
else {
@@ -2721,11 +2723,13 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oFreePunch *c, bool rehash)
if (!c || !con.connected())
return opStatusFail;
- if (!forceRead && !c->existInDB())
- return syncUpdate(c, true);
+ if (!forceRead) {
+ if (!c->existInDB())
+ return syncUpdate(c, true);
- if (!c->changed && skipSynchronize(*c))
- return opStatusOK;
+ if (!c->changed && skipSynchronize(*c))
+ return opStatusOKSkipped;
+ }
try{
Query query = con.query();
@@ -3079,23 +3083,27 @@ bool MeosSQL::syncListRunner(oEvent *oe)
if (!con.connected())
return false;
-
+ int maxCounterRunner = -1;
try{
Query query = con.query();
/*query << "SELECT Id, Counter, Modified, Removed FROM oRunner";
query << " WHERE Counter > " << oe->sqlCounterRunners;
query << " OR Modified > '" << oe->sqlUpdateRunners << "'";*/
- Result res = query.store(selectUpdated("oRunner", oe->sqlUpdateRunners, oe->sqlCounterRunners));
+ Result res = query.store(selectUpdated("oRunner", oe->sqlRunners));
if (res) {
- for (int i=0; igetRunner(Id, 0);
if (r) {
@@ -3108,24 +3116,26 @@ bool MeosSQL::syncListRunner(oEvent *oe)
}
r->changedObject();
- oe->sqlChangedRunners = true;
+ oe->sqlRunners.changed = true;
}
}
else{
oRunner *r=oe->getRunner(Id, 0);
- if (r){
+ if (r) {
if (isOld(counter, modified, r))
- syncRead(false, r);
+ st = syncRead(false, r);
+ else
+ st = opStatusOK;
}
else {
oRunner or(oe, Id);
- syncRead(true, &or, false, false);
+ or.setImplicitlyCreated();
+ st = syncRead(true, &or, false, false);
r = oe->addRunner(or, false);
}
}
- oe->sqlCounterRunners = max(counter, oe->sqlCounterRunners);
- oe->sqlUpdateRunners = max(modified, oe->sqlUpdateRunners);
+ updateCounters(st, counter, modified, oe->sqlRunners, maxCounterRunner);
}
}
}
@@ -3133,59 +3143,60 @@ bool MeosSQL::syncListRunner(oEvent *oe)
alert(string(er.what())+" [SYNCLIST oRunner]");
return false;
}
+
+ if (maxCounterRunner > 0)
+ oe->sqlRunners.counter = maxCounterRunner - 1;
+
return true;
}
-bool MeosSQL::syncListClass(oEvent *oe)
-{
+bool MeosSQL::syncListClass(oEvent *oe) {
errorMessage.clear();
if (!con.connected())
return false;
- try{
+ int maxCounter = -1;
+ try {
Query query = con.query();
- /*
- query << "SELECT Id, Counter, Modified, Removed FROM oClass";
- query << " WHERE Counter > " << oe->sqlCounterClasses;
- query << " OR Modified > '" << oe->sqlUpdateClasses << "'";*/
-
- //Result res = query.store();
- Result res = query.store(selectUpdated("oClass", oe->sqlUpdateClasses, oe->sqlCounterClasses));
+ Result res = query.store(selectUpdated("oClass", oe->sqlClasses));
if (res) {
-
- for (int i=0; igetClass(Id);
+ st = OpFailStatus::opStatusOK;
+ oClass *c = oe->getClass(Id);
if (c) {
c->changedObject();
- c->Removed=true;
+ c->Removed = true;
}
}
else {
- oClass *c=oe->getClass(Id);
+ oClass *c = oe->getClass(Id);
if (!c) {
oClass oc(oe, Id);
- syncRead(true, &oc, false);
- c=oe->addClass(oc);
- if (c!=0) {
+ st = syncRead(true, &oc, false);
+ c = oe->addClass(oc);
+ if (c != 0) {
c->changed = false;
- //syncRead(true, c, false);
}
}
else if (isOld(counter, modified, c))
- syncRead(false, c, false);
+ st = syncRead(false, c, false);
+ else
+ st = opStatusOK;
}
- oe->sqlCounterClasses = max(counter, oe->sqlCounterClasses);
- oe->sqlUpdateClasses = max(modified, oe->sqlUpdateClasses);
+
+ updateCounters(st, counter, modified, oe->sqlClasses, maxCounter);
}
}
}
@@ -3193,119 +3204,127 @@ bool MeosSQL::syncListClass(oEvent *oe)
alert(string(er.what())+" [SYNCLIST oClass]");
return false;
}
+
+ if (maxCounter > 0)
+ oe->sqlClasses.counter = maxCounter - 1;
+
return true;
}
-
bool MeosSQL::syncListClub(oEvent *oe)
{
errorMessage.clear();
if (!con.connected())
return false;
+ int maxCounter = -1;
- try{
+ try {
Query query = con.query();
- /*query << "SELECT Id, Counter, Modified, Removed FROM oClub";
- query << " WHERE Counter > " << oe->sqlCounterClubs;
- query << " OR Modified > '" << oe->sqlUpdateClubs << "'";*/
- Result res = query.store(selectUpdated("oClub", oe->sqlUpdateClubs, oe->sqlCounterClubs));
+ Result res = query.store(selectUpdated("oClub", oe->sqlClubs));
if (res) {
- for(int i=0; igetClub(Id);
+ if (int(row["Removed"])) {
+ st = opStatusOK;
+ oClub *c = oe->getClub(Id);
if (c) {
- c->Removed=true;
+ c->Removed = true;
c->changedObject();
}
}
else {
- oClub *c=oe->getClub(Id);
+ oClub *c = oe->getClub(Id);
- if (c==0) {
+ if (c == 0) {
oClub oc(oe, Id);
- syncRead(true, &oc);
+ oc.setImplicitlyCreated();
+ st = syncRead(true, &oc);
oe->addClub(oc);
}
else if (isOld(counter, modified, c))
- syncRead(false, c);
+ st = syncRead(false, c);
+ else
+ st = opStatusOK;
}
- oe->sqlCounterClubs = max(counter, oe->sqlCounterClubs);
- oe->sqlUpdateClubs = max(modified, oe->sqlUpdateClubs);
+ updateCounters(st, counter, modified, oe->sqlClubs, maxCounter);
}
}
}
- catch (const mysqlpp::Exception& er){
- alert(string(er.what())+" [SYNCLIST oClub]");
+ catch (const mysqlpp::Exception& er) {
+ alert(string(er.what()) + " [SYNCLIST oClub]");
return false;
}
+ if (maxCounter > 0)
+ oe->sqlClubs.counter = maxCounter - 1;
+
return true;
}
-
-bool MeosSQL::syncListCourse(oEvent *oe)
-{
+bool MeosSQL::syncListCourse(oEvent *oe) {
errorMessage.clear();
if (!con.connected())
return false;
-
- try{
+ int maxCounter = -1;
+ try {
Query query = con.query();
- /*
- query << "SELECT Id, Counter, Modified, Removed FROM oCourse";
- query << " WHERE Counter > " << oe->sqlCounterCourses;
- query << " OR Modified > '" << oe->sqlUpdateCourses << "'";
- */
- Result res = query.store(selectUpdated("oCourse", oe->sqlUpdateCourses, oe->sqlCounterCourses));
-
+ Result res = query.store(selectUpdated("oCourse", oe->sqlCourses));
if (res) {
set