Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1a05bd56d |
@ -1585,10 +1585,14 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
wstring bib;
|
wstring bib;
|
||||||
bool doBibs = false;
|
bool doBibs = false;
|
||||||
|
bool bibToVacant = true;
|
||||||
if (gdi.hasWidget("Bib")) {
|
if (gdi.hasWidget("Bib")) {
|
||||||
bib = gdi.getText("Bib");
|
bib = gdi.getText("Bib");
|
||||||
doBibs = gdi.isChecked("HandleBibs");
|
doBibs = gdi.isChecked("HandleBibs");
|
||||||
|
if (gdi.hasWidget("VacantBib")) {
|
||||||
|
bibToVacant = gdi.isChecked("VacantBib");
|
||||||
|
oe->getDI().setInt("NoVacantBib", bibToVacant ? 0 : 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring time = gdi.getText("FirstStart");
|
wstring time = gdi.getText("FirstStart");
|
||||||
@ -1680,7 +1684,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
throw std::exception("Not implemented");
|
throw std::exception("Not implemented");
|
||||||
|
|
||||||
if (doBibs)
|
if (doBibs)
|
||||||
oe->addBib(cid, leg, bib);
|
oe->addBib(cid, leg, bib, bibToVacant);
|
||||||
|
|
||||||
// Clear input
|
// Clear input
|
||||||
gdi.restore("", false);
|
gdi.restore("", false);
|
||||||
@ -1703,6 +1707,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
else if (bi.id=="HandleBibs") {
|
else if (bi.id=="HandleBibs") {
|
||||||
gdi.setInputStatus("Bib", gdi.isChecked("HandleBibs"));
|
gdi.setInputStatus("Bib", gdi.isChecked("HandleBibs"));
|
||||||
|
gdi.setInputStatus("VacantBib", gdi.isChecked("HandleBibs"), true);
|
||||||
}
|
}
|
||||||
else if (bi.id == "DoDeleteStart") {
|
else if (bi.id == "DoDeleteStart") {
|
||||||
pClass pc=oe->getClass(ClassId);
|
pClass pc=oe->getClass(ClassId);
|
||||||
@ -1878,10 +1883,19 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.addString("", 0, "Antal reserverade nummerlappsnummer mellan klasser:");
|
gdi.addString("", 0, "Antal reserverade nummerlappsnummer mellan klasser:");
|
||||||
gdi.dropLine(-0.1);
|
gdi.dropLine(-0.2);
|
||||||
gdi.addInput("BibGap", itow(oe->getBibClassGap()), 5);
|
gdi.addInput("BibGap", itow(oe->getBibClassGap()), 5);
|
||||||
gdi.dropLine(3);
|
|
||||||
|
gdi.dropLine(2.4);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
|
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Vacancy)) {
|
||||||
|
bool bibToVacant = oe->getDCI().getInt("NoVacantBib") == 0;
|
||||||
|
gdi.addCheckbox("VacantBib", "Tilldela nummerlapp till vakanter", nullptr, bibToVacant);
|
||||||
|
gdi.dropLine(2.5);
|
||||||
|
gdi.popX();
|
||||||
|
}
|
||||||
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addButton("DoBibs", "Tilldela", ClassesCB).setDefault();
|
gdi.addButton("DoBibs", "Tilldela", ClassesCB).setDefault();
|
||||||
|
|
||||||
@ -1914,11 +1928,17 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
pc->setBibMode(BibMode(teamBib.first));
|
pc->setBibMode(BibMode(teamBib.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bibToVacant = true;
|
||||||
|
if (gdi.hasWidget("VacantBib")) {
|
||||||
|
bibToVacant = gdi.isChecked("VacantBib");
|
||||||
|
oe->getDI().setInt("NoVacantBib", bibToVacant ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
pc->getDI().setString("Bib", getBibCode(bt, gdi.getText("Bib")));
|
pc->getDI().setString("Bib", getBibCode(bt, gdi.getText("Bib")));
|
||||||
pc->synchronize();
|
pc->synchronize();
|
||||||
int leg = pc->getParentClass() ? -1 : 0;
|
int leg = pc->getParentClass() ? -1 : 0;
|
||||||
if (bt == AutoBibManual) {
|
if (bt == AutoBibManual) {
|
||||||
oe->addBib(cid, leg, gdi.getText("Bib"));
|
oe->addBib(cid, leg, gdi.getText("Bib"), bibToVacant);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
oe->setBibClassGap(gdi.getTextNo("BibGap"));
|
oe->setBibClassGap(gdi.getTextNo("BibGap"));
|
||||||
@ -3691,6 +3711,16 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gdi.hasWidget("VacantBib")) {
|
||||||
|
bool vacantBib = gdi.isChecked("VacantBib");
|
||||||
|
bool vacantBibStored = oe->getDCI().getInt("NoVacantBib") == 0;
|
||||||
|
|
||||||
|
if (vacantBib != vacantBibStored) {
|
||||||
|
oe->getDI().setInt("NoVacantBib", vacantBib ? 0 : 1);
|
||||||
|
modifiedBib = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!modifiedFee.empty() && oe->getNumRunners() > 0) {
|
if (!modifiedFee.empty() && oe->getNumRunners() > 0) {
|
||||||
bool updateFee = gdi.ask(L"ask:changedclassfee");
|
bool updateFee = gdi.ask(L"ask:changedclassfee");
|
||||||
|
|
||||||
@ -3724,10 +3754,18 @@ void TabClass::prepareForDrawing(gdioutput &gdi) {
|
|||||||
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Bib)) {
|
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Bib)) {
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addString("", 0, "Antal reserverade nummerlappsnummer mellan klasser:");
|
gdi.addString("", 0, "Antal reserverade nummerlappsnummer mellan klasser:");
|
||||||
gdi.dropLine(-0.1);
|
gdi.dropLine(-0.2);
|
||||||
gdi.addInput("BibGap", itow(oe->getBibClassGap()), 5);
|
gdi.addInput("BibGap", itow(oe->getBibClassGap()), 5);
|
||||||
|
|
||||||
|
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Vacancy)) {
|
||||||
|
bool bibToVacant = oe->getDCI().getInt("NoVacantBib") == 0;
|
||||||
|
gdi.dropLine(0.2);
|
||||||
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(15));
|
||||||
|
gdi.addCheckbox("VacantBib", "Tilldela nummerlapp till vakanter", nullptr, bibToVacant);
|
||||||
|
}
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.dropLine(1.5);
|
gdi.dropLine(2.4);
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3868,6 +3906,14 @@ void TabClass::drawDialog(gdioutput &gdi, oEvent::DrawMethod method, const oClas
|
|||||||
gdi.addCheckbox("HandleBibs", "Tilldela nummerlappar:", ClassesCB, lastHandleBibs).setSynchData(&lastHandleBibs);
|
gdi.addCheckbox("HandleBibs", "Tilldela nummerlappar:", ClassesCB, lastHandleBibs).setSynchData(&lastHandleBibs);
|
||||||
gdi.dropLine(-0.2);
|
gdi.dropLine(-0.2);
|
||||||
gdi.addInput("Bib", L"", 10, 0, L"", L"Mata in första nummerlappsnummer, eller blankt för att ta bort nummerlappar");
|
gdi.addInput("Bib", L"", 10, 0, L"", L"Mata in första nummerlappsnummer, eller blankt för att ta bort nummerlappar");
|
||||||
|
|
||||||
|
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Vacancy)) {
|
||||||
|
bool bibToVacant = oe->getDCI().getInt("NoVacantBib") == 0;
|
||||||
|
gdi.dropLine(0.2);
|
||||||
|
gdi.addCheckbox("VacantBib", "Tilldela nummerlapp till vakanter", nullptr, bibToVacant);
|
||||||
|
gdi.setInputStatus("VacantBib", lastHandleBibs);
|
||||||
|
}
|
||||||
|
|
||||||
gdi.setInputStatus("Bib", lastHandleBibs);
|
gdi.setInputStatus("Bib", lastHandleBibs);
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.dropLine(2.5);
|
gdi.dropLine(2.5);
|
||||||
@ -3968,6 +4014,7 @@ void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMetho
|
|||||||
if (hasMulti) {
|
if (hasMulti) {
|
||||||
gdi.check("HandleBibs", false);
|
gdi.check("HandleBibs", false);
|
||||||
gdi.setInputStatus("Bib", false);
|
gdi.setInputStatus("Bib", false);
|
||||||
|
gdi.setInputStatus("VacantBib", false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1230,6 +1230,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
else if (lbi.id == "ListSelection") {
|
else if (lbi.id == "ListSelection") {
|
||||||
gdi.getSelection(lbi.id, lastClassSelection);
|
gdi.getSelection(lbi.id, lastClassSelection);
|
||||||
if (gdi.hasWidget("ResultType")) {
|
if (gdi.hasWidget("ResultType")) {
|
||||||
|
lastResultClassSelection = lastClassSelection;
|
||||||
ListBoxInfo entry;
|
ListBoxInfo entry;
|
||||||
gdi.getSelectedItem("ResultType", entry);
|
gdi.getSelectedItem("ResultType", entry);
|
||||||
gdi.setInputStatus("Generate", !lastClassSelection.empty() && int(entry.data) >= 0);
|
gdi.setInputStatus("Generate", !lastClassSelection.empty() && int(entry.data) >= 0);
|
||||||
@ -3011,7 +3012,6 @@ void TabList::setResultOptionsFromType(gdioutput &gdi, int data) {
|
|||||||
gdi.setInputStatus("ShowInterResults", builtIn);
|
gdi.setInputStatus("ShowInterResults", builtIn);
|
||||||
gdi.setInputStatus("ShowSplits", builtIn);
|
gdi.setInputStatus("ShowSplits", builtIn);
|
||||||
|
|
||||||
|
|
||||||
set<int> clsUnused;
|
set<int> clsUnused;
|
||||||
vector< pair<wstring, size_t> > out;
|
vector< pair<wstring, size_t> > out;
|
||||||
|
|
||||||
@ -3022,22 +3022,14 @@ void TabList::setResultOptionsFromType(gdioutput &gdi, int data) {
|
|||||||
if (!out.empty() && lastLeg >= 0)
|
if (!out.empty() && lastLeg >= 0)
|
||||||
gdi.selectItemByData("LegNumber", lastLeg);
|
gdi.selectItemByData("LegNumber", lastLeg);
|
||||||
|
|
||||||
//oe->fillLegNumbers(gdi, "LegNumber", li.isTeamList(), true);
|
|
||||||
gdi.setInputStatus("InputNumber", false);
|
gdi.setInputStatus("InputNumber", false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
gdi.setInputStatus("UseLargeSize", li.supportLarge);
|
gdi.setInputStatus("UseLargeSize", li.supportLarge);
|
||||||
gdi.setInputStatus("InputNumber", li.supportParameter);
|
gdi.setInputStatus("InputNumber", li.supportParameter);
|
||||||
|
|
||||||
//gdi.setInputStatus("SplitAnalysis", li.supportSplitAnalysis);
|
|
||||||
//gdi.setInputStatus("ShowInterResults", li.supportInterResults);
|
|
||||||
//gdi.setInputStatus("PageBreak", li.supportPageBreak);
|
|
||||||
//gdi.setInputStatus("ClassLimit", li.supportClassLimit);
|
|
||||||
|
|
||||||
if (li.supportLegs) {
|
if (li.supportLegs) {
|
||||||
gdi.enableInput("LegNumber");
|
gdi.enableInput("LegNumber");
|
||||||
//oe->fillLegNumbers(gdi, "LegNumber", li.isTeamList(), true);
|
|
||||||
set<int> clsUnused;
|
set<int> clsUnused;
|
||||||
vector< pair<wstring, size_t> > out;
|
vector< pair<wstring, size_t> > out;
|
||||||
oe->fillLegNumbers(clsUnused, li.isTeamList(), true, out);
|
oe->fillLegNumbers(clsUnused, li.isTeamList(), true, out);
|
||||||
@ -3095,12 +3087,19 @@ void TabList::setResultOptionsFromType(gdioutput &gdi, int data) {
|
|||||||
gdi.setSelection("ListSelection", lastResultClassSelection);
|
gdi.setSelection("ListSelection", lastResultClassSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.setInputStatus("Generate", data >= 0 && !lastResultClassSelection.empty());
|
gdi.setInputStatus("Generate", data >= 0 && hasSelectedClass(gdi));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TabList::hasSelectedClass(gdioutput& gdi) {
|
||||||
|
set<int> sel;
|
||||||
|
gdi.getSelection("ListSelection", sel);
|
||||||
|
return !sel.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabList::clearCompetitionData() {
|
void TabList::clearCompetitionData() {
|
||||||
SelectedList = "";
|
SelectedList = "";
|
||||||
lastResultClassSelection.clear();
|
lastResultClassSelection.clear();
|
||||||
|
lastClassSelection.clear();
|
||||||
|
|
||||||
ownWindow = false;
|
ownWindow = false;
|
||||||
hideButtons = false;
|
hideButtons = false;
|
||||||
|
|||||||
@ -49,6 +49,8 @@ protected:
|
|||||||
|
|
||||||
static void createListButtons(gdioutput &gdi);
|
static void createListButtons(gdioutput &gdi);
|
||||||
|
|
||||||
|
static bool hasSelectedClass(gdioutput& gdi);
|
||||||
|
|
||||||
void generateList(gdioutput &gdi, bool forceUpdate = false);
|
void generateList(gdioutput &gdi, bool forceUpdate = false);
|
||||||
void selectGeneralList(gdioutput &gdi, EStdListType type);
|
void selectGeneralList(gdioutput &gdi, EStdListType type);
|
||||||
|
|
||||||
|
|||||||
@ -207,8 +207,8 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
|||||||
vector<int> delta;
|
vector<int> delta;
|
||||||
vector<int> place;
|
vector<int> place;
|
||||||
vector<int> after;
|
vector<int> after;
|
||||||
vector<int> placeAcc;
|
vector<oRunner::ResultData> placeAcc;
|
||||||
vector<int> afterAcc;
|
vector<oRunner::ResultData> afterAcc;
|
||||||
|
|
||||||
r->getSplitAnalysis(delta);
|
r->getSplitAnalysis(delta);
|
||||||
r->getLegTimeAfter(after);
|
r->getLegTimeAfter(after);
|
||||||
@ -221,13 +221,13 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
|||||||
for (size_t k = 0; k < delta.size(); k++) {
|
for (size_t k = 0; k < delta.size(); k++) {
|
||||||
out += itow(place[k]);
|
out += itow(place[k]);
|
||||||
if (k < placeAcc.size())
|
if (k < placeAcc.size())
|
||||||
out += L" (" + itow(placeAcc[k]) + L")";
|
out += L" (" + itow(placeAcc[k].get(false)) + L")";
|
||||||
|
|
||||||
if (after[k] > 0)
|
if (after[k] > 0)
|
||||||
out += L" +" + formatTimeMS(after[k], false);
|
out += L" +" + formatTimeMS(after[k], false);
|
||||||
|
|
||||||
if (k < afterAcc.size() && afterAcc[k]>0)
|
if (k < afterAcc.size() && afterAcc[k].get(false)>0)
|
||||||
out += L" (+" + formatTimeMS(afterAcc[k], false) + L")";
|
out += L" (+" + formatTimeMS(afterAcc[k].get(false), false) + L")";
|
||||||
|
|
||||||
if (delta[k] > 0)
|
if (delta[k] > 0)
|
||||||
out += L" B: " + formatTimeMS(delta[k], false);
|
out += L" B: " + formatTimeMS(delta[k], false);
|
||||||
@ -813,6 +813,15 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
else if (bi.id == "ListenReadout") {
|
else if (bi.id == "ListenReadout") {
|
||||||
listenToPunches = gdi.isChecked(bi.id);
|
listenToPunches = gdi.isChecked(bi.id);
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "HideControls") {
|
||||||
|
hideReportControls = true;
|
||||||
|
listenToPunches = true;
|
||||||
|
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TRunnerTab, 0);
|
||||||
|
}
|
||||||
|
/*else if (bi.id == "ShowReportHeader") {
|
||||||
|
showReportHeader = gdi.isChecked(bi.id);
|
||||||
|
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TRunnerTab, 0);
|
||||||
|
}*/
|
||||||
else if (bi.id=="Unpair") {
|
else if (bi.id=="Unpair") {
|
||||||
ListBoxInfo lbi;
|
ListBoxInfo lbi;
|
||||||
int cid = bi.getExtraInt();
|
int cid = bi.getExtraInt();
|
||||||
@ -1225,7 +1234,14 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
runnerId = bi.data;
|
runnerId = bi.data;
|
||||||
//loadPage(gdi);
|
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TRunnerTab, 0);
|
||||||
|
}
|
||||||
|
else if (bi.id == "NumCols") {
|
||||||
|
numReportColumn = bi.data;
|
||||||
|
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TRunnerTab, 0);
|
||||||
|
}
|
||||||
|
else if (bi.id == "NumRows") {
|
||||||
|
numReportRow = bi.data;
|
||||||
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TRunnerTab, 0);
|
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TRunnerTab, 0);
|
||||||
}
|
}
|
||||||
else if (bi.id=="RClass") {
|
else if (bi.id=="RClass") {
|
||||||
@ -1322,24 +1338,20 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
cellAction(gdi, ei.getData(), b);
|
cellAction(gdi, ei.getData(), b);
|
||||||
}
|
}
|
||||||
else if ((ei.id == "DataUpdate") && listenToPunches && currentMode == 5) {
|
else if (currentMode == 5 && ei.id == "PunchCard") {
|
||||||
if (ei.getData() > 0) {
|
if (listenToPunches && ei.getData() > 0) {
|
||||||
runnerId = ei.getData();
|
addToReport(ei.getData(), true);
|
||||||
}
|
|
||||||
loadPage(gdi);
|
loadPage(gdi);
|
||||||
}
|
}
|
||||||
else if ((ei.id == "ReadCard") &&
|
|
||||||
(listenToPunches || oe->isReadOnly()) && currentMode == 5) {
|
|
||||||
if (ei.getData() > 0) {
|
|
||||||
vector<pRunner> rs;
|
|
||||||
oe->getRunnersByCardNo(ei.getData(), true, oEvent::CardLookupProperty::Any, rs);
|
|
||||||
if (!rs.empty()) {
|
|
||||||
runnersToReport.resize(rs.size());
|
|
||||||
for (size_t k = 0; k<rs.size(); k++)
|
|
||||||
runnersToReport[k] = make_pair(rs[k]->getId(), false);
|
|
||||||
}
|
}
|
||||||
runnerId = 0;
|
else if (currentMode == 5 && ei.id == "DataUpdate" && currentMode == 5) {
|
||||||
|
showRunnerReport(gdi);
|
||||||
}
|
}
|
||||||
|
else if (currentMode == 5 && ei.id == "ReadCard" &&
|
||||||
|
(listenToPunches || oe->isReadOnly())) {
|
||||||
|
if (ei.getData() > 0)
|
||||||
|
addToReport(ei.getData(), oe->isReadOnly());
|
||||||
loadPage(gdi);
|
loadPage(gdi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1610,85 +1622,312 @@ void TabRunner::setCardNo(gdioutput &gdi, int cardNo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string TabRunner::computeKeyForReport() {
|
||||||
|
string key = itos(runnersToReport.size());
|
||||||
|
for (auto &id : runnersToReport) {
|
||||||
|
key += "|" + itos(id.first);
|
||||||
|
pRunner r = oe->getRunner(id.first, 0);
|
||||||
|
if (r) {
|
||||||
|
key += gdioutput::toUTF8(r->getCompleteIdentification() + r->getClass(true));
|
||||||
|
key += itos(r->getStatus()) + itos(r->getFinishTime()) + itos(r->getStartTime());
|
||||||
|
vector<pFreePunch> pl;
|
||||||
|
oe->getPunchesForRunner(id.first, true, pl);
|
||||||
|
for (auto p : pl)
|
||||||
|
key += itos(p->getTimeInt());
|
||||||
|
|
||||||
|
if (r->getCard()) {
|
||||||
|
auto ch = r->getCard()->getCardHash();
|
||||||
|
key += itos(ch.first) + itos(ch.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
void TabRunner::showRunnerReport(gdioutput &gdi) {
|
void TabRunner::showRunnerReport(gdioutput &gdi) {
|
||||||
|
string oldHash, newHash = computeKeyForReport();
|
||||||
|
|
||||||
|
if (gdi.getData("ReportHash", oldHash) && oldHash == newHash)
|
||||||
|
return;
|
||||||
|
|
||||||
gdi.clearPage(true);
|
gdi.clearPage(true);
|
||||||
|
gdi.setData("ReportHash", newHash);
|
||||||
currentMode = 5;
|
currentMode = 5;
|
||||||
|
|
||||||
if (!ownWindow && !oe->isReadOnly())
|
if (!ownWindow && !oe->isReadOnly())
|
||||||
addToolbar(gdi);
|
addToolbar(gdi);
|
||||||
else if (oe->isReadOnly())
|
else if (oe->isReadOnly() && !listenToPunches)
|
||||||
gdi.addString("", fontLarge, makeDash(L"MeOS - Resultatkiosk")).setColor(colorDarkBlue);
|
gdi.addString("", fontLarge, makeDash(L"MeOS - Resultatkiosk")).setColor(colorDarkBlue);
|
||||||
|
|
||||||
gdi.dropLine();
|
if (!hideReportControls) {
|
||||||
|
bool any = false;
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
|
|
||||||
|
if (!oe->isReadOnly() || !listenToPunches) {
|
||||||
|
gdi.dropLine();
|
||||||
gdi.addSelection("ReportRunner", 300, 300, RunnerCB);
|
gdi.addSelection("ReportRunner", 300, 300, RunnerCB);
|
||||||
oe->fillRunners(gdi, "ReportRunner", true, oEvent::RunnerFilterShowAll | oEvent::RunnerCompactMode);
|
oe->fillRunners(gdi, "ReportRunner", true, oEvent::RunnerFilterShowAll | oEvent::RunnerCompactMode);
|
||||||
gdi.selectItemByData("ReportRunner", runnerId);
|
gdi.selectItemByData("ReportRunner", runnerId);
|
||||||
|
gdi.autoGrow("ReportRunner");
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!oe->isReadOnly()) {
|
if (!oe->isReadOnly() && !hideReportControls) {
|
||||||
if (!ownWindow) {
|
if (!ownWindow) {
|
||||||
gdi.addButton("Kiosk", "Resultatkiosk", RunnerCB);
|
gdi.addButton("Kiosk", "Resultatkiosk", RunnerCB);
|
||||||
gdi.addButton("Window", "Eget fönster", RunnerCB, "Öppna i ett nytt fönster.");
|
gdi.addButton("Window", "Eget fönster", RunnerCB, "Öppna i ett nytt fönster.");
|
||||||
}
|
}
|
||||||
gdi.dropLine(0.2);
|
else {
|
||||||
gdi.addCheckbox("ListenReadout", "Visa senast inlästa deltagare", RunnerCB, listenToPunches);
|
gdi.addButton("HideControls", "Dölj inställningar", RunnerCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
any = true;
|
||||||
|
gdi.dropLine(0.2);
|
||||||
|
gdi.addCheckbox("ListenReadout", "Visa senast inlästa deltagare", RunnerCB, listenToPunches);
|
||||||
|
gdi.dropLine(2);
|
||||||
|
gdi.popX();
|
||||||
|
vector<pair<wstring, size_t>> options;
|
||||||
|
for (int i = 1; i <= 10; i++)
|
||||||
|
options.emplace_back(itow(i), i);
|
||||||
|
|
||||||
|
gdi.addString("", 0, "Layout");
|
||||||
|
|
||||||
|
gdi.addSelection("NumRows", 100, 200, RunnerCB);
|
||||||
|
gdi.addString("", 0, "rader");
|
||||||
|
gdi.addItem("NumRows", options);
|
||||||
|
gdi.selectItemByData("NumRows", numReportRow);
|
||||||
|
|
||||||
|
gdi.addSelection("NumCols", 100, 200, RunnerCB);
|
||||||
|
gdi.addString("", 0, "kolumner");
|
||||||
|
gdi.addItem("NumCols", options);
|
||||||
|
gdi.selectItemByData("NumCols", numReportColumn);
|
||||||
|
|
||||||
|
//gdi.addCheckbox("ShowReportHeader", "Visa sidhuvud", RunnerCB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (any)
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
|
}
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.registerEvent("DataUpdate", RunnerCB);
|
gdi.registerEvent("DataUpdate", RunnerCB);
|
||||||
gdi.registerEvent("ReadCard", RunnerCB);
|
gdi.registerEvent("ReadCard", RunnerCB);
|
||||||
|
gdi.registerEvent("PunchCard", RunnerCB);
|
||||||
|
gdi.setData("DataSync", 1);
|
||||||
|
gdi.setData("PunchSync", 1);
|
||||||
|
|
||||||
if (runnerId > 0) {
|
if (runnerId > 0) {
|
||||||
runnersToReport.resize(1);
|
bool found = false;
|
||||||
runnersToReport[0] = make_pair(runnerId, false);
|
addToReport(runnerId);
|
||||||
}
|
}
|
||||||
generateRunnerReport(*oe, gdi, runnersToReport);
|
while (runnersToReport.size() > numReportRow * numReportColumn)
|
||||||
|
runnersToReport.pop_back();
|
||||||
|
|
||||||
if (runnersToReport.size() == 1)
|
generateRunnerReport(*oe, gdi, numReportColumn, numReportRow, true, runnersToReport);
|
||||||
|
|
||||||
|
if (runnersToReport.size() > 0)
|
||||||
runnerId = runnersToReport[0].first;
|
runnerId = runnersToReport[0].first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabRunner::generateRunnerReport(oEvent &oe, gdioutput &gdi, vector<pair<int, bool>> &runnersToReport) {
|
void TabRunner::addToReport(int id) {
|
||||||
|
bool found = false;
|
||||||
|
for (auto& rr : runnersToReport) {
|
||||||
|
if (rr.first == id)
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
runnersToReport.emplace_front(id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabRunner::addToReport(int cardNo, bool punchForShowReport) {
|
||||||
|
vector<pRunner> rs;
|
||||||
|
oe->getRunnersByCardNo(cardNo, true, oEvent::CardLookupProperty::Any, rs);
|
||||||
|
|
||||||
|
if (!punchForShowReport) {
|
||||||
|
// Take away runners with no card
|
||||||
|
vector<pRunner> rsFilter;
|
||||||
|
for (pRunner r : rs) {
|
||||||
|
if (r->getCard())
|
||||||
|
rsFilter.push_back(r);
|
||||||
|
}
|
||||||
|
rs.swap(rsFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rs.empty()) {
|
||||||
|
if (rs.size() == 1) {
|
||||||
|
addToReport(rs[0]->getId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map<int, vector<pRunner>> runnersPerTeam;
|
||||||
|
for (pRunner r : rs) {
|
||||||
|
if (r->getTeam())
|
||||||
|
runnersPerTeam[r->getTeam()->getId()].push_back(r);
|
||||||
|
else
|
||||||
|
runnersPerTeam[0].push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& rpt : runnersPerTeam) {
|
||||||
|
if (rpt.second.size() == 1) {
|
||||||
|
addToReport(rpt.second[0]->getId());
|
||||||
|
}
|
||||||
|
else if (rpt.first == 0) {
|
||||||
|
sort(rpt.second.begin(), rpt.second.end(),
|
||||||
|
[](const pRunner& a, const pRunner& b) {return unsigned(a->getStartTime() - 1) < unsigned(b->getStartTime() - 1); });
|
||||||
|
// Take the last competitor using the card
|
||||||
|
addToReport(rpt.second.back()->getId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sort(rpt.second.begin(), rpt.second.end(),
|
||||||
|
[](const pRunner& a, const pRunner& b) {return a->getLegNumber() < b->getLegNumber(); });
|
||||||
|
bool hasResultAny = false;
|
||||||
|
bool done = false;
|
||||||
|
for (pRunner r : rpt.second) {
|
||||||
|
if (r->hasFinished())
|
||||||
|
hasResultAny = true;
|
||||||
|
else if (hasResultAny) {
|
||||||
|
// Prefer to report the next runner to run
|
||||||
|
addToReport(r->getId());
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!done) {
|
||||||
|
if (hasResultAny) {
|
||||||
|
// Take the last one (final result)
|
||||||
|
addToReport(rpt.second.back()->getId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// None finished. Take first
|
||||||
|
addToReport(rpt.second.front()->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*runnersToReport.resize(rs.size());
|
||||||
|
for (size_t k = 0; k<rs.size(); k++)
|
||||||
|
runnersToReport[k] = make_pair(rs[k]->getId(), false);*/
|
||||||
|
}
|
||||||
|
runnerId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabRunner::generateRunnerReport(oEvent &oe, gdioutput &gdi,
|
||||||
|
int numX, int numY,
|
||||||
|
bool onlySelectedRunner,
|
||||||
|
const deque<pair<int, bool>> &runnersToReport) {
|
||||||
oe.synchronizeList({ oListId::oLRunnerId, oListId::oLTeamId, oListId::oLPunchId });
|
oe.synchronizeList({ oListId::oLRunnerId, oListId::oLTeamId, oListId::oLPunchId });
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
|
int xx, yy;
|
||||||
|
int margin = gdi.scaleLength(16);
|
||||||
|
gdi.getTargetDimension(xx, yy);
|
||||||
|
|
||||||
cTeam t = 0;
|
int maxWidth = max(gdi.scaleLength(130 * 3) + 2*margin, xx / numX - margin * (numX + 1));
|
||||||
|
if (numX == 1 && numY == 1)
|
||||||
|
maxWidth = min(maxWidth, gdi.scaleLength(130)*6+margin);
|
||||||
|
|
||||||
|
bool frame = true;
|
||||||
|
|
||||||
|
vector<const oTeam *> tList;
|
||||||
set<int> clsSet;
|
set<int> clsSet;
|
||||||
|
|
||||||
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
||||||
pRunner r = oe.getRunner(runnersToReport[k].first, 0);
|
pRunner r = oe.getRunner(runnersToReport[k].first, 0);
|
||||||
if (!r)
|
if (!r)
|
||||||
continue;
|
continue;
|
||||||
clsSet.insert(r->getClassId(true));
|
clsSet.insert(r->getClassId(true));
|
||||||
if (r && r->getTeam()) {
|
pTeam t = r->getTeam();
|
||||||
|
if (t) {
|
||||||
pClass cls = r->getClassRef(true);
|
pClass cls = r->getClassRef(true);
|
||||||
if (cls && cls->getClassType() != oClassRelay)
|
if (cls && cls->getClassType() != oClassRelay)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (t == 0)
|
bool added = count(tList.begin(), tList.end(), t) > 0;
|
||||||
t = r->getTeam();
|
if (added)
|
||||||
|
continue;
|
||||||
|
tList.push_back(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oe.calculateResults(clsSet, oEvent::ResultType::PreliminarySplitResults, true);
|
oe.calculateResults(clsSet, oEvent::ResultType::PreliminarySplitResults, true);
|
||||||
oe.calculateResults(clsSet, oEvent::ResultType::ClassResult);
|
oe.calculateResults(clsSet, oEvent::ResultType::ClassResult);
|
||||||
|
|
||||||
if (t == 0) {
|
RECT rcFrame;
|
||||||
for (size_t k = 0; k < runnersToReport.size(); k++)
|
|
||||||
runnerReport(oe, gdi, runnersToReport[k].first, runnersToReport[k].second);
|
auto drawBox = [&gdi](RECT &rcFrame) {
|
||||||
|
RECT rc = rcFrame;
|
||||||
|
int mg = gdi.scaleLength(5);
|
||||||
|
rc.left -= mg;
|
||||||
|
rc.top -= mg;
|
||||||
|
rc.right += mg;
|
||||||
|
rc.bottom += mg;
|
||||||
|
gdi.addRectangle(rc, GDICOLOR::colorLightCyan, true, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
int baseX = gdi.getCX();
|
||||||
|
int baseY = gdi.getCY();
|
||||||
|
vector<RECT> rcList;
|
||||||
|
|
||||||
|
auto updatePositionDrawBox = [&](bool force) {
|
||||||
|
if (!force)
|
||||||
|
rcList.push_back(rcFrame);
|
||||||
|
|
||||||
|
if ((force && !rcList.empty()) || rcList.size() == numX) {
|
||||||
|
int maxYP = 0;
|
||||||
|
for (RECT& rc : rcList)
|
||||||
|
maxYP = max<int>(maxYP, rc.bottom);
|
||||||
|
for (RECT& rc : rcList) {
|
||||||
|
rc.bottom = maxYP;
|
||||||
|
drawBox(rc);
|
||||||
}
|
}
|
||||||
else {
|
rcList.clear();
|
||||||
|
baseY = maxYP + margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdi.setCY(baseY);
|
||||||
|
gdi.setCX(baseX + (maxWidth + margin) * rcList.size());
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
||||||
|
pRunner r = oe.getRunner(runnersToReport[k].first, 0);
|
||||||
|
if (!r)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (count(tList.begin(), tList.end(), r->getTeam()) == 0) {
|
||||||
|
runnerReport(oe, gdi, runnersToReport[k].first, runnersToReport[k].second, maxWidth, rcFrame);
|
||||||
|
updatePositionDrawBox(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tList.size() > 0) {
|
||||||
oe.calculateTeamResults(clsSet, oEvent::ResultType::ClassResult);
|
oe.calculateTeamResults(clsSet, oEvent::ResultType::ClassResult);
|
||||||
|
for (const oTeam *t : tList) {
|
||||||
|
teamReport(oe, gdi, t, onlySelectedRunner, runnersToReport, maxWidth, rcFrame);
|
||||||
|
updatePositionDrawBox(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePositionDrawBox(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabRunner::teamReport(oEvent& oe, gdioutput& gdi,
|
||||||
|
const oTeam* t,
|
||||||
|
bool onlySelectedRunner,
|
||||||
|
const deque<pair<int, bool>>& runnersToReport,
|
||||||
|
int maxWidth,
|
||||||
|
RECT& rc) {
|
||||||
|
rc.top = gdi.getCY();
|
||||||
|
rc.left = gdi.getCX();
|
||||||
|
rc.right = rc.left + maxWidth;
|
||||||
|
|
||||||
set<int> selectedRunners;
|
set<int> selectedRunners;
|
||||||
bool selHasRes = false;
|
bool selHasPartialRes = false;
|
||||||
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
||||||
selectedRunners.insert(runnersToReport[k].first);
|
|
||||||
pRunner r = oe.getRunner(runnersToReport[k].first, 0);
|
pRunner r = oe.getRunner(runnersToReport[k].first, 0);
|
||||||
|
if (r && r->getTeam() == t) {
|
||||||
|
selectedRunners.insert(runnersToReport[k].first);
|
||||||
if (r && r->hasOnCourseResult())
|
if (r && r->hasOnCourseResult())
|
||||||
selHasRes = true;
|
selHasPartialRes = true; //Partial (radio) or complete result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring tInfo = t->getName();
|
wstring tInfo = t->getName();
|
||||||
@ -1705,32 +1944,70 @@ void TabRunner::showRunnerReport(gdioutput &gdi) {
|
|||||||
gdi.addStringUT(boldLarge, tInfo);
|
gdi.addStringUT(boldLarge, tInfo);
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
|
|
||||||
|
pClass cls = t->getClassRef(false);
|
||||||
|
|
||||||
bool visitedSelected = false;
|
bool visitedSelected = false;
|
||||||
for (int leg = 0; leg < t->getNumRunners(); leg++) {
|
for (int leg = 0; leg < t->getNumRunners(); leg++) {
|
||||||
if (selHasRes && visitedSelected)
|
if ((selHasPartialRes || onlySelectedRunner) && visitedSelected)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pRunner r = t->getRunner(leg);
|
pRunner r = t->getRunner(leg);
|
||||||
|
|
||||||
pRunner nextR = t->getRunner(leg + 1);
|
pRunner nextR = t->getRunner(leg + 1);
|
||||||
bool nextSelected = nextR && selectedRunners.count(nextR->getId());
|
bool nextSelected = false;
|
||||||
|
if (cls) {
|
||||||
|
// Check if leg has the selected runner (parallel legs)
|
||||||
|
int legNr, legOrd;
|
||||||
|
cls->splitLegNumberParallel(leg, legNr, legOrd);
|
||||||
|
int nextLeg = leg;
|
||||||
|
while (++nextLeg < t->getNumRunners()) {
|
||||||
|
int legNrN, legOrdN;
|
||||||
|
cls->splitLegNumberParallel(leg, legNrN, legOrdN);
|
||||||
|
if (legNrN == legNr + 1) {
|
||||||
|
nextR = t->getRunner(nextLeg);
|
||||||
|
nextSelected = nextR && selectedRunners.count(nextR->getId());
|
||||||
|
if (nextSelected)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nextSelected = nextR && selectedRunners.count(nextR->getId());
|
||||||
|
}
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
bool selected = selectedRunners.count(r->getId()) > 0;
|
bool selected = selectedRunners.count(r->getId()) > 0;
|
||||||
|
|
||||||
if (selHasRes) {
|
if (onlySelectedRunner && !selected) {
|
||||||
runnerReport(oe, gdi, r->getId(), !selected);
|
if (!nextSelected)
|
||||||
|
continue; // Always skip if next is not selected
|
||||||
|
if (nextR->hasResult())
|
||||||
|
continue; // Only include previous if next does not have results
|
||||||
|
}
|
||||||
|
RECT dmy;
|
||||||
|
if (selHasPartialRes) {
|
||||||
|
// The selected runner has some result. Focus on that
|
||||||
|
runnerReport(oe, gdi, r->getId(), !selected, maxWidth, dmy);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
runnerReport(oe, gdi, r->getId(), !nextSelected);
|
// The selected runner has not started. Focus on previous result
|
||||||
|
runnerReport(oe, gdi, r->getId(), !nextSelected, maxWidth, dmy);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitedSelected |= selected;
|
visitedSelected |= selected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
rc.bottom = gdi.getCY();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi,
|
||||||
|
int id, bool compact,
|
||||||
|
int maxWidth, RECT &rc) {
|
||||||
|
|
||||||
|
rc.top = gdi.getCY();
|
||||||
|
rc.left = gdi.getCX();
|
||||||
|
rc.right = rc.left + maxWidth;
|
||||||
|
|
||||||
pRunner r = oe.getRunner(id, 0);
|
pRunner r = oe.getRunner(id, 0);
|
||||||
if (!r || ! r->getClassRef(false))
|
if (!r || ! r->getClassRef(false))
|
||||||
return;
|
return;
|
||||||
@ -1739,7 +2016,8 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
if (r->getTeam() == 0) {
|
if (r->getTeam() == 0) {
|
||||||
gdi.addStringUT(fontMediumPlus, r->getClass(true));
|
gdi.addStringUT(fontMediumPlus, r->getClass(true));
|
||||||
gdi.addStringUT(boldLarge, r->getCompleteIdentification());
|
gdi.addStringUT(gdi.getCY(), gdi.getCX(), boldLarge,
|
||||||
|
r->getCompleteIdentification(), maxWidth - 4);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wstring s;
|
wstring s;
|
||||||
@ -1784,20 +2062,31 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
|
int ww = gdi.scaleLength(120);
|
||||||
|
auto optionalBreakLine = [&] {
|
||||||
|
if (gdi.getCX() + ww > rc.left + maxWidth) {
|
||||||
|
gdi.popX();
|
||||||
|
gdi.dropLine();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (r->getStartTime() > 0)
|
if (r->getStartTime() > 0) {
|
||||||
|
optionalBreakLine();
|
||||||
gdi.addString("", fontMedium, L"Starttid: X #" + r->getStartTimeCompact());
|
gdi.addString("", fontMedium, L"Starttid: X #" + r->getStartTimeCompact());
|
||||||
|
}
|
||||||
if (r->getFinishTime() > 0)
|
if (r->getFinishTime() > 0) {
|
||||||
|
optionalBreakLine();
|
||||||
gdi.addString("", fontMedium, L"Måltid: X #" + r->getFinishTimeS(false, SubSecond::Auto));
|
gdi.addString("", fontMedium, L"Måltid: X #" + r->getFinishTimeS(false, SubSecond::Auto));
|
||||||
|
}
|
||||||
const wstring &after = oe.formatListString(lRunnerTimeAfter, r);
|
const wstring &after = oe.formatListString(lRunnerTimeAfter, r);
|
||||||
if (!after.empty()) {
|
if (!after.empty()) {
|
||||||
|
optionalBreakLine();
|
||||||
gdi.addString("", fontMedium, L"Tid efter: X #" + after);
|
gdi.addString("", fontMedium, L"Tid efter: X #" + after);
|
||||||
}
|
}
|
||||||
|
|
||||||
const wstring &lost = oe.formatListString(lRunnerLostTime, r);
|
const wstring &lost = oe.formatListString(lRunnerLostTime, r);
|
||||||
if (!lost.empty()) {
|
if (!lost.empty()) {
|
||||||
|
optionalBreakLine();
|
||||||
gdi.addString("", fontMedium, L"Bomtid: X #" + lost).setColor(colorDarkRed);
|
gdi.addString("", fontMedium, L"Bomtid: X #" + lost).setColor(colorDarkRed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1813,17 +2102,28 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
int xp = gdi.getCX();
|
int xp = gdi.getCX();
|
||||||
int yp = gdi.getCY();
|
int yp = gdi.getCY();
|
||||||
int xw = gdi.scaleLength(130);
|
int xw = gdi.scaleLength(130);
|
||||||
int cx = xp;
|
int mg4 = gdi.scaleLength(4);
|
||||||
|
int cx = xp + mg4;
|
||||||
int limit = (9*xw)/10;
|
int limit = (9*xw)/10;
|
||||||
int lh = gdi.getLineHeight();
|
int lh = gdi.getLineHeight();
|
||||||
|
int maxTimesPerLine = min(10, max(3, maxWidth / xw));
|
||||||
|
|
||||||
|
auto drawBox = [&gdi, xw, mg4, lh](int yp, int cx, GDICOLOR color) {
|
||||||
|
RECT rc;
|
||||||
|
rc.top = yp - mg4 / 2;
|
||||||
|
rc.bottom = yp + lh * 5 - mg4;
|
||||||
|
rc.left = cx - mg4;
|
||||||
|
rc.right = cx + xw - mg4 * 2;
|
||||||
|
gdi.addRectangle(rc, color);
|
||||||
|
};
|
||||||
|
|
||||||
if (crs && r->getStatus() != StatusUnknown) {
|
if (crs && r->getStatus() != StatusUnknown) {
|
||||||
int nc = crs->getNumControls();
|
int nc = crs->getNumControls();
|
||||||
vector<int> delta;
|
vector<int> delta;
|
||||||
vector<int> place;
|
vector<int> place;
|
||||||
vector<int> after;
|
vector<int> after;
|
||||||
vector<int> placeAcc;
|
vector<oRunner::ResultData> placeAcc;
|
||||||
vector<int> afterAcc;
|
vector<oRunner::ResultData> afterAcc;
|
||||||
|
|
||||||
r->getSplitAnalysis(delta);
|
r->getSplitAnalysis(delta);
|
||||||
r->getLegTimeAfter(after);
|
r->getLegTimeAfter(after);
|
||||||
@ -1844,7 +2144,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
else
|
else
|
||||||
gdi.addStringUT(yp, cx, boldText, name, limit);
|
gdi.addStringUT(yp, cx, boldText, name, limit);
|
||||||
|
|
||||||
wstring split = r->getSplitTimeS(k, false);
|
wstring split = r->getSplitTimeS(k, false, SubSecond::Off);
|
||||||
|
|
||||||
int bestTime = 0;
|
int bestTime = 0;
|
||||||
if ( k < int(after.size()) && after[k] >= 0)
|
if ( k < int(after.size()) && after[k] >= 0)
|
||||||
@ -1865,14 +2165,14 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
gdi.addStringUT(yp + lh, cx, fontMedium, split, limit);
|
gdi.addStringUT(yp + lh, cx, fontMedium, split, limit);
|
||||||
|
|
||||||
if (k>0 && k < int(placeAcc.size())) {
|
if (k>0 && k < int(placeAcc.size())) {
|
||||||
split = r->getPunchTimeS(k, false, false, SubSecond::Auto);
|
split = r->getPunchTimeS(k, false, false, false, SubSecond::Auto);
|
||||||
wstring pl = placeAcc[k] > 0 ? itow(placeAcc[k]) : L"-";
|
wstring pl = placeAcc[k].get(false) > 0 ? itow(placeAcc[k].get(false)) : L"-";
|
||||||
if (k < int(afterAcc.size()) ) {
|
if (k < int(afterAcc.size()) ) {
|
||||||
if (afterAcc[k] > 0)
|
if (afterAcc[k].get(false) > 0)
|
||||||
split += L" (" + pl + L", +" + formatTimeMS(afterAcc[k], false) + L")";
|
split += L" (" + pl + L", +" + formatTimeMS(afterAcc[k].get(false), false) + L")";
|
||||||
else if (placeAcc[k] == 1)
|
else if (placeAcc[k].get(false) == 1)
|
||||||
split += lang.tl(" (ledare)");
|
split += lang.tl(" (ledare)");
|
||||||
else if (placeAcc[k] > 0)
|
else if (placeAcc[k].get(false) > 0)
|
||||||
split += L" " + pl;
|
split += L" " + pl;
|
||||||
}
|
}
|
||||||
gdi.addStringUT(yp + 2*lh, cx, fontMedium, split, limit).setColor(colorDarkBlue);
|
gdi.addStringUT(yp + 2*lh, cx, fontMedium, split, limit).setColor(colorDarkBlue);
|
||||||
@ -1885,18 +2185,10 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
colorMediumDarkRed : colorMediumRed;
|
colorMediumDarkRed : colorMediumRed;
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT rc;
|
drawBox(yp, cx, color);
|
||||||
rc.top = yp - 2;
|
|
||||||
rc.bottom = yp + lh*5 - 4;
|
|
||||||
rc.left = cx - 4;
|
|
||||||
rc.right = cx + xw - 8;
|
|
||||||
|
|
||||||
gdi.addRectangle(rc, color);
|
|
||||||
|
|
||||||
cx += xw;
|
cx += xw;
|
||||||
|
if ( (k+1) % maxTimesPerLine == 0) {
|
||||||
if (k % 6 == 5) {
|
cx = xp + mg4;
|
||||||
cx = xp;
|
|
||||||
yp += lh * 5;
|
yp += lh * 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1950,26 +2242,19 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
|
|
||||||
GDICOLOR color = colorDefault;
|
GDICOLOR color = colorDefault;
|
||||||
|
|
||||||
RECT rc;
|
drawBox(yp, cx, color);
|
||||||
rc.top = yp - 2;
|
|
||||||
rc.bottom = yp + lh*5 - 4;
|
|
||||||
rc.left = cx - 4;
|
|
||||||
rc.right = cx + xw - 8;
|
|
||||||
|
|
||||||
gdi.addRectangle(rc, color);
|
|
||||||
cx += xw;
|
cx += xw;
|
||||||
if (k % 6 == 5) {
|
if ((k + 1) % maxTimesPerLine == 0) {
|
||||||
cx = xp;
|
cx = xp + mg4;
|
||||||
yp += lh * 5;
|
yp += lh * 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.dropLine(3);
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
rc.bottom = gdi.getCY();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TabRunner::showVacancyList(gdioutput &gdi, const string &method, int classId)
|
void TabRunner::showVacancyList(gdioutput &gdi, const string &method, int classId)
|
||||||
{
|
{
|
||||||
gdi.clearPage(true);
|
gdi.clearPage(true);
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "tabbase.h"
|
#include "tabbase.h"
|
||||||
#include "Printer.h"
|
#include "Printer.h"
|
||||||
#include "autocompletehandler.h"
|
#include "autocompletehandler.h"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
class Table;
|
class Table;
|
||||||
struct AutoCompleteRecord;
|
struct AutoCompleteRecord;
|
||||||
@ -43,6 +44,15 @@ private:
|
|||||||
|
|
||||||
void selectRunner(gdioutput &gdi, pRunner r);
|
void selectRunner(gdioutput &gdi, pRunner r);
|
||||||
|
|
||||||
|
int numReportRow = 1;
|
||||||
|
int numReportColumn = 1;
|
||||||
|
bool hideReportControls = false;
|
||||||
|
bool showReportHeader = true;
|
||||||
|
void addToReport(int cardNo, bool punchForShowReport);
|
||||||
|
void addToReport(int id);
|
||||||
|
|
||||||
|
string computeKeyForReport();
|
||||||
|
|
||||||
wstring lastSearchExpr;
|
wstring lastSearchExpr;
|
||||||
unordered_set<int> lastFilter;
|
unordered_set<int> lastFilter;
|
||||||
DWORD timeToFill;
|
DWORD timeToFill;
|
||||||
@ -64,7 +74,7 @@ private:
|
|||||||
int runnerId;
|
int runnerId;
|
||||||
bool ownWindow;
|
bool ownWindow;
|
||||||
bool listenToPunches;
|
bool listenToPunches;
|
||||||
vector< pair<int, bool> > runnersToReport;
|
deque<pair<int, bool>> runnersToReport;
|
||||||
|
|
||||||
vector<pRunner> unknown_dns;
|
vector<pRunner> unknown_dns;
|
||||||
vector<pRunner> known_dns;
|
vector<pRunner> known_dns;
|
||||||
@ -76,7 +86,19 @@ private:
|
|||||||
PrinterObject splitPrinter;
|
PrinterObject splitPrinter;
|
||||||
|
|
||||||
void showRunnerReport(gdioutput &gdi);
|
void showRunnerReport(gdioutput &gdi);
|
||||||
static void runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compactReport);
|
|
||||||
|
static void runnerReport(oEvent &oe, gdioutput &gdi,
|
||||||
|
int id, bool compactReport,
|
||||||
|
int maxWidth,
|
||||||
|
RECT& rc);
|
||||||
|
|
||||||
|
static void teamReport(oEvent& oe, gdioutput& gdi,
|
||||||
|
const oTeam *team,
|
||||||
|
bool onlySelectedRunner,
|
||||||
|
const deque<pair<int, bool>> &runners,
|
||||||
|
int maxWidth,
|
||||||
|
RECT &rc);
|
||||||
|
|
||||||
|
|
||||||
void showVacancyList(gdioutput &gdi, const string &method="", int classId=0);
|
void showVacancyList(gdioutput &gdi, const string &method="", int classId=0);
|
||||||
void showCardsList(gdioutput &gdi);
|
void showCardsList(gdioutput &gdi);
|
||||||
@ -126,7 +148,11 @@ public:
|
|||||||
bool loadPage(gdioutput &gdi);
|
bool loadPage(gdioutput &gdi);
|
||||||
bool loadPage(gdioutput &gdi, int runnerId);
|
bool loadPage(gdioutput &gdi, int runnerId);
|
||||||
|
|
||||||
static void generateRunnerReport(oEvent &oe, gdioutput &gdi, vector<pair<int, bool>> &runnersToReport);
|
static void generateRunnerReport(oEvent &oe,
|
||||||
|
gdioutput &gdi,
|
||||||
|
int numX, int numY,
|
||||||
|
bool onlySelectedRunner,
|
||||||
|
const deque<pair<int, bool>> &runnersToReport);
|
||||||
|
|
||||||
TabRunner(oEvent *oe);
|
TabRunner(oEvent *oe);
|
||||||
~TabRunner(void);
|
~TabRunner(void);
|
||||||
|
|||||||
258
code/TabSI.cpp
258
code/TabSI.cpp
@ -84,7 +84,6 @@ TabSI::TabSI(oEvent* poe) :TabBase(poe), activeSIC(ConvertedTimeStatus::Unknown)
|
|||||||
minRunnerId = 0;
|
minRunnerId = 0;
|
||||||
inputId = 0;
|
inputId = 0;
|
||||||
printErrorShown = false;
|
printErrorShown = false;
|
||||||
NC = 8;
|
|
||||||
splitPrinter.onlyChanged = false;
|
splitPrinter.onlyChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,8 +144,7 @@ string TabSI::typeFromSndType(SND s) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
int TabSI::siCB(gdioutput& gdi, int type, void* data) {
|
||||||
{
|
|
||||||
if (type == GUI_BUTTON) {
|
if (type == GUI_BUTTON) {
|
||||||
ButtonInfo bi = *(ButtonInfo*)data;
|
ButtonInfo bi = *(ButtonInfo*)data;
|
||||||
|
|
||||||
@ -351,6 +349,12 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
ListBoxInfo lbi;
|
ListBoxInfo lbi;
|
||||||
if (gdi.getSelectedItem("ComPort", lbi)) {
|
if (gdi.getSelectedItem("ComPort", lbi)) {
|
||||||
|
|
||||||
|
if (lbi.data == 9999) {
|
||||||
|
showTestingPanel = !showTestingPanel;
|
||||||
|
loadPage(gdi);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
swprintf_s(bf, 64, L"COM%d", lbi.getDataInt());
|
swprintf_s(bf, 64, L"COM%d", lbi.getDataInt());
|
||||||
wstring port = bf;
|
wstring port = bf;
|
||||||
|
|
||||||
@ -705,11 +709,20 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
sic.CardNumber = gdi.getTextNo("SI");
|
sic.CardNumber = gdi.getTextNo("SI");
|
||||||
int f = convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum());
|
int f = convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum());
|
||||||
int s = convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum());
|
int s = convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum());
|
||||||
|
int c = convertAbsoluteTimeHMS(gdi.getText("Check"), oe->getZeroTimeNum());
|
||||||
|
|
||||||
|
testStartTime.clear();
|
||||||
|
testFinishTime.clear();
|
||||||
|
testCheckTime.clear();
|
||||||
|
testCardNumber = 0;
|
||||||
|
|
||||||
if (f < s) {
|
if (f < s) {
|
||||||
f += 24 * timeConstHour;
|
f += 24 * timeConstHour;
|
||||||
}
|
}
|
||||||
sic.FinishPunch.Time = f % (24 * timeConstHour);
|
sic.FinishPunch.Time = f % (24 * timeConstHour);
|
||||||
sic.StartPunch.Time = s % (24 * timeConstHour);
|
sic.StartPunch.Time = s % (24 * timeConstHour);
|
||||||
|
sic.CheckPunch.Time = c % (24 * timeConstHour);
|
||||||
|
|
||||||
if (!gdi.isChecked("HasFinish")) {
|
if (!gdi.isChecked("HasFinish")) {
|
||||||
sic.FinishPunch.Code = -1;
|
sic.FinishPunch.Code = -1;
|
||||||
sic.FinishPunch.Time = 0;
|
sic.FinishPunch.Time = 0;
|
||||||
@ -720,9 +733,20 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
sic.StartPunch.Time = 0;
|
sic.StartPunch.Time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gdi.isChecked("HasCheck")) {
|
||||||
|
sic.CheckPunch.Code = -1;
|
||||||
|
sic.CheckPunch.Time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NC > testControls.size())
|
||||||
|
testControls.resize(NC);
|
||||||
|
|
||||||
|
for (int i = 0; i < NC; i++)
|
||||||
|
testControls[i] = gdi.getTextNo("C" + itos(i + 1));
|
||||||
|
|
||||||
double t = 0.1;
|
double t = 0.1;
|
||||||
for (sic.nPunch = 0; sic.nPunch<unsigned(NC); sic.nPunch++) {
|
for (sic.nPunch = 0; sic.nPunch<unsigned(NC); sic.nPunch++) {
|
||||||
int c = gdi.getTextNo("C" + itos(sic.nPunch + 1));
|
int c = testControls[sic.nPunch];
|
||||||
sic.Punch[sic.nPunch].Time = ((int(f * t + s * (1.0 - t))/ timeUnitsPerSecond) % (24 * timeConstSecPerHour)) * timeUnitsPerSecond;
|
sic.Punch[sic.nPunch].Time = ((int(f * t + s * (1.0 - t))/ timeUnitsPerSecond) % (24 * timeConstSecPerHour)) * timeUnitsPerSecond;
|
||||||
t += ((1.0 - t) * (sic.nPunch + 1) / 10.0) * ((rand() % 100) + 400.0) / 500.0;
|
t += ((1.0 - t) * (sic.nPunch + 1) / 10.0) * ((rand() % 100) + 400.0) / 500.0;
|
||||||
if ((sic.nPunch % 11) == 1 || 5 == (sic.nPunch % 8))
|
if ((sic.nPunch % 11) == 1 || 5 == (sic.nPunch % 8))
|
||||||
@ -754,31 +778,34 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
sic.FinishPunch.Code = -1;
|
sic.FinishPunch.Code = -1;
|
||||||
sic.CheckPunch.Code = -1;
|
sic.CheckPunch.Code = -1;
|
||||||
sic.StartPunch.Code = -1;
|
sic.StartPunch.Code = -1;
|
||||||
|
|
||||||
sic.CardNumber = gdi.getTextNo("SI");
|
sic.CardNumber = gdi.getTextNo("SI");
|
||||||
int f = convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum());
|
int t = convertAbsoluteTimeHMS(gdi.getText("PunchTime"), oe->getZeroTimeNum());
|
||||||
if (f > 0) {
|
testPunchTime.clear();
|
||||||
sic.FinishPunch.Time = f;
|
testCardNumber = 0;
|
||||||
sic.FinishPunch.Code = 1;
|
|
||||||
sic.punchOnly = true;
|
|
||||||
gSI->addCard(sic);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int s = convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum());
|
if (t > 0) {
|
||||||
if (s > 0) {
|
if (testType == oPunch::PunchStart) {
|
||||||
sic.StartPunch.Time = s;
|
sic.StartPunch.Time = t;
|
||||||
sic.StartPunch.Code = 1;
|
sic.StartPunch.Code = 1;
|
||||||
|
}
|
||||||
|
else if (testType == oPunch::PunchFinish) {
|
||||||
|
sic.FinishPunch.Time = t;
|
||||||
|
sic.FinishPunch.Code = 1;
|
||||||
|
}
|
||||||
|
else if (testType == oPunch::PunchCheck) {
|
||||||
|
sic.CheckPunch.Time = t;
|
||||||
|
sic.CheckPunch.Code = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sic.Punch[sic.nPunch].Code = gdi.getTextNo("ControlNumber");
|
||||||
|
sic.Punch[sic.nPunch].Time = t;
|
||||||
|
sic.nPunch = 1;
|
||||||
|
}
|
||||||
sic.punchOnly = true;
|
sic.punchOnly = true;
|
||||||
|
sic.convertedTime = ConvertedTimeStatus::Hour24;
|
||||||
gSI->addCard(sic);
|
gSI->addCard(sic);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sic.Punch[sic.nPunch].Code = gdi.getTextNo("C1");
|
|
||||||
sic.Punch[sic.nPunch].Time = convertAbsoluteTimeHMS(gdi.getText("C2"), oe->getZeroTimeNum());
|
|
||||||
sic.nPunch = 1;
|
|
||||||
sic.punchOnly = true;
|
|
||||||
gSI->addCard(sic);
|
|
||||||
}
|
}
|
||||||
else if (bi.id == "Cancel") {
|
else if (bi.id == "Cancel") {
|
||||||
int origin = bi.getExtraInt();
|
int origin = bi.getExtraInt();
|
||||||
@ -1411,14 +1438,20 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
updateEntryInfo(gdi);
|
updateEntryInfo(gdi);
|
||||||
}
|
}
|
||||||
else if (bi.id == "ComPort") {
|
else if (bi.id == "ComPort") {
|
||||||
|
bool active = true;
|
||||||
|
if (bi.data == 9999)
|
||||||
|
active = showTestingPanel;
|
||||||
|
else {
|
||||||
wchar_t bf[64];
|
wchar_t bf[64];
|
||||||
|
|
||||||
if (bi.text.substr(0, 3) != L"TCP")
|
if (bi.text.substr(0, 3) != L"TCP")
|
||||||
swprintf_s(bf, 64, L"COM%d", bi.getDataInt());
|
swprintf_s(bf, 64, L"COM%d", bi.getDataInt());
|
||||||
else
|
else
|
||||||
wcscpy_s(bf, L"TCP");
|
wcscpy_s(bf, L"TCP");
|
||||||
|
|
||||||
if (gSI->isPortOpen(bf))
|
active = gSI->isPortOpen(bf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active)
|
||||||
gdi.setText("StartSI", lang.tl("Koppla ifrån"));
|
gdi.setText("StartSI", lang.tl("Koppla ifrån"));
|
||||||
else
|
else
|
||||||
gdi.setText("StartSI", lang.tl("Aktivera"));
|
gdi.setText("StartSI", lang.tl("Aktivera"));
|
||||||
@ -1463,9 +1496,15 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
updateEntryInfo(gdi);
|
updateEntryInfo(gdi);
|
||||||
}
|
}
|
||||||
else if (bi.id == "NC") {
|
else if (bi.id == "NC") {
|
||||||
|
readTestData(gdi);
|
||||||
NC = bi.data;
|
NC = bi.data;
|
||||||
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TSITab, 0);
|
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TSITab, 0);
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "TestType") {
|
||||||
|
readTestData(gdi);
|
||||||
|
testType = bi.data;
|
||||||
|
PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TSITab, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type == GUI_LINK) {
|
else if (type == GUI_LINK) {
|
||||||
TextInfo ti = *(TextInfo*)data;
|
TextInfo ti = *(TextInfo*)data;
|
||||||
@ -1483,6 +1522,13 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
runnerMatchedId = r->getId();
|
runnerMatchedId = r->getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ti.id == "edit") {
|
||||||
|
int rId = ti.getExtraInt();
|
||||||
|
if (oe->getRunner(rId, 0)) {
|
||||||
|
TabRunner& tr = dynamic_cast<TabRunner&>(*gdi.getTabs().get(TRunnerTab));
|
||||||
|
tr.loadPage(gdi, rId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type == GUI_COMBO) {
|
else if (type == GUI_COMBO) {
|
||||||
ListBoxInfo bi = *(ListBoxInfo*)data;
|
ListBoxInfo bi = *(ListBoxInfo*)data;
|
||||||
@ -1672,16 +1718,25 @@ int TabSI::siCB(gdioutput& gdi, int type, void* data)
|
|||||||
}
|
}
|
||||||
else if (ii.id == "SI") {
|
else if (ii.id == "SI") {
|
||||||
pRunner r = oe->getRunnerByCardNo(_wtoi(ii.text.c_str()), 0, oEvent::CardLookupProperty::ForReadout);
|
pRunner r = oe->getRunnerByCardNo(_wtoi(ii.text.c_str()), 0, oEvent::CardLookupProperty::ForReadout);
|
||||||
if (r && r->getStartTime() > 0) {
|
if (testType == 0 && r) {
|
||||||
|
if (r->getStartTime() > 0) {
|
||||||
gdi.setText("Start", r->getStartTimeS());
|
gdi.setText("Start", r->getStartTimeS());
|
||||||
gdi.check("HasStart", false);
|
gdi.check("HasStart", false);
|
||||||
int f = r->getStartTime() + (2800 + rand() % 1200) * timeConstSecond;
|
int f = r->getStartTime() + (2800 + rand() % 1200) * timeConstSecond;
|
||||||
gdi.setText("Finish", oe->getAbsTime(f));
|
gdi.setText("Finish", oe->getAbsTime(f));
|
||||||
|
int c = r->getStartTime() - (120 + rand() % 30) * timeConstSecond;
|
||||||
|
gdi.setText("Check", oe->getAbsTime(c));
|
||||||
|
}
|
||||||
|
|
||||||
pCourse pc = r->getCourse(false);
|
pCourse pc = r->getCourse(false);
|
||||||
if (pc) {
|
if (pc) {
|
||||||
|
if (testControls.size() < pc->getNumControls())
|
||||||
|
testControls.resize(pc->getNumControls());
|
||||||
for (int n = 0; n < pc->getNumControls(); n++) {
|
for (int n = 0; n < pc->getNumControls(); n++) {
|
||||||
if (pc->getControl(n) && n < NC) {
|
if (pc->getControl(n)) {
|
||||||
gdi.setText("C" + itos(n + 1), pc->getControl(n)->getFirstNumber());
|
testControls[n] = pc->getControl(n)->getFirstNumber();
|
||||||
|
if (n < NC)
|
||||||
|
gdi.setText("C" + itos(n + 1), testControls[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1833,7 +1888,11 @@ void TabSI::refillComPorts(gdioutput& gdi)
|
|||||||
gdi.addItem("ComPort", L"TCP [OK]", active);
|
gdi.addItem("ComPort", L"TCP [OK]", active);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gdi.addItem("ComPort", L"TCP");
|
gdi.addItem("ComPort", L"TCP", 0);
|
||||||
|
|
||||||
|
gdi.addItem("ComPort", lang.tl("Testning"), 9999);
|
||||||
|
if (showTestingPanel)
|
||||||
|
active = 9999;
|
||||||
|
|
||||||
if (addTestPort)
|
if (addTestPort)
|
||||||
gdi.addItem("ComPort", L"TEST");
|
gdi.addItem("ComPort", L"TEST");
|
||||||
@ -1909,7 +1968,7 @@ void TabSI::showReadCards(gdioutput& gdi, vector<SICard>& cards)
|
|||||||
if (r != 0)
|
if (r != 0)
|
||||||
gdi.addStringUT(yp, xp + off[1], 0, r->getName(), off[2] - off[1] + margin);
|
gdi.addStringUT(yp, xp + off[1], 0, r->getName(), off[2] - off[1] + margin);
|
||||||
|
|
||||||
gdi.addStringUT(yp, xp + off[2], 0, oe->getAbsTime(cards[k].FinishPunch.Time));
|
gdi.addStringUT(yp, xp + off[2], 0, formatTimeHMS(cards[k].FinishPunch.Time));
|
||||||
yp += gdi.getLineHeight();
|
yp += gdi.getLineHeight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1941,28 +2000,66 @@ bool TabSI::loadPage(gdioutput& gdi) {
|
|||||||
|
|
||||||
firstLoadedAfterNew = false;
|
firstLoadedAfterNew = false;
|
||||||
}
|
}
|
||||||
#ifdef _DEBUG
|
|
||||||
|
if (showTestingPanel) {
|
||||||
|
RECT rc;
|
||||||
|
rc.left = gdi.getCX();
|
||||||
|
rc.top = gdi.getCY();
|
||||||
|
|
||||||
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(4));
|
||||||
|
gdi.setCY(gdi.getCY() + gdi.scaleLength(4));
|
||||||
|
|
||||||
|
gdi.addString("", fontMediumPlus, "Inmatning Testning");
|
||||||
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.addInput("SI", L"", 10, SportIdentCB, L"SI");
|
|
||||||
|
gdi.addSelection("TestType", 100, 100, SportIdentCB, L"Typ:");
|
||||||
|
gdi.addItem("TestType", lang.tl("Avläsning"), 0);
|
||||||
|
gdi.addItem("TestType", lang.tl("Mål"), 2);
|
||||||
|
gdi.addItem("TestType", lang.tl("Start"), 1);
|
||||||
|
gdi.addItem("TestType", lang.tl("Check"), 3);
|
||||||
|
gdi.addItem("TestType", lang.tl("Radio"), 10);
|
||||||
|
|
||||||
|
gdi.selectItemByData("TestType", testType);
|
||||||
|
|
||||||
|
gdi.addInput("SI", testCardNumber > 0 ? itow(testCardNumber) : L"", 10, SportIdentCB, L"Bricknummer:");
|
||||||
|
|
||||||
|
if (testType == 0) {
|
||||||
int s = timeConstHour + (rand() % 60) * timeConstMinute;
|
int s = timeConstHour + (rand() % 60) * timeConstMinute;
|
||||||
int f = s + timeConstHour / 2 + ((rand() % 3600) / 3) * timeConstSecond;
|
int f = s + timeConstHour / 2 + ((rand() % 3600) / 3) * timeConstSecond;
|
||||||
|
wstring ss = oe->getAbsTime(s);
|
||||||
|
wstring fs = oe->getAbsTime(f);
|
||||||
|
wstring cs = oe->getAbsTime(s - (60 + rand() % 60) * timeConstSecond);
|
||||||
|
|
||||||
|
if (!testStartTime.empty())
|
||||||
|
ss = testStartTime;
|
||||||
|
if (!testFinishTime.empty())
|
||||||
|
fs = testFinishTime;
|
||||||
|
if (!testCheckTime.empty())
|
||||||
|
cs = testCheckTime;
|
||||||
|
|
||||||
gdi.setCX(gdi.getCX() + gdi.getLineHeight());
|
gdi.setCX(gdi.getCX() + gdi.getLineHeight());
|
||||||
|
|
||||||
gdi.dropLine(1.4);
|
gdi.dropLine(1.6);
|
||||||
gdi.addCheckbox("HasStart", "");
|
gdi.addCheckbox("HasCheck", "", nullptr, useTestCheck);
|
||||||
gdi.dropLine(-1.4);
|
gdi.dropLine(-1.6);
|
||||||
gdi.setCX(gdi.getCX() - gdi.getLineHeight());
|
gdi.setCX(gdi.getCX() - gdi.getLineHeight());
|
||||||
gdi.addInput("Start", oe->getAbsTime(s), 6, 0, L"Start");
|
gdi.addInput("Check", cs, 6, 0, L"Check:");
|
||||||
|
|
||||||
gdi.dropLine(1.4);
|
gdi.dropLine(1.6);
|
||||||
gdi.addCheckbox("HasFinish", "");
|
gdi.addCheckbox("HasStart", "", nullptr, useTestStart);
|
||||||
gdi.dropLine(-1.4);
|
gdi.dropLine(-1.6);
|
||||||
|
gdi.setCX(gdi.getCX() - gdi.getLineHeight());
|
||||||
|
gdi.addInput("Start", ss, 6, 0, L"Start:");
|
||||||
|
|
||||||
|
gdi.dropLine(1.6);
|
||||||
|
gdi.addCheckbox("HasFinish", "", nullptr, useTestFinish);
|
||||||
|
gdi.dropLine(-1.6);
|
||||||
gdi.setCX(gdi.getCX() - gdi.getLineHeight());
|
gdi.setCX(gdi.getCX() - gdi.getLineHeight());
|
||||||
|
|
||||||
gdi.addInput("Finish", oe->getAbsTime(f), 6, 0, L"Mål");
|
gdi.addInput("Finish", fs, 6, 0, L"Mål:");
|
||||||
gdi.addSelection("NC", 45, 200, SportIdentCB, L"NC");
|
gdi.addSelection("NC", 45, 200, SportIdentCB, L"Stämplingar:");
|
||||||
const int src[11] = { 33, 34, 45, 50, 36, 38, 59, 61, 62, 67, 100 };
|
const int src[11] = { 33, 34, 45, 50, 36, 38, 59, 61, 62, 67, 100 };
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
@ -1984,16 +2081,41 @@ bool TabSI::loadPage(gdioutput& gdi) {
|
|||||||
c = src[ix] + level * 10;
|
c = src[ix] + level * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i < testControls.size())
|
||||||
|
c = testControls[i];
|
||||||
|
|
||||||
gdi.addInput("C" + itos(i + 1), itow(c), 3, 0, L"#C" + itow(i + 1));
|
gdi.addInput("C" + itos(i + 1), itow(c), 3, 0, L"#C" + itow(i + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.addButton("Save", "Bricka", SportIdentCB);
|
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
|
gdi.addButton("Save", "Spara", SportIdentCB);
|
||||||
gdi.addButton("SaveP", "Stämpling", SportIdentCB);
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
#endif
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int p = timeConstHour + (rand() % 60) * timeConstMinute;
|
||||||
|
wstring ps = oe->getAbsTime(p);
|
||||||
|
|
||||||
|
if (!testPunchTime.empty())
|
||||||
|
ps = testPunchTime;
|
||||||
|
|
||||||
|
if (testType == 10)
|
||||||
|
gdi.addInput("ControlNumber", itow(testRadioNumber), 6, 0, L"Kontroll:");
|
||||||
|
|
||||||
|
gdi.addInput("PunchTime", ps, 6, 0, L"Tid:");
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.fillDown();
|
||||||
|
gdi.addButton("SaveP", "Spara", SportIdentCB);
|
||||||
|
gdi.popX();
|
||||||
|
}
|
||||||
|
rc.right = gdi.getWidth();
|
||||||
|
rc.bottom = gdi.getCY();
|
||||||
|
gdi.addRectangle(rc, GDICOLOR::colorLightMagenta);
|
||||||
|
gdi.dropLine();
|
||||||
|
}
|
||||||
|
|
||||||
gdi.addString("", boldLarge, "SportIdent");
|
gdi.addString("", boldLarge, "SportIdent");
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
|
|
||||||
@ -2944,6 +3066,7 @@ bool TabSI::processCard(gdioutput& gdi, pRunner runner, const SICard& csic, bool
|
|||||||
runner->setStatus(StatusOK, true, oBase::ChangeType::Update, false);
|
runner->setStatus(StatusOK, true, oBase::ChangeType::Update, false);
|
||||||
SICard sic(csic);
|
SICard sic(csic);
|
||||||
StoredReadout rout;
|
StoredReadout rout;
|
||||||
|
rout.runnerId = runner->getId();
|
||||||
|
|
||||||
if (!csic.isManualInput()) {
|
if (!csic.isManualInput()) {
|
||||||
pCard card = gEvent->allocateCard(runner);
|
pCard card = gEvent->allocateCard(runner);
|
||||||
@ -3125,6 +3248,12 @@ RECT TabSI::StoredReadout::computeRC(gdioutput& gdi) const {
|
|||||||
void TabSI::StoredReadout::render(gdioutput& gdi, const RECT& rc) const {
|
void TabSI::StoredReadout::render(gdioutput& gdi, const RECT& rc) const {
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addRectangle(rc, color, true);
|
gdi.addRectangle(rc, color, true);
|
||||||
|
|
||||||
|
//gdi.addString("edit", rc.right - gdi.scaleLength(30), rc.top+gdi.scaleLength(4), textImage, "S" + itos(gdi.scaleLength(24)));
|
||||||
|
if (runnerId > 0) {
|
||||||
|
gdi.addImage("edit", rc.top + gdi.scaleLength(4), rc.right - gdi.scaleLength(30), 0,
|
||||||
|
itow(IDI_MEOSEDIT), gdi.scaleLength(24), gdi.scaleLength(24), SportIdentCB).setExtra(runnerId);
|
||||||
|
}
|
||||||
int lh = gdi.getLineHeight();
|
int lh = gdi.getLineHeight();
|
||||||
int marg = gdi.scaleLength(20);
|
int marg = gdi.scaleLength(20);
|
||||||
int tmarg = gdi.scaleLength(6);
|
int tmarg = gdi.scaleLength(6);
|
||||||
@ -3215,6 +3344,8 @@ wstring TabSI::getTimeAfterString(const oRunner* runner) {
|
|||||||
|
|
||||||
void TabSI::processPunchOnly(gdioutput& gdi, const SICard& csic)
|
void TabSI::processPunchOnly(gdioutput& gdi, const SICard& csic)
|
||||||
{
|
{
|
||||||
|
gdi.makeEvent("PunchCard", "sireadout", csic.CardNumber, 0, true);
|
||||||
|
|
||||||
SICard sic = csic;
|
SICard sic = csic;
|
||||||
DWORD loaded;
|
DWORD loaded;
|
||||||
gEvent->convertTimes(nullptr, sic);
|
gEvent->convertTimes(nullptr, sic);
|
||||||
@ -3707,19 +3838,10 @@ void TabSI::tieCard(gdioutput& gdi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TabSI::showAssignCard(gdioutput& gdi, bool showHelp) {
|
void TabSI::showAssignCard(gdioutput& gdi, bool showHelp) {
|
||||||
//gdi.fillDown();
|
|
||||||
//gdi.setRestorePoint("AssignCardBase");
|
|
||||||
if (interactiveReadout) {
|
if (interactiveReadout) {
|
||||||
if (showHelp) {
|
if (showHelp) {
|
||||||
checkBoxToolBar(gdi, { CheckBox::Interactive, CheckBox::AutoTie, CheckBox::AutoTieRent });
|
checkBoxToolBar(gdi, { CheckBox::Interactive, CheckBox::AutoTie, CheckBox::AutoTieRent });
|
||||||
gdi.addString("", 10, L"Avmarkera 'X' för att hantera alla bricktildelningar samtidigt.#" + lang.tl("Interaktiv inläsning"));
|
gdi.addString("", 10, L"Avmarkera 'X' för att hantera alla bricktildelningar samtidigt.#" + lang.tl("Interaktiv inläsning"));
|
||||||
/*gdi.dropLine(0.5);
|
|
||||||
gdi.addCheckbox("AutoTie", "Knyt automatiskt efter inläsning", SportIdentCB, oe->getPropertyInt("AutoTie", 1) != 0);
|
|
||||||
gdi.addCheckbox("AutoTieRent", "Automatisk hyrbrickshantering genom registrerade hyrbrickor", SportIdentCB, oe->getPropertyInt("AutoTieRent", 1) != 0);
|
|
||||||
if (!oe->hasHiredCardData()) {
|
|
||||||
gdi.disableInput("AutoTieRent");
|
|
||||||
gdi.check("AutoTieRent", false);
|
|
||||||
}*/
|
|
||||||
gdi.dropLine(0.5);
|
gdi.dropLine(0.5);
|
||||||
gdi.setRestorePoint("ManualTie");
|
gdi.setRestorePoint("ManualTie");
|
||||||
}
|
}
|
||||||
@ -3730,8 +3852,7 @@ void TabSI::showAssignCard(gdioutput& gdi, bool showHelp) {
|
|||||||
gdi.addString("", 10, L"Markera 'X' för att hantera deltagarna en och en.#" + lang.tl("Interaktiv inläsning"));
|
gdi.addString("", 10, L"Markera 'X' för att hantera deltagarna en och en.#" + lang.tl("Interaktiv inläsning"));
|
||||||
}
|
}
|
||||||
|
|
||||||
gEvent->assignCardInteractive(gdi, SportIdentCB);
|
gEvent->assignCardInteractive(gdi, SportIdentCB, sortAssignCards);
|
||||||
gdi.refresh();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4291,6 +4412,8 @@ void TabSI::clearCompetitionData() {
|
|||||||
|
|
||||||
logger.reset();
|
logger.reset();
|
||||||
numSavedCardsOnCmpOpen = savedCards.size();
|
numSavedCardsOnCmpOpen = savedCards.size();
|
||||||
|
|
||||||
|
sortAssignCards = SortOrder::Custom;
|
||||||
}
|
}
|
||||||
|
|
||||||
SICard& TabSI::getCard(int id) const {
|
SICard& TabSI::getCard(int id) const {
|
||||||
@ -5088,7 +5211,7 @@ void TabSI::showReadoutStatus(gdioutput& gdi, const oRunner* r,
|
|||||||
|
|
||||||
if (rentalCard) {
|
if (rentalCard) {
|
||||||
gdi.addRectangle(rc, colorYellow);
|
gdi.addRectangle(rc, colorYellow);
|
||||||
gdi.addStringUT(rc.top + (rc.bottom - rc.top) / 3, mrg, boldHuge | textCenter,
|
gdi.addString("", rc.top + (rc.bottom - rc.top) / 3, mrg, boldHuge | textCenter,
|
||||||
"Vänligen återlämna hyrbrickan.", w - 3 * mrg);
|
"Vänligen återlämna hyrbrickan.", w - 3 * mrg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5168,3 +5291,26 @@ void TabSI::fillMappings(gdioutput& gdi) const {
|
|||||||
gdi.addItem("Mappings", itow(mp.first) + L" \u21A6 " + oPunch::getType(mp.second), mp.first);
|
gdi.addItem("Mappings", itow(mp.first) + L" \u21A6 " + oPunch::getType(mp.second), mp.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabSI::readTestData(gdioutput& gdi) {
|
||||||
|
testCardNumber = gdi.getTextNo("SI");
|
||||||
|
if (gdi.hasWidget("PunchTime")) {
|
||||||
|
testPunchTime = gdi.getText("PunchTime");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
useTestCheck = gdi.isChecked("HasCheck");
|
||||||
|
useTestStart = gdi.isChecked("HasStart");
|
||||||
|
useTestFinish = gdi.isChecked("HasFinish");
|
||||||
|
|
||||||
|
testStartTime = gdi.getText("Start");
|
||||||
|
testFinishTime = gdi.getText("Finish");
|
||||||
|
testCheckTime = gdi.getText("Check");
|
||||||
|
|
||||||
|
if (NC > testControls.size())
|
||||||
|
testControls.resize(NC);
|
||||||
|
|
||||||
|
for (int i = 0; i < NC; i++)
|
||||||
|
testControls[i] = gdi.getTextNo("C" + itos(i+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
26
code/TabSI.h
26
code/TabSI.h
@ -94,6 +94,8 @@ private:
|
|||||||
shared_ptr<GuiHandler> resetHiredCardHandler;
|
shared_ptr<GuiHandler> resetHiredCardHandler;
|
||||||
GuiHandler *getResetHiredCardHandler();
|
GuiHandler *getResetHiredCardHandler();
|
||||||
|
|
||||||
|
SortOrder sortAssignCards = SortOrder::Custom;
|
||||||
|
|
||||||
int runnerMatchedId;
|
int runnerMatchedId;
|
||||||
bool printErrorShown;
|
bool printErrorShown;
|
||||||
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
|
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
|
||||||
@ -185,17 +187,32 @@ private:
|
|||||||
|
|
||||||
static int analyzePunch(SIPunch &p, int &start, int &accTime, int &days);
|
static int analyzePunch(SIPunch &p, int &start, int &accTime, int &days);
|
||||||
|
|
||||||
|
|
||||||
void createCompetitionFromCards(gdioutput &gdi);
|
void createCompetitionFromCards(gdioutput &gdi);
|
||||||
|
|
||||||
int NC;
|
int NC = 8;
|
||||||
|
int testType = 0;
|
||||||
|
bool showTestingPanel = false;
|
||||||
|
wstring testStartTime;
|
||||||
|
bool useTestStart = true;
|
||||||
|
wstring testFinishTime;
|
||||||
|
bool useTestFinish = true;
|
||||||
|
wstring testCheckTime;
|
||||||
|
bool useTestCheck = false;
|
||||||
|
int testRadioNumber = 50;
|
||||||
|
wstring testPunchTime;
|
||||||
|
vector<int> testControls;
|
||||||
|
int testCardNumber = 0;
|
||||||
|
|
||||||
|
void readTestData(gdioutput& gdi);
|
||||||
|
|
||||||
|
|
||||||
class EditCardData : public GuiHandler {
|
class EditCardData : public GuiHandler {
|
||||||
TabSI *tabSI;
|
TabSI *tabSI;
|
||||||
EditCardData(const EditCardData&);
|
|
||||||
EditCardData &operator=(const EditCardData&);
|
|
||||||
public:
|
public:
|
||||||
EditCardData() : tabSI(0) {}
|
EditCardData() : tabSI(0) {}
|
||||||
|
EditCardData(const EditCardData&) = delete;
|
||||||
|
EditCardData& operator=(const EditCardData&) = delete;
|
||||||
|
|
||||||
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);
|
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);
|
||||||
friend class TabSI;
|
friend class TabSI;
|
||||||
};
|
};
|
||||||
@ -252,6 +269,7 @@ private:
|
|||||||
vector<int> MP;
|
vector<int> MP;
|
||||||
GDICOLOR color;
|
GDICOLOR color;
|
||||||
bool rentCard = false;
|
bool rentCard = false;
|
||||||
|
int runnerId = 0;
|
||||||
|
|
||||||
RECT computeRC(gdioutput &gdi) const;
|
RECT computeRC(gdioutput &gdi) const;
|
||||||
void render(gdioutput &gdi, const RECT &rc) const;
|
void render(gdioutput &gdi, const RECT &rc) const;
|
||||||
|
|||||||
@ -241,11 +241,11 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
|||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.registerEvent("DataUpdate", tabSpeakerCB);
|
gdi.registerEvent("DataUpdate", tabSpeakerCB);
|
||||||
vector<pair<int, bool>> runnersToReport;
|
deque<pair<int, bool>> runnersToReport;
|
||||||
if (runnerId > 0) {
|
if (runnerId > 0) {
|
||||||
runnersToReport.emplace_back(runnerId, false);
|
runnersToReport.emplace_back(runnerId, false);
|
||||||
}
|
}
|
||||||
TabRunner::generateRunnerReport(*oe, gdi, runnersToReport);
|
TabRunner::generateRunnerReport(*oe, gdi, 1, 1, false, runnersToReport);
|
||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
else if (bu.id == "Priority") {
|
else if (bu.id == "Priority") {
|
||||||
|
|||||||
@ -274,7 +274,7 @@ void Table::filter(int col, const wstring &filt, bool forceFilter)
|
|||||||
|
|
||||||
wchar_t filt_lc[1024];
|
wchar_t filt_lc[1024];
|
||||||
wcscpy_s(filt_lc, filt.c_str());
|
wcscpy_s(filt_lc, filt.c_str());
|
||||||
CharLowerBuff(filt_lc, filt.length());
|
prepareMatchString(filt_lc, filt.length());
|
||||||
|
|
||||||
sortIndex.resize(2);
|
sortIndex.resize(2);
|
||||||
for (size_t k=2;k<baseIndex.size();k++) {
|
for (size_t k=2;k<baseIndex.size();k++) {
|
||||||
|
|||||||
BIN
code/edit.png
Normal file
BIN
code/edit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 677 B |
@ -256,7 +256,7 @@ Checkenhet = Check unit
|
|||||||
Choose result module = Choose result module
|
Choose result module = Choose result module
|
||||||
ClassAvailableMaps = Available maps for class
|
ClassAvailableMaps = Available maps for class
|
||||||
ClassCourseResult = Class, course, result
|
ClassCourseResult = Class, course, result
|
||||||
ClassDefaultResult = Class, Default result
|
ClassDefaultResult = Class, default result
|
||||||
ClassFinishTime = Class, finish time
|
ClassFinishTime = Class, finish time
|
||||||
ClassKnockoutTotalResult = Class, knock-out total result
|
ClassKnockoutTotalResult = Class, knock-out total result
|
||||||
ClassLength = Course length for class
|
ClassLength = Course length for class
|
||||||
@ -2674,3 +2674,8 @@ Bevara höjd/bredd-relationen = Preserve aspect ratio
|
|||||||
RunnerLegTeamLeaderName = First competitor in team to finish leg
|
RunnerLegTeamLeaderName = First competitor in team to finish leg
|
||||||
info:offsetclassid = If you import entries and classes from different sources to the same competition, it might happen that there are clashes in the Id numbers of the classes. To separate the classes, you may enter an offset for the Class Id when working with files from a particular source; this will be added to the Id numbers.\n\nYou must specify the same offset each time you import from that source.\n\n A suitble number could be1000 (which will work as long as every Id is less that 1000).
|
info:offsetclassid = If you import entries and classes from different sources to the same competition, it might happen that there are clashes in the Id numbers of the classes. To separate the classes, you may enter an offset for the Class Id when working with files from a particular source; this will be added to the Id numbers.\n\nYou must specify the same offset each time you import from that source.\n\n A suitble number could be1000 (which will work as long as every Id is less that 1000).
|
||||||
Förskjutning av klassers Id = Offset Class ID
|
Förskjutning av klassers Id = Offset Class ID
|
||||||
|
Tilldela nummerlapp till vakanter = Assign bibs to vacancies
|
||||||
|
Avläsning = Readout
|
||||||
|
Inmatning Testning = Input Testing
|
||||||
|
Testning = Testing
|
||||||
|
CourseNumControls = Number of controls
|
||||||
|
|||||||
@ -214,7 +214,9 @@ Bevakar händelser i X = Moniteur d'évènement X
|
|||||||
Bevakningsprioritering = Sélectionner le coureur à surveiller
|
Bevakningsprioritering = Sélectionner le coureur à surveiller
|
||||||
Bevara höjd/bredd-relationen = Conserver les proportions
|
Bevara höjd/bredd-relationen = Conserver les proportions
|
||||||
Bibs = Dossards
|
Bibs = Dossards
|
||||||
|
Bild = Image
|
||||||
Bild under text = Mettre l'image sous le texte
|
Bild under text = Mettre l'image sous le texte
|
||||||
|
Bilder = Images
|
||||||
Block = Bloc
|
Block = Bloc
|
||||||
Blockbredd = Largeur de bloc
|
Blockbredd = Largeur de bloc
|
||||||
Bläddra = Parcourir
|
Bläddra = Parcourir
|
||||||
@ -265,7 +267,7 @@ ClassKnockoutTotalResult = Class, knock-out total result
|
|||||||
ClassLength = Longueur du circuit pour la catégorie
|
ClassLength = Longueur du circuit pour la catégorie
|
||||||
ClassLiveResult = Live results (temps radios), par catégorie
|
ClassLiveResult = Live results (temps radios), par catégorie
|
||||||
ClassName = Catégorie
|
ClassName = Catégorie
|
||||||
ClassNumEntries = Nombre d'inscrits
|
ClassNumEntries = Nombre d'inscrits dans la catégorie
|
||||||
ClassPoints = Catégorie, points
|
ClassPoints = Catégorie, points
|
||||||
ClassResult = Catégorie, résultat
|
ClassResult = Catégorie, résultat
|
||||||
ClassResultFraction = Pourcentage de la catégorie ayant terminé
|
ClassResultFraction = Pourcentage de la catégorie ayant terminé
|
||||||
@ -422,6 +424,7 @@ Elektronisk godkänd = Accepté électroniquement
|
|||||||
Elit = Élite
|
Elit = Élite
|
||||||
Elitavgift = Frais élites
|
Elitavgift = Frais élites
|
||||||
Elitklasser = Catégorie élite
|
Elitklasser = Catégorie élite
|
||||||
|
Empty Results Split Print = Temps intermédiaires sans résultats
|
||||||
En bana med slingor tillåter deltagaren att ta slingorna i valfri ordning = Un circuit avec des boucles autorise le coureur à effectuer les boucles dans n'importe quel ordre.
|
En bana med slingor tillåter deltagaren att ta slingorna i valfri ordning = Un circuit avec des boucles autorise le coureur à effectuer les boucles dans n'importe quel ordre.
|
||||||
En gafflad sträcka = Circuit avec variations
|
En gafflad sträcka = Circuit avec variations
|
||||||
En klass kan inte slås ihop med sig själv = Vous ne pouvez pas fusionner une catégorie avec elle-même
|
En klass kan inte slås ihop med sig själv = Vous ne pouvez pas fusionner une catégorie avec elle-même
|
||||||
@ -621,6 +624,7 @@ Förhindra att laget deltar i någon omstart = Permet à l'équipe de ne pas pre
|
|||||||
Förhindra omstart = Refuser le départ des attardés
|
Förhindra omstart = Refuser le départ des attardés
|
||||||
Förhöjd avgift = Frais supplémentaires
|
Förhöjd avgift = Frais supplémentaires
|
||||||
Förskjutning = Déplacement
|
Förskjutning = Déplacement
|
||||||
|
Förskjutning av klassers Id = Décalage de l'identifiant de catégorie
|
||||||
Först = En premier
|
Först = En premier
|
||||||
Först-i-mål, gemensam = Du premier au dernier, commun
|
Först-i-mål, gemensam = Du premier au dernier, commun
|
||||||
Först-i-mål, klassvis = Du premier au dernier, par catégorie
|
Först-i-mål, klassvis = Du premier au dernier, par catégorie
|
||||||
@ -685,6 +689,7 @@ Hittar inte hjälpfilen, X = Documentation introuvable, X
|
|||||||
Hittar inte klass X = Impossible de trouver la catégorie X
|
Hittar inte klass X = Impossible de trouver la catégorie X
|
||||||
Hjälp = Aide
|
Hjälp = Aide
|
||||||
Hoppar över stafettklass: X = Sauter la catégorie de relais: X
|
Hoppar över stafettklass: X = Sauter la catégorie de relais: X
|
||||||
|
Horisontell = Horizontal
|
||||||
Horizontell = Horizontalement
|
Horizontell = Horizontalement
|
||||||
Huvudlista = Liste principale
|
Huvudlista = Liste principale
|
||||||
Hyravgift = Tarif de location
|
Hyravgift = Tarif de location
|
||||||
@ -763,6 +768,8 @@ Inconsistent qualification rule, X = Règle de qualification incohérente, X
|
|||||||
Index = Index
|
Index = Index
|
||||||
Index in X[index] = Index en X[index]
|
Index in X[index] = Index en X[index]
|
||||||
Individual Example = Exemple de course individuelle
|
Individual Example = Exemple de course individuelle
|
||||||
|
Individual Results Split Print = Avec résultats individuels
|
||||||
|
Individual Rogaining Split Print = Avec résultats de la course au score
|
||||||
Individual result by finish time = Résultat individuel sur l'heure d'arrivée
|
Individual result by finish time = Résultat individuel sur l'heure d'arrivée
|
||||||
Individual results in a club = Résultats individuel au sein du club
|
Individual results in a club = Résultats individuel au sein du club
|
||||||
Individuell = par catégorie
|
Individuell = par catégorie
|
||||||
@ -1009,6 +1016,7 @@ Liveresultat, radiotider = Résultats en direct avec radios
|
|||||||
Ljud = Son
|
Ljud = Son
|
||||||
Ljudfiler, baskatalog = Répertoire de base des fichiers sonores
|
Ljudfiler, baskatalog = Répertoire de base des fichiers sonores
|
||||||
Ljudval = Sélection des sons
|
Ljudval = Sélection des sons
|
||||||
|
Lokal kopia från X = Copie locale de X
|
||||||
Lokalt = Localement
|
Lokalt = Localement
|
||||||
Long = Longue
|
Long = Longue
|
||||||
Longitud = Longitude
|
Longitud = Longitude
|
||||||
@ -1402,6 +1410,8 @@ Relation till föregående = Lien avec le précédent
|
|||||||
Relativ skalfaktor för typsnittets storlek i procent = Facteur d'échelle pour la police (pourcentage)
|
Relativ skalfaktor för typsnittets storlek i procent = Facteur d'échelle pour la police (pourcentage)
|
||||||
Relay Example = Exemple de relais
|
Relay Example = Exemple de relais
|
||||||
Relay Example (Lokal kopia från: localhost) = Exemple de relais (Copie locale depuis : localhost)
|
Relay Example (Lokal kopia från: localhost) = Exemple de relais (Copie locale depuis : localhost)
|
||||||
|
Relay Results Split Print = Avec résultats du relais
|
||||||
|
Relay/Team Results Split Print = Avec résultats du relais/de l'équipe
|
||||||
Relays = Relais
|
Relays = Relais
|
||||||
Rep = Arrêt attardés
|
Rep = Arrêt attardés
|
||||||
Reparera vald tävling = Réparer la compétition sélectionnée
|
Reparera vald tävling = Réparer la compétition sélectionnée
|
||||||
@ -1526,6 +1536,7 @@ RunnerId = Licence/ID
|
|||||||
RunnerLeg = Concurrent (variation spécifique)
|
RunnerLeg = Concurrent (variation spécifique)
|
||||||
RunnerLegNumber = Numéro de relais groupé du coureur
|
RunnerLegNumber = Numéro de relais groupé du coureur
|
||||||
RunnerLegNumberAlpha = Numéro de relais exact du coureur
|
RunnerLegNumberAlpha = Numéro de relais exact du coureur
|
||||||
|
RunnerLegTeamLeaderName = Premier membre de l'équipe à terminer son circuit
|
||||||
RunnerName = Nom du coureur
|
RunnerName = Nom du coureur
|
||||||
RunnerNationality = Nationalité du coureur
|
RunnerNationality = Nationalité du coureur
|
||||||
RunnerPaid = Payé
|
RunnerPaid = Payé
|
||||||
@ -1888,6 +1899,7 @@ Tabelläge = Mode table
|
|||||||
Tar bort X = Retrait de X
|
Tar bort X = Retrait de X
|
||||||
Team = Équipe
|
Team = Équipe
|
||||||
Team Rogaining = Course au score en équipe
|
Team Rogaining = Course au score en équipe
|
||||||
|
Team Rogaining Split Print = Avec résultats de la course au score en équipe
|
||||||
TeamBib = Dossard de l'équipe
|
TeamBib = Dossard de l'équipe
|
||||||
TeamClub = Club de l'équipe
|
TeamClub = Club de l'équipe
|
||||||
TeamCourseName = Nom du circuit pour l'équipe/la branche
|
TeamCourseName = Nom du circuit pour l'équipe/la branche
|
||||||
@ -2217,6 +2229,7 @@ Välj alla klasser = Sélectionner toutes les catégories
|
|||||||
Välj allt = Sélectionner tout
|
Välj allt = Sélectionner tout
|
||||||
Välj automatiskt = Sélection automatique
|
Välj automatiskt = Sélection automatique
|
||||||
Välj bild = Choisir une image
|
Välj bild = Choisir une image
|
||||||
|
Välj bland befintliga bilder = Sélectionner une image existante
|
||||||
Välj deltagare för förhandsgranskning = Sélectionner un coureur pour prévisualisation
|
Välj deltagare för förhandsgranskning = Sélectionner un coureur pour prévisualisation
|
||||||
Välj den etapp som föregår denna tävling = Sélectionner l'étape précédente
|
Välj den etapp som föregår denna tävling = Sélectionner l'étape précédente
|
||||||
Välj den etapp som kommer efter denna tävling = Sélectionner l'étape suivante
|
Välj den etapp som kommer efter denna tävling = Sélectionner l'étape suivante
|
||||||
@ -2428,11 +2441,12 @@ info:mapcontrol = MeOS ne sait pas déterminer la fonction d'un boîtier s'il n'
|
|||||||
info:multieventnetwork = Pour prendre en charge plus d'une étape vous devez travailler localement. Faite une copie de sauvegarde de la compétition, ouvrez-la en local et transférez les résultats à l'étape suivante. Enfin, remontez l'étape suivante sur le serveur.
|
info:multieventnetwork = Pour prendre en charge plus d'une étape vous devez travailler localement. Faite une copie de sauvegarde de la compétition, ouvrez-la en local et transférez les résultats à l'étape suivante. Enfin, remontez l'étape suivante sur le serveur.
|
||||||
info:multiple_start = Un coureur peut faire plusieurs fois le même circuit. Une nouvelle inscription est créée à chaque lecture de la puce
|
info:multiple_start = Un coureur peut faire plusieurs fois le même circuit. Une nouvelle inscription est créée à chaque lecture de la puce
|
||||||
info:nosplitprint = Chargement de la liste personnalisée impossible\n\nCelle par défaut la remplace
|
info:nosplitprint = Chargement de la liste personnalisée impossible\n\nCelle par défaut la remplace
|
||||||
|
info:offsetclassid = Si vous importez des inscrits et des catégories depuis des sources différentes dans la même compétition, il peut y avoir des conflits entre les numéros d'identifiant des catégories. Pour différencier les catégories, vous pouvez entrer un décalage de la valeur de l'identifiant des catégorires pour chacune des sources. Celui-ci sera ajouté à l'identifiant existant.\n\nVous pouvez par exemple entrer 1000 (si aucune catégorie n'a déjà un identifiant supérieur à 1000).
|
||||||
info:pageswithcolumns = Montrer la liste page par page, avec un nombre spécifié de colonnes. Les infos sont mises à jour à chaque bouclage.
|
info:pageswithcolumns = Montrer la liste page par page, avec un nombre spécifié de colonnes. Les infos sont mises à jour à chaque bouclage.
|
||||||
info:readout_action = X: Puce no. Y lue.\nDes actions manuelles sont requises.
|
info:readout_action = X: Puce no. Y lue.\nDes actions manuelles sont requises.
|
||||||
info:readout_queue = X: Puce no. Y lue.\nLa puce a été mise en file d'attente.
|
info:readout_queue = X: Puce no. Y lue.\nLa puce a été mise en file d'attente.
|
||||||
info:readoutbase = Activez le boîtier SI en sélectionnant son port COM ou en recherchant les boîtiers SI installés. Appuyez sur Information pour obtenir le statut du port sélectionné.\n\nLecture Interactive vous permet de gérer directement les problèmes tels qu'un numéro de puce erroné. N'utilisez pas cette possibilité quand les coureurs ayant des problèmes sont pris en charge séparément.\n\nLa base de données des coureurs est utilisée si vous voulez ajouter automatiquement de nouveaux coureurs. Les poinçons sont utilisés pour trouver (détecter) la bonne catégorie.
|
info:readoutbase = Activez le boîtier SI en sélectionnant son port COM ou en recherchant les boîtiers SI installés. Appuyez sur Information pour obtenir le statut du port sélectionné.\n\nLecture Interactive vous permet de gérer directement les problèmes tels qu'un numéro de puce erroné. N'utilisez pas cette possibilité quand les coureurs ayant des problèmes sont pris en charge séparément.\n\nLa base de données des coureurs est utilisée si vous voulez ajouter automatiquement de nouveaux coureurs. Les poinçons sont utilisés pour trouver (détecter) la bonne catégorie.
|
||||||
info:readoutmore = Verrouillez la fonction pour éviter toute modification accidentelle.\n\nSélection des sons vous permet de lancer différents sons lors de la lecture des puces pour être plus facilement informé des problèmes.\n\n"Fenêtre de prévisualisation coureur" affiche une nouvelle fenêtre destinée au coureur qui lit sa puce, regroupant les informations principales de sa course.\n\nPlusieurs courses pour un coureur est utile si un coureur est autorisé a faire plusieurs fois son circuit. Une nouvelle inscriprion est créée à chaque lecture de la puce.
|
info:readoutmore = Verrouillez la fonction pour éviter toute modification accidentelle.\n\nSélection des sons vous permet de lancer différents sons lors de la lecture des puces pour être plus facilement informé des problèmes.\n\n"Fenêtre de prévisualisation coureur" affiche une nouvelle fenêtre destinée au coureur qui lit sa puce, regroupant les informations principales de sa course.\n\nPlusieurs courses pour un coureur est utile si un coureur est autorisé a faire plusieurs fois son circuit. Une nouvelle inscription est créée à chaque lecture de la puce.
|
||||||
info:readoutwindow = Cette fenêtre affiche les informations principales de chaque lecture de puce
|
info:readoutwindow = Cette fenêtre affiche les informations principales de chaque lecture de puce
|
||||||
info:runnerdbonline = Comme vous êtes connecté à un serveur, il n'est pas possible d'éditer les bases de données club et coureurs manuellement. Effectuez les changements avant d'uploader la compétition sur un serveur. Il est également possible de remplacer la base de données existante sur le serveur en important une nouvelle base (à partir de IOF XML).
|
info:runnerdbonline = Comme vous êtes connecté à un serveur, il n'est pas possible d'éditer les bases de données club et coureurs manuellement. Effectuez les changements avant d'uploader la compétition sur un serveur. Il est également possible de remplacer la base de données existante sur le serveur en important une nouvelle base (à partir de IOF XML).
|
||||||
info:teamcourseassignment = Le fichier des circuits IOF XML 3.0 contient les variations des équipes. Pour importer ces données, vous devez préparer la compétition en fonction des données du fichier :\n\n1.Assurez-vous que les catégories de relais ont le bon nombre de branches.\n2. Affectez les dossards à chaque catégorie. Passez par la Configuration Rapide dans l'onglet Catégories et renseignez le premier dossard de chaque catégorie (avec la répartition automatique des dossards). Vous pouvez aussi importer les équipes et leur attribuer des dossards comme d'habitude.\n\n\n3. Importez les circuits. Vous pouvez importer plusieurs fois ce fichier si nécessaire pour mettre à jour les variations.
|
info:teamcourseassignment = Le fichier des circuits IOF XML 3.0 contient les variations des équipes. Pour importer ces données, vous devez préparer la compétition en fonction des données du fichier :\n\n1.Assurez-vous que les catégories de relais ont le bon nombre de branches.\n2. Affectez les dossards à chaque catégorie. Passez par la Configuration Rapide dans l'onglet Catégories et renseignez le premier dossard de chaque catégorie (avec la répartition automatique des dossards). Vous pouvez aussi importer les équipes et leur attribuer des dossards comme d'habitude.\n\n\n3. Importez les circuits. Vous pouvez importer plusieurs fois ce fichier si nécessaire pour mettre à jour les variations.
|
||||||
|
|||||||
@ -888,6 +888,7 @@ TextInfo& gdioutput::addImage(const string& id, int yp, int xp, int format,
|
|||||||
|
|
||||||
imageReferences.push_back(&TI);
|
imageReferences.push_back(&TI);
|
||||||
|
|
||||||
|
TI.id = id;
|
||||||
TI.format = format | textImage;
|
TI.format = format | textImage;
|
||||||
TI.xp = xp;
|
TI.xp = xp;
|
||||||
TI.yp = yp;
|
TI.yp = yp;
|
||||||
@ -1256,7 +1257,7 @@ ButtonInfo &gdioutput::addButton(int x, int y, int w, const string &id,
|
|||||||
updatePos(x, y, w+scaleLength(GDI_BUTTON_SPACING), height+5);
|
updatePos(x, y, w+scaleLength(GDI_BUTTON_SPACING), height+5);
|
||||||
|
|
||||||
bi.xp=x;
|
bi.xp=x;
|
||||||
bi.yp=y;
|
bi.yp = y - 1;
|
||||||
bi.width = w;
|
bi.width = w;
|
||||||
bi.text=ttext;
|
bi.text=ttext;
|
||||||
bi.id=id;
|
bi.id=id;
|
||||||
@ -1345,9 +1346,10 @@ ButtonInfo &gdioutput::addCheckbox(int x, int y, const string &id, const wstring
|
|||||||
GetTextExtentPoint32(hDC, ttext.c_str(), ttext.length(), &size);
|
GetTextExtentPoint32(hDC, ttext.c_str(), ttext.length(), &size);
|
||||||
ReleaseDC(hWndTarget, hDC);
|
ReleaseDC(hWndTarget, hDC);
|
||||||
|
|
||||||
|
int cbY = y + (size.cy - h) / 2;
|
||||||
bi.hWnd = CreateWindowEx(0, L"BUTTON", L"", WS_TABSTOP | WS_VISIBLE |
|
bi.hWnd = CreateWindowEx(0, L"BUTTON", L"", WS_TABSTOP | WS_VISIBLE |
|
||||||
WS_CHILD | WS_CLIPSIBLINGS | BS_AUTOCHECKBOX | BS_NOTIFY,
|
WS_CHILD | WS_CLIPSIBLINGS | BS_AUTOCHECKBOX | BS_NOTIFY,
|
||||||
x-ox, y-oy + (size.cy-h)/2, h, h, hWndTarget, NULL,
|
x - ox, cbY - oy, h, h, hWndTarget, NULL,
|
||||||
(HINSTANCE)GetWindowLongPtr(hWndTarget, GWLP_HINSTANCE), NULL);
|
(HINSTANCE)GetWindowLongPtr(hWndTarget, GWLP_HINSTANCE), NULL);
|
||||||
|
|
||||||
TextInfo& desc = addStringUT(y, x + (3 * h) / 2, 0, ttext, 0, checkBoxCallback);
|
TextInfo& desc = addStringUT(y, x + (3 * h) / 2, 0, ttext, 0, checkBoxCallback);
|
||||||
@ -1372,7 +1374,7 @@ ButtonInfo &gdioutput::addCheckbox(int x, int y, const string &id, const wstring
|
|||||||
}
|
}
|
||||||
bi.isCheckbox = true;
|
bi.isCheckbox = true;
|
||||||
bi.xp = x;
|
bi.xp = x;
|
||||||
bi.yp=y;
|
bi.yp = cbY;
|
||||||
bi.width = desc.textRect.right - (x - ox);
|
bi.width = desc.textRect.right - (x - ox);
|
||||||
bi.text = ttext;
|
bi.text = ttext;
|
||||||
bi.id = id;
|
bi.id = id;
|
||||||
@ -2240,7 +2242,7 @@ void gdioutput::processButtonMessage(ButtonInfo &bi, WPARAM wParam)
|
|||||||
if (bi.isCheckbox)
|
if (bi.isCheckbox)
|
||||||
bi.checked = SendMessage(bi.hWnd, BM_GETCHECK, 0, 0)==BST_CHECKED;
|
bi.checked = SendMessage(bi.hWnd, BM_GETCHECK, 0, 0)==BST_CHECKED;
|
||||||
bi.synchData();
|
bi.synchData();
|
||||||
if (bi.callBack || bi.handler) {
|
if (bi.callBack || bi.hasEventHandler()) {
|
||||||
setWaitCursor(true);
|
setWaitCursor(true);
|
||||||
if (!bi.handleEvent(*this, GUI_BUTTON) && bi.callBack)
|
if (!bi.handleEvent(*this, GUI_BUTTON) && bi.callBack)
|
||||||
bi.callBack(this, GUI_BUTTON, &bi); //it may be destroyed here...
|
bi.callBack(this, GUI_BUTTON, &bi); //it may be destroyed here...
|
||||||
@ -3027,10 +3029,8 @@ void gdioutput::doEnter() {
|
|||||||
HWND hWnd=GetFocus();
|
HWND hWnd=GetFocus();
|
||||||
|
|
||||||
for (list<ButtonInfo>::iterator it=BI.begin(); it!=BI.end(); ++it)
|
for (list<ButtonInfo>::iterator it=BI.begin(); it!=BI.end(); ++it)
|
||||||
if (it->isDefaultButton() && (it->callBack || it->handler)) {
|
if (it->isDefaultButton()) {
|
||||||
if (it->handler)
|
if (!it->handleEvent(*this, GUI_BUTTON) && it->callBack)
|
||||||
it->handleEvent(*this, GUI_BUTTON);
|
|
||||||
else
|
|
||||||
it->callBack(this, GUI_BUTTON, &*it);
|
it->callBack(this, GUI_BUTTON, &*it);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3038,13 +3038,11 @@ void gdioutput::doEnter() {
|
|||||||
list<InputInfo>::iterator it;
|
list<InputInfo>::iterator it;
|
||||||
|
|
||||||
for(it=II.begin(); it != II.end(); ++it)
|
for(it=II.begin(); it != II.end(); ++it)
|
||||||
if (it->hWnd==hWnd && (it->callBack || it->handler)){
|
if (it->hWnd==hWnd && (it->hasEventHandler() || it->callBack)){
|
||||||
TCHAR bf[1024];
|
TCHAR bf[1024];
|
||||||
GetWindowText(hWnd, bf, 1024);
|
GetWindowText(hWnd, bf, 1024);
|
||||||
it->text = bf;
|
it->text = bf;
|
||||||
if (it->handler)
|
if (!it->handleEvent(*this, GUI_INPUT))
|
||||||
it->handleEvent(*this, GUI_INPUT);
|
|
||||||
else
|
|
||||||
it->callBack(this, GUI_INPUT, &*it);
|
it->callBack(this, GUI_INPUT, &*it);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3139,10 +3137,8 @@ void gdioutput::doEscape()
|
|||||||
tit->table->escape(*this);
|
tit->table->escape(*this);
|
||||||
|
|
||||||
for (list<ButtonInfo>::iterator it=BI.begin(); it!=BI.end(); ++it) {
|
for (list<ButtonInfo>::iterator it=BI.begin(); it!=BI.end(); ++it) {
|
||||||
if (it->isCancelButton() && (it->callBack || it->handler) ) {
|
if (it->isCancelButton() && (it->callBack || it->hasEventHandler()) ) {
|
||||||
if (it->handler)
|
if (!it->handleEvent(*this, GUI_BUTTON))
|
||||||
it->handleEvent(*this, GUI_BUTTON);
|
|
||||||
else
|
|
||||||
it->callBack(this, GUI_BUTTON, &*it);
|
it->callBack(this, GUI_BUTTON, &*it);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3523,7 +3519,7 @@ bool gdioutput::insertText(const string &id, const wstring &text)
|
|||||||
SetWindowText(it->hWnd, text.c_str());
|
SetWindowText(it->hWnd, text.c_str());
|
||||||
it->text = text;
|
it->text = text;
|
||||||
|
|
||||||
if (it->handler)
|
if (it->hasEventHandler())
|
||||||
it->handleEvent(*this, GUI_INPUT);
|
it->handleEvent(*this, GUI_INPUT);
|
||||||
else if (it->callBack)
|
else if (it->callBack)
|
||||||
it->callBack(this, GUI_INPUT, &*it);
|
it->callBack(this, GUI_INPUT, &*it);
|
||||||
@ -4385,9 +4381,6 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC) {
|
|||||||
h = ti.textRect.bottom - ti.textRect.top;
|
h = ti.textRect.bottom - ti.textRect.top;
|
||||||
|
|
||||||
image.drawImage(imgId, Image::ImageMethod::Default, hDC, rc.left, rc.top, w, h);
|
image.drawImage(imgId, Image::ImageMethod::Default, hDC, rc.left, rc.top, w, h);
|
||||||
|
|
||||||
//width = image.getWidth(imgId);
|
|
||||||
//height = image.getHeight(imgId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fixedRect) {
|
if (!fixedRect) {
|
||||||
@ -5503,7 +5496,7 @@ int gdioutput::sendCtrlMessage(const string &id)
|
|||||||
{
|
{
|
||||||
for (list<ButtonInfo>::iterator it=BI.begin(); it != BI.end(); ++it) {
|
for (list<ButtonInfo>::iterator it=BI.begin(); it != BI.end(); ++it) {
|
||||||
if (id==it->id) {
|
if (id==it->id) {
|
||||||
if (it->handler)
|
if (it->hasEventHandler())
|
||||||
return it->handleEvent(*this, GUI_BUTTON);
|
return it->handleEvent(*this, GUI_BUTTON);
|
||||||
else if (it->callBack)
|
else if (it->callBack)
|
||||||
return it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
|
return it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
|
||||||
@ -7201,11 +7194,11 @@ string gdioutput::dbPress(const string &id, int extra) {
|
|||||||
if (it->isCheckbox) {
|
if (it->isCheckbox) {
|
||||||
check(id, !isChecked(id));
|
check(id, !isChecked(id));
|
||||||
}
|
}
|
||||||
else if(!it->callBack && !it->handler)
|
else if(!it->callBack && !it->hasEventHandler())
|
||||||
throw meosException("Button " + id + " is not active.");
|
throw meosException("Button " + id + " is not active.");
|
||||||
|
|
||||||
wstring val = it->text;
|
wstring val = it->text;
|
||||||
if (it->handler)
|
if (it->hasEventHandler())
|
||||||
it->handleEvent(*this, GUI_BUTTON);
|
it->handleEvent(*this, GUI_BUTTON);
|
||||||
else if (it->callBack)
|
else if (it->callBack)
|
||||||
it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
|
it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
|
||||||
@ -7229,11 +7222,11 @@ string gdioutput::dbPress(const string &id, const char *extra) {
|
|||||||
if (it->isCheckbox) {
|
if (it->isCheckbox) {
|
||||||
check(id, !isChecked(id));
|
check(id, !isChecked(id));
|
||||||
}
|
}
|
||||||
else if(!it->callBack && !it->handler)
|
else if(!it->callBack && !it->hasEventHandler())
|
||||||
throw meosException("Button " + id + " is not active.");
|
throw meosException("Button " + id + " is not active.");
|
||||||
|
|
||||||
wstring val = it->text;
|
wstring val = it->text;
|
||||||
if (it->handler)
|
if (it->hasEventHandler())
|
||||||
it->handleEvent(*this, GUI_BUTTON);
|
it->handleEvent(*this, GUI_BUTTON);
|
||||||
else if (it->callBack)
|
else if (it->callBack)
|
||||||
it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
|
it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
|
||||||
@ -7272,12 +7265,12 @@ string gdioutput::dbSelect(const string &id, int data) {
|
|||||||
|
|
||||||
void gdioutput::internalSelect(ListBoxInfo &bi) {
|
void gdioutput::internalSelect(ListBoxInfo &bi) {
|
||||||
bi.syncData();
|
bi.syncData();
|
||||||
if (bi.callBack || bi.handler) {
|
if (bi.callBack || bi.handler || bi.managedHandler) {
|
||||||
setWaitCursor(true);
|
setWaitCursor(true);
|
||||||
hasCleared = false;
|
hasCleared = false;
|
||||||
try {
|
try {
|
||||||
bi.writeLock = true;
|
bi.writeLock = true;
|
||||||
if (bi.handler)
|
if (bi.hasEventHandler())
|
||||||
bi.handleEvent(*this, GUI_LISTBOX);
|
bi.handleEvent(*this, GUI_LISTBOX);
|
||||||
else
|
else
|
||||||
bi.callBack(this, GUI_LISTBOX, &bi); //it may be destroyed here... Then hasCleared is set.
|
bi.callBack(this, GUI_LISTBOX, &bi); //it may be destroyed here... Then hasCleared is set.
|
||||||
@ -7304,7 +7297,7 @@ void gdioutput::dbInput(const string &id, const string &text) {
|
|||||||
SetWindowText(it->hWnd, widen(text).c_str());
|
SetWindowText(it->hWnd, widen(text).c_str());
|
||||||
it->text = widen(text);
|
it->text = widen(text);
|
||||||
it->data = -1;
|
it->data = -1;
|
||||||
if (it->handler)
|
if (it->hasEventHandler())
|
||||||
it->handleEvent(*this, GUI_COMBO);
|
it->handleEvent(*this, GUI_COMBO);
|
||||||
else if (it->callBack)
|
else if (it->callBack)
|
||||||
it->callBack(this, GUI_COMBO, &*it); //it may be destroyed here...
|
it->callBack(this, GUI_COMBO, &*it); //it may be destroyed here...
|
||||||
@ -7319,7 +7312,7 @@ void gdioutput::dbInput(const string &id, const string &text) {
|
|||||||
|
|
||||||
it->text = widen(text);
|
it->text = widen(text);
|
||||||
SetWindowText(it->hWnd, widen(text).c_str());
|
SetWindowText(it->hWnd, widen(text).c_str());
|
||||||
if (it->handler)
|
if (it->hasEventHandler())
|
||||||
it->handleEvent(*this, GUI_INPUT);
|
it->handleEvent(*this, GUI_INPUT);
|
||||||
else if (it->callBack)
|
else if (it->callBack)
|
||||||
it->callBack(this, GUI_INPUT, &*it);
|
it->callBack(this, GUI_INPUT, &*it);
|
||||||
@ -7357,7 +7350,7 @@ void gdioutput::dbDblClick(const string &id, int data) {
|
|||||||
if (!IsWindowEnabled(it->hWnd))
|
if (!IsWindowEnabled(it->hWnd))
|
||||||
throw meosException("Selection " + id + " is not active.");
|
throw meosException("Selection " + id + " is not active.");
|
||||||
selectItemByData(id, data);
|
selectItemByData(id, data);
|
||||||
if (it->handler)
|
if (it->hasEventHandler())
|
||||||
it->handleEvent(*this, GUI_LISTBOXSELECT);
|
it->handleEvent(*this, GUI_LISTBOXSELECT);
|
||||||
else if (it->callBack)
|
else if (it->callBack)
|
||||||
it->callBack(this, GUI_LISTBOXSELECT, &*it); //it may be destroyed here...
|
it->callBack(this, GUI_LISTBOXSELECT, &*it); //it may be destroyed here...
|
||||||
|
|||||||
@ -2417,7 +2417,10 @@ pRunner IOF30Interface::readPersonResult(gdioutput &gdi, pClass pc, xmlobject &x
|
|||||||
wstring s;
|
wstring s;
|
||||||
for (auto &split : splits) {
|
for (auto &split : splits) {
|
||||||
int code = split.getObjectInt("ControlCode");
|
int code = split.getObjectInt("ControlCode");
|
||||||
int time = split.getObjectInt("Time");
|
wstring out;
|
||||||
|
split.getObjectString("Time", out);
|
||||||
|
double t = _wtof(out.c_str());
|
||||||
|
int time = int(t * timeConstSecond);
|
||||||
split.getObjectString("status", s);
|
split.getObjectString("status", s);
|
||||||
if (s != L"missing")
|
if (s != L"missing")
|
||||||
card->addPunch(code, st + time, 0, 0);
|
card->addPunch(code, st + time, 0, 0);
|
||||||
|
|||||||
@ -463,6 +463,8 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||||||
gdi_main->init(hWndWorkspace, hWndMain, hMainTab);
|
gdi_main->init(hWndWorkspace, hWndMain, hMainTab);
|
||||||
gdi_main->getTabs().get(TCmpTab)->loadPage(*gdi_main);
|
gdi_main->getTabs().get(TCmpTab)->loadPage(*gdi_main);
|
||||||
|
|
||||||
|
image.loadImage(IDI_MEOSEDIT, Image::ImageMethod::Default);
|
||||||
|
|
||||||
autoTask = new AutoTask(hWndMain, *gEvent, *gdi_main);
|
autoTask = new AutoTask(hWndMain, *gEvent, *gdi_main);
|
||||||
|
|
||||||
autoTask->setTimers();
|
autoTask->setTimers();
|
||||||
|
|||||||
@ -53,6 +53,7 @@ IDB_ECO BITMAP "bmp00001.bmp"
|
|||||||
IDI_SPLASHIMAGE PNG "meos.png"
|
IDI_SPLASHIMAGE PNG "meos.png"
|
||||||
IDI_MEOSIMAGE PNG "title.png"
|
IDI_MEOSIMAGE PNG "title.png"
|
||||||
IDI_MEOSINFO PNG "info24.png"
|
IDI_MEOSINFO PNG "info24.png"
|
||||||
|
IDI_MEOSEDIT PNG "edit.png"
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// English (United States) resources
|
// English (United States) resources
|
||||||
|
|
||||||
|
|||||||
@ -919,16 +919,10 @@ string itos(uint64_t i)
|
|||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void prepareMatchString(wchar_t* data_c, int size) {
|
||||||
bool filterMatchString(const string &c, const char *filt_lc)
|
CharLowerBuff(data_c, size);
|
||||||
{
|
for (int j = 0; j < size; j++)
|
||||||
if (filt_lc[0] == 0)
|
data_c[j] = toLowerStripped(data_c[j]);
|
||||||
return true;
|
|
||||||
char key[2048];
|
|
||||||
strcpy_s(key, c.c_str());
|
|
||||||
CharLowerBuffA(key, c.length());
|
|
||||||
|
|
||||||
return strstr(key, filt_lc)!=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filterMatchString(const wstring &c, const wchar_t *filt_lc, int &score) {
|
bool filterMatchString(const wstring &c, const wchar_t *filt_lc, int &score) {
|
||||||
@ -937,7 +931,11 @@ bool filterMatchString(const wstring &c, const wchar_t *filt_lc, int &score) {
|
|||||||
return true;
|
return true;
|
||||||
wchar_t key[2048];
|
wchar_t key[2048];
|
||||||
wcscpy_s(key, c.c_str());
|
wcscpy_s(key, c.c_str());
|
||||||
CharLowerBuff(key, c.length());
|
int cl = c.length();
|
||||||
|
CharLowerBuff(key, cl);
|
||||||
|
for (int j = 0; j < cl; j++)
|
||||||
|
key[j] = toLowerStripped(key[j]);
|
||||||
|
|
||||||
bool match = wcsstr(key, filt_lc) != 0;
|
bool match = wcsstr(key, filt_lc) != 0;
|
||||||
if (match) {
|
if (match) {
|
||||||
while (filt_lc[score] && key[score] && filt_lc[score] == key[score])
|
while (filt_lc[score] && key[score] && filt_lc[score] == key[score])
|
||||||
@ -1259,14 +1257,14 @@ int toLowerStripped(wchar_t c) {
|
|||||||
return c;
|
return c;
|
||||||
|
|
||||||
static wchar_t *map = 0;
|
static wchar_t *map = 0;
|
||||||
if (map == 0) {
|
if (map == nullptr) {
|
||||||
map = new wchar_t[65536];
|
map = new wchar_t[65536];
|
||||||
for (int i = 0; i < 65536; i++)
|
for (int i = 0; i < 65536; i++)
|
||||||
map[i] = i;
|
map[i] = i;
|
||||||
|
|
||||||
setChar(map, L'Å', L'å');
|
setChar(map, L'Å', L'a');
|
||||||
setChar(map, L'Ä', L'ä');
|
setChar(map, L'Ä', L'a');
|
||||||
setChar(map, L'Ö', L'ö');
|
setChar(map, L'Ö', L'o');
|
||||||
|
|
||||||
setChar(map, L'É', L'e');
|
setChar(map, L'É', L'e');
|
||||||
setChar(map, L'é', L'e');
|
setChar(map, L'é', L'e');
|
||||||
@ -1289,6 +1287,8 @@ int toLowerStripped(wchar_t c) {
|
|||||||
setChar(map, L'ñ', L'n');
|
setChar(map, L'ñ', L'n');
|
||||||
setChar(map, L'Ñ', L'n');
|
setChar(map, L'Ñ', L'n');
|
||||||
|
|
||||||
|
setChar(map, L'ä', L'a');
|
||||||
|
setChar(map, L'å', L'a');
|
||||||
setChar(map, L'á', L'a');
|
setChar(map, L'á', L'a');
|
||||||
setChar(map, L'Á', L'a');
|
setChar(map, L'Á', L'a');
|
||||||
setChar(map, L'à', L'a');
|
setChar(map, L'à', L'a');
|
||||||
@ -1315,19 +1315,29 @@ int toLowerStripped(wchar_t c) {
|
|||||||
setChar(map, L'Õ', L'o');
|
setChar(map, L'Õ', L'o');
|
||||||
setChar(map, L'ô', L'o');
|
setChar(map, L'ô', L'o');
|
||||||
setChar(map, L'Ô', L'o');
|
setChar(map, L'Ô', L'o');
|
||||||
|
setChar(map, L'ö', L'o');
|
||||||
|
|
||||||
setChar(map, L'ý', L'y');
|
setChar(map, L'ý', L'y');
|
||||||
setChar(map, L'Ý', L'Y');
|
setChar(map, L'Ý', L'Y');
|
||||||
setChar(map, L'ÿ', L'y');
|
setChar(map, L'ÿ', L'y');
|
||||||
|
|
||||||
setChar(map, L'Æ', L'ä');
|
setChar(map, L'Æ', L'a');
|
||||||
setChar(map, L'æ', L'ä');
|
setChar(map, L'æ', L'a');
|
||||||
|
|
||||||
setChar(map, L'Ø', L'ö');
|
setChar(map, L'Ø', L'o');
|
||||||
setChar(map, L'ø', L'ö');
|
setChar(map, L'ø', L'o');
|
||||||
|
|
||||||
setChar(map, L'Ç', L'c');
|
setChar(map, L'Ç', L'c');
|
||||||
setChar(map, L'ç', L'c');
|
setChar(map, L'ç', L'c');
|
||||||
|
|
||||||
|
wstring srcEx = L"Ă㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻĽľĿŀŁł"
|
||||||
|
L"ŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽž";
|
||||||
|
wstring dstEx = L"aaaaccccccccddddeeeeeeeeeegggggggghhhhiiiiiiiiiijjjjkkklllllllll"
|
||||||
|
L"nnnnnnnnnooooooaarrrrrrssssssssttttttuuuuuuuuuuuuwwyyyzzzzzz";
|
||||||
|
|
||||||
|
assert(srcEx.size() == dstEx.size());
|
||||||
|
for (int j = 0; j < srcEx.size(); j++)
|
||||||
|
setChar(map, srcEx[j], dstEx[j]);
|
||||||
}
|
}
|
||||||
int a = map[c];
|
int a = map[c];
|
||||||
return a;
|
return a;
|
||||||
|
|||||||
@ -152,10 +152,13 @@ wstring itow(int64_t i);
|
|||||||
wstring itow(uint64_t i);
|
wstring itow(uint64_t i);
|
||||||
|
|
||||||
|
|
||||||
///Lower case match (filt_lc must be lc)
|
///Lower case match (filt_lc must be lc and stripped of accents)
|
||||||
bool filterMatchString(const string &c, const char *filt_lc);
|
|
||||||
bool filterMatchString(const wstring &c, const wchar_t *filt_lc, int &score);
|
bool filterMatchString(const wstring &c, const wchar_t *filt_lc, int &score);
|
||||||
|
|
||||||
|
/** To lower case and strip accants */
|
||||||
|
void prepareMatchString(wchar_t* data_c, int size);
|
||||||
|
|
||||||
|
|
||||||
bool matchNumber(int number, const wchar_t *key);
|
bool matchNumber(int number, const wchar_t *key);
|
||||||
|
|
||||||
int getMeosBuild();
|
int getMeosBuild();
|
||||||
|
|||||||
@ -25,12 +25,12 @@
|
|||||||
|
|
||||||
//ABCDEFGHIJKLMNOP
|
//ABCDEFGHIJKLMNOP
|
||||||
int getMeosBuild() {
|
int getMeosBuild() {
|
||||||
string revision("$Rev: 1263 $");
|
string revision("$Rev: 1266 $");
|
||||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getMeosDate() {
|
wstring getMeosDate() {
|
||||||
wstring date(L"$Date: 2023-05-12 16:11:34 +0200 (fre, 12 maj 2023) $");
|
wstring date(L"$Date: 2023-06-01 22:17:24 +0200 (tor, 01 jun 2023) $");
|
||||||
return date.substr(7,10);
|
return date.substr(7,10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ wstring getBuildType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wstring getMajorVersion() {
|
wstring getMajorVersion() {
|
||||||
return L"3.9";
|
return L"4.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getMeosFullVersion() {
|
wstring getMeosFullVersion() {
|
||||||
|
|||||||
@ -2198,6 +2198,7 @@ void MetaList::initSymbols() {
|
|||||||
typeToSymbol[lCourseUsage] = L"CourseUsage";
|
typeToSymbol[lCourseUsage] = L"CourseUsage";
|
||||||
typeToSymbol[lCourseUsageNoVacant] = L"CourseUsageNoVacant";
|
typeToSymbol[lCourseUsageNoVacant] = L"CourseUsageNoVacant";
|
||||||
typeToSymbol[lCourseClasses] = L"CourseClasses";
|
typeToSymbol[lCourseClasses] = L"CourseClasses";
|
||||||
|
typeToSymbol[lCourseNumControls] = L"CourseNumControls";
|
||||||
typeToSymbol[lCourseShortening] = L"CourseShortening";
|
typeToSymbol[lCourseShortening] = L"CourseShortening";
|
||||||
typeToSymbol[lRunnerName] = L"RunnerName";
|
typeToSymbol[lRunnerName] = L"RunnerName";
|
||||||
typeToSymbol[lRunnerGivenName] = L"RunnerGivenName";
|
typeToSymbol[lRunnerGivenName] = L"RunnerGivenName";
|
||||||
@ -2301,18 +2302,26 @@ void MetaList::initSymbols() {
|
|||||||
typeToSymbol[lPunchNamedTime] = L"PunchNamedTime";
|
typeToSymbol[lPunchNamedTime] = L"PunchNamedTime";
|
||||||
typeToSymbol[lPunchName] = L"PunchName";
|
typeToSymbol[lPunchName] = L"PunchName";
|
||||||
typeToSymbol[lPunchNamedSplit] = L"PunchNamedSplit";
|
typeToSymbol[lPunchNamedSplit] = L"PunchNamedSplit";
|
||||||
|
typeToSymbol[lPunchTeamTotalNamedTime] = L"PunchTeamTotalNamedTime";
|
||||||
|
|
||||||
typeToSymbol[lPunchTime] = L"PunchTime";
|
typeToSymbol[lPunchTime] = L"PunchTime";
|
||||||
|
typeToSymbol[lPunchTeamTime] = L"PunchTeamTime";
|
||||||
|
|
||||||
typeToSymbol[lPunchControlNumber] = L"PunchControlNumber";
|
typeToSymbol[lPunchControlNumber] = L"PunchControlNumber";
|
||||||
typeToSymbol[lPunchControlCode] = L"PunchControlCode";
|
typeToSymbol[lPunchControlCode] = L"PunchControlCode";
|
||||||
typeToSymbol[lPunchLostTime] = L"PunchLostTime";
|
typeToSymbol[lPunchLostTime] = L"PunchLostTime";
|
||||||
typeToSymbol[lPunchControlPlace] = L"PunchControlPlace";
|
typeToSymbol[lPunchControlPlace] = L"PunchControlPlace";
|
||||||
typeToSymbol[lPunchControlPlaceAcc] = L"PunchControlPlaceAcc";
|
typeToSymbol[lPunchControlPlaceAcc] = L"PunchControlPlaceAcc";
|
||||||
|
typeToSymbol[lPunchControlPlaceTeamAcc] = L"PunchControlPlaceTeamAcc";
|
||||||
|
|
||||||
typeToSymbol[lPunchSplitTime] = L"PunchSplitTime";
|
typeToSymbol[lPunchSplitTime] = L"PunchSplitTime";
|
||||||
typeToSymbol[lPunchTotalTime] = L"PunchTotalTime";
|
typeToSymbol[lPunchTotalTime] = L"PunchTotalTime";
|
||||||
|
typeToSymbol[lPunchTeamTotalTime] = L"PunchTeamTotalTime";
|
||||||
|
|
||||||
typeToSymbol[lPunchAbsTime] = L"PunchAbsTime";
|
typeToSymbol[lPunchAbsTime] = L"PunchAbsTime";
|
||||||
typeToSymbol[lPunchTotalTimeAfter] = L"PunchTotalTimeAfter";
|
typeToSymbol[lPunchTotalTimeAfter] = L"PunchTotalTimeAfter";
|
||||||
|
typeToSymbol[lPunchTeamTotalTimeAfter] = L"PunchTeamTotalTimeAfter";
|
||||||
|
|
||||||
typeToSymbol[lPunchTimeSinceLast] = L"PunchTimeSinceLast";
|
typeToSymbol[lPunchTimeSinceLast] = L"PunchTimeSinceLast";
|
||||||
|
|
||||||
typeToSymbol[lRogainingPunch] = L"RogainingPunch";
|
typeToSymbol[lRogainingPunch] = L"RogainingPunch";
|
||||||
@ -3461,7 +3470,7 @@ void MetaList::getAutoComplete(const wstring& w, vector<AutoCompleteRecord>& rec
|
|||||||
s_lc[j].resize(ws[j].size() + 1);
|
s_lc[j].resize(ws[j].size() + 1);
|
||||||
ws[j] = trim(ws[j]);
|
ws[j] = trim(ws[j]);
|
||||||
wcscpy_s(s_lc[j].data(), s_lc[j].size(), ws[j].c_str());
|
wcscpy_s(s_lc[j].data(), s_lc[j].size(), ws[j].c_str());
|
||||||
CharLowerBuff(s_lc[j].data(), ws[j].length());
|
prepareMatchString(s_lc[j].data(), ws[j].length());
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring tl;
|
wstring tl;
|
||||||
|
|||||||
@ -434,6 +434,10 @@ public:
|
|||||||
|
|
||||||
static void fillSymbols(vector < pair<wstring, size_t>> &symb);
|
static void fillSymbols(vector < pair<wstring, size_t>> &symb);
|
||||||
|
|
||||||
|
static const map<SortOrder, string>& getOrderToSymbol() {
|
||||||
|
return orderToSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
friend class MetaListPost;
|
friend class MetaListPost;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -815,7 +815,7 @@ wstring oCard::getCardVoltage() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wstring oCard::getCardVoltage(int miliVolt) {
|
wstring oCard::getCardVoltage(int miliVolt) {
|
||||||
if (miliVolt == 0)
|
if (miliVolt <= 10)
|
||||||
return L"";
|
return L"";
|
||||||
int vi = miliVolt / 1000;
|
int vi = miliVolt / 1000;
|
||||||
int vd = (miliVolt % 1000) / 10;
|
int vd = (miliVolt % 1000) / 10;
|
||||||
@ -830,9 +830,9 @@ oCard::BatteryStatus oCard::isCriticalCardVoltage() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oCard::BatteryStatus oCard::isCriticalCardVoltage(int miliVolt) {
|
oCard::BatteryStatus oCard::isCriticalCardVoltage(int miliVolt) {
|
||||||
if (miliVolt > 0 && miliVolt < 2445)
|
if (miliVolt > 10 && miliVolt < 2445)
|
||||||
return BatteryStatus::Bad;
|
return BatteryStatus::Bad;
|
||||||
else if (miliVolt > 0 && miliVolt <= 2710)
|
else if (miliVolt > 10 && miliVolt <= 2710)
|
||||||
return BatteryStatus::Warning;
|
return BatteryStatus::Warning;
|
||||||
|
|
||||||
return BatteryStatus::OK;
|
return BatteryStatus::OK;
|
||||||
|
|||||||
106
code/oClass.cpp
106
code/oClass.cpp
@ -404,7 +404,7 @@ int oClass::getNumRunners(bool checkFirstLeg, bool noCountVacant, bool noCountNo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
string key = getCountTypeKey(checkFirstLeg ? 0 : -1,
|
string key = getCountTypeKey(checkFirstLeg ? 0 : -1,
|
||||||
noCountNotCompeting ? CountKeyType::All : CountKeyType::IncludeNotCompeting,
|
noCountNotCompeting ? CountKeyType::AllCompeting : CountKeyType::IncludeNotCompeting,
|
||||||
!noCountVacant);
|
!noCountVacant);
|
||||||
|
|
||||||
auto res = tTypeKeyToRunnerCount.second.find(key);
|
auto res = tTypeKeyToRunnerCount.second.find(key);
|
||||||
@ -419,7 +419,7 @@ int oClass::getNumRunners(bool checkFirstLeg, bool noCountVacant, bool noCountNo
|
|||||||
continue;
|
continue;
|
||||||
if (noCountVacant && r.isVacant())
|
if (noCountVacant && r.isVacant())
|
||||||
continue;
|
continue;
|
||||||
if (noCountNotCompeting && r.getStatus() == StatusNotCompetiting)
|
if (noCountNotCompeting && (r.getStatus() == StatusNotCompetiting || r.getStatus() == StatusCANCEL))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int id = r.getClassId(true);
|
int id = r.getClassId(true);
|
||||||
@ -3371,6 +3371,16 @@ int oClass::getLegPlace(int ifrom, int ito, int time) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int oClass::getAccLegControlLeader(int teamLeg, int courseControlId) const {
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oClass::getAccLegControlPlace(int teamLeg, int courseControlId, int time) const {
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void oClass::insertAccLegPlace(int courseId, int controlNo, int time, int place)
|
void oClass::insertAccLegPlace(int courseId, int controlNo, int time, int place)
|
||||||
{ /*
|
{ /*
|
||||||
char bf[256];
|
char bf[256];
|
||||||
@ -3441,7 +3451,6 @@ int oClass::getAccLegPlace(int courseId, int controlNo, int time) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void oClass::calculateSplits() {
|
void oClass::calculateSplits() {
|
||||||
clearSplitAnalysis();
|
clearSplitAnalysis();
|
||||||
set<pCourse> cSet;
|
set<pCourse> cSet;
|
||||||
@ -3460,23 +3469,35 @@ void oClass::calculateSplits() {
|
|||||||
LegResult legBestTime;
|
LegResult legBestTime;
|
||||||
vector<pRunner> rCls;
|
vector<pRunner> rCls;
|
||||||
oe->getRunners(Id, -1, rCls, false);
|
oe->getRunners(Id, -1, rCls, false);
|
||||||
/*
|
|
||||||
if (isQualificationFinalBaseClass() || isQualificationFinalBaseClass()) {
|
|
||||||
|
|
||||||
for (auto &r : oe->Runners) {
|
for (pRunner it : rCls) {
|
||||||
if (!r.isRemoved() && r.getClassRef(true) == this)
|
pCourse tpc = it->getCourse(false);
|
||||||
rCls.push_back(&r);
|
if (tpc == nullptr)
|
||||||
|
continue;
|
||||||
|
cSet.insert(tpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map<int, vector<pRunner>> rClsCrs;
|
||||||
|
if (cSet.size() > 1) {
|
||||||
|
for (pRunner it : rCls) {
|
||||||
|
pCourse tpc = it->getCourse(false);
|
||||||
|
if (tpc)
|
||||||
|
rClsCrs[tpc->getId()].push_back(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool multiLeg = getNumStages() > 1; // Perhaps ignore parallell legs...
|
||||||
|
|
||||||
|
if (multiLeg) {
|
||||||
|
teamLegCourseControlToLeaderPlace.resize(getNumStages());
|
||||||
|
for (auto& lp : teamLegCourseControlToLeaderPlace)
|
||||||
|
lp.clear();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (auto &r : oe->Runners) {
|
teamLegCourseControlToLeaderPlace.clear();
|
||||||
if (!r.isRemoved() && r.Class == this)
|
|
||||||
rCls.push_back(&r);
|
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
for (set<pCourse>::iterator cit = cSet.begin(); cit!= cSet.end(); ++cit) {
|
for (pCourse pc : cSet) {
|
||||||
pCourse pc = *cit;
|
|
||||||
// Store all split times in a matrix
|
// Store all split times in a matrix
|
||||||
const unsigned nc = pc->getNumControls();
|
const unsigned nc = pc->getNumControls();
|
||||||
if (nc == 0)
|
if (nc == 0)
|
||||||
@ -3484,9 +3505,14 @@ void oClass::calculateSplits() {
|
|||||||
|
|
||||||
vector<vector<int>> splits(nc+1);
|
vector<vector<int>> splits(nc+1);
|
||||||
vector<vector<int>> splitsAcc(nc+1);
|
vector<vector<int>> splitsAcc(nc+1);
|
||||||
vector<bool> acceptMissingPunch(nc+1, true);
|
vector<int8_t> acceptMissingPunch(nc+1, true);
|
||||||
|
vector<pRunner>* rList;
|
||||||
|
if (rClsCrs.empty())
|
||||||
|
rList = &rCls;
|
||||||
|
else
|
||||||
|
rList = &rClsCrs[pc->getId()];
|
||||||
|
|
||||||
for (pRunner it : rCls) {
|
for (pRunner it : *rList) {
|
||||||
pCourse tpc = it->getCourse(false);
|
pCourse tpc = it->getCourse(false);
|
||||||
if (tpc != pc || tpc == 0)
|
if (tpc != pc || tpc == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -3504,7 +3530,7 @@ void oClass::calculateSplits() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pRunner it : rCls) {
|
for (pRunner it : *rList) {
|
||||||
pCourse tpc = it->getCourse(false);
|
pCourse tpc = it->getCourse(false);
|
||||||
|
|
||||||
if (tpc != pc)
|
if (tpc != pc)
|
||||||
@ -3513,17 +3539,46 @@ void oClass::calculateSplits() {
|
|||||||
const vector<SplitData> &sp = it->getSplitTimes(true);
|
const vector<SplitData> &sp = it->getSplitTimes(true);
|
||||||
const int s = min<int>(nc, sp.size());
|
const int s = min<int>(nc, sp.size());
|
||||||
|
|
||||||
|
int off = 0;
|
||||||
|
unordered_map<int, PlaceTime>* teamAccTimes = nullptr;
|
||||||
|
if (multiLeg && it->tInTeam)
|
||||||
|
off = it->tInTeam->getTotalRunningTimeAtLegStart(it->tLeg, false);
|
||||||
|
|
||||||
|
if (off > 0 && it->tLeg < teamLegCourseControlToLeaderPlace.size())
|
||||||
|
teamAccTimes = &teamLegCourseControlToLeaderPlace[it->tLeg];
|
||||||
|
|
||||||
vector<int> &tLegTimes = it->tLegTimes;
|
vector<int> &tLegTimes = it->tLegTimes;
|
||||||
tLegTimes.resize(nc + 1);
|
tLegTimes.resize(nc + 1);
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
|
// Acc team finish time
|
||||||
|
if (teamAccTimes && it->FinishTime > 0 && (it->tStatus == StatusOK || it->tStatus == StatusUnknown)) {
|
||||||
|
int ccId = oPunch::PunchFinish;
|
||||||
|
int t = it->getRunningTime(false);
|
||||||
|
auto& res = (*teamAccTimes)[ccId];
|
||||||
|
if (res.leader <= 0 || res.leader > t + off)
|
||||||
|
res.leader = t + off;
|
||||||
|
// Count times
|
||||||
|
++res.timeToPlace[t + off];
|
||||||
|
}
|
||||||
|
|
||||||
for (int k = 0; k < s; k++) {
|
for (int k = 0; k < s; k++) {
|
||||||
if (sp[k].getTime(true) > 0) {
|
if (sp[k].getTime(true) > 0) {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
// Store accumulated times
|
// Store accumulated times
|
||||||
int t = sp[k].getTime(true) - it->tStartTime;
|
int t = sp[k].getTime(true) - it->tStartTime;
|
||||||
if (it->tStartTime>0 && t>0)
|
if (it->tStartTime > 0 && t > 0) {
|
||||||
splitsAcc[k].push_back(t);
|
splitsAcc[k].push_back(t);
|
||||||
|
if (teamAccTimes) {
|
||||||
|
int ccId = pc->getCourseControlId(k);
|
||||||
|
auto& res = (*teamAccTimes)[ccId];
|
||||||
|
if (res.leader <= 0 || res.leader > t + off)
|
||||||
|
res.leader = t + off;
|
||||||
|
|
||||||
|
// Count times
|
||||||
|
++res.timeToPlace[t + off];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k == 0) { // start -> first
|
if (k == 0) { // start -> first
|
||||||
@ -3636,8 +3691,7 @@ void oClass::calculateSplits() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (set<pCourse>::iterator cit = cSet.begin(); cit != cSet.end(); ++cit) {
|
for (pCourse pc : cSet) {
|
||||||
pCourse pc = *cit;
|
|
||||||
const unsigned nc = pc->getNumControls();
|
const unsigned nc = pc->getNumControls();
|
||||||
vector<int> normRes(nc+1);
|
vector<int> normRes(nc+1);
|
||||||
vector<int> bestRes(nc+1);
|
vector<int> bestRes(nc+1);
|
||||||
@ -3655,6 +3709,18 @@ void oClass::calculateSplits() {
|
|||||||
swap(tSplitAnalysisData[pc->getId()], normRes);
|
swap(tSplitAnalysisData[pc->getId()], normRes);
|
||||||
swap(tCourseLegLeaderTime[pc->getId()], bestRes);
|
swap(tCourseLegLeaderTime[pc->getId()], bestRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert number of competitors with time to place
|
||||||
|
for (auto& courseControlLeaderPlace : teamLegCourseControlToLeaderPlace) {
|
||||||
|
for (auto& leaderPlace : courseControlLeaderPlace) {
|
||||||
|
int place = 1;
|
||||||
|
for (auto& numTimes : leaderPlace.second.timeToPlace) {
|
||||||
|
int num = numTimes.second;
|
||||||
|
numTimes.second = place;
|
||||||
|
place += num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oClass::isRogaining() const {
|
bool oClass::isRogaining() const {
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include "inthashmap.h"
|
#include "inthashmap.h"
|
||||||
class oClass;
|
class oClass;
|
||||||
typedef oClass* pClass;
|
typedef oClass* pClass;
|
||||||
@ -260,9 +261,20 @@ protected:
|
|||||||
inthashmap *tLegTimeToPlace;
|
inthashmap *tLegTimeToPlace;
|
||||||
inthashmap *tLegAccTimeToPlace;
|
inthashmap *tLegAccTimeToPlace;
|
||||||
|
|
||||||
|
struct PlaceTime {
|
||||||
|
int leader = -1;
|
||||||
|
map<int, int> timeToPlace;
|
||||||
|
};
|
||||||
|
|
||||||
|
vector<unordered_map<int, PlaceTime>> teamLegCourseControlToLeaderPlace;
|
||||||
|
|
||||||
void insertLegPlace(int from, int to, int time, int place);
|
void insertLegPlace(int from, int to, int time, int place);
|
||||||
void insertAccLegPlace(int courseId, int controlNo, int time, int place);
|
void insertAccLegPlace(int courseId, int controlNo, int time, int place);
|
||||||
|
|
||||||
|
/** Get relay/team accumulated leader time/place at control. */
|
||||||
|
int getAccLegControlLeader(int teamLeg, int courseControlId) const;
|
||||||
|
int getAccLegControlPlace(int teamLeg, int courseControlId, int time) const;
|
||||||
|
|
||||||
// For sub split times
|
// For sub split times
|
||||||
int tLegLeaderTime;
|
int tLegLeaderTime;
|
||||||
mutable int tNoTiming;
|
mutable int tNoTiming;
|
||||||
@ -357,7 +369,7 @@ protected:
|
|||||||
mutable pair<int, map<string, int>> tTypeKeyToRunnerCount;
|
mutable pair<int, map<string, int>> tTypeKeyToRunnerCount;
|
||||||
|
|
||||||
enum CountKeyType {
|
enum CountKeyType {
|
||||||
All,
|
AllCompeting,
|
||||||
Finished,
|
Finished,
|
||||||
ExpectedStarting,
|
ExpectedStarting,
|
||||||
DNS,
|
DNS,
|
||||||
@ -620,7 +632,7 @@ public:
|
|||||||
bool hasTrueMultiCourse() const;
|
bool hasTrueMultiCourse() const;
|
||||||
|
|
||||||
unsigned getNumStages() const {return MultiCourse.size();}
|
unsigned getNumStages() const {return MultiCourse.size();}
|
||||||
/** Get the set of true legs, identifying parallell legs etc. Returns indecs into
|
/** Get the set of true legs, identifying parallell legs etc. Returns indices into
|
||||||
legInfo of the last leg of the true leg (first), and true leg (second).*/
|
legInfo of the last leg of the true leg (first), and true leg (second).*/
|
||||||
struct TrueLegInfo {
|
struct TrueLegInfo {
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@ -653,7 +653,8 @@ const vector< pair<wstring, size_t> > &oEvent::getCourses(vector<pair<wstring, s
|
|||||||
|
|
||||||
vector<wchar_t> filt_lc(filter.length() + 1);
|
vector<wchar_t> filt_lc(filter.length() + 1);
|
||||||
wcscpy_s(filt_lc.data(), filt_lc.size(), filter.c_str());
|
wcscpy_s(filt_lc.data(), filt_lc.size(), filter.c_str());
|
||||||
CharLowerBuff(filt_lc.data(), filter.length());
|
prepareMatchString(filt_lc.data(), filter.length());
|
||||||
|
|
||||||
int score;
|
int score;
|
||||||
wstring b;
|
wstring b;
|
||||||
for (size_t k = 0; k < ac.size(); k++) {
|
for (size_t k = 0; k < ac.size(); k++) {
|
||||||
|
|||||||
116
code/oEvent.cpp
116
code/oEvent.cpp
@ -70,7 +70,7 @@
|
|||||||
extern Image image;
|
extern Image image;
|
||||||
|
|
||||||
//Version of database
|
//Version of database
|
||||||
int oEvent::dbVersion = 90;
|
int oEvent::dbVersion = 91;
|
||||||
|
|
||||||
bool oEvent::useSubSecond() const {
|
bool oEvent::useSubSecond() const {
|
||||||
if (useSubsecondsVersion == dataRevision)
|
if (useSubsecondsVersion == dataRevision)
|
||||||
@ -540,6 +540,8 @@ oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
|
|||||||
oEventData->addVariableString("MergeTag", 12, "Tag");
|
oEventData->addVariableString("MergeTag", 12, "Tag");
|
||||||
oEventData->addVariableString("MergeInfo", "MergeInfo");
|
oEventData->addVariableString("MergeInfo", "MergeInfo");
|
||||||
oEventData->addVariableString("SplitPrint", 40, "Sträcktidslista"); // Id from MetaListContainer::getUniqueId
|
oEventData->addVariableString("SplitPrint", 40, "Sträcktidslista"); // Id from MetaListContainer::getUniqueId
|
||||||
|
oEventData->addVariableInt("NoVacantBib", oDataContainer::oIS8U, "Inga vakanta nummerlappar");
|
||||||
|
|
||||||
oEventData->initData(this, dataSize);
|
oEventData->initData(this, dataSize);
|
||||||
|
|
||||||
oClubData=new oDataContainer(oClub::dataSize);
|
oClubData=new oDataContainer(oClub::dataSize);
|
||||||
@ -4781,7 +4783,7 @@ bool oEvent::hasTeam() const
|
|||||||
return Teams.size() > 0;
|
return Teams.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber, bool assignToVacant) {
|
||||||
if ( !classHasTeams(ClassId) ) {
|
if ( !classHasTeams(ClassId) ) {
|
||||||
sortRunners(ClassStartTimeClub);
|
sortRunners(ClassStartTimeClub);
|
||||||
oRunnerList::iterator it;
|
oRunnerList::iterator it;
|
||||||
@ -4804,6 +4806,8 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
|||||||
if (it->isRemoved())
|
if (it->isRemoved())
|
||||||
continue;
|
continue;
|
||||||
if ( (ClassId==0 || it->getClassId(true)==ClassId) && (it->legToRun()==leg || leg == -1)) {
|
if ( (ClassId==0 || it->getClassId(true)==ClassId) && (it->legToRun()==leg || leg == -1)) {
|
||||||
|
if (!assignToVacant && it->isVacant())
|
||||||
|
continue;
|
||||||
wchar_t bib[32];
|
wchar_t bib[32];
|
||||||
swprintf_s(bib, pattern, num);
|
swprintf_s(bib, pattern, num);
|
||||||
pClass pc = it->getClassRef(true);
|
pClass pc = it->getClassRef(true);
|
||||||
@ -4832,6 +4836,8 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
|||||||
for (auto it = Teams.begin(); it != Teams.end(); ++it) {
|
for (auto it = Teams.begin(); it != Teams.end(); ++it) {
|
||||||
if (it->isRemoved())
|
if (it->isRemoved())
|
||||||
continue;
|
continue;
|
||||||
|
if (!assignToVacant && it->isVacant())
|
||||||
|
continue;
|
||||||
if (ClassId == 0 || it->getClassId(false) == ClassId) {
|
if (ClassId == 0 || it->getClassId(false) == ClassId) {
|
||||||
if (it->getClassRef(false) && it->getClassRef(false)->getBibMode() != BibFree) {
|
if (it->getClassRef(false) && it->getClassRef(false)->getBibMode() != BibFree) {
|
||||||
for (size_t i = 0; i < it->Runners.size(); i++) {
|
for (size_t i = 0; i < it->Runners.size(); i++) {
|
||||||
@ -4847,7 +4853,7 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sortTeams(ClassStartTime, 0, true); // Sort on first leg starttime and sortindex
|
sortTeams(ClassStartTimeClub, 0, true); // Sort on first leg starttime and sortindex
|
||||||
|
|
||||||
if (!firstNumber.empty()) {
|
if (!firstNumber.empty()) {
|
||||||
wchar_t pattern[32];
|
wchar_t pattern[32];
|
||||||
@ -4856,6 +4862,8 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
|||||||
for (auto it=Teams.begin(); it != Teams.end(); ++it) {
|
for (auto it=Teams.begin(); it != Teams.end(); ++it) {
|
||||||
if (it->isRemoved())
|
if (it->isRemoved())
|
||||||
continue;
|
continue;
|
||||||
|
if (!assignToVacant && it->isVacant())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (ClassId == 0 || it->getClassId(false) == ClassId) {
|
if (ClassId == 0 || it->getClassId(false) == ClassId) {
|
||||||
wchar_t bib[32];
|
wchar_t bib[32];
|
||||||
@ -4887,6 +4895,8 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::addAutoBib() {
|
void oEvent::addAutoBib() {
|
||||||
|
bool noBibToVacant = oe->getDCI().getInt("NoVacantBib") != 0;
|
||||||
|
|
||||||
sortRunners(ClassStartTimeClub);
|
sortRunners(ClassStartTimeClub);
|
||||||
oRunnerList::iterator it;
|
oRunnerList::iterator it;
|
||||||
int clsId = -1;
|
int clsId = -1;
|
||||||
@ -4907,6 +4917,7 @@ void oEvent::addAutoBib() {
|
|||||||
pClass cls = tit->getClassRef(false);
|
pClass cls = tit->getClassRef(false);
|
||||||
if (cls == 0)
|
if (cls == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
teamStartNo[tit->getId()] = tit->getStartNo();
|
teamStartNo[tit->getId()] = tit->getStartNo();
|
||||||
|
|
||||||
wstring bibInfo = cls->getDCI().getString("Bib");
|
wstring bibInfo = cls->getDCI().getString("Bib");
|
||||||
@ -4935,7 +4946,7 @@ void oEvent::addAutoBib() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sortTeams(ClassStartTime, 0, true); // Sort on first leg starttime and sortindex
|
sortTeams(ClassStartTimeClub, 0, true); // Sort on first leg starttime and sortindex
|
||||||
map<int, vector<pTeam> > cls2TeamList;
|
map<int, vector<pTeam> > cls2TeamList;
|
||||||
|
|
||||||
for (oTeamList::iterator tit = Teams.begin(); tit != Teams.end(); ++tit) {
|
for (oTeamList::iterator tit = Teams.begin(); tit != Teams.end(); ++tit) {
|
||||||
@ -5015,6 +5026,11 @@ void oEvent::addAutoBib() {
|
|||||||
else {
|
else {
|
||||||
bool lockedForking = cls->lockedForking();
|
bool lockedForking = cls->lockedForking();
|
||||||
for (size_t k = 0; k < tl.size(); k++) {
|
for (size_t k = 0; k < tl.size(); k++) {
|
||||||
|
|
||||||
|
if (noBibToVacant && tl[k]->isVacant()) {
|
||||||
|
tl[k]->getDI().setString("Bib", L""); //Remove only bib
|
||||||
|
}
|
||||||
|
else {
|
||||||
wchar_t buff[32];
|
wchar_t buff[32];
|
||||||
swprintf_s(buff, pattern, number);
|
swprintf_s(buff, pattern, number);
|
||||||
|
|
||||||
@ -5026,6 +5042,7 @@ void oEvent::addAutoBib() {
|
|||||||
tl[k]->setBib(buff, number, true);
|
tl[k]->setBib(buff, number, true);
|
||||||
}
|
}
|
||||||
number += interval;
|
number += interval;
|
||||||
|
}
|
||||||
tl[k]->applyBibs();
|
tl[k]->applyBibs();
|
||||||
tl[k]->evaluate(ChangeType::Update);
|
tl[k]->evaluate(ChangeType::Update);
|
||||||
}
|
}
|
||||||
@ -5046,7 +5063,7 @@ void oEvent::addAutoBib() {
|
|||||||
cls->synchronize(true);
|
cls->synchronize(true);
|
||||||
}
|
}
|
||||||
for (size_t k = 0; k < rl.size(); k++) {
|
for (size_t k = 0; k < rl.size(); k++) {
|
||||||
if (pattern[0]) {
|
if (pattern[0] && (!noBibToVacant || !rl[k]->isVacant())) {
|
||||||
wchar_t buff[32];
|
wchar_t buff[32];
|
||||||
swprintf_s(buff, pattern, number);
|
swprintf_s(buff, pattern, number);
|
||||||
rl[k]->setBib(buff, number, !locked);
|
rl[k]->setBib(buff, number, !locked);
|
||||||
@ -5267,18 +5284,72 @@ bool compareClubClassTeamName(const oRunner &a, const oRunner &b)
|
|||||||
return a.getClub()<b.getClub();
|
return a.getClub()<b.getClub();
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::assignCardInteractive(gdioutput &gdi, GUICALLBACK cb)
|
void oEvent::assignCardInteractive(gdioutput& gdi, GUICALLBACK cb, SortOrder& orderRunners)
|
||||||
{
|
{
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.dropLine(1);
|
gdi.dropLine(1);
|
||||||
gdi.addString("", 2, "Tilldelning av hyrbrickor");
|
gdi.addString("", 2, "Tilldelning av hyrbrickor");
|
||||||
|
|
||||||
|
class SortUpdate : public GuiHandler {
|
||||||
|
SortOrder& orderRunners;
|
||||||
|
oEvent* oe;
|
||||||
|
GUICALLBACK cb;
|
||||||
|
public:
|
||||||
|
SortUpdate(oEvent *oe, GUICALLBACK cb, SortOrder& orderRunners) :
|
||||||
|
orderRunners(orderRunners), cb(cb), oe(oe) { }
|
||||||
|
|
||||||
|
void handle(gdioutput& gdi, BaseInfo& info, GuiEventType type) final {
|
||||||
|
ListBoxInfo& lb = dynamic_cast<ListBoxInfo&>(info);
|
||||||
|
orderRunners = SortOrder(lb.data);
|
||||||
|
oe->assignCardInteractive(gdi, cb, orderRunners);
|
||||||
|
}
|
||||||
|
~SortUpdate() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (gdi.hasData("AssignCardMark")) {
|
||||||
|
gdi.restore("AssignCardRP", false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto h = make_shared<SortUpdate>(this, cb, orderRunners);
|
||||||
|
gdi.dropLine(0.5);
|
||||||
|
gdi.addSelection("Sorting", 200, 300, nullptr, L"Sortering:").setHandler(h);
|
||||||
|
|
||||||
|
vector<pair<wstring, size_t> > orders;
|
||||||
|
for (auto ord : MetaList::getOrderToSymbol()) {
|
||||||
|
if (ord.first != SortOrder::Custom && ord.first != SortOrder::ClassDefaultResult)
|
||||||
|
orders.push_back(make_pair(lang.tl(ord.second), ord.first));
|
||||||
|
}
|
||||||
|
sort(orders.begin(), orders.end());
|
||||||
|
orders.insert(orders.begin(), make_pair(lang.tl("Standard"), SortOrder::Custom));
|
||||||
|
|
||||||
|
gdi.addItem("Sorting", orders);
|
||||||
|
gdi.selectItemByData("Sorting", orderRunners);
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.setData("AssignCardMark", 1);
|
||||||
|
gdi.setRestorePoint("AssignCardRP");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderRunners == SortOrder::Custom) {
|
||||||
Runners.sort(compareClubClassTeamName);
|
Runners.sort(compareClubClassTeamName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CurrentSortOrder = orderRunners;
|
||||||
|
Runners.sort();
|
||||||
|
}
|
||||||
|
|
||||||
oRunnerList::iterator it;
|
oRunnerList::iterator it;
|
||||||
pClub lastClub=0;
|
pClub lastClub = nullptr;
|
||||||
|
pClass lastClass = nullptr;
|
||||||
|
|
||||||
|
const int px4 = gdi.scaleLength(4);
|
||||||
|
const int px450 = gdi.scaleLength(450);
|
||||||
|
|
||||||
int k = 0;
|
int k = 0;
|
||||||
|
bool groupByClub = orderRunners == SortOrder::Custom || orderRunners == ClubClassStartTime;
|
||||||
|
bool groupByClass = orderByClass(orderRunners);
|
||||||
|
|
||||||
for (it = Runners.begin(); it != Runners.end(); ++it) {
|
for (it = Runners.begin(); it != Runners.end(); ++it) {
|
||||||
|
|
||||||
if (it->skip() || it->getCardNo() || it->isVacant() || it->needNoCard())
|
if (it->skip() || it->getCardNo() || it->isVacant() || it->needNoCard())
|
||||||
@ -5287,28 +5358,43 @@ void oEvent::assignCardInteractive(gdioutput &gdi, GUICALLBACK cb)
|
|||||||
if (it->getStatus() == StatusDNS || it->getStatus() == StatusCANCEL || it->getStatus() == StatusNotCompetiting)
|
if (it->getStatus() == StatusDNS || it->getStatus() == StatusCANCEL || it->getStatus() == StatusNotCompetiting)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (it->Club!=lastClub) {
|
if (groupByClub && it->Club != lastClub) {
|
||||||
lastClub = it->Club;
|
lastClub = it->Club;
|
||||||
gdi.dropLine(0.5);
|
gdi.dropLine(0.5);
|
||||||
gdi.addString("", 1, it->getClub());
|
gdi.addStringUT(1, it->getClub());
|
||||||
|
}
|
||||||
|
else if (groupByClass && it->Class != lastClass) {
|
||||||
|
lastClass = it->getClassRef(true);
|
||||||
|
gdi.dropLine(0.5);
|
||||||
|
gdi.addStringUT(1, it->getClass(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring r;
|
wstring r;
|
||||||
if (it->Class)
|
if (!groupByClass && it->Class)
|
||||||
r += it->getClass(false) + L", ";
|
r += it->getClass(false) + L", ";
|
||||||
|
|
||||||
if (it->tInTeam) {
|
if (!groupByClub && it->Club)
|
||||||
r+=itow(it->tInTeam->getStartNo()) + L" " + it->tInTeam->getName() + L", ";
|
r += it->getClub() + L", ";
|
||||||
}
|
|
||||||
|
|
||||||
|
if (it->tInTeam) {
|
||||||
|
if (!it->tInTeam->getBib().empty())
|
||||||
|
r += it->tInTeam->getBib() + L" ";
|
||||||
|
|
||||||
|
r += it->tInTeam->getName() + L", ";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!it->getBib().empty())
|
||||||
|
r += it->getBib() + L" ";
|
||||||
|
}
|
||||||
r += it->getName() + L":";
|
r += it->getName() + L":";
|
||||||
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.addStringUT(0, r);
|
gdi.addStringUT(0, r);
|
||||||
char id[24];
|
char id[24];
|
||||||
sprintf_s(id, "*%d", k++);
|
sprintf_s(id, "*%d", k++);
|
||||||
|
|
||||||
gdi.addInput(max(gdi.getCX(), 450), gdi.getCY()-4,
|
gdi.addInput(max(gdi.getCX(), px450), gdi.getCY() - px4,
|
||||||
id, L"", 10, cb).setExtra(it->getId());
|
id, L"", 10, cb).setExtra(it->getId());
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
@ -5318,6 +5404,8 @@ void oEvent::assignCardInteractive(gdioutput &gdi, GUICALLBACK cb)
|
|||||||
|
|
||||||
if (k == 0)
|
if (k == 0)
|
||||||
gdi.addString("", 0, "Ingen löpare saknar bricka");
|
gdi.addString("", 0, "Ingen löpare saknar bricka");
|
||||||
|
|
||||||
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::calcUseStartSeconds()
|
void oEvent::calcUseStartSeconds()
|
||||||
|
|||||||
@ -726,7 +726,7 @@ public:
|
|||||||
inline bool useStartSeconds() const {return tUseStartSeconds;}
|
inline bool useStartSeconds() const {return tUseStartSeconds;}
|
||||||
void calcUseStartSeconds();
|
void calcUseStartSeconds();
|
||||||
|
|
||||||
void assignCardInteractive(gdioutput &gdi, GUICALLBACK cb);
|
void assignCardInteractive(gdioutput &gdi, GUICALLBACK cb, SortOrder& orderRunners);
|
||||||
|
|
||||||
int getPropertyInt(const char *name, int def);
|
int getPropertyInt(const char *name, int def);
|
||||||
const string &getPropertyString(const char *name, const string &def);
|
const string &getPropertyString(const char *name, const string &def);
|
||||||
@ -820,7 +820,7 @@ public:
|
|||||||
|
|
||||||
void checkOrderIdMultipleCourses(int ClassId);
|
void checkOrderIdMultipleCourses(int ClassId);
|
||||||
|
|
||||||
void addBib(int ClassId, int leg, const wstring &firstNumber);
|
void addBib(int ClassId, int leg, const wstring &firstNumber, bool assignVacant);
|
||||||
void addAutoBib();
|
void addAutoBib();
|
||||||
|
|
||||||
//Speaker functions.
|
//Speaker functions.
|
||||||
|
|||||||
@ -510,10 +510,13 @@ private:
|
|||||||
else {
|
else {
|
||||||
vector<pRunner> cr;
|
vector<pRunner> cr;
|
||||||
oe->getRunners(c_it->getId(), 0, cr, false);
|
oe->getRunners(c_it->getId(), 0, cr, false);
|
||||||
for (pRunner r : cr)
|
for (pRunner r : cr) {
|
||||||
|
if (r->getStatus() == StatusNotCompetiting || r->getStatus() == StatusCANCEL)
|
||||||
|
continue;
|
||||||
if (r->getStartGroup(true) == ci.startGroupId)
|
if (r->getStartGroup(true) == ci.startGroupId)
|
||||||
nr++;
|
nr++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ci.nVacant == -1 || !ci.nVacantSpecified || di.changedVacancyInfo) {
|
if (ci.nVacant == -1 || !ci.nVacantSpecified || di.changedVacancyInfo) {
|
||||||
// Auto initialize
|
// Auto initialize
|
||||||
@ -996,6 +999,7 @@ void oEvent::loadDrawSettings(const set<int> &classes, DrawInfo &drawInfo, vecto
|
|||||||
cInfo[k].nRunnersCourse = runnerPerCourse[cInfo[k].courseId];
|
cInfo[k].nRunnersCourse = runnerPerCourse[cInfo[k].courseId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::drawRemaining(DrawMethod method, bool placeAfter)
|
void oEvent::drawRemaining(DrawMethod method, bool placeAfter)
|
||||||
{
|
{
|
||||||
DrawType drawType = placeAfter ? DrawType::RemainingAfter : DrawType::RemainingBefore;
|
DrawType drawType = placeAfter ? DrawType::RemainingAfter : DrawType::RemainingBefore;
|
||||||
@ -1770,7 +1774,7 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
|||||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||||
int cid = it->getClassId(true);
|
int cid = it->getClassId(true);
|
||||||
if (!it->isRemoved() && clsId2Ix.count(cid)) {
|
if (!it->isRemoved() && clsId2Ix.count(cid)) {
|
||||||
if (it->getStatus() == StatusNotCompetiting)
|
if (it->getStatus() == StatusNotCompetiting || it->getStatus() == StatusCANCEL)
|
||||||
continue;
|
continue;
|
||||||
int ix = clsId2Ix[cid];
|
int ix = clsId2Ix[cid];
|
||||||
if (spec[ix].startGroup != 0 && it->getStartGroup(true) != spec[ix].startGroup)
|
if (spec[ix].startGroup != 0 && it->getStartGroup(true) != spec[ix].startGroup)
|
||||||
@ -1792,7 +1796,7 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
|||||||
|
|
||||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||||
if (!it->isRemoved() && clsId2Ix.count(it->getClassId(true))) {
|
if (!it->isRemoved() && clsId2Ix.count(it->getClassId(true))) {
|
||||||
if (it->getStatus() == StatusNotCompetiting)
|
if (it->getStatus() == StatusNotCompetiting || it->getStatus() == StatusCANCEL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int st = it->getStartTime();
|
int st = it->getStartTime();
|
||||||
|
|||||||
@ -1051,8 +1051,9 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
if (ccId <= 0)
|
if (ccId <= 0)
|
||||||
continue;
|
continue;
|
||||||
int crs = r->getCourse(false)->getId();
|
int crs = r->getCourse(false)->getId();
|
||||||
int time = p.getTimeInt() - r->getStartTime(); //XXX Team time
|
int time = p.getTimeInt() - r->getStartTime();
|
||||||
r->tOnCourseResults.emplace_back(ccId, courseCCid2CourseIx[make_pair(crs, ccId)], time);
|
int teamTotalTime = time + (r->tInTeam ? r->tInTeam->getTotalRunningTimeAtLegStart(r->tLeg, false) : 0);
|
||||||
|
r->tOnCourseResults.emplace_back(ccId, courseCCid2CourseIx[make_pair(crs, ccId)], time, teamTotalTime);
|
||||||
int clsId = r->getClassId(true);
|
int clsId = r->getClassId(true);
|
||||||
int leg = r->getLegNumber();
|
int leg = r->getLegNumber();
|
||||||
if (cls->getQualificationFinal())
|
if (cls->getQualificationFinal())
|
||||||
@ -1072,6 +1073,8 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
|
|
||||||
const set<int> &expectedCCid = classLeg2ExistingCCId[make_pair(clsId, leg)];
|
const set<int> &expectedCCid = classLeg2ExistingCCId[make_pair(clsId, leg)];
|
||||||
size_t nRT = 0;
|
size_t nRT = 0;
|
||||||
|
int teamTotalOff = r.tInTeam ? r.tInTeam->getTotalRunningTimeAtLegStart(r.tLeg, false) : 0;
|
||||||
|
|
||||||
for (auto &radioTimes : r.tOnCourseResults.res) {
|
for (auto &radioTimes : r.tOnCourseResults.res) {
|
||||||
if (expectedCCid.count(radioTimes.courseControlId))
|
if (expectedCCid.count(radioTimes.courseControlId))
|
||||||
nRT++;
|
nRT++;
|
||||||
@ -1091,8 +1094,9 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!added) {
|
if (!added) {
|
||||||
int time = p.getTimeInt() - r.getStartTime(); //XXX Team time
|
int time = p.getTimeInt() - r.getStartTime();
|
||||||
r.tOnCourseResults.emplace_back(ccId, p.tIndex, time);
|
int teamTotalTime = time + teamTotalOff;
|
||||||
|
r.tOnCourseResults.emplace_back(ccId, p.tIndex, time, teamTotalTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1101,11 +1105,13 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector<tuple<int, int, int>> timeRunnerIx;
|
vector<tuple<int, int, int>> timeRunnerIx;
|
||||||
|
vector<tuple<int, int, int>> totalTimeRunnerIx;
|
||||||
|
|
||||||
for (auto rList : runnerByClassLeg) {
|
for (auto rList : runnerByClassLeg) {
|
||||||
auto &rr = rList.second;
|
auto &rr = rList.second;
|
||||||
pClass cls = getClass(rList.first.first);
|
pClass cls = getClass(rList.first.first);
|
||||||
assert(cls);
|
assert(cls);
|
||||||
bool totRes = cls->getNumStages() > 1;
|
//bool totRes = cls->getNumStages() > 1;
|
||||||
|
|
||||||
set<int> &legCCId = classLeg2ExistingCCId[rList.first];
|
set<int> &legCCId = classLeg2ExistingCCId[rList.first];
|
||||||
legCCId.insert(oPunch::PunchFinish);
|
legCCId.insert(oPunch::PunchFinish);
|
||||||
@ -1113,18 +1119,17 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
// Leg with negative sign
|
// Leg with negative sign
|
||||||
int negLeg = 0;
|
int negLeg = 0;
|
||||||
timeRunnerIx.clear();
|
timeRunnerIx.clear();
|
||||||
|
totalTimeRunnerIx.clear();
|
||||||
|
|
||||||
int nRun = rr.size();
|
int nRun = rr.size();
|
||||||
if (ccId == oPunch::PunchFinish) {
|
if (ccId == oPunch::PunchFinish) {
|
||||||
negLeg = -1000; //Finish, smallest number
|
negLeg = -1000; //Finish, smallest number
|
||||||
for (int j = 0; j < nRun; j++) {
|
for (int j = 0; j < nRun; j++) {
|
||||||
auto r = rr[j];
|
auto r = rr[j];
|
||||||
if (r->prelStatusOK(true, false, false)) {
|
if (r->prelStatusOK(true, false, false)) {
|
||||||
int time;
|
int time = r->getRunningTime(true);
|
||||||
if (!r->tInTeam || !totRes)
|
int teamTotalTime = r->tInTeam ? r->tInTeam->getLegRunningTime(r->tLeg, true, false) : time;
|
||||||
time = r->getRunningTime(true);
|
|
||||||
else {
|
|
||||||
time = r->tInTeam->getLegRunningTime(r->tLeg, true, false);
|
|
||||||
}
|
|
||||||
int ix = -1;
|
int ix = -1;
|
||||||
int nr = r->tOnCourseResults.res.size();
|
int nr = r->tOnCourseResults.res.size();
|
||||||
for (int i = 0; i < nr; i++) {
|
for (int i = 0; i < nr; i++) {
|
||||||
@ -1139,9 +1144,10 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
pCourse crs = r->getCourse(false);
|
pCourse crs = r->getCourse(false);
|
||||||
if (crs)
|
if (crs)
|
||||||
nc = crs->getNumControls();
|
nc = crs->getNumControls();
|
||||||
r->tOnCourseResults.emplace_back(ccId, nc, time);
|
r->tOnCourseResults.emplace_back(ccId, nc, time, teamTotalTime);
|
||||||
}
|
}
|
||||||
timeRunnerIx.emplace_back(time, j, ix);
|
timeRunnerIx.emplace_back(time, j, ix);
|
||||||
|
totalTimeRunnerIx.emplace_back(teamTotalTime, j, ix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1152,12 +1158,16 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
for (int i = 0; i < nr; i++) {
|
for (int i = 0; i < nr; i++) {
|
||||||
if (r->tOnCourseResults.res[i].courseControlId == ccId) {
|
if (r->tOnCourseResults.res[i].courseControlId == ccId) {
|
||||||
timeRunnerIx.emplace_back(r->tOnCourseResults.res[i].time, j, i);
|
timeRunnerIx.emplace_back(r->tOnCourseResults.res[i].time, j, i);
|
||||||
|
totalTimeRunnerIx.emplace_back(r->tOnCourseResults.res[i].teamTotalTime, j, i);
|
||||||
|
|
||||||
negLeg = min(negLeg, -r->tOnCourseResults.res[i].controlIx);
|
negLeg = min(negLeg, -r->tOnCourseResults.res[i].controlIx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto computeResult = [&rr, &negLeg](vector<tuple<int, int, int>>& timeRunnerIx, bool total) {
|
||||||
sort(timeRunnerIx.begin(), timeRunnerIx.end());
|
sort(timeRunnerIx.begin(), timeRunnerIx.end());
|
||||||
|
|
||||||
int place = 0;
|
int place = 0;
|
||||||
@ -1174,6 +1184,11 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
}
|
}
|
||||||
auto r = rr[get<1>(timeRunnerIx[i])];
|
auto r = rr[get<1>(timeRunnerIx[i])];
|
||||||
int locIx = get<2>(timeRunnerIx[i]);
|
int locIx = get<2>(timeRunnerIx[i]);
|
||||||
|
if (total) {
|
||||||
|
r->tOnCourseResults.res[locIx].teamTotalPlace = place;
|
||||||
|
r->tOnCourseResults.res[locIx].teamTotalAfter = time - leadTime;
|
||||||
|
}
|
||||||
|
else {
|
||||||
r->tOnCourseResults.res[locIx].place = place;
|
r->tOnCourseResults.res[locIx].place = place;
|
||||||
r->tOnCourseResults.res[locIx].after = time - leadTime;
|
r->tOnCourseResults.res[locIx].after = time - leadTime;
|
||||||
|
|
||||||
@ -1184,5 +1199,10 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
computeResult(timeRunnerIx, false);
|
||||||
|
computeResult(totalTimeRunnerIx, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -331,7 +331,8 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
|||||||
break;
|
break;
|
||||||
case lPunchName:
|
case lPunchName:
|
||||||
case lControlName:
|
case lControlName:
|
||||||
case lPunchNamedTime: {
|
case lPunchNamedTime:
|
||||||
|
case lPunchTeamTotalNamedTime: {
|
||||||
wstring maxcn = lang.tl("Mål");
|
wstring maxcn = lang.tl("Mål");
|
||||||
vector<pControl> ctrl;
|
vector<pControl> ctrl;
|
||||||
oe->getControls(ctrl, false);
|
oe->getControls(ctrl, false);
|
||||||
@ -342,6 +343,8 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
|||||||
}
|
}
|
||||||
if (pps[k].type == lPunchNamedTime)
|
if (pps[k].type == lPunchNamedTime)
|
||||||
extra = maxcn + L": 50:50 (50:50)";
|
extra = maxcn + L": 50:50 (50:50)";
|
||||||
|
if (pps[k].type == lPunchTeamTotalNamedTime)
|
||||||
|
extra = maxcn + L": 2:50:50 (50:50)";
|
||||||
else
|
else
|
||||||
maxcn.swap(extra);
|
maxcn.swap(extra);
|
||||||
}
|
}
|
||||||
@ -366,6 +369,7 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
|||||||
case lRunnerTimeAdjustment:
|
case lRunnerTimeAdjustment:
|
||||||
case lRunnerGeneralTimeAfter:
|
case lRunnerGeneralTimeAfter:
|
||||||
case lPunchTotalTimeAfter:
|
case lPunchTotalTimeAfter:
|
||||||
|
case lPunchTeamTotalTimeAfter:
|
||||||
extra = L"+10:00";
|
extra = L"+10:00";
|
||||||
break;
|
break;
|
||||||
case lTeamRogainingPointOvertime:
|
case lTeamRogainingPointOvertime:
|
||||||
@ -390,12 +394,15 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
|||||||
case lRunnerStageStatus:
|
case lRunnerStageStatus:
|
||||||
case lRunnerTimePlaceFixed:
|
case lRunnerTimePlaceFixed:
|
||||||
case lPunchLostTime:
|
case lPunchLostTime:
|
||||||
case lPunchTotalTime:
|
|
||||||
case lPunchTimeSinceLast:
|
case lPunchTimeSinceLast:
|
||||||
case lPunchSplitTime:
|
case lPunchSplitTime:
|
||||||
case lPunchNamedSplit:
|
case lPunchNamedSplit:
|
||||||
extra = L"50:50";
|
extra = L"50:50";
|
||||||
break;
|
break;
|
||||||
|
case lPunchTotalTime:
|
||||||
|
case lPunchTeamTotalTime:
|
||||||
|
extra = L"1:50:50";
|
||||||
|
break;
|
||||||
case lRunnerGeneralTimeStatus:
|
case lRunnerGeneralTimeStatus:
|
||||||
case lClassStartTimeRange:
|
case lClassStartTimeRange:
|
||||||
extra = L"50:50 (50:50)";
|
extra = L"50:50 (50:50)";
|
||||||
@ -415,6 +422,7 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
|||||||
case lTeamTotalPlace:
|
case lTeamTotalPlace:
|
||||||
case lPunchControlPlace:
|
case lPunchControlPlace:
|
||||||
case lPunchControlPlaceAcc:
|
case lPunchControlPlaceAcc:
|
||||||
|
case lPunchControlPlaceTeamAcc:
|
||||||
case lRunnerStagePlace:
|
case lRunnerStagePlace:
|
||||||
extra = L"99.";
|
extra = L"99.";
|
||||||
break;
|
break;
|
||||||
@ -517,7 +525,7 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
|||||||
pp.linearLegIndex = true;
|
pp.linearLegIndex = true;
|
||||||
int numIter = 1;
|
int numIter = 1;
|
||||||
|
|
||||||
if (pp.type == lPunchNamedTime || pp.type == lPunchTime) {
|
if (pp.type == lPunchNamedTime || pp.type == lPunchTime || pp.type == lPunchTeamTime) {
|
||||||
row[k] = max(row[k], 10);
|
row[k] = max(row[k], 10);
|
||||||
pRunner r = pRunner(&*it);
|
pRunner r = pRunner(&*it);
|
||||||
numIter = (r && r->getCard()) ? r->getCard()->getNumPunches() + 1 : 1;
|
numIter = (r && r->getCard()) ? r->getCard()->getNumPunches() + 1 : 1;
|
||||||
@ -693,14 +701,16 @@ const wstring &oEvent::formatPunchStringAux(const oPrintPost &pp, const oListPar
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case lPunchTime:
|
case lPunchTime:
|
||||||
|
case lPunchTeamTime:
|
||||||
case lPunchControlNumber:
|
case lPunchControlNumber:
|
||||||
case lPunchControlCode:
|
case lPunchControlCode:
|
||||||
case lPunchLostTime:
|
case lPunchLostTime:
|
||||||
case lPunchControlPlace:
|
case lPunchControlPlace:
|
||||||
case lPunchControlPlaceAcc:
|
case lPunchControlPlaceAcc:
|
||||||
|
case lPunchControlPlaceTeamAcc:
|
||||||
case lPunchSplitTime:
|
case lPunchSplitTime:
|
||||||
case lPunchTotalTime:
|
case lPunchTotalTime:
|
||||||
|
case lPunchTeamTotalTime:
|
||||||
case lPunchAbsTime:
|
case lPunchAbsTime:
|
||||||
if (punch && r && !invalidClass) {
|
if (punch && r && !invalidClass) {
|
||||||
if (punch->tIndex >= 0) {
|
if (punch->tIndex >= 0) {
|
||||||
@ -710,9 +720,14 @@ const wstring &oEvent::formatPunchStringAux(const oPrintPost &pp, const oListPar
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (pp.type) {
|
switch (pp.type) {
|
||||||
case lPunchTime: {
|
case lPunchTime:
|
||||||
|
case lPunchTeamTime: {
|
||||||
if (punch->hasTime()) {
|
if (punch->hasTime()) {
|
||||||
swprintf_s(bfw, L"\u2013 (%s)", formatTime(punch->getTimeInt() - r->getStartTime()).c_str());
|
int off = 0;
|
||||||
|
if (pp.type == lPunchTeamTime && r->getTeam())
|
||||||
|
off = r->getTeam()->getTotalRunningTimeAtLegStart(r->getLegNumber(), false);
|
||||||
|
|
||||||
|
swprintf_s(bfw, L"\u2013 (%s)", formatTime(off + punch->getTimeInt() - r->getStartTime(), SubSecond::Off).c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wsptr = &makeDash(L"- (-)");
|
wsptr = &makeDash(L"- (-)");
|
||||||
@ -733,12 +748,24 @@ const wstring &oEvent::formatPunchStringAux(const oPrintPost &pp, const oListPar
|
|||||||
}
|
}
|
||||||
case lPunchAbsTime: {
|
case lPunchAbsTime: {
|
||||||
if (punch->hasTime())
|
if (punch->hasTime())
|
||||||
wsptr = &getAbsTime(punch->getTimeInt());
|
wsptr = &getAbsTime(punch->getTimeInt(), SubSecond::Off);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lPunchTotalTime: {
|
case lPunchTotalTime: {
|
||||||
if (punch->hasTime())
|
if (punch->hasTime())
|
||||||
wsptr = &formatTime(punch->getTimeInt() - r->getStartTime());
|
wsptr = &formatTime(punch->getTimeInt() - r->getStartTime(), SubSecond::Off);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case lPunchTeamTotalTime: {
|
||||||
|
if (punch->hasTime()) {
|
||||||
|
pTeam t = r->getTeam();
|
||||||
|
if (!t || r->getLegNumber() == 0)
|
||||||
|
wsptr = &formatTime(punch->getTimeInt() - r->getStartTime(), SubSecond::Off);
|
||||||
|
else {
|
||||||
|
int input = t->getTotalRunningTimeAtLegStart(r->getLegNumber(), false);
|
||||||
|
wsptr = &formatTime(input + punch->getTimeInt() - r->getStartTime(), SubSecond::Off);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -865,6 +892,11 @@ const wstring &oEvent::formatSpecialStringAux(const oPrintPost &pp, const oListP
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case lCourseNumControls:
|
||||||
|
if (pc)
|
||||||
|
wsptr = &itow(pc->getNumControls());
|
||||||
|
break;
|
||||||
|
|
||||||
case lCourseClasses:
|
case lCourseClasses:
|
||||||
if (pc) {
|
if (pc) {
|
||||||
vector<pClass> cls;
|
vector<pClass> cls;
|
||||||
@ -1175,11 +1207,21 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case lCourseClimb:
|
case lCourseClimb:
|
||||||
|
case lCourseUsageNoVacant:
|
||||||
|
case lCourseUsage:
|
||||||
if (r) {
|
if (r) {
|
||||||
pCourse crs = r->getCourse(false);
|
pCourse crs = r->getCourse(false);
|
||||||
return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter);
|
return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case lCourseNumControls:
|
||||||
|
if (r) {
|
||||||
|
pCourse crs = r->getCourse(true);
|
||||||
|
return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case lCourseShortening:
|
case lCourseShortening:
|
||||||
if (r) {
|
if (r) {
|
||||||
int sh = r->getNumShortening();
|
int sh = r->getNumShortening();
|
||||||
@ -2259,17 +2301,22 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
case lControlName:
|
case lControlName:
|
||||||
case lPunchName:
|
case lPunchName:
|
||||||
case lPunchNamedTime:
|
case lPunchNamedTime:
|
||||||
|
case lPunchTeamTotalNamedTime:
|
||||||
case lPunchNamedSplit:
|
case lPunchNamedSplit:
|
||||||
case lPunchTime:
|
case lPunchTime:
|
||||||
|
case lPunchTeamTime:
|
||||||
case lPunchSplitTime:
|
case lPunchSplitTime:
|
||||||
case lPunchTotalTime:
|
case lPunchTotalTime:
|
||||||
|
case lPunchTeamTotalTime:
|
||||||
case lPunchControlNumber:
|
case lPunchControlNumber:
|
||||||
case lPunchControlCode:
|
case lPunchControlCode:
|
||||||
case lPunchLostTime:
|
case lPunchLostTime:
|
||||||
case lPunchControlPlace:
|
case lPunchControlPlace:
|
||||||
case lPunchControlPlaceAcc:
|
case lPunchControlPlaceAcc:
|
||||||
|
case lPunchControlPlaceTeamAcc:
|
||||||
case lPunchAbsTime:
|
case lPunchAbsTime:
|
||||||
case lPunchTotalTimeAfter:
|
case lPunchTotalTimeAfter:
|
||||||
|
case lPunchTeamTotalTimeAfter:
|
||||||
if (r && r->getCourse(false) && !invalidClass) {
|
if (r && r->getCourse(false) && !invalidClass) {
|
||||||
const pCourse crs=r->getCourse(true);
|
const pCourse crs=r->getCourse(true);
|
||||||
const oControl *ctrl = nullptr;
|
const oControl *ctrl = nullptr;
|
||||||
@ -2281,22 +2328,23 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
}
|
}
|
||||||
switch (pp.type) {
|
switch (pp.type) {
|
||||||
case lPunchNamedSplit:
|
case lPunchNamedSplit:
|
||||||
if (ctrl && ctrl->hasName() && r->getPunchTime(counter.level3, false, true) > 0) {
|
if (ctrl && ctrl->hasName() && r->getPunchTime(counter.level3, false, true, false) > 0) {
|
||||||
swprintf_s(wbf, L"%s", r->getNamedSplitS(counter.level3).c_str());
|
swprintf_s(wbf, L"%s", r->getNamedSplitS(counter.level3, SubSecond::Off).c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lPunchNamedTime:
|
case lPunchNamedTime:
|
||||||
if (ctrl && ctrl->hasName() && (!par.lineBreakControlList || r->getPunchTime(counter.level3, false, true) > 0)) {
|
case lPunchTeamTotalNamedTime:
|
||||||
|
if (ctrl && ctrl->hasName() && (!par.lineBreakControlList || r->getPunchTime(counter.level3, false, true, false) > 0)) {
|
||||||
swprintf_s(wbf, L"%s: %s (%s)", ctrl->getName().c_str(),
|
swprintf_s(wbf, L"%s: %s (%s)", ctrl->getName().c_str(),
|
||||||
r->getNamedSplitS(counter.level3).c_str(),
|
r->getNamedSplitS(counter.level3, SubSecond::Off).c_str(),
|
||||||
r->getPunchTimeS(counter.level3, false, true, SubSecond::Off).c_str());
|
r->getPunchTimeS(counter.level3, false, true, pp.type == lPunchTeamTotalNamedTime, SubSecond::Off).c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lControlName:
|
case lControlName:
|
||||||
case lPunchName:
|
case lPunchName:
|
||||||
if (ctrl && ctrl->hasName() && (!par.lineBreakControlList || r->getPunchTime(counter.level3, false, true) > 0)) {
|
if (ctrl && ctrl->hasName() && (!par.lineBreakControlList || r->getPunchTime(counter.level3, false, true, false) > 0)) {
|
||||||
swprintf_s(wbf, L"%s", ctrl->getName().c_str());
|
swprintf_s(wbf, L"%s", ctrl->getName().c_str());
|
||||||
}
|
}
|
||||||
else if (counter.level3 == nCtrl) {
|
else if (counter.level3 == nCtrl) {
|
||||||
@ -2304,27 +2352,30 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lPunchTime: {
|
case lPunchTime:
|
||||||
|
case lPunchTeamTime: {
|
||||||
swprintf_s(wbf, L"%s (%s)",
|
swprintf_s(wbf, L"%s (%s)",
|
||||||
r->getSplitTimeS(counter.level3, false).c_str(),
|
r->getSplitTimeS(counter.level3, false, SubSecond::Off).c_str(),
|
||||||
r->getPunchTimeS(counter.level3, false, true, SubSecond::Off).c_str());
|
r->getPunchTimeS(counter.level3, false, true, pp.type == lPunchTeamTime, SubSecond::Off).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lPunchSplitTime: {
|
case lPunchSplitTime: {
|
||||||
wcscpy_s(wbf, r->getSplitTimeS(counter.level3, false).c_str());
|
wcscpy_s(wbf, r->getSplitTimeS(counter.level3, false, SubSecond::Off).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lPunchTotalTime: {
|
case lPunchTotalTime:
|
||||||
if (r->getPunchTime(counter.level3, false, true) > 0) {
|
case lPunchTeamTotalTime: {
|
||||||
wcscpy_s(wbf, r->getPunchTimeS(counter.level3, false, true, SubSecond::Off).c_str());
|
int pt = r->getPunchTime(counter.level3, false, true, pp.type == lPunchTeamTotalTime);
|
||||||
}
|
if (pt > 0)
|
||||||
|
wsptr = &formatTime(pt, SubSecond::Off);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lPunchTotalTimeAfter: {
|
case lPunchTotalTimeAfter:
|
||||||
if (r->getPunchTime(counter.level3, false, true) > 0) {
|
case lPunchTeamTotalTimeAfter: {
|
||||||
int rt = r->getLegTimeAfterAcc(counter.level3);
|
if (r->getPunchTime(counter.level3, false, true, false) > 0) {
|
||||||
|
int rt = r->getLegTimeAfterAcc(counter.level3, pp.type == lPunchTeamTotalTimeAfter);
|
||||||
if (rt > 0)
|
if (rt > 0)
|
||||||
wcscpy_s(wbf, (L"+" + formatTime(rt)).c_str());
|
wcscpy_s(wbf, (L"+" + formatTime(rt, SubSecond::Off)).c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2350,8 +2401,9 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
swprintf_s(wbf, L"%d", p);
|
swprintf_s(wbf, L"%d", p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lPunchControlPlaceAcc: {
|
case lPunchControlPlaceAcc:
|
||||||
int p = r->getLegPlaceAcc(counter.level3);
|
case lPunchControlPlaceTeamAcc: {
|
||||||
|
int p = r->getLegPlaceAcc(counter.level3, pp.type == lPunchControlPlaceTeamAcc);
|
||||||
if (p > 0)
|
if (p > 0)
|
||||||
swprintf_s(wbf, L"%d", p);
|
swprintf_s(wbf, L"%d", p);
|
||||||
break;
|
break;
|
||||||
@ -2361,7 +2413,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lPunchAbsTime: {
|
case lPunchAbsTime: {
|
||||||
int t = r->getPunchTime(counter.level3, false, true);
|
int t = r->getPunchTime(counter.level3, false, true, false);
|
||||||
if (t > 0)
|
if (t > 0)
|
||||||
wsptr = &getAbsTime(r->tStartTime + t);
|
wsptr = &getAbsTime(r->tStartTime + t);
|
||||||
break;
|
break;
|
||||||
@ -3360,7 +3412,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
|||||||
}
|
}
|
||||||
else if (li.listSubType == li.EBaseTypeCoursePunches ||
|
else if (li.listSubType == li.EBaseTypeCoursePunches ||
|
||||||
li.listSubType == li.EBaseTypeAllPunches) {
|
li.listSubType == li.EBaseTypeAllPunches) {
|
||||||
pRunner r = it->Runners.empty() ? 0 : it->Runners[0];
|
pRunner r = it->getRunner(linearLegSpec);
|
||||||
if (!r)
|
if (!r)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,7 @@ enum EPostType {
|
|||||||
lCourseUsage,
|
lCourseUsage,
|
||||||
lCourseUsageNoVacant,
|
lCourseUsageNoVacant,
|
||||||
lCourseClasses,
|
lCourseClasses,
|
||||||
|
lCourseNumControls,
|
||||||
lRunnerName,
|
lRunnerName,
|
||||||
lRunnerGivenName,
|
lRunnerGivenName,
|
||||||
lRunnerFamilyName,
|
lRunnerFamilyName,
|
||||||
@ -172,19 +173,28 @@ enum EPostType {
|
|||||||
lTeamPlaceDiff,
|
lTeamPlaceDiff,
|
||||||
|
|
||||||
lPunchNamedTime,
|
lPunchNamedTime,
|
||||||
|
lPunchTeamTotalNamedTime,
|
||||||
lPunchNamedSplit,
|
lPunchNamedSplit,
|
||||||
|
|
||||||
lPunchName,
|
lPunchName,
|
||||||
|
|
||||||
lPunchTime,
|
lPunchTime,
|
||||||
|
lPunchTeamTime,
|
||||||
|
|
||||||
lPunchControlNumber,
|
lPunchControlNumber,
|
||||||
lPunchControlCode,
|
lPunchControlCode,
|
||||||
lPunchLostTime,
|
lPunchLostTime,
|
||||||
lPunchControlPlace,
|
lPunchControlPlace,
|
||||||
lPunchControlPlaceAcc,
|
lPunchControlPlaceAcc,
|
||||||
|
lPunchControlPlaceTeamAcc,
|
||||||
|
|
||||||
lPunchSplitTime,
|
lPunchSplitTime,
|
||||||
lPunchTotalTime,
|
lPunchTotalTime,
|
||||||
lPunchTotalTimeAfter,
|
lPunchTotalTimeAfter,
|
||||||
|
|
||||||
|
lPunchTeamTotalTime,
|
||||||
|
lPunchTeamTotalTimeAfter,
|
||||||
|
|
||||||
lPunchAbsTime,
|
lPunchAbsTime,
|
||||||
lPunchTimeSinceLast,
|
lPunchTimeSinceLast,
|
||||||
|
|
||||||
|
|||||||
137
code/oRunner.cpp
137
code/oRunner.cpp
@ -2027,19 +2027,9 @@ bool oRunner::operator<(const oRunner &c) const {
|
|||||||
pClub cl = getClubRef();
|
pClub cl = getClubRef();
|
||||||
pClub ocl = c.getClubRef();
|
pClub ocl = c.getClubRef();
|
||||||
if (cl != ocl) {
|
if (cl != ocl) {
|
||||||
if (cl == nullptr && ocl)
|
int cres = compareClubs(cl, ocl);
|
||||||
return true;
|
if (cres != 2)
|
||||||
else if (ocl == nullptr)
|
return cres != 0;
|
||||||
return false;
|
|
||||||
|
|
||||||
const wstring a = cl->getName();
|
|
||||||
const wstring b = ocl->getName();
|
|
||||||
int res = CompareString(LOCALE_USER_DEFAULT, 0,
|
|
||||||
a.c_str(), a.length(),
|
|
||||||
b.c_str(), b.length());
|
|
||||||
|
|
||||||
if (res != CSTR_EQUAL)
|
|
||||||
return res == CSTR_LESS_THAN;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2401,7 +2391,9 @@ bool oRunner::operator<(const oRunner &c) const {
|
|||||||
else return tStartTime < c.tStartTime;
|
else return tStartTime < c.tStartTime;
|
||||||
}
|
}
|
||||||
else if (Club != c.Club) {
|
else if (Club != c.Club) {
|
||||||
return getClub() < c.getClub();
|
int cres = compareClubs(Club, c.Club);
|
||||||
|
if (cres != 2)
|
||||||
|
return cres != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (oe->CurrentSortOrder == ClassTeamLeg) {
|
else if (oe->CurrentSortOrder == ClassTeamLeg) {
|
||||||
@ -4173,11 +4165,11 @@ int oRunner::getSplitTime(int controlNumber, bool normalized) const
|
|||||||
{
|
{
|
||||||
if (!Card) {
|
if (!Card) {
|
||||||
if (controlNumber == 0)
|
if (controlNumber == 0)
|
||||||
return getPunchTime(0, false, true);
|
return getPunchTime(0, false, true, false);
|
||||||
else {
|
else {
|
||||||
int ct = getPunchTime(controlNumber, false, true);
|
int ct = getPunchTime(controlNumber, false, true, false);
|
||||||
if (ct > 0) {
|
if (ct > 0) {
|
||||||
int dt = getPunchTime(controlNumber - 1, false, true);
|
int dt = getPunchTime(controlNumber - 1, false, true, false);
|
||||||
if (dt > 0 && ct > dt)
|
if (dt > 0 && ct > dt)
|
||||||
return ct - dt;
|
return ct - dt;
|
||||||
}
|
}
|
||||||
@ -4219,7 +4211,7 @@ int oRunner::getNamedSplit(int controlNumber) const {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int k=controlNumber-1;
|
int k=controlNumber-1;
|
||||||
int ct = getPunchTime(controlNumber, false, true);
|
int ct = getPunchTime(controlNumber, false, true, false);
|
||||||
if (ct <= 0)
|
if (ct <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -4228,7 +4220,7 @@ int oRunner::getNamedSplit(int controlNumber) const {
|
|||||||
pControl c = crs->Controls[k];
|
pControl c = crs->Controls[k];
|
||||||
|
|
||||||
if (c && c->hasName()) {
|
if (c && c->hasName()) {
|
||||||
int dt = getPunchTime(k, false, true);
|
int dt = getPunchTime(k, false, true, false);
|
||||||
if (dt > 0 && ct > dt)
|
if (dt > 0 && ct > dt)
|
||||||
return max(ct - dt, -1);
|
return max(ct - dt, -1);
|
||||||
else return -1;
|
else return -1;
|
||||||
@ -4240,52 +4232,53 @@ int oRunner::getNamedSplit(int controlNumber) const {
|
|||||||
return ct;
|
return ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring oRunner::getSplitTimeS(int controlNumber, bool normalized) const
|
const wstring &oRunner::getSplitTimeS(int controlNumber, bool normalized, SubSecond mode) const
|
||||||
{
|
{
|
||||||
return formatTime(getSplitTime(controlNumber, normalized));
|
return formatTime(getSplitTime(controlNumber, normalized), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring oRunner::getNamedSplitS(int controlNumber) const
|
const wstring &oRunner::getNamedSplitS(int controlNumber, SubSecond mode) const
|
||||||
{
|
{
|
||||||
return formatTime(getNamedSplit(controlNumber));
|
return formatTime(getNamedSplit(controlNumber), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int oRunner::getPunchTime(int controlNumber, bool normalized, bool adjusted) const
|
int oRunner::getPunchTime(int controlIndex, bool normalized, bool adjusted, bool teamTotal) const
|
||||||
{
|
{
|
||||||
|
int off = teamTotal && tInTeam ? tInTeam->getTotalRunningTimeAtLegStart(getLegNumber(), false) : 0;
|
||||||
|
|
||||||
if (!Card) {
|
if (!Card) {
|
||||||
pCourse pc = getCourse(false);
|
pCourse pc = getCourse(false);
|
||||||
if (!pc || controlNumber > pc->getNumControls())
|
if (!pc || controlIndex > pc->getNumControls())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (controlNumber == pc->getNumControls())
|
if (controlIndex == pc->getNumControls())
|
||||||
return getFinishTime() - tStartTime;
|
return getFinishTime() - tStartTime + off;
|
||||||
|
|
||||||
int ccId = pc->getCourseControlId(controlNumber);
|
int ccId = pc->getCourseControlId(controlIndex);
|
||||||
pFreePunch fp = oe->getPunch(Id, ccId, getCardNo());
|
pFreePunch fp = oe->getPunch(Id, ccId, getCardNo());
|
||||||
if (fp)
|
if (fp)
|
||||||
return fp->getTimeInt() - tStartTime;
|
return fp->getTimeInt() - tStartTime + off;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
const vector<SplitData> &st = getSplitTimes(normalized);
|
const vector<SplitData> &st = getSplitTimes(normalized);
|
||||||
|
|
||||||
if (unsigned(controlNumber) < st.size()) {
|
if (unsigned(controlIndex) < st.size()) {
|
||||||
if (st[controlNumber].hasTime())
|
if (st[controlIndex].hasTime())
|
||||||
return st[controlNumber].getTime(adjusted) - tStartTime;
|
return st[controlIndex].getTime(adjusted) - tStartTime + off;
|
||||||
else return -1;
|
else return -1;
|
||||||
}
|
}
|
||||||
else if (unsigned(controlNumber) == st.size())
|
else if (unsigned(controlIndex) == st.size())
|
||||||
return FinishTime - tStartTime;
|
return FinishTime - tStartTime + off;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring oRunner::getPunchTimeS(int controlNumber, bool normalized, bool adjusted, SubSecond mode) const
|
const wstring &oRunner::getPunchTimeS(int controlIndex, bool normalized, bool adjusted,
|
||||||
{
|
bool teamTotal, SubSecond mode) const {
|
||||||
return formatTime(getPunchTime(controlNumber, normalized, adjusted), mode);
|
return formatTime(getPunchTime(controlIndex, normalized, adjusted, teamTotal), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oAbstractRunner::isVacant() const
|
bool oAbstractRunner::isVacant() const {
|
||||||
{
|
|
||||||
int vacClub = oe->getVacantClubIfExist(false);
|
int vacClub = oe->getVacantClubIfExist(false);
|
||||||
return vacClub > 0 && getClubId()==vacClub;
|
return vacClub > 0 && getClubId()==vacClub;
|
||||||
}
|
}
|
||||||
@ -4409,7 +4402,8 @@ void oRunner::fillSpeakerObject(int leg, int courseControlId, int previousContro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pRunner oEvent::findRunner(const wstring &s, int lastId, const unordered_set<int> &inputFilter,
|
pRunner oEvent::findRunner(const wstring &s, int lastId,
|
||||||
|
const unordered_set<int> &inputFilter,
|
||||||
unordered_set<int> &matchFilter) const
|
unordered_set<int> &matchFilter) const
|
||||||
{
|
{
|
||||||
matchFilter.clear();
|
matchFilter.clear();
|
||||||
@ -4418,7 +4412,7 @@ pRunner oEvent::findRunner(const wstring &s, int lastId, const unordered_set<int
|
|||||||
int sn = _wtoi(trm.c_str());
|
int sn = _wtoi(trm.c_str());
|
||||||
wchar_t s_lc[1024];
|
wchar_t s_lc[1024];
|
||||||
wcscpy_s(s_lc, s.c_str());
|
wcscpy_s(s_lc, s.c_str());
|
||||||
CharLowerBuff(s_lc, len);
|
prepareMatchString(s_lc, len);
|
||||||
int score;
|
int score;
|
||||||
pRunner res = 0;
|
pRunner res = 0;
|
||||||
|
|
||||||
@ -4929,7 +4923,7 @@ void oRunner::printSplits(gdioutput& gdi, const oListInfo* li) const {
|
|||||||
if (pc) {
|
if (pc) {
|
||||||
for (int n = 0; n < pc->nControls; n++) {
|
for (int n = 0; n < pc->nControls; n++) {
|
||||||
spMax = max(spMax, getSplitTime(n, false));
|
spMax = max(spMax, getSplitTime(n, false));
|
||||||
totMax = max(totMax, getPunchTime(n, false, false));
|
totMax = max(totMax, getPunchTime(n, false, false, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool moreThanHour = max(totMax, getRunningTime(true)) >= timeConstHour;
|
bool moreThanHour = max(totMax, getRunningTime(true)) >= timeConstHour;
|
||||||
@ -5082,7 +5076,7 @@ void oRunner::printSplits(gdioutput& gdi, const oListInfo* li) const {
|
|||||||
adjust = getTimeAdjust(controlLegIndex);
|
adjust = getTimeAdjust(controlLegIndex);
|
||||||
sp = getSplitTime(controlLegIndex, false);
|
sp = getSplitTime(controlLegIndex, false);
|
||||||
if (sp > 0) {
|
if (sp > 0) {
|
||||||
punchTime = getPunchTimeS(controlLegIndex, false, false, SubSecond::Off);
|
punchTime = getPunchTimeS(controlLegIndex, false, false, false, SubSecond::Off);
|
||||||
gdi.addStringUT(cy, cx + c2, fontSmall | textRight, formatTime(sp, SubSecond::Off));
|
gdi.addStringUT(cy, cx + c2, fontSmall | textRight, formatTime(sp, SubSecond::Off));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5807,7 +5801,7 @@ void oRunner::getLegTimeAfter(vector<int> ×) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oRunner::getLegTimeAfterAcc(vector<int> ×) const
|
void oRunner::getLegTimeAfterAcc(vector<ResultData> ×) const
|
||||||
{
|
{
|
||||||
times.clear();
|
times.clear();
|
||||||
if (splitTimes.empty() || !Class || tStartTime<=0)
|
if (splitTimes.empty() || !Class || tStartTime<=0)
|
||||||
@ -5835,6 +5829,9 @@ void oRunner::getLegTimeAfterAcc(vector<int> ×) const
|
|||||||
//xxx reorder output
|
//xxx reorder output
|
||||||
times.resize(nc+1);
|
times.resize(nc+1);
|
||||||
|
|
||||||
|
bool isRelayTeam = tInTeam != nullptr;
|
||||||
|
int off = tInTeam ? tInTeam->getTotalRunningTimeAtLegStart(tLeg, false) : 0;
|
||||||
|
|
||||||
for (unsigned k = 0; k<=nc; k++) {
|
for (unsigned k = 0; k<=nc; k++) {
|
||||||
int s = 0;
|
int s = 0;
|
||||||
if (k < sp.size())
|
if (k < sp.size())
|
||||||
@ -5843,18 +5840,27 @@ void oRunner::getLegTimeAfterAcc(vector<int> ×) const
|
|||||||
s = FinishTime;
|
s = FinishTime;
|
||||||
|
|
||||||
if (s>0) {
|
if (s>0) {
|
||||||
times[k] = s - tStartTime - leaders[k];
|
times[k].data = s - tStartTime - leaders[k];
|
||||||
if (times[k]<0)
|
if (times[k].data < 0)
|
||||||
times[k] = -1;
|
times[k].data = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
times[k] = -1;
|
times[k].data = -1;
|
||||||
|
|
||||||
|
if (!isRelayTeam || times[k].data < 0)
|
||||||
|
times[k].teamTotalData = times[k].data;
|
||||||
|
else {
|
||||||
|
if (k < nc)
|
||||||
|
times[k].teamTotalData = s - tStartTime + off - cls->getAccLegControlLeader(tLeg, pc->getCourseControlId(k));
|
||||||
|
else
|
||||||
|
times[k].teamTotalData = s - tStartTime + off - cls->getAccLegControlLeader(tLeg, oPunch::PunchFinish);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalized order
|
// Normalized order
|
||||||
const vector<int> &reorder = getCourse(true)->getMapToOriginalOrder();
|
const vector<int> &reorder = getCourse(true)->getMapToOriginalOrder();
|
||||||
if (!reorder.empty()) {
|
if (!reorder.empty()) {
|
||||||
vector<int> orderedTimes(times.size());
|
vector<ResultData> orderedTimes(times.size());
|
||||||
for (size_t k = 0; k < min(reorder.size(), times.size()); k++) {
|
for (size_t k = 0; k < min(reorder.size(), times.size()); k++) {
|
||||||
orderedTimes[k] = times[reorder[k]];
|
orderedTimes[k] = times[reorder[k]];
|
||||||
}
|
}
|
||||||
@ -5862,7 +5868,7 @@ void oRunner::getLegTimeAfterAcc(vector<int> ×) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oRunner::getLegPlacesAcc(vector<int> &places) const
|
void oRunner::getLegPlacesAcc(vector<ResultData> &places) const
|
||||||
{
|
{
|
||||||
places.clear();
|
places.clear();
|
||||||
pCourse pc = getCourse(false);
|
pCourse pc = getCourse(false);
|
||||||
@ -5880,6 +5886,10 @@ void oRunner::getLegPlacesAcc(vector<int> &places) const
|
|||||||
const unsigned nc = pc->getNumControls();
|
const unsigned nc = pc->getNumControls();
|
||||||
const vector<SplitData> &sp = getSplitTimes(true);
|
const vector<SplitData> &sp = getSplitTimes(true);
|
||||||
places.resize(nc+1);
|
places.resize(nc+1);
|
||||||
|
|
||||||
|
bool isRelayTeam = tInTeam != nullptr;
|
||||||
|
int off = tInTeam ? tInTeam->getTotalRunningTimeAtLegStart(tLeg, false) : 0;
|
||||||
|
|
||||||
for (unsigned k = 0; k<=nc; k++) {
|
for (unsigned k = 0; k<=nc; k++) {
|
||||||
int s = 0;
|
int s = 0;
|
||||||
if (k < sp.size())
|
if (k < sp.size())
|
||||||
@ -5890,17 +5900,24 @@ void oRunner::getLegPlacesAcc(vector<int> &places) const
|
|||||||
if (s>0) {
|
if (s>0) {
|
||||||
int time = s - tStartTime;
|
int time = s - tStartTime;
|
||||||
|
|
||||||
if (time>0)
|
if (time > 0) {
|
||||||
places[k] = cls->getAccLegPlace(id, k, time);
|
places[k].data = cls->getAccLegPlace(id, k, time);
|
||||||
|
if (k < nc)
|
||||||
|
places[k].teamTotalData = cls->getAccLegControlPlace(tLeg, pc->getCourseControlId(k), time + off);
|
||||||
else
|
else
|
||||||
places[k] = 0;
|
places[k].teamTotalData = cls->getAccLegControlPlace(tLeg, oPunch::PunchFinish, time + off);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
places[k].data = 0;
|
||||||
|
places[k].teamTotalData = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalized order
|
// Normalized order
|
||||||
const vector<int> &reorder = getCourse(true)->getMapToOriginalOrder();
|
const vector<int> &reorder = getCourse(true)->getMapToOriginalOrder();
|
||||||
if (!reorder.empty()) {
|
if (!reorder.empty()) {
|
||||||
vector<int> orderedPlaces(reorder.size());
|
vector<ResultData> orderedPlaces(reorder.size());
|
||||||
for (size_t k = 0; k < reorder.size(); k++) {
|
for (size_t k = 0; k < reorder.size(); k++) {
|
||||||
orderedPlaces[k] = places[reorder[k]];
|
orderedPlaces[k] = places[reorder[k]];
|
||||||
}
|
}
|
||||||
@ -5974,31 +5991,31 @@ int oRunner::getLegTimeAfter(int ctrlNo) const {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oRunner::getLegPlaceAcc(int ctrlNo) const {
|
int oRunner::getLegPlaceAcc(int ctrlNo, bool teamTotal) const {
|
||||||
for (auto &res : tOnCourseResults.res) {
|
for (auto &res : tOnCourseResults.res) {
|
||||||
if (res.controlIx == ctrlNo)
|
if (res.controlIx == ctrlNo)
|
||||||
return res.place;
|
return teamTotal ? res.place : res.teamTotalPlace;
|
||||||
}
|
}
|
||||||
if (!Card) {
|
if (!Card) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
setupRunnerStatistics();
|
setupRunnerStatistics();
|
||||||
if (unsigned(ctrlNo) < tPlaceLegAcc.size())
|
if (unsigned(ctrlNo) < tPlaceLegAcc.size())
|
||||||
return tPlaceLegAcc[ctrlNo];
|
return tPlaceLegAcc[ctrlNo].get(teamTotal);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oRunner::getLegTimeAfterAcc(int ctrlNo) const {
|
int oRunner::getLegTimeAfterAcc(int ctrlNo, bool teamTotal) const {
|
||||||
for (auto &res : tOnCourseResults.res) {
|
for (auto &res : tOnCourseResults.res) {
|
||||||
if (res.controlIx == ctrlNo)
|
if (res.controlIx == ctrlNo)
|
||||||
return res.after;
|
return teamTotal ? res.teamTotalAfter : res.after;
|
||||||
}
|
}
|
||||||
if (!Card)
|
if (!Card)
|
||||||
return -1;
|
return -1;
|
||||||
setupRunnerStatistics();
|
setupRunnerStatistics();
|
||||||
if (unsigned(ctrlNo) < tAfterLegAcc.size())
|
if (unsigned(ctrlNo) < tAfterLegAcc.size())
|
||||||
return tAfterLegAcc[ctrlNo];
|
return tAfterLegAcc[ctrlNo].get(teamTotal);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,25 @@ enum SortOrder {
|
|||||||
SortEnumLastItem
|
SortEnumLastItem
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool orderByClass(SortOrder so) {
|
||||||
|
switch (so) {
|
||||||
|
case ClassStartTime:
|
||||||
|
case ClassTeamLeg:
|
||||||
|
case ClassResult:
|
||||||
|
case ClassDefaultResult:
|
||||||
|
case ClassCourseResult:
|
||||||
|
case ClassTotalResult:
|
||||||
|
case ClassTeamLegResult:
|
||||||
|
case ClassFinishTime:
|
||||||
|
case ClassStartTimeClub:
|
||||||
|
case ClassPoints:
|
||||||
|
case ClassLiveResult:
|
||||||
|
case ClassKnockoutTotalResult:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class oRunner;
|
class oRunner;
|
||||||
typedef oRunner* pRunner;
|
typedef oRunner* pRunner;
|
||||||
typedef const oRunner* cRunner;
|
typedef const oRunner* cRunner;
|
||||||
@ -178,6 +197,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
TempResult tmpResult;
|
TempResult tmpResult;
|
||||||
|
|
||||||
|
/** Return 1 if a<b, 0 if b<a, otherwise 2.*/
|
||||||
|
static int compareClubs(const oClub* a, const oClub* b);
|
||||||
|
|
||||||
mutable int tTimeAdjustment;
|
mutable int tTimeAdjustment;
|
||||||
mutable int tPointAdjustment;
|
mutable int tPointAdjustment;
|
||||||
mutable int tAdjustDataRevision;
|
mutable int tAdjustDataRevision;
|
||||||
@ -551,6 +573,23 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class oRunner final: public oAbstractRunner {
|
class oRunner final: public oAbstractRunner {
|
||||||
|
public:
|
||||||
|
struct ResultData {
|
||||||
|
private:
|
||||||
|
int data = 0;
|
||||||
|
int teamTotalData = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ResultData(int data, int teamTotalData) : data(data), teamTotalData(teamTotalData) { }
|
||||||
|
ResultData() = default;
|
||||||
|
|
||||||
|
int get(bool total) const {
|
||||||
|
return total ? teamTotalData : data;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class oRunner;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
pCourse Course;
|
pCourse Course;
|
||||||
|
|
||||||
@ -633,24 +672,32 @@ protected:
|
|||||||
|
|
||||||
void clearOnChangedRunningTime();
|
void clearOnChangedRunningTime();
|
||||||
|
|
||||||
|
|
||||||
// Cached runner statistics
|
// Cached runner statistics
|
||||||
mutable vector<int> tMissedTime;
|
mutable vector<int> tMissedTime;
|
||||||
mutable vector<int> tPlaceLeg;
|
mutable vector<int> tPlaceLeg;
|
||||||
mutable vector<int> tAfterLeg;
|
mutable vector<int> tAfterLeg;
|
||||||
mutable vector<int> tPlaceLegAcc;
|
mutable vector<ResultData> tPlaceLegAcc;
|
||||||
mutable vector<int> tAfterLegAcc;
|
mutable vector<ResultData> tAfterLegAcc;
|
||||||
|
|
||||||
// Used to calculate temporary split time results
|
// Used to calculate temporary split time results
|
||||||
struct OnCourseResult {
|
struct OnCourseResult {
|
||||||
OnCourseResult(int courseControlId,
|
OnCourseResult(int courseControlId,
|
||||||
int controlIx,
|
int controlIx,
|
||||||
int time) : courseControlId(courseControlId),
|
int time,
|
||||||
controlIx(controlIx), time(time) {}
|
int teamTotalTime) : courseControlId(courseControlId),
|
||||||
|
controlIx(controlIx), time(time),
|
||||||
|
teamTotalTime(teamTotalTime) {}
|
||||||
int courseControlId;
|
int courseControlId;
|
||||||
int controlIx;
|
int controlIx;
|
||||||
int time;
|
int time;
|
||||||
int place;
|
int teamTotalTime;
|
||||||
int after;
|
|
||||||
|
int place = -1;
|
||||||
|
int after = -1;
|
||||||
|
|
||||||
|
int teamTotalPlace = -1;
|
||||||
|
int teamTotalAfter = -1;
|
||||||
};
|
};
|
||||||
mutable pair<int, int> currentControlTime;
|
mutable pair<int, int> currentControlTime;
|
||||||
|
|
||||||
@ -660,8 +707,9 @@ protected:
|
|||||||
void clear() { hasAnyRes = false; res.clear(); }
|
void clear() { hasAnyRes = false; res.clear(); }
|
||||||
void emplace_back(int courseControlId,
|
void emplace_back(int courseControlId,
|
||||||
int controlIx,
|
int controlIx,
|
||||||
int time) {
|
int time,
|
||||||
res.emplace_back(courseControlId, controlIx, time);
|
int teamTotalTime) {
|
||||||
|
res.emplace_back(courseControlId, controlIx, time, teamTotalTime);
|
||||||
hasAnyRes = true;
|
hasAnyRes = true;
|
||||||
}
|
}
|
||||||
bool empty() const { return hasAnyRes == false; }
|
bool empty() const { return hasAnyRes == false; }
|
||||||
@ -867,8 +915,8 @@ public:
|
|||||||
int getMissedTime(int ctrlNo) const;
|
int getMissedTime(int ctrlNo) const;
|
||||||
int getLegPlace(int ctrlNo) const;
|
int getLegPlace(int ctrlNo) const;
|
||||||
int getLegTimeAfter(int ctrlNo) const;
|
int getLegTimeAfter(int ctrlNo) const;
|
||||||
int getLegPlaceAcc(int ctrlNo) const;
|
int getLegPlaceAcc(int ctrlNo, bool teamTotal) const;
|
||||||
int getLegTimeAfterAcc(int ctrlNo) const;
|
int getLegTimeAfterAcc(int ctrlNo, bool teamTotal) const;
|
||||||
|
|
||||||
/** Calculate the time when the runners place is fixed, i.e,
|
/** Calculate the time when the runners place is fixed, i.e,
|
||||||
when no other runner can threaten the place.
|
when no other runner can threaten the place.
|
||||||
@ -957,22 +1005,25 @@ public:
|
|||||||
void getLegPlaces(vector<int> &places) const;
|
void getLegPlaces(vector<int> &places) const;
|
||||||
void getLegTimeAfter(vector<int> &deltaTimes) const;
|
void getLegTimeAfter(vector<int> &deltaTimes) const;
|
||||||
|
|
||||||
void getLegPlacesAcc(vector<int> &places) const;
|
void getLegPlacesAcc(vector<ResultData> &places) const;
|
||||||
void getLegTimeAfterAcc(vector<int> &deltaTimes) const;
|
void getLegTimeAfterAcc(vector<ResultData> &deltaTimes) const;
|
||||||
|
|
||||||
// Normalized = true means permuted to the unlooped version of the course
|
// Normalized = true means permuted to the unlooped version of the course
|
||||||
int getSplitTime(int controlNumber, bool normalized) const;
|
int getSplitTime(int controlNumber, bool normalized) const;
|
||||||
int getTimeAdjust(int controlNumber) const;
|
int getTimeAdjust(int controlNumber) const;
|
||||||
|
|
||||||
int getNamedSplit(int controlNumber) const;
|
int getNamedSplit(int controlNumber) const;
|
||||||
wstring getNamedSplitS(int controlNumber) const;
|
const wstring &getNamedSplitS(int controlNumber, SubSecond mode) const;
|
||||||
|
|
||||||
|
/** Get running time from start to a control (specified by its index on the course)
|
||||||
|
normalized: true means permuted to the unlooped version of the course
|
||||||
|
teamTotalTime: true means time is measured from the team's starting time
|
||||||
|
*/
|
||||||
|
int getPunchTime(int controlIndex, bool normalized, bool adjusted, bool teamTotalTime) const;
|
||||||
|
const wstring &getPunchTimeS(int controlIndex, bool normalized, bool adjusted, bool teamTotalTime, SubSecond mode) const;
|
||||||
|
|
||||||
// Normalized = true means permuted to the unlooped version of the course
|
// Normalized = true means permuted to the unlooped version of the course
|
||||||
int getPunchTime(int controlNumber, bool normalized, bool adjusted) const;
|
const wstring &getSplitTimeS(int controlNumber, bool normalized, SubSecond mode) const;
|
||||||
wstring getPunchTimeS(int controlNumber, bool normalized, bool adjusted, SubSecond mode) const;
|
|
||||||
|
|
||||||
// Normalized = true means permuted to the unlooped version of the course
|
|
||||||
wstring getSplitTimeS(int controlNumber, bool normalized) const;
|
|
||||||
|
|
||||||
void addTableRow(Table &table) const;
|
void addTableRow(Table &table) const;
|
||||||
pair<int, bool> inputData(int id, const wstring &input,
|
pair<int, bool> inputData(int id, const wstring &input,
|
||||||
|
|||||||
@ -436,6 +436,17 @@ int oTeam::getLegFinishTime(int leg) const
|
|||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int oTeam::getTotalRunningTimeAtLegStart(int leg, bool multidayTotal) const {
|
||||||
|
int off = multidayTotal ? max(0, getInputTime()) : 0;
|
||||||
|
if (!Class || leg == 0)
|
||||||
|
return off;
|
||||||
|
int pleg = Class->getPreceedingLeg(leg);
|
||||||
|
if (pleg < 0)
|
||||||
|
return off;
|
||||||
|
|
||||||
|
return getLegRunningTime(pleg, false, multidayTotal);
|
||||||
|
}
|
||||||
|
|
||||||
int oTeam::getRunningTime(bool computedTime) const {
|
int oTeam::getRunningTime(bool computedTime) const {
|
||||||
return getLegRunningTime(-1, computedTime, false);
|
return getLegRunningTime(-1, computedTime, false);
|
||||||
}
|
}
|
||||||
@ -812,9 +823,7 @@ wstring oTeam::getLegPrintPlaceS(int leg, bool multidayTotal, bool withDot) cons
|
|||||||
return _EmptyWString;
|
return _EmptyWString;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oTeam::compareResultClub(const oTeam& a, const oTeam& b) {
|
int oAbstractRunner::compareClubs(const oClub* ca, const oClub* cb) {
|
||||||
pClub ca = a.getClubRef();
|
|
||||||
pClub cb = b.getClubRef();
|
|
||||||
if (ca != cb) {
|
if (ca != cb) {
|
||||||
if (ca == nullptr && cb)
|
if (ca == nullptr && cb)
|
||||||
return true;
|
return true;
|
||||||
@ -830,6 +839,17 @@ bool oTeam::compareResultClub(const oTeam& a, const oTeam& b) {
|
|||||||
if (res != CSTR_EQUAL)
|
if (res != CSTR_EQUAL)
|
||||||
return res == CSTR_LESS_THAN;
|
return res == CSTR_LESS_THAN;
|
||||||
}
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool oTeam::compareResultClub(const oTeam& a, const oTeam& b) {
|
||||||
|
pClub ca = a.getClubRef();
|
||||||
|
pClub cb = b.getClubRef();
|
||||||
|
if (ca != cb) {
|
||||||
|
int cres = compareClubs(ca, cb);
|
||||||
|
if (cres != 2)
|
||||||
|
return cres != 0;
|
||||||
|
}
|
||||||
return compareResult(a, b);
|
return compareResult(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -855,8 +875,13 @@ bool oTeam::compareResult(const oTeam &a, const oTeam &b)
|
|||||||
|
|
||||||
int aix = a.getDCI().getInt("SortIndex");
|
int aix = a.getDCI().getInt("SortIndex");
|
||||||
int bix = b.getDCI().getInt("SortIndex");
|
int bix = b.getDCI().getInt("SortIndex");
|
||||||
if (aix != bix)
|
if (aix != bix) {
|
||||||
|
if (aix == 0)
|
||||||
|
aix = numeric_limits<int>::max();
|
||||||
|
if (bix == 0)
|
||||||
|
bix = numeric_limits<int>::max();
|
||||||
return aix < bix;
|
return aix < bix;
|
||||||
|
}
|
||||||
|
|
||||||
return CompareString(LOCALE_USER_DEFAULT, 0,
|
return CompareString(LOCALE_USER_DEFAULT, 0,
|
||||||
a.sName.c_str(), a.sName.length(),
|
a.sName.c_str(), a.sName.length(),
|
||||||
@ -877,6 +902,24 @@ bool oTeam::compareResultNoSno(const oTeam &a, const oTeam &b)
|
|||||||
else if (a.tmpSortTime != b.tmpSortTime)
|
else if (a.tmpSortTime != b.tmpSortTime)
|
||||||
return a.tmpSortTime<b.tmpSortTime;
|
return a.tmpSortTime<b.tmpSortTime;
|
||||||
|
|
||||||
|
int aix = a.getDCI().getInt("SortIndex");
|
||||||
|
int bix = b.getDCI().getInt("SortIndex");
|
||||||
|
if (aix != bix) {
|
||||||
|
if (aix == 0)
|
||||||
|
aix = numeric_limits<int>::max();
|
||||||
|
if (bix == 0)
|
||||||
|
bix = numeric_limits<int>::max();
|
||||||
|
return aix < bix;
|
||||||
|
}
|
||||||
|
|
||||||
|
pClub ca = a.getClubRef();
|
||||||
|
pClub cb = b.getClubRef();
|
||||||
|
if (ca != cb) {
|
||||||
|
int cres = compareClubs(ca, cb);
|
||||||
|
if (cres != 2)
|
||||||
|
return cres != 0;
|
||||||
|
}
|
||||||
|
|
||||||
return CompareString(LOCALE_USER_DEFAULT, 0,
|
return CompareString(LOCALE_USER_DEFAULT, 0,
|
||||||
a.sName.c_str(), a.sName.length(),
|
a.sName.c_str(), a.sName.length(),
|
||||||
b.sName.c_str(), b.sName.length()) == CSTR_LESS_THAN;
|
b.sName.c_str(), b.sName.length()) == CSTR_LESS_THAN;
|
||||||
@ -1751,7 +1794,7 @@ pRunner oTeam::getRunner(unsigned leg) const {
|
|||||||
if (leg==-1)
|
if (leg==-1)
|
||||||
leg=Runners.size()-1;
|
leg=Runners.size()-1;
|
||||||
|
|
||||||
return leg<Runners.size() ? Runners[leg] : 0;
|
return leg<Runners.size() ? Runners[leg] : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oTeam::getRogainingPoints(bool computed, bool multidayTotal) const {
|
int oTeam::getRogainingPoints(bool computed, bool multidayTotal) const {
|
||||||
|
|||||||
@ -269,6 +269,9 @@ public:
|
|||||||
|
|
||||||
int getLegRunningTime(int leg, bool computed, bool multidayTotal) const;
|
int getLegRunningTime(int leg, bool computed, bool multidayTotal) const;
|
||||||
|
|
||||||
|
// Get the team's total running time when starting specified leg
|
||||||
|
int getTotalRunningTimeAtLegStart(int leg, bool multidayTotal) const;
|
||||||
|
|
||||||
RunnerStatus getLegStatus(int leg, bool computed, bool multidayTotal) const;
|
RunnerStatus getLegStatus(int leg, bool computed, bool multidayTotal) const;
|
||||||
const wstring &getLegStatusS(int leg, bool computed, bool multidayTotal) const;
|
const wstring &getLegStatusS(int leg, bool computed, bool multidayTotal) const;
|
||||||
|
|
||||||
|
|||||||
@ -240,7 +240,7 @@ pTeam oEvent::findTeam(const wstring &s, int lastId, unordered_set<int> &filter)
|
|||||||
int len = trm.length();
|
int len = trm.length();
|
||||||
wchar_t s_lc[1024];
|
wchar_t s_lc[1024];
|
||||||
wcscpy_s(s_lc, trm.c_str());
|
wcscpy_s(s_lc, trm.c_str());
|
||||||
CharLowerBuff(s_lc, len);
|
prepareMatchString(s_lc, len);
|
||||||
|
|
||||||
int sn = _wtoi(s.c_str());
|
int sn = _wtoi(s.c_str());
|
||||||
oTeamList::const_iterator it;
|
oTeamList::const_iterator it;
|
||||||
|
|||||||
@ -478,7 +478,7 @@ void OnlineInput::processEntries(oEvent &oe, const xmlList &entries) {
|
|||||||
bool paid = entry.getObjectBool("paid");
|
bool paid = entry.getObjectBool("paid");
|
||||||
|
|
||||||
xmlobject xname = entry.getObject("name");
|
xmlobject xname = entry.getObject("name");
|
||||||
wstring birthyear = 0;
|
wstring birthyear;
|
||||||
if (xname) {
|
if (xname) {
|
||||||
xname.getObjectString("birthyear", birthyear);
|
xname.getObjectString("birthyear", birthyear);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#define IDI_SPLASHIMAGE 512
|
#define IDI_SPLASHIMAGE 512
|
||||||
#define IDI_MEOSIMAGE 513
|
#define IDI_MEOSIMAGE 513
|
||||||
#define IDI_MEOSINFO 514
|
#define IDI_MEOSINFO 514
|
||||||
|
#define IDI_MEOSEDIT 515
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
|
|||||||
@ -1150,7 +1150,7 @@ void RestServer::lookup(oEvent &oe, const string &what, const multimap<string, s
|
|||||||
auto &sd = r->getSplitTimes(false);
|
auto &sd = r->getSplitTimes(false);
|
||||||
vector<int> after;
|
vector<int> after;
|
||||||
r->getLegTimeAfter(after);
|
r->getLegTimeAfter(after);
|
||||||
vector<int> afterAcc;
|
vector<oRunner::ResultData> afterAcc;
|
||||||
r->getLegTimeAfterAcc(afterAcc);
|
r->getLegTimeAfterAcc(afterAcc);
|
||||||
vector<int> delta;
|
vector<int> delta;
|
||||||
r->getSplitAnalysis(delta);
|
r->getSplitAnalysis(delta);
|
||||||
@ -1177,8 +1177,8 @@ void RestServer::lookup(oEvent &oe, const string &what, const multimap<string, s
|
|||||||
else
|
else
|
||||||
analysis[0].second = L"";
|
analysis[0].second = L"";
|
||||||
|
|
||||||
if (afterAcc[ix] > 0)
|
if (afterAcc[ix].get(0) > 0)
|
||||||
analysis[1].second = formatTime(afterAcc[ix]);
|
analysis[1].second = formatTime(afterAcc[ix].get(false));
|
||||||
else
|
else
|
||||||
analysis[1].second = L"";
|
analysis[1].second = L"";
|
||||||
|
|
||||||
@ -1190,7 +1190,7 @@ void RestServer::lookup(oEvent &oe, const string &what, const multimap<string, s
|
|||||||
int place = r->getLegPlace(ix);
|
int place = r->getLegPlace(ix);
|
||||||
analysis[3].second = place > 0 ? itow(place) : L"";
|
analysis[3].second = place > 0 ? itow(place) : L"";
|
||||||
|
|
||||||
int placeAcc = r->getLegPlaceAcc(ix);
|
int placeAcc = r->getLegPlaceAcc(ix, false);
|
||||||
analysis[4].second = placeAcc > 0 ? itow(placeAcc) : L"";
|
analysis[4].second = placeAcc > 0 ? itow(placeAcc) : L"";
|
||||||
|
|
||||||
xml.write("Analysis", analysis, L"");
|
xml.write("Analysis", analysis, L"");
|
||||||
|
|||||||
@ -2683,3 +2683,8 @@ Bevara höjd/bredd-relationen = Bevara höjd/bredd-relationen
|
|||||||
RunnerLegTeamLeaderName = Först i mål på sträckan
|
RunnerLegTeamLeaderName = Först i mål på sträckan
|
||||||
info:offsetclassid = Om du importerar anmälningar och klasser från olika källor till samma tävling kan det hända att klassernas Id-nummer krockar. För att hålla isär klasserna kan du då ange en förskjutning av Id-nummer när du arbetar med datafiler från en viss källa; denna kommer att adderas till klassernas Id-nummer.\n\nDu måste ange samma förskjutning varje gång du importerar från en viss källa. Ett lämpligt värde kan vara 1000 (som fungerar om all Id-nummer är mindre än 1000).
|
info:offsetclassid = Om du importerar anmälningar och klasser från olika källor till samma tävling kan det hända att klassernas Id-nummer krockar. För att hålla isär klasserna kan du då ange en förskjutning av Id-nummer när du arbetar med datafiler från en viss källa; denna kommer att adderas till klassernas Id-nummer.\n\nDu måste ange samma förskjutning varje gång du importerar från en viss källa. Ett lämpligt värde kan vara 1000 (som fungerar om all Id-nummer är mindre än 1000).
|
||||||
Förskjutning av klassers Id = Förskjutning av klassers Id
|
Förskjutning av klassers Id = Förskjutning av klassers Id
|
||||||
|
Tilldela nummerlapp till vakanter = Tilldela nummerlapp till vakanter
|
||||||
|
Avläsning = Avläsning
|
||||||
|
Inmatning Testning = Inmatning Testning
|
||||||
|
Testning = Testning
|
||||||
|
CourseNumControls = Antal kontroller
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user