MeOS version 3.5.808.
This commit is contained in:
parent
adba758c26
commit
4da3c93866
@ -2,13 +2,15 @@
|
||||
#include "RestService.h"
|
||||
#include "meos_util.h"
|
||||
#include "restserver.h"
|
||||
#include "meosexception.h"
|
||||
|
||||
#include <ShellAPI.h>
|
||||
|
||||
int AutomaticCB(gdioutput *gdi, int type, void *data);
|
||||
|
||||
RestService::RestService() : AutoMachine("RestService"), port(-1) {
|
||||
RestService::RestService() : AutoMachine("Informationsserver"), port(-1) {
|
||||
}
|
||||
|
||||
|
||||
RestService::~RestService() {
|
||||
if (server) {
|
||||
server->stop();
|
||||
@ -17,14 +19,17 @@ RestService::~RestService() {
|
||||
}
|
||||
|
||||
void RestService::save(oEvent &oe, gdioutput &gdi) {
|
||||
if (!server)
|
||||
if (!server) {
|
||||
server = RestServer::construct();
|
||||
|
||||
int port = gdi.getTextNo("Port");
|
||||
if (port > 0 && port < 65536)
|
||||
server->startService(port);
|
||||
else
|
||||
throw std::exception("Invalid port number");
|
||||
|
||||
int xport = gdi.getTextNo("Port");
|
||||
if (xport > 0 && xport < 65536) {
|
||||
port = xport;
|
||||
server->startService(port);
|
||||
}
|
||||
else
|
||||
throw meosException("Invalid port number");
|
||||
}
|
||||
}
|
||||
|
||||
void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
@ -35,7 +40,7 @@ void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
startCancelInterval(gdi, "Save", created, IntervalNone, L"");
|
||||
|
||||
if (!server)
|
||||
gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"Testa genom http://localhost:[PORT]/meos");
|
||||
gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"#http://localhost:[PORT]/meos");
|
||||
else
|
||||
gdi.addString("", 0, "Server startad på X#" + itos(port));
|
||||
|
||||
@ -46,29 +51,21 @@ void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void RestService::status(gdioutput &gdi) {
|
||||
gdi.pushX();
|
||||
gdi.addString("", 1, name);
|
||||
/*if (!baseFile.empty()) {
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
gdi.addString("", 0, L"Destination: X#" + baseFile);
|
||||
|
||||
if (interval>0) {
|
||||
gdi.popX();
|
||||
gdi.dropLine(1);
|
||||
gdi.addString("", 0, "Säkerhetskopierar om: ");
|
||||
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign, (GetTickCount() - timeout) / 1000);
|
||||
}
|
||||
|
||||
gdi.popX();
|
||||
}*/
|
||||
|
||||
if (server) {
|
||||
gdi.addString("", 0, "Server startad på port X#" + itos(port));
|
||||
gdi.addString("", 0, "Server startad på X#" + itos(port));
|
||||
|
||||
RestServer::Statistics rs;
|
||||
server->getStatistics(rs);
|
||||
gdi.addString("", 0, "Antal förfrågningar: X#" + itos(rs.numRequests));
|
||||
gdi.addString("", 0, "Genomsnittlig svarstid: X ms#" + itos(rs.averageResponseTime));
|
||||
gdi.addString("", 0, "Längsta svarstid: X ms#" + itos(rs.maxResponseTime));
|
||||
gdi.addString("", 0, "Antal förfrågningar: X.#" + itos(rs.numRequests));
|
||||
gdi.addString("", 0, "Genomsnittlig svarstid: X ms.#" + itos(rs.averageResponseTime));
|
||||
gdi.addString("", 0, "Längsta svarstid: X ms.#" + itos(rs.maxResponseTime));
|
||||
|
||||
gdi.dropLine(0.6);
|
||||
gdi.addButton("Update", "Uppdatera").setHandler(this);
|
||||
gdi.dropLine(0.6);
|
||||
gdi.addString("", 1, "Testa servern:");
|
||||
gdi.addString("link", 0, "#http://localhost:" + itos(port) + "/meos").setHandler(this);
|
||||
}
|
||||
|
||||
gdi.dropLine(2);
|
||||
@ -87,6 +84,12 @@ void RestService::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
|
||||
void RestService::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
|
||||
if (type == GUI_BUTTON) {
|
||||
ButtonInfo &bi = static_cast<ButtonInfo&>(info);
|
||||
|
||||
if (bi.id == "Update") {
|
||||
gdi.getTabs().get(TAutoTab)->loadPage(gdi);
|
||||
}
|
||||
}
|
||||
else if (type == GUI_LINK) {
|
||||
wstring url = L"http://localhost:" + itow(port) + L"/meos";
|
||||
ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
}
|
||||
@ -23,13 +23,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <memory>
|
||||
#include <tchar.h>
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <crtdbg.h>
|
||||
|
||||
using namespace std;
|
||||
bool getUserFile(wchar_t *fileNamePath, const wchar_t *fileName);
|
||||
|
||||
@ -671,8 +671,11 @@ void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, bool c
|
||||
else if (type == IntervalSecond)
|
||||
gdi.addInput("Interval", intervalIn, 7, 0, L"Tidsintervall (sekunder):");
|
||||
gdi.dropLine(1);
|
||||
gdi.addButton(startCommand, "Starta automaten", AutomaticCB).setExtra(getId());
|
||||
gdi.addButton(created ? "Stop":"Cancel", "Avbryt", AutomaticCB).setExtra(getId());
|
||||
gdi.addButton(startCommand, created ? "Starta automaten" : "OK", AutomaticCB).setExtra(getId());
|
||||
if (!created)
|
||||
gdi.addButton("Cancel", "Avbryt", AutomaticCB).setExtra(getId());
|
||||
|
||||
gdi.addButton("Stop", created ? "Avbryt" : "Stoppa automaten", AutomaticCB).setExtra(getId());
|
||||
|
||||
gdi.popX();
|
||||
gdi.fillDown();
|
||||
|
||||
@ -1325,6 +1325,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
return false;
|
||||
|
||||
DWORD cid=ClassId;
|
||||
pClass pc = oe->getClass(cid);
|
||||
DrawMethod method = DrawMethod(gdi.getSelectedItem("Method").first);
|
||||
|
||||
int interval = 0;
|
||||
@ -1339,6 +1340,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
if (gdi.hasField("Leg")) {
|
||||
leg = gdi.getSelectedItem("Leg").first;
|
||||
}
|
||||
else if (pc && pc->getParentClass() != 0)
|
||||
leg = -1;
|
||||
|
||||
wstring bib;
|
||||
bool doBibs = false;
|
||||
@ -1536,6 +1539,19 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
setMultiDayClass(gdi, gdi.isChecked(bi.id), lastDrawMethod);
|
||||
|
||||
}
|
||||
else if (bi.id == "QualificationFinal") {
|
||||
save(gdi, true);
|
||||
pClass pc = oe->getClass(ClassId);
|
||||
if (!pc)
|
||||
throw std::exception("Class not found");
|
||||
|
||||
vector< pair<wstring, wstring> > ext;
|
||||
ext.push_back(make_pair(L"Qualfication/Final", L"*.xml"));
|
||||
wstring fileName = gdi.browseForOpen(ext, L"xml");
|
||||
pc->loadQualificationFinalScheme(fileName);
|
||||
pc->updateFinalClasses(0, true);
|
||||
loadPage(gdi);
|
||||
}
|
||||
else if (bi.id=="Bibs") {
|
||||
save(gdi, true);
|
||||
if (!checkClassSelected(gdi))
|
||||
@ -1572,7 +1588,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.selectItemByData("BibSettings", bt);
|
||||
wstring bib = pc->getDCI().getString("Bib");
|
||||
|
||||
if (pc->getNumDistinctRunners() > 1) {
|
||||
if (pc->getNumDistinctRunners() > 1 || pc->getQualificationFinal()) {
|
||||
bibTeamOptions.push_back(make_pair(lang.tl("Oberoende"), BibFree));
|
||||
bibTeamOptions.push_back(make_pair(lang.tl("Samma"), BibSame));
|
||||
bibTeamOptions.push_back(make_pair(lang.tl("Ökande"), BibAdd));
|
||||
@ -1620,16 +1636,16 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
AutoBibType bt = AutoBibType(gdi.getSelectedItem("BibSettings").first);
|
||||
|
||||
pair<int, bool> teamBib = gdi.getSelectedItem("TeamBib");
|
||||
pair<int, bool> teamBib = gdi.getSelectedItem("BibTeam");
|
||||
if (teamBib.second) {
|
||||
pc->setBibMode(BibMode(teamBib.first));
|
||||
}
|
||||
|
||||
pc->getDI().setString("Bib", getBibCode(bt, gdi.getText("Bib")));
|
||||
pc->synchronize();
|
||||
|
||||
int leg = pc->getParentClass() ? -1 : 0;
|
||||
if (bt == AutoBibManual) {
|
||||
oe->addBib(cid, 0, gdi.getText("Bib"));
|
||||
oe->addBib(cid, leg, gdi.getText("Bib"));
|
||||
}
|
||||
else {
|
||||
oe->setBibClassGap(gdi.getTextNo("BibGap"));
|
||||
@ -1644,7 +1660,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
par.selection.insert(cid);
|
||||
oListInfo info;
|
||||
par.listCode = EStdStartList;
|
||||
par.setLegNumberCoded(0);
|
||||
par.setLegNumberCoded(leg);
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), info);
|
||||
oe->generateList(gdi, false, info, true);
|
||||
|
||||
@ -2223,6 +2239,10 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
||||
if (gdi.hasField("DirectResult"))
|
||||
gdi.check("DirectResult", false);
|
||||
|
||||
if (gdi.hasField("LockStartList")) {
|
||||
gdi.check("LockStartList", false);
|
||||
gdi.setInputStatus("LockStartList", false);
|
||||
}
|
||||
gdi.check("NoTiming", false);
|
||||
|
||||
ClassId=cid;
|
||||
@ -2274,6 +2294,11 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
||||
if (gdi.hasField("DirectResult"))
|
||||
gdi.check("DirectResult", pc->hasDirectResult());
|
||||
|
||||
if (gdi.hasField("LockStartList")) {
|
||||
bool active = pc->getParentClass() != 0;
|
||||
gdi.setInputStatus("LockStartList", active);
|
||||
gdi.check("LockStartList", active && pc->lockedClassAssignment());
|
||||
}
|
||||
ClassId=cid;
|
||||
|
||||
if (pc->hasTrueMultiCourse()) {
|
||||
@ -2344,9 +2369,10 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
||||
pCourse pcourse = pc->getCourse();
|
||||
gdi.selectItemByData("Courses", pcourse ? pcourse->getId():-2);
|
||||
}
|
||||
if (gdi.hasField("QualificationFinal"))
|
||||
gdi.setInputStatus("QualificationFinal", pc->getParentClass() == 0);
|
||||
|
||||
gdi.selectItemByData("Classes", cid);
|
||||
|
||||
ClassId=cid;
|
||||
EditChanged=false;
|
||||
}
|
||||
@ -2672,6 +2698,12 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
|
||||
pc->setDirectResult(withDirect);
|
||||
}
|
||||
|
||||
if (gdi.hasField("LockStartList")) {
|
||||
bool locked = gdi.isChecked("LockStartList");
|
||||
if (pc->getParentClass())
|
||||
pc->lockedClassAssignment(locked);
|
||||
}
|
||||
|
||||
int crs = gdi.getSelectedItem("Courses").first;
|
||||
|
||||
if (crs==0) {
|
||||
@ -2893,11 +2925,28 @@ bool TabClass::loadPage(gdioutput &gdi)
|
||||
|
||||
gdi.addCheckbox("DirectResult", "Resultat vid målstämpling", 0, false,
|
||||
"help:DirectResult");
|
||||
|
||||
}
|
||||
gdi.dropLine(2);
|
||||
gdi.popX();
|
||||
|
||||
{
|
||||
vector<pClass> pcls;
|
||||
oe->getClasses(pcls, false);
|
||||
bool hasCF = false;
|
||||
for (pClass pc : pcls) {
|
||||
if (pc->getQualificationFinal()) {
|
||||
hasCF = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasCF) {
|
||||
gdi.addCheckbox("LockStartList", "Lås startlista", 0, false,
|
||||
"help:LockStartList");
|
||||
|
||||
gdi.dropLine(2);
|
||||
gdi.popX();
|
||||
}
|
||||
}
|
||||
vector<ButtonData> func;
|
||||
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::DrawStartList))
|
||||
func.push_back(ButtonData("Draw", "Lotta / starttider...", false));
|
||||
@ -2960,6 +3009,9 @@ bool TabClass::loadPage(gdioutput &gdi)
|
||||
|
||||
func.push_back(ButtonData("QuickSettings", "Snabbinställningar", true));
|
||||
|
||||
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::MultipleRaces))
|
||||
func.push_back(ButtonData("QualificationFinal", "Kval-Final-Schema", false));
|
||||
|
||||
RECT funRect;
|
||||
funRect.right = gdi.getCX() - 7;
|
||||
funRect.top = gdi.getCY() - 2;
|
||||
@ -3216,7 +3268,7 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
|
||||
if (method != DMSimultaneous)
|
||||
gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):").setSynchData(&lastInterval);
|
||||
|
||||
if (method == DMRandom || method == DMSOFT || method == DMClumped)
|
||||
if (method == DMRandom || method == DMSOFT || method == DMClumped && pc.getParentClass() == 0)
|
||||
gdi.addInput("Vacanses", itow(vac), 10, 0, L"Antal vakanser:").setSynchData(&lastNumVac);
|
||||
|
||||
if ((method == DMRandom || method == DMSOFT || method == DMSeeded) && pc.getNumStages() > 1 && pc.getClassType() != oClassPatrol) {
|
||||
@ -3765,7 +3817,7 @@ void TabClass::getClassSettingsTable(gdioutput &gdi, GUICALLBACK cb) {
|
||||
else
|
||||
gdi.setText("Bib"+ id, bib);
|
||||
|
||||
if (useTeam && it->getNumDistinctRunners() > 1) {
|
||||
if (useTeam && (it->getNumDistinctRunners() > 1 || it->getQualificationFinal())) {
|
||||
gdi.addSelection(et, cyp, "BibTeam" + id, 80, 100, 0, L"", L"Ange relation mellan lagets och deltagarnas nummerlappar.");
|
||||
gdi.addItem("BibTeam" + id, bibTeamOptions);
|
||||
gdi.selectItemByData("BibTeam" + id, it->getBibMode());
|
||||
|
||||
@ -528,7 +528,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
|
||||
else
|
||||
fee = di.getInt("Fee");
|
||||
|
||||
wstring info = filtered[k]->getClass() + L", " + filtered[k]->getCompleteIdentification();
|
||||
wstring info = filtered[k]->getClass(false) + L", " + filtered[k]->getCompleteIdentification();
|
||||
|
||||
gdi.addStringUT(0, info + L" (" + oe->formatCurrency(fee) + L")");
|
||||
if (count % 5 == 0)
|
||||
|
||||
@ -110,22 +110,23 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
|
||||
bool oldLT = oe->useLongTimes();
|
||||
wstring oldDate = oe->getDate();
|
||||
|
||||
if ((newZT != oldZT ||
|
||||
longTimes != oldLT ||
|
||||
(longTimes && date != oldDate)) && oe->classHasResults(0)) {
|
||||
if ((newZT != oldZT ||
|
||||
longTimes != oldLT ||
|
||||
(longTimes && date != oldDate)) && oe->classHasResults(0)) {
|
||||
if (!gdi.ask(L"warn:changedtimezero")) {
|
||||
gdi.setText("ZeroTime", oe->getZeroTime());
|
||||
gdi.check("LongTimes", oe->useLongTimes());
|
||||
gdi.setText("Date", oe->getDate());
|
||||
return 0;
|
||||
}
|
||||
bool updateTimes = newZT != oldZT && oe->getNumRunners() > 0 && gdi.ask(L"ask:updatetimes");
|
||||
}
|
||||
bool updateTimes = newZT != oldZT && oe->getNumRunners() > 0 && gdi.ask(L"ask:updatetimes");
|
||||
|
||||
if (updateTimes) {
|
||||
int delta = oldZT - newZT;
|
||||
oe->updateStartTimes(delta);
|
||||
}
|
||||
if (updateTimes) {
|
||||
int delta = oldZT - newZT;
|
||||
oe->updateStartTimes(delta);
|
||||
}
|
||||
|
||||
oe->setDate(date);
|
||||
oe->useLongTimes(longTimes);
|
||||
oe->setName(gdi.getText("Name"));
|
||||
@ -3228,7 +3229,7 @@ void TabCompetition::welcomeToMeOS(gdioutput &gdi) {
|
||||
|
||||
void TabCompetition::displayRunners(gdioutput &gdi, const vector<pRunner> &changedClass) const {
|
||||
for (size_t k = 0; k<changedClass.size(); k++) {
|
||||
gdi.addStringUT(0, changedClass[k]->getName() + L" (" + changedClass[k]->getClass() + L", " +
|
||||
gdi.addStringUT(0, changedClass[k]->getName() + L" (" + changedClass[k]->getClass(true) + L", " +
|
||||
changedClass[k]->getStartTimeS() + L")");
|
||||
}
|
||||
}
|
||||
@ -3991,7 +3992,7 @@ void TabCompetition::checkReadyForResultExport(gdioutput &gdi, const set<int> &c
|
||||
int numVacant = 0;
|
||||
|
||||
for (pRunner r : runners) {
|
||||
if (!classFilter.empty() && !classFilter.count(r->getClassId()))
|
||||
if (!classFilter.empty() && !classFilter.count(r->getClassId(false)))
|
||||
continue;
|
||||
|
||||
if (r->isVacant())
|
||||
|
||||
192
code/TabList.cpp
192
code/TabList.cpp
@ -601,7 +601,6 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
lastSplitState = par.showSplitTimes;
|
||||
lastLargeSize = par.useLargeSize;
|
||||
|
||||
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
|
||||
generateList(gdi);
|
||||
@ -635,10 +634,8 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
oListParam par;
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
getResultIndividual(par, cnf);
|
||||
cnf.getIndividual(par.selection);
|
||||
par.listCode = EStdResultList;
|
||||
par.showInterTimes = true;
|
||||
par.setLegNumberCoded(-1);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
|
||||
@ -667,12 +664,10 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id=="StartIndividual") {
|
||||
oe->sanityCheck(gdi, false);
|
||||
oListParam par;
|
||||
par.listCode = EStdStartList;
|
||||
par.setLegNumberCoded(-1);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
cnf.getIndividual(par.selection);
|
||||
getStartIndividual(par, cnf);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
currentList.setCallback(openRunnerTeamCB);
|
||||
generateList(gdi);
|
||||
@ -681,33 +676,22 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id=="StartClub") {
|
||||
oe->sanityCheck(gdi, false);
|
||||
oListParam par;
|
||||
par.listCode = EStdClubStartList;
|
||||
getStartClub(par);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.setLegNumberCoded(-1);
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
//cnf.getIndividual(par.selection);
|
||||
//cnf.getPatrol(par.selection);
|
||||
|
||||
// oListInfo foo = currentList;
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
currentList.setCallback(openRunnerTeamCB);
|
||||
//currentList.addList(foo);
|
||||
generateList(gdi);
|
||||
gdi.refresh();
|
||||
}
|
||||
else if (bi.id=="ResultClub") {
|
||||
oe->sanityCheck(gdi, false);
|
||||
oListParam par;
|
||||
par.listCode = EStdClubResultList;
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
par.setLegNumberCoded(-1);
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
cnf.getIndividual(par.selection);
|
||||
cnf.getPatrol(par.selection);
|
||||
getResultClub(par, cnf);
|
||||
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
currentList.setCallback(openRunnerTeamCB);
|
||||
generateList(gdi);
|
||||
@ -735,12 +719,10 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id=="TeamStartList") {
|
||||
oe->sanityCheck(gdi, false);
|
||||
oListParam par;
|
||||
par.listCode = EStdTeamStartList;
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
cnf.getRelay(par.selection);
|
||||
getStartTeam(par, cnf);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.setLegNumberCoded(0);
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
currentList.setCallback(openRunnerTeamCB);
|
||||
generateList(gdi);
|
||||
@ -779,11 +761,10 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id=="PatrolStartList") {
|
||||
oe->sanityCheck(gdi, false);
|
||||
oListParam par;
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.listCode = EStdPatrolStartList;
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
cnf.getPatrol(par.selection);
|
||||
getStartPatrol(par, cnf);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
currentList.setCallback(openRunnerTeamCB);
|
||||
generateList(gdi);
|
||||
@ -792,15 +773,12 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id=="TeamResults") {
|
||||
oe->sanityCheck(gdi, true);
|
||||
oListParam par;
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
par.listCode = EStdTeamResultListAll;
|
||||
|
||||
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
|
||||
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
cnf.getRelay(par.selection);
|
||||
getResultTeam(par, cnf);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
generateList(gdi);
|
||||
gdi.refresh();
|
||||
@ -823,7 +801,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
oListParam par;
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
int race = int(bi.getExtra());
|
||||
int race = bi.getExtraInt();
|
||||
par.setLegNumberCoded(race);
|
||||
par.listCode = EStdIndMultiResultListLeg;
|
||||
ClassConfigInfo cnf;
|
||||
@ -854,13 +832,11 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id=="PatrolResultList") {
|
||||
oe->sanityCheck(gdi, false);
|
||||
oListParam par;
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
par.listCode = EStdPatrolResultList;
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
cnf.getPatrol(par.selection);
|
||||
|
||||
getResultPatrol(par, cnf);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
|
||||
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
@ -871,13 +847,11 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id=="RogainingResultList") {
|
||||
oe->sanityCheck(gdi, true);
|
||||
oListParam par;
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
par.listCode = ERogainingInd;
|
||||
ClassConfigInfo cnf;
|
||||
oe->getClassConfigurationInfo(cnf);
|
||||
cnf.getRogaining(par.selection);
|
||||
|
||||
getResultRogaining(par, cnf);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
|
||||
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
|
||||
@ -2420,3 +2394,127 @@ void TabList::setAnimationMode(gdioutput &gdi) {
|
||||
gdi.setAnimationMode(make_shared<AnimationData>(gdi, par.timePerPage, par.nColumns,
|
||||
par.margin, par.animate));
|
||||
}
|
||||
|
||||
void TabList::getStartIndividual(oListParam &par, ClassConfigInfo &cnf){
|
||||
par.listCode = EStdStartList;
|
||||
par.setLegNumberCoded(-1);
|
||||
cnf.getIndividual(par.selection);
|
||||
}
|
||||
|
||||
void TabList::getStartClub(oListParam &par) {
|
||||
par.listCode = EStdClubStartList;
|
||||
par.setLegNumberCoded(-1);
|
||||
}
|
||||
|
||||
void TabList::getResultIndividual(oListParam &par, ClassConfigInfo &cnf) {
|
||||
cnf.getIndividual(par.selection);
|
||||
par.listCode = EStdResultList;
|
||||
par.showInterTimes = true;
|
||||
par.setLegNumberCoded(-1);
|
||||
}
|
||||
|
||||
void TabList::getResultClub(oListParam &par, ClassConfigInfo &cnf) {
|
||||
par.listCode = EStdClubResultList;
|
||||
par.setLegNumberCoded(-1);
|
||||
cnf.getIndividual(par.selection);
|
||||
cnf.getPatrol(par.selection);
|
||||
}
|
||||
|
||||
void TabList::getStartPatrol(oListParam &par, ClassConfigInfo &cnf) {
|
||||
par.listCode = EStdPatrolStartList;
|
||||
cnf.getPatrol(par.selection);
|
||||
}
|
||||
|
||||
void TabList::getResultPatrol(oListParam &par, ClassConfigInfo &cnf) {
|
||||
par.listCode = EStdPatrolResultList;
|
||||
cnf.getPatrol(par.selection);
|
||||
}
|
||||
|
||||
void TabList::getStartTeam(oListParam &par, ClassConfigInfo &cnf) {
|
||||
par.listCode = EStdTeamStartList;
|
||||
cnf.getRelay(par.selection);
|
||||
par.setLegNumberCoded(0);
|
||||
}
|
||||
|
||||
void TabList::getResultTeam(oListParam &par, ClassConfigInfo &cnf) {
|
||||
par.listCode = EStdTeamResultListAll;
|
||||
cnf.getRelay(par.selection);
|
||||
}
|
||||
|
||||
void TabList::getResultRogaining(oListParam &par, ClassConfigInfo &cnf) {
|
||||
par.listCode = ERogainingInd;
|
||||
cnf.getRogaining(par.selection);
|
||||
}
|
||||
|
||||
void TabList::getPublicLists(oEvent &oe, vector<oListParam> &lists) {
|
||||
lists.clear();
|
||||
|
||||
ClassConfigInfo cnf;
|
||||
oe.getClassConfigurationInfo(cnf);
|
||||
if (!cnf.empty()) {
|
||||
if (cnf.hasIndividual()) {
|
||||
lists.push_back(oListParam());
|
||||
getStartIndividual(lists.back(), cnf);
|
||||
|
||||
if (oe.getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
|
||||
lists.push_back(oListParam());
|
||||
getStartClub(lists.back());
|
||||
}
|
||||
}
|
||||
|
||||
if (cnf.hasRelay()) {
|
||||
lists.push_back(oListParam());
|
||||
getStartTeam(lists.back(), cnf);
|
||||
}
|
||||
if (cnf.hasPatrol()) {
|
||||
lists.push_back(oListParam());
|
||||
getStartPatrol(lists.back(), cnf);
|
||||
}
|
||||
|
||||
if (cnf.isMultiStageEvent()) {
|
||||
//gdi.addButton("StartL:inputresult", "Input Results", ListsCB);
|
||||
}
|
||||
|
||||
if (cnf.hasIndividual()) {
|
||||
lists.push_back(oListParam());
|
||||
getResultIndividual(lists.back(), cnf);
|
||||
if (oe.getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
|
||||
lists.push_back(oListParam());
|
||||
getResultClub(lists.back(), cnf);
|
||||
}
|
||||
|
||||
//gdi.addButton("ResultIndSplit", "Sträcktider", ListsCB);
|
||||
|
||||
if (cnf.isMultiStageEvent()) {
|
||||
//gdi.addButton("Result:stageresult", "Etappresultat", ListsCB);
|
||||
|
||||
//gdi.addButton("Result:finalresult", "Slutresultat", ListsCB);
|
||||
}
|
||||
}
|
||||
if (cnf.hasRelay()) {
|
||||
lists.push_back(oListParam());
|
||||
getResultTeam(lists.back(), cnf);
|
||||
}
|
||||
if (cnf.hasPatrol()) {
|
||||
lists.push_back(oListParam());
|
||||
getResultPatrol(lists.back(), cnf);
|
||||
}
|
||||
|
||||
if (cnf.hasRogaining()) {
|
||||
//gdi.addButton("Result:rogainingind", "Rogaining", ListsCB).setExtra(2);
|
||||
}
|
||||
}
|
||||
|
||||
MetaListContainer &lc = oe.getListContainer();
|
||||
|
||||
vector< pair<wstring, size_t> > savedParams;
|
||||
lc.getListParam(savedParams);
|
||||
for (auto &p : savedParams) {
|
||||
oListParam &par = lc.getParam(p.second);
|
||||
lists.push_back(par);
|
||||
}
|
||||
|
||||
if (cnf.hasIndividual()) {
|
||||
//gdi.addButton("PriceList", "Prisutdelningslista", ListsCB);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +87,25 @@ private:
|
||||
|
||||
/** Set animation mode*/
|
||||
void setAnimationMode(gdioutput &gdi);
|
||||
|
||||
static void getStartIndividual(oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getStartClub(oListParam &par);
|
||||
static void getResultIndividual(oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getResultClub(oListParam &par, ClassConfigInfo &cnf);
|
||||
|
||||
static void getStartPatrol(oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getResultPatrol(oListParam &par, ClassConfigInfo &cnf);
|
||||
|
||||
static void getStartTeam(oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getResultTeam(oListParam &par, ClassConfigInfo &cnf);
|
||||
|
||||
static void getResultRogaining(oListParam &par, ClassConfigInfo &cnf);
|
||||
|
||||
|
||||
public:
|
||||
/** Returns a collection of public lists. */
|
||||
void static getPublicLists(oEvent &oe, vector<oListParam> &lists);
|
||||
|
||||
bool loadPage(gdioutput &gdi);
|
||||
bool loadPage(gdioutput &gdi, const string &command);
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@ void TabRunner::enableControlButtons(gdioutput &gdi, bool enable, bool vacant)
|
||||
|
||||
void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
if (!r) {
|
||||
runnerId=0;
|
||||
runnerId = 0;
|
||||
gdi.setText("Name", L"");
|
||||
gdi.setText("Bib", L"");
|
||||
gdi.selectItemByData("RCourse", 0);
|
||||
@ -158,7 +158,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
gdi.enableEditControls(true);
|
||||
disablePunchCourse(gdi);
|
||||
|
||||
pRunner parent=r->getMultiRunner(0);
|
||||
pRunner parent = r->getMultiRunner(0);
|
||||
|
||||
r->synchronizeAll();
|
||||
//r->apply(false);
|
||||
@ -172,14 +172,14 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
|
||||
gdi.selectItemByData("Runners", parent->getId());
|
||||
|
||||
runnerId=r->getId();
|
||||
runnerId = r->getId();
|
||||
|
||||
gdi.setText("Name", r->getNameRaw());
|
||||
wstring bib = r->getBib();
|
||||
|
||||
if (gdi.hasField("Bib")) {
|
||||
gdi.setText("Bib", bib);
|
||||
bool controlBib = r->getTeam() == 0 || (r->getClassRef() && r->getClassRef()->getBibMode() == BibFree);
|
||||
bool controlBib = r->getTeam() == 0 || (r->getClassRef(true) && r->getClassRef(true)->getBibMode() == BibFree);
|
||||
gdi.setInputStatus("Bib", controlBib);
|
||||
}
|
||||
|
||||
@ -187,10 +187,10 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
|
||||
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterNone);
|
||||
gdi.addItem("RClass", lang.tl("Ingen klass"), 0);
|
||||
gdi.selectItemByData("RClass", r->getClassId());
|
||||
gdi.selectItemByData("RClass", r->getClassId(true));
|
||||
|
||||
if (gdi.hasField("EditTeam")) {
|
||||
gdi.setInputStatus("EditTeam", r->getTeam()!=0);
|
||||
gdi.setInputStatus("EditTeam", r->getTeam() != 0);
|
||||
|
||||
if (r->getTeam()) {
|
||||
gdi.setText("Team", r->getTeam()->getName());
|
||||
@ -217,19 +217,19 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
r->getLegPlacesAcc(placeAcc);
|
||||
|
||||
wstring out;
|
||||
for (size_t k = 0; k<delta.size(); k++) {
|
||||
for (size_t k = 0; k < delta.size(); k++) {
|
||||
out += itow(place[k]);
|
||||
if (k<placeAcc.size())
|
||||
if (k < placeAcc.size())
|
||||
out += L" (" + itow(placeAcc[k]) + L")";
|
||||
|
||||
if (after[k]>0)
|
||||
out+= L" +" + getTimeMS(after[k]);
|
||||
if (after[k] > 0)
|
||||
out += L" +" + getTimeMS(after[k]);
|
||||
|
||||
if (k<afterAcc.size() && afterAcc[k]>0)
|
||||
out+= L" (+" + getTimeMS(afterAcc[k]) + L")";
|
||||
if (k < afterAcc.size() && afterAcc[k]>0)
|
||||
out += L" (+" + getTimeMS(afterAcc[k]) + L")";
|
||||
|
||||
if (delta[k]>0)
|
||||
out+= L" B: " + getTimeMS(delta[k]);
|
||||
if (delta[k] > 0)
|
||||
out += L" B: " + getTimeMS(delta[k]);
|
||||
|
||||
out += L" | ";
|
||||
|
||||
@ -241,18 +241,18 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
#endif
|
||||
|
||||
if (gdi.hasField("MultiR")) {
|
||||
int numMulti=parent->getNumMulti();
|
||||
if (numMulti==0) {
|
||||
int numMulti = parent->getNumMulti();
|
||||
if (numMulti == 0) {
|
||||
gdi.clearList("MultiR");
|
||||
gdi.disableInput("MultiR");
|
||||
lastRace=0;
|
||||
lastRace = 0;
|
||||
}
|
||||
else {
|
||||
gdi.clearList("MultiR");
|
||||
gdi.enableInput("MultiR");
|
||||
|
||||
for (int k=0;k<numMulti+1;k++) {
|
||||
gdi.addItem("MultiR", lang.tl("Lopp X#" + itos(k+1)), k);
|
||||
for (int k = 0; k < numMulti + 1; k++) {
|
||||
gdi.addItem("MultiR", lang.tl("Lopp X#" + itos(k + 1)), k);
|
||||
}
|
||||
gdi.selectItemByData("MultiR", r->getRaceNo());
|
||||
}
|
||||
@ -264,7 +264,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
updateNumShort(gdi, r->getCourse(false), r);
|
||||
|
||||
int cno = parent->getCardNo();
|
||||
gdi.setText("CardNo", cno>0 ? itow(cno) : L"");
|
||||
gdi.setText("CardNo", cno > 0 ? itow(cno) : L"");
|
||||
|
||||
warnDuplicateCard(gdi, cno, r);
|
||||
|
||||
@ -316,9 +316,9 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
gdi.setText("PointIn", r->getInputPoints());
|
||||
}
|
||||
|
||||
pCard pc=r->getCard();
|
||||
pCard pc = r->getCard();
|
||||
|
||||
pCourse pcourse=r->getCourse(true);
|
||||
pCourse pcourse = r->getCourse(true);
|
||||
|
||||
if (pc) {
|
||||
gdi.setTabStops("Punches", 70);
|
||||
@ -337,6 +337,12 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
||||
gdi.clearList("Course");
|
||||
gdi.disableInput("AddAllC");
|
||||
}
|
||||
|
||||
gdioutput *gdi_settings = getExtraWindow("ecosettings", false);
|
||||
if (gdi_settings) {
|
||||
TabRunner &dst = dynamic_cast<TabRunner&>(*gdi_settings->getTabs().get(TabType::TRunnerTab));
|
||||
dst.loadEconomy(*gdi_settings, *r);
|
||||
}
|
||||
}
|
||||
|
||||
int RunnerCB(gdioutput *gdi, int type, void *data)
|
||||
@ -579,6 +585,12 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
if (gdi.hasField("Fee"))
|
||||
r->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee")));
|
||||
|
||||
gdioutput *gdi_settings = getExtraWindow("ecosettings", false);
|
||||
if (gdi_settings) {
|
||||
TabRunner &dst = dynamic_cast<TabRunner&>(*gdi_settings->getTabs().get(TabType::TRunnerTab));
|
||||
dst.getEconomyHandler(*r)->save(*gdi_settings);
|
||||
}
|
||||
|
||||
r->setStartTimeS(gdi.getText("Start"));
|
||||
r->setFinishTimeS(gdi.getText("Finish"));
|
||||
|
||||
@ -608,14 +620,14 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
gdi.alert("För att delta i en lagklass måste deltagaren ingå i ett lag.");
|
||||
classId = 0;
|
||||
}
|
||||
else if (r->getTeam()->getClassId() != classId && r->getClassId() != classId) {
|
||||
else if (r->getTeam()->getClassId(true) != classId && r->getClassId(true) != classId) {
|
||||
gdi.alert("Deltagarens klass styrs av laget.");
|
||||
classId = r->getTeam()->getClassId();
|
||||
classId = r->getTeam()->getClassId(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool readStatusIn = true;
|
||||
if (r->getClassId() != classId && r->getInputStatus() != StatusNotCompetiting && r->hasInputData()) {
|
||||
if (r->getClassId(true) != classId && r->getInputStatus() != StatusNotCompetiting && r->hasInputData()) {
|
||||
if (gdi.ask(L"Vill du sätta resultatet från tidigare etapper till <Deltar ej>?")) {
|
||||
r->resetInputData();
|
||||
readStatusIn = false;
|
||||
@ -635,7 +647,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
vector<int> mp;
|
||||
r->evaluateCard(true, mp, 0, true);
|
||||
|
||||
if (r->getClassId() != classId) {
|
||||
if (r->getClassId(true) != classId) {
|
||||
gdi.alert("Deltagarens klass styrs av laget.");
|
||||
}
|
||||
|
||||
@ -652,11 +664,14 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
|
||||
r->synchronizeAll();
|
||||
|
||||
if (r->getClassRef() && r->getClassRef()->hasClassGlobalDependance()) {
|
||||
if (r->getClassRef(false) && r->getClassRef(false)->hasClassGlobalDependence()) {
|
||||
set<int> cls;
|
||||
cls.insert(r->getClassId());
|
||||
cls.insert(r->getClassId(false));
|
||||
oe->reEvaluateAll(cls, false);
|
||||
}
|
||||
|
||||
if (r->getClassRef(false))
|
||||
r->getClassRef(false)->updateFinalClasses(r, false);
|
||||
}
|
||||
else
|
||||
runnerId=0;
|
||||
@ -938,9 +953,11 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
if (!runnerId)
|
||||
return 0;
|
||||
pRunner r = oe->getRunner(runnerId, 0);
|
||||
gdioutput *settings = createExtraWindow("ecosettings", L"Economy for X#" + r->getName(), 400, 200);
|
||||
|
||||
|
||||
if (getExtraWindow("ecosettings", true) == 0) {
|
||||
gdioutput *settings = createExtraWindow("ecosettings", L"Economy", 550, 350);
|
||||
TabRunner &dst = dynamic_cast<TabRunner&>(*settings->getTabs().get(TabType::TRunnerTab));
|
||||
dst.loadEconomy(*settings, *r);
|
||||
}
|
||||
}
|
||||
else if (bi.id=="NoStart") {
|
||||
if (!runnerId)
|
||||
@ -950,7 +967,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
if (r && gdi.ask(L"Bekräfta att deltagaren har lämnat återbud.")) {
|
||||
if (r->getStartTime()>0) {
|
||||
pRunner newRunner = oe->addRunnerVacant(r->getClassId());
|
||||
pRunner newRunner = oe->addRunnerVacant(r->getClassId(true));
|
||||
newRunner->cloneStartTime(r);
|
||||
newRunner->setStartNo(r->getStartNo(), false);
|
||||
if (r->getCourseId())
|
||||
@ -1045,12 +1062,18 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
if (gdi.isInputChanged("")) {
|
||||
pRunner r = oe->getRunner(runnerId, 0);
|
||||
bool newName = r && r->getName() != gdi.getText("Name");
|
||||
|
||||
save(gdi, runnerId, true);
|
||||
|
||||
if (newName)
|
||||
fillRunnerList(gdi);
|
||||
}
|
||||
else {
|
||||
pRunner r = oe->getRunner(runnerId, 0);
|
||||
gdioutput *gdi_settings = getExtraWindow("ecosettings", false);
|
||||
if (gdi_settings) {
|
||||
TabRunner &dst = dynamic_cast<TabRunner&>(*gdi_settings->getTabs().get(TabType::TRunnerTab));
|
||||
dst.getEconomyHandler(*r)->save(*gdi_settings);
|
||||
}
|
||||
}
|
||||
|
||||
if (bi.data == -1) {
|
||||
fillRunnerList(gdi);
|
||||
@ -1193,16 +1216,20 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
}
|
||||
else if (type==GUI_CLEAR) {
|
||||
gdioutput *gdi_settings = getExtraWindow("ecosettings", false);
|
||||
if (gdi_settings)
|
||||
gdi_settings->closeWindow();
|
||||
|
||||
if (runnerId>0 && currentMode == 0)
|
||||
save(gdi, runnerId, true);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (type == GUI_LINK) {
|
||||
int id = static_cast<TextInfo*>(data)->getExtraInt();
|
||||
oRunner *vacancy = oe->getRunner(id, 0);
|
||||
|
||||
if (vacancy==0 || vacancy->getClassId()==0)
|
||||
if (vacancy==0 || vacancy->getClassId(false)==0)
|
||||
return -1;
|
||||
|
||||
pRunner r = oe->getRunner(runnerId, 0);
|
||||
@ -1215,7 +1242,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
wchar_t bf[1024];
|
||||
swprintf_s(bf, lang.tl("Bekräfta att %s byter klass till %s.").c_str(),
|
||||
r->getName().c_str(), vacancy->getClass().c_str());
|
||||
r->getName().c_str(), vacancy->getClass(true).c_str());
|
||||
if (gdi.ask(wstring(L"#") + bf)) {
|
||||
|
||||
vacancy->synchronize();
|
||||
@ -1226,11 +1253,11 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
temp.setTemporary();
|
||||
temp.setBib(r->getBib(), 0, false, false);
|
||||
temp.setStartNo(r->getStartNo(), false);
|
||||
temp.setClassId(r->getClassId(), true);
|
||||
temp.setClassId(r->getClassId(true), true);
|
||||
temp.apply(false, 0, false);
|
||||
temp.cloneStartTime(r);
|
||||
|
||||
r->setClassId(vacancy->getClassId(), true);
|
||||
r->setClassId(vacancy->getClassId(true), true);
|
||||
// Remove or create multi runners
|
||||
r->createMultiRunner(true, true);
|
||||
r->apply(false, 0, false);
|
||||
@ -1243,7 +1270,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
r->resetInputData();
|
||||
}
|
||||
|
||||
vacancy->setClassId(temp.getClassId(), true);
|
||||
vacancy->setClassId(temp.getClassId(true), true);
|
||||
// Remove or create multi runners
|
||||
vacancy->createMultiRunner(true, true);
|
||||
vacancy->apply(false, 0, false);
|
||||
@ -1321,7 +1348,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
|
||||
int birthYear = 0;
|
||||
pClub pc = oe->getClubCreate(0, club);
|
||||
|
||||
r->updateFromDB(name, pc->getId(), r->getClassId(), cardNo, birthYear);
|
||||
r->updateFromDB(name, pc->getId(), r->getClassId(false), cardNo, birthYear);
|
||||
|
||||
r->setName(name, true);
|
||||
r->setCardNo(cardNo, true);
|
||||
@ -1377,7 +1404,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
|
||||
// Print start certificate
|
||||
tsi.generateStartInfo(gdi, *r);
|
||||
|
||||
showVacancyList(gdi, "", r->getClassId());
|
||||
showVacancyList(gdi, "", r->getClassId(true));
|
||||
}
|
||||
else if (type==GUI_INPUT) {
|
||||
InputInfo ii=*(InputInfo *)data;
|
||||
@ -1473,7 +1500,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
|
||||
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
||||
pRunner r = oe->getRunner(runnersToReport[k].first, 0);
|
||||
if (r && r->getTeam()) {
|
||||
pClass cls = oe->getClass(r->getClassId());
|
||||
pClass cls = r->getClassRef(true);
|
||||
if (cls && cls->getClassType() == oClassPatrol)
|
||||
continue;
|
||||
|
||||
@ -1511,7 +1538,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
|
||||
tInfo += L" " + t->getStatusS();
|
||||
}
|
||||
|
||||
gdi.addStringUT(fontMediumPlus, t->getClass());
|
||||
gdi.addStringUT(fontMediumPlus, t->getClass(true));
|
||||
gdi.addStringUT(boldLarge, tInfo);
|
||||
gdi.dropLine();
|
||||
|
||||
@ -1542,19 +1569,19 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
|
||||
|
||||
void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
|
||||
pRunner r = oe->getRunner(id, 0);
|
||||
if (!r || ! r->getClassRef())
|
||||
if (!r || ! r->getClassRef(false))
|
||||
return;
|
||||
|
||||
gdi.pushX();
|
||||
gdi.fillDown();
|
||||
if (r->getTeam() == 0) {
|
||||
gdi.addStringUT(fontMediumPlus, r->getClass());
|
||||
gdi.addStringUT(fontMediumPlus, r->getClass(true));
|
||||
gdi.addStringUT(boldLarge, r->getCompleteIdentification());
|
||||
}
|
||||
else {
|
||||
wstring s;
|
||||
if (r->getTeam())
|
||||
s += r->getClassRef()->getLegNumber(r->getLegNumber());
|
||||
s += r->getClassRef(false)->getLegNumber(r->getLegNumber());
|
||||
|
||||
s += L": " + r->getName();
|
||||
gdi.addStringUT(boldText, s);
|
||||
@ -1573,7 +1600,7 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
|
||||
|
||||
if (r->statusOK()) {
|
||||
int total, finished, dns;
|
||||
oe->getNumClassRunners(r->getClassId(), r->getLegNumber(), total, finished, dns);
|
||||
oe->getNumClassRunners(r->getClassId(true), r->getLegNumber(), total, finished, dns);
|
||||
|
||||
if (r->getTeam() == 0) {
|
||||
gdi.addString("", fontMediumPlus, L"Tid: X, nuvarande placering Y/Z.#" + str + L"#" + r->getPlaceS() + L"#" + itow(finished));
|
||||
@ -2005,7 +2032,7 @@ void TabRunner::listRunners(gdioutput &gdi, const vector<pRunner> &r, bool filte
|
||||
sprintf_s(bf, "%d.", k+1);
|
||||
gdi.addStringUT(yp, xp, 0, bf);
|
||||
gdi.addStringUT(yp, xp+40, 0, r[k]->getNameAndRace(true), 190);
|
||||
gdi.addStringUT(yp, xp+200, 0, r[k]->getClass(), 140);
|
||||
gdi.addStringUT(yp, xp+200, 0, r[k]->getClass(true), 140);
|
||||
gdi.addStringUT(yp, xp+350, 0, r[k]->getClub(), 190);
|
||||
int c = r[k]->getCardNo();
|
||||
if (c>0) {
|
||||
@ -2224,6 +2251,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
card->synchronize();
|
||||
r->synchronize(true);
|
||||
r->evaluateCard(true, mp);
|
||||
r->hasManuallyUpdatedTimeStatus();
|
||||
card->fillPunches(gdi, "Punches", pc);
|
||||
UpdateStatus(gdi, r);
|
||||
}
|
||||
@ -2246,6 +2274,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
r->synchronize(true);
|
||||
r->evaluateCard(true, mp);
|
||||
card->fillPunches(gdi, "Punches", r->getCourse(true));
|
||||
r->hasManuallyUpdatedTimeStatus();
|
||||
UpdateStatus(gdi, r);
|
||||
}
|
||||
else if (bi.id=="SaveC"){
|
||||
@ -2274,6 +2303,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
card->synchronize();
|
||||
r->synchronize();
|
||||
r->evaluateCard(true, mp);
|
||||
r->hasManuallyUpdatedTimeStatus();
|
||||
card->fillPunches(gdi, "Punches", r->getCourse(true));
|
||||
UpdateStatus(gdi, r);
|
||||
gdi.selectItemByData("Punches", lbi.data);
|
||||
@ -2380,14 +2410,17 @@ bool TabRunner::loadPage(gdioutput &gdi)
|
||||
}
|
||||
|
||||
gdi.fillRight();
|
||||
gdi.addSelection("RClass", 130, 300, RunnerCB, L"Klass:");
|
||||
bool hasEco = oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy);
|
||||
gdi.addSelection("RClass", hasEco ? 130 : 170, 300, RunnerCB, L"Klass:");
|
||||
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterNone);
|
||||
gdi.addItem("RClass", lang.tl("Ingen klass"), 0);
|
||||
|
||||
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy)) {
|
||||
if (hasEco) {
|
||||
//gdi.addInput("Fee", L"", 4, 0, L"Avgift:");
|
||||
gdi.fillDown();
|
||||
gdi.addInput("Fee", L"", 4, 0, L"Avgift:");
|
||||
//gdi.addButton("Economy", "@" + itos(131), RunnerCB, "Ekonomi...");
|
||||
gdi.dropLine();
|
||||
gdi.addButton("Economy", "Ekonomi...", RunnerCB, "");
|
||||
|
||||
}
|
||||
else {
|
||||
gdi.fillDown();
|
||||
@ -2652,7 +2685,7 @@ void TabRunner::fillRunnerList(gdioutput &gdi) {
|
||||
}
|
||||
|
||||
bool TabRunner::canSetStart(pRunner r) const {
|
||||
pClass pc = r->getTeam() ? r->getTeam()->getClassRef() : r->getClassRef();
|
||||
pClass pc = r->getTeam() ? r->getTeam()->getClassRef(false) : r->getClassRef(true);
|
||||
|
||||
if (pc && pc->getNumStages() > 0) {
|
||||
StartTypes st = pc->getStartType(r->getLegNumber());
|
||||
@ -2778,3 +2811,138 @@ void TabRunner::autoGrowCourse(gdioutput &gdi) {
|
||||
gdi.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TabRunner::EconomyHandler::init(oRunner &r) {
|
||||
oe = r.getEvent();
|
||||
runnerId = r.getId();
|
||||
}
|
||||
|
||||
oRunner &TabRunner::EconomyHandler::getRunner() const {
|
||||
pRunner p = oe->getRunner(runnerId, 0);
|
||||
if (!p)
|
||||
throw meosException("Löpare saknas");
|
||||
return *p;
|
||||
}
|
||||
|
||||
TabRunner::EconomyHandler *TabRunner::getEconomyHandler(oRunner &r) {
|
||||
if (!ecoHandler)
|
||||
ecoHandler = make_shared<EconomyHandler>();
|
||||
|
||||
ecoHandler->init(r);
|
||||
return ecoHandler.get();
|
||||
}
|
||||
|
||||
void TabRunner::EconomyHandler::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
|
||||
if (type == GuiEventType::GUI_BUTTON) {
|
||||
ButtonInfo &bi = dynamic_cast<ButtonInfo &>(info);
|
||||
if (bi.id == "Close") {
|
||||
save(gdi);
|
||||
gdi.closeWindow();
|
||||
}
|
||||
else if (bi.id == "Save") {
|
||||
save(gdi);
|
||||
}
|
||||
else if (bi.id == "Cancel") {
|
||||
TabRunner &dst = dynamic_cast<TabRunner&>(*gdi.getTabs().get(TabType::TRunnerTab));
|
||||
dst.loadEconomy(gdi, getRunner());
|
||||
}
|
||||
}
|
||||
else if (type == GuiEventType::GUI_INPUTCHANGE) {
|
||||
InputInfo &ii = dynamic_cast<InputInfo &>(info);
|
||||
if (ii.id == "Fee") {
|
||||
gdi.check("ModFee", ii.changed() || getRunner().hasFlag(oAbstractRunner::FlagFeeSpecified));
|
||||
}
|
||||
else if (ii.id == "PaidAmount") {
|
||||
int paid = oe->interpretCurrency(ii.text);
|
||||
gdi.setInputStatus("PayMode", paid != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TabRunner::EconomyHandler::save(gdioutput &gdi) {
|
||||
oRunner &r = getRunner();
|
||||
if (r.getTeam() == 0) {
|
||||
r.getDI().setDate("EntryDate", gdi.getText("EntryDate"));
|
||||
int t = convertAbsoluteTimeHMS(gdi.getText("EntryTime"), -1);
|
||||
r.getDI().setInt("EntryTime", t);
|
||||
}
|
||||
int fee = oe->interpretCurrency(gdi.getText("Fee"));
|
||||
if (r.getClassRef(true)) {
|
||||
int def = r.getClassRef(true)->getEntryFee(r.getEntryDate(), r.getBirthAge());
|
||||
r.setFlag(oAbstractRunner::FlagFeeSpecified, def != fee);
|
||||
}
|
||||
r.getDI().setInt("Fee", fee);
|
||||
int cf = oe->interpretCurrency(gdi.getText("Card"));
|
||||
if (cf > 0 || cf == 0 && r.getDCI().getInt("CardFee") != -1)
|
||||
r.getDI().setInt("CardFee", cf);
|
||||
int paid = oe->interpretCurrency(gdi.getText("PaidAmount"));
|
||||
r.getDI().setInt("Paid", paid);
|
||||
|
||||
|
||||
if (paid != 0) {
|
||||
int m = gdi.getSelectedItem("").first;
|
||||
if (m != 1000)
|
||||
r.getDI().setInt("PayMode", m);
|
||||
}
|
||||
}
|
||||
|
||||
void TabRunner::loadEconomy(gdioutput &gdi, oRunner &r) {
|
||||
gdi.clearPage(false);
|
||||
gdi.fillDown();
|
||||
gdi.pushX();
|
||||
gdi.addString("", fontMediumPlus, L"Ekonomihantering, X#" + r.getCompleteIdentification());
|
||||
auto h = getEconomyHandler(r);
|
||||
|
||||
gdi.fillRight();
|
||||
gdi.addInput("EntryDate", r.getEntryDate(true), 10, 0, L"Anmälningsdatum:");
|
||||
gdi.fillDown();
|
||||
gdi.addInput("EntryTime", formatTime(r.getDCI().getInt("EntryTime")), 10, 0, L"Anmälningstid:");
|
||||
gdi.setInputStatus("EntryDate", r.getTeam() == 0);
|
||||
gdi.setInputStatus("EntryTime", r.getTeam() == 0);
|
||||
|
||||
gdi.popX();
|
||||
gdi.dropLine();
|
||||
|
||||
gdi.fillRight();
|
||||
gdi.addInput("Fee", oe->formatCurrency(r.getDCI().getInt("Fee")), 5, 0, L"Avgift:").setHandler(h);
|
||||
int cf = r.getDCI().getInt("CardFee");
|
||||
if (cf == -1) // Borrowed, zero fee
|
||||
cf = 0;
|
||||
gdi.addInput("Card", oe->formatCurrency(cf), 5, 0, L"Brickhyra:");
|
||||
int paid = r.getDCI().getInt("Paid");
|
||||
gdi.addInput("PaidAmount", oe->formatCurrency(paid), 5, 0, L"Betalat:").setHandler(h);
|
||||
gdi.fillDown();
|
||||
gdi.dropLine();
|
||||
vector< pair<wstring, size_t> > pm;
|
||||
oe->getPayModes(pm);
|
||||
int mypm = r.getDCI().getInt("PayMode");
|
||||
//pm.insert(pm.begin(), make_pair(lang.tl(L"Faktureras"), 1000));
|
||||
gdi.addSelection("PayMode", 110, 100, SportIdentCB);
|
||||
gdi.addItem("PayMode", pm);
|
||||
gdi.selectItemByData("PayMode", mypm);
|
||||
gdi.autoGrow("PayMode");
|
||||
gdi.setInputStatus("PayMode", paid != 0);
|
||||
|
||||
gdi.dropLine();
|
||||
gdi.popX();
|
||||
|
||||
gdi.addString("", 1, "Manuellt gjorda justeringar");
|
||||
gdi.fillRight();
|
||||
|
||||
gdi.addCheckbox("ModFee", "Avgift", 0, r.hasFlag(oAbstractRunner::FlagFeeSpecified));
|
||||
gdi.disableInput("ModFee");
|
||||
|
||||
gdi.addCheckbox("ModCls", "Klass", 0, r.hasFlag(oAbstractRunner::FlagUpdateClass));
|
||||
gdi.disableInput("ModCls");
|
||||
|
||||
gdi.fillDown();
|
||||
gdi.addCheckbox("ModCls", "Namn", 0, r.hasFlag(oAbstractRunner::FlagUpdateName));
|
||||
gdi.disableInput("ModCls");
|
||||
|
||||
gdi.fillRight();
|
||||
gdi.addButton("Cancel", "Ångra").setHandler(h);
|
||||
gdi.addButton("Close", "Stäng").setHandler(h);
|
||||
gdi.addButton("Save", "Spara").setHandler(h);
|
||||
gdi.refresh();
|
||||
}
|
||||
|
||||
@ -91,6 +91,21 @@ private:
|
||||
|
||||
static void autoGrowCourse(gdioutput &gdi);
|
||||
|
||||
void loadEconomy(gdioutput &gdi, oRunner &r);
|
||||
|
||||
class EconomyHandler : public GuiHandler {
|
||||
int runnerId;
|
||||
oEvent *oe;
|
||||
oRunner &getRunner() const;
|
||||
public:
|
||||
void init(oRunner &r);
|
||||
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);
|
||||
void save(gdioutput &gdi);
|
||||
};
|
||||
|
||||
shared_ptr<EconomyHandler> ecoHandler;
|
||||
EconomyHandler *getEconomyHandler(oRunner &r);
|
||||
|
||||
protected:
|
||||
void clearCompetitionData();
|
||||
|
||||
@ -104,6 +119,8 @@ public:
|
||||
bool loadPage(gdioutput &gdi);
|
||||
bool loadPage(gdioutput &gdi, int runnerId);
|
||||
|
||||
|
||||
|
||||
TabRunner(oEvent *oe);
|
||||
~TabRunner(void);
|
||||
|
||||
|
||||
@ -818,7 +818,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
pRunner cardRunner = oe->getRunnerByCardNo(cardNo, 0, true);
|
||||
if (cardNo>0 && cardRunner!=0 && cardRunner!=r) {
|
||||
gdi.alert(L"Bricknummret är upptaget (X).#" + cardRunner->getName() + L", " + cardRunner->getClass());
|
||||
gdi.alert(L"Bricknummret är upptaget (X).#" + cardRunner->getName() + L", " + cardRunner->getClass(true));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -857,7 +857,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
|
||||
lastClubId=r->getClubId();
|
||||
lastClassId=r->getClassId();
|
||||
lastClassId=r->getClassId(true);
|
||||
lastFee = gdi.getText("Fee", true);
|
||||
int lastFeeNum = oe->interpretCurrency(lastFee);
|
||||
|
||||
@ -890,10 +890,10 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
wchar_t bf[256];
|
||||
if (r->getClubId() != 0) {
|
||||
swprintf_s(bf, L"(%d), %s, %s", r->getCardNo(), r->getClub().c_str(),
|
||||
r->getClass().c_str());
|
||||
r->getClass(true).c_str());
|
||||
}
|
||||
else {
|
||||
swprintf_s(bf, L"(%d), %s", r->getCardNo(), r->getClass().c_str());
|
||||
swprintf_s(bf, L"(%d), %s", r->getCardNo(), r->getClass(true).c_str());
|
||||
}
|
||||
|
||||
wstring info(bf);
|
||||
@ -1810,7 +1810,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
autoAssignClass(r, sic);
|
||||
|
||||
if (interactiveReadout) {
|
||||
if (r && r->getClassId() && !readBefore && !sameCardNewRace) {
|
||||
if (r && r->getClassId(false) && !readBefore && !sameCardNewRace) {
|
||||
//We can do a silent read-out...
|
||||
processCard(gdi, r, sic, true);
|
||||
return;
|
||||
@ -1823,7 +1823,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
}
|
||||
else {
|
||||
if (!readBefore) {
|
||||
if (r && r->getClassId() && !sameCardNewRace)
|
||||
if (r && r->getClassId(false) && !sameCardNewRace)
|
||||
processCard(gdi, r, sic, true);
|
||||
else
|
||||
processUnmatched(gdi, sic, true);
|
||||
@ -1839,7 +1839,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
// Assign a class if not already done
|
||||
autoAssignClass(r, sic);
|
||||
|
||||
if (r && r->getClassId() && !readBefore && !sameCardNewRace) {
|
||||
if (r && r->getClassId(false) && !readBefore && !sameCardNewRace) {
|
||||
//We can do a silent read-out...
|
||||
processCard(gdi, r, sic, true);
|
||||
return;
|
||||
@ -1923,7 +1923,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
// Assign a class if not already done
|
||||
autoAssignClass(r, sic);
|
||||
|
||||
if (r && r->getClassId() && !r->getCard()) {
|
||||
if (r && r->getClassId(false) && !r->getCard()) {
|
||||
SICard copy = sic;
|
||||
activeSIC.clear(0);
|
||||
processCard(gdi, r, copy); //Everyting is OK
|
||||
@ -2148,11 +2148,11 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
//Update from SQL-source
|
||||
runner->synchronize();
|
||||
|
||||
if (!runner->getClassId())
|
||||
if (!runner->getClassId(false))
|
||||
runner->setClassId(gEvent->addClass(lang.tl(L"Okänd klass"))->getId(), true);
|
||||
|
||||
// Choose course from pool
|
||||
pClass cls=gEvent->getClass(runner->getClassId());
|
||||
pClass cls = runner->getClassRef(false);
|
||||
if (cls && cls->hasCoursePool()) {
|
||||
unsigned leg=runner->legToRun();
|
||||
|
||||
@ -2171,11 +2171,11 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
}
|
||||
}
|
||||
|
||||
pClass pclass=gEvent->getClass(runner->getClassId());
|
||||
pClass pclass = runner->getClassRef(true);
|
||||
if (!runner->getCourse(false) && !csic.isManualInput()) {
|
||||
|
||||
if (pclass && !pclass->hasMultiCourse() && !pclass->hasDirectResult()) {
|
||||
pCourse pcourse=gEvent->addCourse(runner->getClass());
|
||||
pCourse pcourse=gEvent->addCourse(pclass->getName());
|
||||
pclass->setCourse(pcourse);
|
||||
|
||||
for(unsigned i=0;i<csic.nPunch; i++)
|
||||
@ -2222,8 +2222,10 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
|
||||
cardno = itow(sic.CardNumber);
|
||||
|
||||
info = runner->getName() + L" (" + cardno + L"), " + runner->getClub()
|
||||
+ L", " + runner->getClass();
|
||||
info = runner->getName() + L" (" + cardno + L"), ";
|
||||
if (!runner->getClub().empty())
|
||||
info += runner->getClub() + +L", ";
|
||||
info += runner->getClass(true);
|
||||
|
||||
// Write read card to log
|
||||
logCard(sic);
|
||||
@ -2260,7 +2262,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
}
|
||||
else {
|
||||
//Manual input
|
||||
info = runner->getName() + L", " + runner->getClub() + L", " + runner->getClass();
|
||||
info = runner->getName() + L", " + runner->getClub() + L", " + runner->getClass(true);
|
||||
runner->setCard(0);
|
||||
|
||||
if (csic.statusOK) {
|
||||
@ -2297,7 +2299,10 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
gEvent->calculateResults(oEvent::RTClassResult);
|
||||
if (runner->getTeam())
|
||||
gEvent->calculateTeamResults(runner->getLegNumber(), false);
|
||||
wstring placeS = runner->getTeam() ? runner->getTeam()->getLegPlaceS(runner->getLegNumber(), false) : runner->getPlaceS();
|
||||
bool qfClass = runner->getClassId(false) != runner->getClassId(true);
|
||||
wstring placeS = (runner->getTeam() && !qfClass) ?
|
||||
runner->getTeam()->getLegPlaceS(runner->getLegNumber(), false) :
|
||||
runner->getPlaceS();
|
||||
|
||||
if (!silent) {
|
||||
gdi.fillDown();
|
||||
@ -2322,7 +2327,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
}
|
||||
else {
|
||||
wstring msg = L"#" + runner->getName() + L" (" + cardno + L")\n"+
|
||||
runner->getClub() + L". " + runner->getClass() +
|
||||
runner->getClub() + L". " + runner->getClass(true) +
|
||||
L"\n" + lang.tl("Tid: ") + runner->getRunningTimeS() + lang.tl(L", Plats ") + placeS;
|
||||
|
||||
gdi.addInfoBox("SIINFO", msg, 10000);
|
||||
@ -2359,7 +2364,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
}
|
||||
else {
|
||||
wstring statusmsg = L"#" + runner->getName() + L" (" + cardno + L")\n"+
|
||||
runner->getClub() + L". "+ runner->getClass() +
|
||||
runner->getClub() + L". "+ runner->getClass(true) +
|
||||
L"\n" + msg;
|
||||
|
||||
gdi.addInfoBox("SIINFO", statusmsg, 10000);
|
||||
@ -2594,7 +2599,7 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r)
|
||||
if (gdi.hasField("Club")) {
|
||||
gdi.selectItemByData("Club", r->getClubId());
|
||||
}
|
||||
gdi.selectItemByData("Class", r->getClassId());
|
||||
gdi.selectItemByData("Class", r->getClassId(true));
|
||||
|
||||
oDataConstInterface dci = r->getDCI();
|
||||
if (gdi.hasField("Fee"))
|
||||
@ -2729,7 +2734,7 @@ void TabSI::checkMoreCardsInQueue(gdioutput &gdi) {
|
||||
}
|
||||
|
||||
bool TabSI::autoAssignClass(pRunner r, const SICard &sic) {
|
||||
if (r && r->getClassId()==0) {
|
||||
if (r && r->getClassId(false)==0) {
|
||||
vector<pClass> classes;
|
||||
int dist = oe->findBestClass(sic, classes);
|
||||
|
||||
@ -2737,7 +2742,7 @@ bool TabSI::autoAssignClass(pRunner r, const SICard &sic) {
|
||||
r->setClassId(classes[0]->getId(), true);
|
||||
}
|
||||
|
||||
return r && r->getClassId() != 0;
|
||||
return r && r->getClassId(false) != 0;
|
||||
}
|
||||
|
||||
void TabSI::showManualInput(gdioutput &gdi) {
|
||||
|
||||
@ -717,6 +717,10 @@ void TabSpeaker::generateControlList(gdioutput &gdi, int classId)
|
||||
|
||||
vector<oClass::TrueLegInfo> stages;
|
||||
pc->getTrueStages(stages);
|
||||
if (pc->getQualificationFinal()) {
|
||||
while (stages.size() > 1)
|
||||
stages.pop_back(); //Ignore for qualification race
|
||||
}
|
||||
int leg = selectedControl[pc->getId()].getLeg();
|
||||
const bool multiDay = oe->hasPrevStage();
|
||||
|
||||
@ -1017,6 +1021,8 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
}
|
||||
}
|
||||
|
||||
gdi.setRestorePoint("classes");
|
||||
|
||||
if (classId == -1) {
|
||||
string btn = "Events";
|
||||
if (gdi.hasField(btn))
|
||||
@ -1028,8 +1034,6 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
gdi.sendCtrlMessage(btn);
|
||||
}
|
||||
|
||||
|
||||
gdi.setRestorePoint("classes");
|
||||
gdi.refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
|
||||
gdi.enableInput("Remove");
|
||||
|
||||
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterNone);
|
||||
gdi.selectItemByData("RClass", t->getClassId());
|
||||
gdi.selectItemByData("RClass", t->getClassId(false));
|
||||
gdi.selectItemByData("Teams", t->getId());
|
||||
|
||||
if (gdi.hasField("StatusIn")) {
|
||||
@ -353,14 +353,14 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
||||
gdi.getSelectedItem("RClass", lbi);
|
||||
|
||||
int classId = lbi.data;
|
||||
bool newClass = t->getClassId() != classId;
|
||||
bool newClass = t->getClassId(false) != classId;
|
||||
set<int> classes;
|
||||
bool globalDep = false;
|
||||
if (t->getClassRef())
|
||||
globalDep = t->getClassRef()->hasClassGlobalDependance();
|
||||
if (t->getClassRef(false))
|
||||
globalDep = t->getClassRef(false)->hasClassGlobalDependence();
|
||||
|
||||
classes.insert(classId);
|
||||
classes.insert(t->getClassId());
|
||||
classes.insert(t->getClassId(false));
|
||||
|
||||
bool readStatusIn = true;
|
||||
if (newClass && t->getInputStatus() != StatusNotCompetiting && t->hasInputData()) {
|
||||
@ -402,7 +402,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
||||
pClass pc=oe->getClass(classId);
|
||||
|
||||
if (pc) {
|
||||
globalDep |= pc->hasClassGlobalDependance();
|
||||
globalDep |= pc->hasClassGlobalDependence();
|
||||
|
||||
for (unsigned i=0;i<pc->getNumStages(); i++) {
|
||||
char bf[16];
|
||||
@ -428,7 +428,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
||||
// Same runner set
|
||||
if (oldId == r->getId()) {
|
||||
if (newName) {
|
||||
r->updateFromDB(name, r->getClubId(), r->getClassId(),
|
||||
r->updateFromDB(name, r->getClubId(), r->getClassId(false),
|
||||
cardNo, 0);
|
||||
r->setName(name, true);
|
||||
}
|
||||
@ -447,12 +447,12 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
||||
if (!t->getClub().empty())
|
||||
r->setClub(t->getClub());
|
||||
r->resetPersonalData();
|
||||
r->updateFromDB(name, r->getClubId(), r->getClassId(),
|
||||
r->updateFromDB(name, r->getClubId(), r->getClassId(false),
|
||||
cardNo, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
r=oe->addRunner(name, t->getClubId(), t->getClassId(), cardNo, 0, false);
|
||||
r=oe->addRunner(name, t->getClubId(), t->getClassId(false), cardNo, 0, false);
|
||||
|
||||
r->setName(name, true);
|
||||
r->setCardNo(cardNo, true);
|
||||
@ -594,7 +594,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
else if (bi.id == "DirOK") {
|
||||
pTeam t = oe->getTeam(teamId);
|
||||
if (!t || !t->getClassRef())
|
||||
if (!t || !t->getClassRef(false))
|
||||
return 0;
|
||||
|
||||
int leg = bi.getExtraInt();
|
||||
@ -632,7 +632,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
bool rent = gdi.isChecked("DirRent");
|
||||
|
||||
if (r == 0) {
|
||||
r = oe->addRunner(name, clb ? clb->getId() : t->getClubId(), t->getClassId(), card, 0, false);
|
||||
r = oe->addRunner(name, clb ? clb->getId() : t->getClubId(), t->getClassId(false), card, 0, false);
|
||||
}
|
||||
if (rent)
|
||||
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee"));
|
||||
@ -671,10 +671,10 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
else if (bi.id == "ChangeKey") {
|
||||
pTeam t = oe->getTeam(teamId);
|
||||
if (!t || !t->getClassRef())
|
||||
if (!t || !t->getClassRef(false))
|
||||
return 0;
|
||||
|
||||
pClass pc = t->getClassRef();
|
||||
pClass pc = t->getClassRef(false);
|
||||
gdi.restore("ChangeKey", false);
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
@ -695,10 +695,10 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
else if (bi.id == "SaveKey") {
|
||||
pTeam t = oe->getTeam(teamId);
|
||||
if (!t || !t->getClassRef())
|
||||
if (!t || !t->getClassRef(false))
|
||||
return 0;
|
||||
|
||||
pClass pc = t->getClassRef();
|
||||
pClass pc = t->getClassRef(false);
|
||||
int nf = pc->getNumForks();
|
||||
ListBoxInfo lbi;
|
||||
gdi.getSelectedItem("ForkKey", lbi);
|
||||
@ -752,7 +752,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
pTeam t = oe->getTeam(teamId);
|
||||
if (t == 0)
|
||||
return 0;
|
||||
pClass pc = t->getClassRef();
|
||||
pClass pc = t->getClassRef(false);
|
||||
if (pc == 0)
|
||||
return 0;
|
||||
|
||||
@ -806,7 +806,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
continue;
|
||||
if (clubs.count(clsR[i]->getClubId()) == 0)
|
||||
continue;
|
||||
if (clsR[i]->getClassId() != t->getClassId())
|
||||
if (clsR[i]->getClassId(false) != t->getClassId(false))
|
||||
continue;
|
||||
if (clsR[i]->getName() == anon)
|
||||
continue;
|
||||
@ -839,7 +839,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
if (usedR.count(clsR[i]->getId()))
|
||||
continue;
|
||||
const wstring &club = clsR[i]->getClub();
|
||||
wstring id = clsR[i]->getName() + L", " + clsR[i]->getClass();
|
||||
wstring id = clsR[i]->getName() + L", " + clsR[i]->getClass(false);
|
||||
if (!club.empty())
|
||||
id += L" (" + club + L")";
|
||||
|
||||
@ -999,7 +999,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
pc->getNumStages() == shownRunners) {
|
||||
// Keep team setup, i.e. do nothing
|
||||
}
|
||||
else if (t && pc && (t->getClassId()==bi.data
|
||||
else if (t && pc && (t->getClassId(false)==bi.data
|
||||
|| t->getNumRunners()==pc->getNumStages()) )
|
||||
loadTeamMembers(gdi, 0,0,t);
|
||||
else
|
||||
@ -1134,7 +1134,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
|
||||
{
|
||||
if (ClassId==0)
|
||||
if (t) ClassId=t->getClassId();
|
||||
if (t) ClassId=t->getClassId(false);
|
||||
|
||||
classId=ClassId;
|
||||
gdi.restore("",false);
|
||||
@ -1696,7 +1696,7 @@ void TabTeam::doAddTeamMembers(gdioutput &gdi) {
|
||||
|
||||
for (size_t k = 0; k < t.size(); k++) {
|
||||
pTeam mt = t[k];
|
||||
pClass cls = mt->getClassRef();
|
||||
pClass cls = mt->getClassRef(false);
|
||||
if (cls == 0)
|
||||
continue;
|
||||
bool ch = false;
|
||||
@ -1845,7 +1845,7 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
|
||||
else if (oldR) {
|
||||
t->setRunner(leg, 0, false);
|
||||
t->synchronize(true);
|
||||
oldR->setClassId(r->getClassId(), true);
|
||||
oldR->setClassId(r->getClassId(false), true);
|
||||
oldR->evaluateCard(true, mp, 0, true);
|
||||
oldR->synchronize(true);
|
||||
}
|
||||
|
||||
BIN
code/bmp00001.bmp
Normal file
BIN
code/bmp00001.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 406 B |
@ -352,7 +352,7 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
|
||||
|
||||
if (pc) {
|
||||
pc->synchronize();
|
||||
if (pr->getClassId() == 0 || !pr->hasFlag(oAbstractRunner::FlagUpdateClass))
|
||||
if (pr->getClassId(false) == 0 || !pr->hasFlag(oAbstractRunner::FlagUpdateClass))
|
||||
pr->setClassId(pc->getId(), false);
|
||||
}
|
||||
}
|
||||
@ -397,8 +397,8 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
|
||||
course->synchronize();
|
||||
}
|
||||
if (course) {
|
||||
if (pr->getClassId() != 0)
|
||||
event.getClass(pr->getClassId())->setCourse(course);
|
||||
if (pr->getClassId(false) != 0)
|
||||
event.getClass(pr->getClassId(false))->setCourse(course);
|
||||
else
|
||||
pr->setCourseId(course->getId());
|
||||
}
|
||||
@ -1253,23 +1253,71 @@ void csvparser::parse(const wstring &file, list< vector<string> > &data) {
|
||||
fin.close();
|
||||
}*/
|
||||
|
||||
|
||||
void csvparser::parseUnicode(const wstring &file, list< vector<wstring> > &data) {
|
||||
fin.open(file, ifstream::in | ifstream::binary);
|
||||
fin.seekg(0, ios_base::end);
|
||||
size_t len = int(fin.tellg())-2;
|
||||
if (len == 0)
|
||||
return;
|
||||
fin.seekg(2); // BOM
|
||||
assert(len % 2 == 0);
|
||||
vector<wchar_t> bf(len / 2 + 1);
|
||||
fin.read((char *)&bf[0], len);
|
||||
vector<wstring> rows;
|
||||
int spp = 0;
|
||||
for (size_t k = 0; k < len / 2; k++) {
|
||||
if (bf[spp] == '\r')
|
||||
spp++;
|
||||
if (bf[k] == '\n') {
|
||||
bf[k] = 0;
|
||||
if (k > 0 && bf[k - 1] == '\r')
|
||||
bf[k - 1] = 0;
|
||||
wstring r = &bf[spp];
|
||||
spp = k + 1;
|
||||
rows.push_back(r);
|
||||
}
|
||||
}
|
||||
if (size_t(spp + 1) < len / 2) {
|
||||
wstring r = &bf[spp];
|
||||
rows.push_back(r);
|
||||
}
|
||||
vector<wchar_t *> sp;
|
||||
|
||||
for (size_t k = 0; k < rows.size(); k++) {
|
||||
split(const_cast<wchar_t*>(rows[k].c_str()), sp);
|
||||
|
||||
if (!sp.empty()) {
|
||||
data.push_back(vector<wstring>());
|
||||
data.back().resize(sp.size());
|
||||
for (size_t k = 0; k < sp.size(); k++) {
|
||||
data.back()[k] = sp[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void csvparser::parse(const wstring &file, list< vector<wstring> > &data) {
|
||||
data.clear();
|
||||
|
||||
fin.open(file);
|
||||
// const size_t bf_size = 8192;
|
||||
|
||||
fin.seekg(0, ios_base::end);
|
||||
auto len = fin.tellg();
|
||||
fin.seekg(0);
|
||||
|
||||
string rbf;
|
||||
|
||||
if (!fin.good())
|
||||
throw meosException("Failed to read file");
|
||||
|
||||
bool isUTF8 = false;
|
||||
bool isUnicode = false;
|
||||
bool firstLine = true;
|
||||
vector<wchar_t *> sp;
|
||||
wchar_t wbf[buff_pre_alloc];
|
||||
vector<wchar_t> wbf_a;
|
||||
wbf_a.resize(size_t(len));
|
||||
wchar_t *wbf = &wbf_a[0];
|
||||
wstring w;
|
||||
|
||||
while(std::getline(fin, rbf)) {
|
||||
const char *bf = rbf.c_str();
|
||||
if (firstLine) {
|
||||
@ -1278,27 +1326,23 @@ void csvparser::parse(const wstring &file, list< vector<wstring> > &data) {
|
||||
bf += 3;
|
||||
}
|
||||
else if (bf[0] == -1 && bf[1] == -2) {
|
||||
isUnicode = true;
|
||||
bf += 2;
|
||||
fin.close();
|
||||
vector<wchar_t>().swap(wbf_a);
|
||||
parseUnicode(file, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isUnicode) {
|
||||
int len = 0;
|
||||
if (bf[len] == 0 && bf[len+1] != 0)
|
||||
len++;
|
||||
split((wchar_t*)&bf[len], sp);
|
||||
}
|
||||
else if (isUTF8) {
|
||||
|
||||
if (isUTF8) {
|
||||
int len = strlen(bf);
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, bf, len, wbf, buff_pre_alloc);
|
||||
wbf[wlen] = 0;
|
||||
split(wbf, sp);
|
||||
split(&wbf[0], sp);
|
||||
}
|
||||
else {
|
||||
w = gdi_main->recodeToWide(bf);
|
||||
wchar_t *wbf = const_cast<wchar_t *>(w.c_str());
|
||||
split(wbf, sp);
|
||||
wchar_t *wbfL = const_cast<wchar_t *>(w.c_str());
|
||||
split(wbfL, sp);
|
||||
}
|
||||
firstLine = false;
|
||||
|
||||
|
||||
@ -99,6 +99,8 @@ protected:
|
||||
map<SIConfigFields, int> siconfigmap;
|
||||
const wchar_t *getSIC(SIConfigFields sic, const vector<wstring> &sp) const;
|
||||
|
||||
void parseUnicode(const wstring &file, list< vector<wstring> > &data);
|
||||
|
||||
// Check and process a punch line
|
||||
static int selectPunchIndex(const wstring &competitionDate, const vector<wstring> &sp,
|
||||
int &cardIndex, int &timeIndex, int &dateIndex,
|
||||
|
||||
@ -2284,3 +2284,17 @@ RunnerEntryTime = Competitor's entry time
|
||||
RunnerPaid = Paid amount
|
||||
RunnerPayMethod = Payment method
|
||||
EntryTime = Entry Time
|
||||
Ekonomihantering, X = Economy status, X
|
||||
Manuellt gjorda justeringar = Manually made adjustments
|
||||
Antal förfrågningar: X = Number of requests: X
|
||||
Genomsnittlig svarstid: X ms = Average response time: X ms
|
||||
Informationsserver = Information server
|
||||
Längsta svarstid: X ms = Longest response time: X ms
|
||||
MeOS Informationsserver REST-API = MeOS Information Server REST-API
|
||||
Testa servern = Test the server
|
||||
help:rest = MeOS REST API lets you access competition data via a webb connection. You can show result lists directly in a webb browser, but you can also request competition data and results in a XML format, suitble for further processing in third party programs and apps.
|
||||
Server startad på X = Server running on port X
|
||||
Inconsistent qualification rule, X = Inconsistent qualification rule, X
|
||||
help:LockStartList = MeOS will not update assignement to a locked class even if qualification results are altered.
|
||||
Kval-Final-Schema = Load qualification scheme
|
||||
Lås startlista = Lock start list
|
||||
|
||||
@ -4215,7 +4215,7 @@ void gdioutput::calcStringSize(TextInfo &ti, HDC hDC_in) const
|
||||
HDC hDC=hDC_in;
|
||||
|
||||
if (!hDC) {
|
||||
assert(hWndTarget!=0);
|
||||
// assert(hWndTarget!=0);
|
||||
hDC=GetDC(hWndTarget);
|
||||
}
|
||||
RECT rc;
|
||||
|
||||
@ -78,6 +78,7 @@ GeneralResult::GeneralResult(void) {
|
||||
GeneralResult::~GeneralResult(void) {
|
||||
}
|
||||
|
||||
// Needed to generate template instances
|
||||
void GRINSTANCE() {
|
||||
vector<oRunner *> a;
|
||||
vector<oTeam *> b;
|
||||
@ -86,6 +87,7 @@ void GRINSTANCE() {
|
||||
gr.sort(b, SortByFinishTime);
|
||||
}
|
||||
|
||||
|
||||
void GeneralResult::setContext(const oListParam *contextIn) {
|
||||
context = contextIn;
|
||||
}
|
||||
@ -230,8 +232,10 @@ template<class T> void GeneralResult::sort(vector<T *> &rt, SortOrder so) const
|
||||
const int maxT = 3600 * 100;
|
||||
for(size_t k = 0; k < rt.size(); k++) {
|
||||
arr[k].first = 0;
|
||||
if (ps == ClassWise)
|
||||
arr[k].first = rt[k]->getClassRef() ? rt[k]->getClassRef()->getSortIndex() : 0;
|
||||
if (ps == ClassWise) {
|
||||
pClass sclass = rt[k]->getClassRef(true);
|
||||
arr[k].first = sclass ? sclass->getSortIndex() : 0;
|
||||
}
|
||||
else if (ps == CourseWise) {
|
||||
oRunner *r = dynamic_cast<oRunner *>(rt[k]);
|
||||
arr[k].first = r && r->getCourse(false) ? r->getCourse(false)->getId() : 0;
|
||||
@ -266,7 +270,10 @@ template<class T> void GeneralResult::sort(vector<T *> &rt, SortOrder so) const
|
||||
}
|
||||
}
|
||||
|
||||
void GeneralResult::calculateIndividualResults(vector<oRunner *> &runners, oListInfo::ResultType resType, bool sortRunners, int inputNumber) const {
|
||||
void GeneralResult::calculateIndividualResults(vector<oRunner *> &runners,
|
||||
oListInfo::ResultType resType,
|
||||
bool sortRunners,
|
||||
int inputNumber) const {
|
||||
|
||||
if (runners.empty())
|
||||
return;
|
||||
@ -286,7 +293,7 @@ void GeneralResult::calculateIndividualResults(vector<oRunner *> &runners, oList
|
||||
int ln = r->getLegNumber();
|
||||
const oTeam *pt = r->getTeam();
|
||||
if (pt) {
|
||||
const oClass *tcls = pt->getClassRef();
|
||||
const oClass *tcls = pt->getClassRef(false);
|
||||
if (tcls && tcls->getClassType() == oClassRelay) {
|
||||
int dummy;
|
||||
tcls->splitLegNumberParallel(r->getLegNumber(), ln, dummy);
|
||||
@ -294,6 +301,10 @@ void GeneralResult::calculateIndividualResults(vector<oRunner *> &runners, oList
|
||||
}
|
||||
runnerScore[k].principalSort = runnerScore[k].principalSort * 50 + ln;
|
||||
}
|
||||
else if (resType == oListInfo::Coursewise) {
|
||||
pCourse crs = r->getCourse(false);
|
||||
runnerScore[k].principalSort = crs ? crs->getId() : 0;
|
||||
}
|
||||
else
|
||||
runnerScore[k].principalSort = 0;
|
||||
|
||||
@ -474,10 +485,10 @@ RunnerStatus TotalResultAtControl::deduceStatus(oRunner &runner) const {
|
||||
if (runner.getTeam() && getListParamTimeFromControl() <= 0) {
|
||||
// Only use input time when start time is used
|
||||
const pTeam t = runner.getTeam();
|
||||
if (runner.getLegNumber()>0 && t->getClassRef()) {
|
||||
if (runner.getLegNumber()>0 && t->getClassRef(false)) {
|
||||
// Find base leg
|
||||
int legIx = runner.getLegNumber();
|
||||
const pClass cls = t->getClassRef();
|
||||
const pClass cls = t->getClassRef(false);
|
||||
while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx)))
|
||||
legIx--;
|
||||
if (legIx > 0)
|
||||
@ -504,10 +515,10 @@ int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const {
|
||||
if (runner.getTeam() && getListParamTimeFromControl() <= 0) {
|
||||
// Only use input time when start time is used
|
||||
const pTeam t = runner.getTeam();
|
||||
if (runner.getLegNumber()>0 && t->getClassRef()) {
|
||||
if (runner.getLegNumber()>0 && t->getClassRef(false)) {
|
||||
// Find base leg
|
||||
int legIx = runner.getLegNumber();
|
||||
const pClass cls = t->getClassRef();
|
||||
const pClass cls = t->getClassRef(false);
|
||||
while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx)))
|
||||
legIx--;
|
||||
if (legIx > 0)
|
||||
@ -1125,11 +1136,10 @@ void DynamicResult::prepareCalculations(oTeam &team) const {
|
||||
parser.addSymbol("RunnerCourse", team.getResultCache(oTeam::RCCCourse));
|
||||
parser.addSymbol("RunnerSplitTimes", team.getResultCache(oTeam::RCCSplitTime));
|
||||
|
||||
pClass cls = team.getClassRef();
|
||||
pClass cls = team.getClassRef(true);
|
||||
if (cls) {
|
||||
int nl = max<int>(1, cls->getNumStages()-1);
|
||||
parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(nl, false));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,7 +1247,7 @@ void DynamicResult::prepareCalculations(oRunner &runner) const {
|
||||
parser.addSymbol("SplitTimesAccumulated", e);
|
||||
}
|
||||
|
||||
pClass cls = runner.getClassRef();
|
||||
pClass cls = runner.getClassRef(true);
|
||||
if (cls) {
|
||||
int nl = runner.getLegNumber();
|
||||
parser.addSymbol("ShortestClassTime", cls->getBestLegTime(nl));
|
||||
@ -1303,3 +1313,294 @@ void DynamicResult::debugDumpVariables(gdioutput &gdi, bool includeSymbols) cons
|
||||
gdi.dropLine();
|
||||
}
|
||||
}
|
||||
|
||||
void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
|
||||
const pair<int, int> & controlId,
|
||||
bool totalResults,
|
||||
const string &resTag,
|
||||
oListInfo::ResultType resType,
|
||||
int inputNumber,
|
||||
oEvent &oe,
|
||||
vector<GeneralResultInfo> &results) {
|
||||
|
||||
results.reserve(runners.size());
|
||||
|
||||
if (resTag.empty() && resType == ClassWise) {
|
||||
GeneralResultInfo ri;
|
||||
if (controlId.second == oPunch::PunchFinish &&
|
||||
controlId.first == oPunch::PunchStart) {
|
||||
|
||||
if (!totalResults) {
|
||||
oe.calculateResults(oEvent::RTClassResult, true);
|
||||
for (pRunner r : runners) {
|
||||
ri.status = r->getStatus();
|
||||
if (ri.status == StatusUnknown) {
|
||||
if (r->getFinishTime() == 0)
|
||||
continue;
|
||||
ri.status = StatusOK; // Preliminary status
|
||||
}
|
||||
if (ri.status == StatusOK)
|
||||
ri.place = r->getPlace();
|
||||
else
|
||||
ri.place = 0;
|
||||
|
||||
ri.score = r->getRogainingPoints(false);
|
||||
ri.time = r->getRunningTime();
|
||||
ri.src = r;
|
||||
results.push_back(ri);
|
||||
}
|
||||
}
|
||||
else {
|
||||
oe.calculateResults(oEvent::RTTotalResult, true);
|
||||
for (pRunner r : runners) {
|
||||
ri.status = r->getTotalStatus();
|
||||
if (ri.status == StatusUnknown && r->getInputStatus() == StatusOK) {
|
||||
if (r->getFinishTime() == 0)
|
||||
continue;
|
||||
ri.status = StatusOK; // Preliminary status
|
||||
}
|
||||
if (ri.status == StatusOK)
|
||||
ri.place = r->getTotalPlace();
|
||||
else
|
||||
ri.place = 0;
|
||||
|
||||
ri.score = r->getRogainingPoints(true);
|
||||
ri.time = r->getTotalRunningTime();
|
||||
ri.src = r;
|
||||
results.push_back(ri);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
oe.calculateSplitResults(controlId.first, controlId.second);
|
||||
|
||||
ri.score = 0; // Undefined
|
||||
for (pRunner r : runners) {
|
||||
ri.status = r->getTempStatus();
|
||||
if (ri.status == StatusUnknown) {
|
||||
continue;
|
||||
}
|
||||
if (ri.status == StatusMP && r->getStatus() != StatusMP)
|
||||
continue; // Control that is not needed requested
|
||||
|
||||
if (ri.status == StatusOK)
|
||||
ri.place = r->getPlace();
|
||||
else
|
||||
ri.place = 0;
|
||||
|
||||
ri.time = r->getTempTime();
|
||||
|
||||
if (ri.time <= 0 && ri.status == StatusOK)
|
||||
continue;
|
||||
ri.src = r;
|
||||
results.push_back(ri);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
wstring srcDMY;
|
||||
GeneralResult *gResult = 0;
|
||||
shared_ptr<GeneralResult> specialInstance;
|
||||
oListParam param;
|
||||
param.useControlIdResultTo = controlId.second;
|
||||
param.useControlIdResultFrom = controlId.first;
|
||||
|
||||
if (!resTag.empty())
|
||||
gResult = &oe.getGeneralResult(resTag, srcDMY);
|
||||
else {
|
||||
if (controlId.second == oPunch::PunchFinish &&
|
||||
controlId.first == oPunch::PunchStart && !totalResults)
|
||||
specialInstance = make_shared<GeneralResult>();
|
||||
else if (!totalResults)
|
||||
specialInstance = make_shared<ResultAtControl>();
|
||||
else
|
||||
specialInstance = make_shared<TotalResultAtControl>();
|
||||
|
||||
gResult = specialInstance.get();
|
||||
}
|
||||
gResult->setContext(¶m);
|
||||
gResult->calculateIndividualResults(runners, resType, true, inputNumber);
|
||||
gResult->clearContext();
|
||||
map<int, bool> mapHasCourse;
|
||||
GeneralResultInfo ri;
|
||||
for (pRunner r : runners) {
|
||||
const auto &tmp = r->getTempResult(0);
|
||||
ri.status = tmp.getStatus();
|
||||
if (ri.status == StatusUnknown) {
|
||||
if (r->getFinishTime() == 0)
|
||||
continue;
|
||||
ri.status = StatusOK; // Preliminary status
|
||||
}
|
||||
if (ri.status == StatusOK)
|
||||
ri.place = tmp.getPlace();
|
||||
else
|
||||
ri.place = 0;
|
||||
|
||||
if ((controlId.first != oPunch::PunchStart ||
|
||||
controlId.second != oPunch::PunchFinish) && ri.status == StatusMP && r->getStatus() != StatusMP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ri.score = tmp.getPoints();
|
||||
ri.time = tmp.getRunningTime();
|
||||
|
||||
|
||||
if (controlId.first != oPunch::PunchStart && ri.time <= 0 && ri.status == StatusOK)
|
||||
continue; // Wrong order, skip
|
||||
|
||||
ri.src = r;
|
||||
results.push_back(ri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<GeneralResult::BaseResultContext>
|
||||
GeneralResult::calculateTeamResults(vector<pTeam> &teams,
|
||||
int leg,
|
||||
const pair<int, int> &controlId,
|
||||
bool totalResults,
|
||||
const string &resTag,
|
||||
oListInfo::ResultType resType,
|
||||
int inputNumber,
|
||||
oEvent &oe,
|
||||
vector<GeneralResultInfo> &results) {
|
||||
shared_ptr<BaseResultContext> out = make_shared<BaseResultContext>();
|
||||
out->leg = leg;
|
||||
out->controlId = controlId;
|
||||
out->totalResults = totalResults;
|
||||
results.reserve(teams.size());
|
||||
|
||||
if (resTag.empty()) {
|
||||
out->useModule = false;
|
||||
if (controlId.second == oPunch::PunchFinish) {
|
||||
oe.calculateTeamResults(false);
|
||||
GeneralResultInfo ri;
|
||||
for (pTeam r : teams) {
|
||||
ri.status = r->getStatus();
|
||||
if (ri.status == StatusUnknown) {
|
||||
if (r->getFinishTime() == 0)
|
||||
continue;
|
||||
ri.status = StatusOK; // Preliminary status
|
||||
}
|
||||
if (ri.status == StatusOK)
|
||||
ri.place = r->getPlace();
|
||||
else
|
||||
ri.place = 0;
|
||||
|
||||
ri.score = r->getRogainingPoints(false);
|
||||
ri.status = r->getStatus();
|
||||
ri.time = r->getRunningTime();
|
||||
ri.src = r;
|
||||
results.push_back(ri);
|
||||
}
|
||||
}
|
||||
else {
|
||||
set<int> clsId;
|
||||
for (pTeam t : teams)
|
||||
clsId.insert(t->getClassId(false));
|
||||
|
||||
oe.calculateTeamResultAtControl(clsId, leg, controlId.second, totalResults);
|
||||
GeneralResultInfo ri;
|
||||
for (pTeam r : teams) {
|
||||
const auto &tmp = r->getTempResult(0);
|
||||
ri.status = tmp.getStatus();
|
||||
if (ri.status == StatusUnknown || ri.status == StatusMP)
|
||||
continue;
|
||||
ri.place = tmp.getPlace();
|
||||
ri.score = tmp.getPoints();
|
||||
ri.time = tmp.getRunningTime();
|
||||
ri.src = r;
|
||||
results.push_back(ri);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
out->useModule = true;
|
||||
wstring srcDMY;
|
||||
auto &gResult = oe.getGeneralResult(resTag, srcDMY);
|
||||
gResult.calculateTeamResults(teams, resType, true, inputNumber);
|
||||
GeneralResultInfo ri;
|
||||
for (pTeam r : teams) {
|
||||
const auto &tmp = r->getTempResult(0);
|
||||
ri.status = tmp.getStatus();
|
||||
if (ri.status == StatusUnknown) {
|
||||
if (r->getFinishTime() == 0)
|
||||
continue;
|
||||
ri.status = StatusOK; // Preliminary status
|
||||
}
|
||||
if (ri.status == StatusOK)
|
||||
ri.place = tmp.getPlace();
|
||||
else
|
||||
ri.place = 0;
|
||||
|
||||
ri.score = tmp.getPoints();
|
||||
ri.time = tmp.getRunningTime();
|
||||
ri.src = r;
|
||||
results.push_back(ri);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int GeneralResult::GeneralResultInfo::getNumSubresult(const BaseResultContext &context) const {
|
||||
int cid = src->getClassId(false);
|
||||
if (cid == 0)
|
||||
return 0;
|
||||
|
||||
if (context.resIntervalCache.count(cid)) {
|
||||
const auto &cached = context.resIntervalCache[cid];
|
||||
return cached.second - cached.first;
|
||||
}
|
||||
else {
|
||||
const pClass cls = src->getClassRef(false);
|
||||
int leg = context.leg == -1 ? cls->getNumStages() : context.leg;
|
||||
|
||||
int nb = cls->getNextBaseLeg(leg);
|
||||
if (nb == -1)
|
||||
nb = cls->getNumStages();
|
||||
|
||||
int pb = cls->getPreceedingLeg(leg)+1;
|
||||
|
||||
context.resIntervalCache[cid] = make_pair(pb, nb);
|
||||
return nb - pb;
|
||||
}
|
||||
}
|
||||
|
||||
bool GeneralResult::GeneralResultInfo::getSubResult(const BaseResultContext &context,
|
||||
int ix, GeneralResultInfo &out) const {
|
||||
|
||||
if (getNumSubresult(context) == 0)
|
||||
return false; // Ensure cache is setup
|
||||
int base = context.resIntervalCache[src->getClassId(false)].first;
|
||||
pRunner r = pTeam(src)->getRunner(base + ix);
|
||||
if (r == 0)
|
||||
return false;
|
||||
out.place = 0; // Not defined
|
||||
out.src = r;
|
||||
|
||||
if (context.useModule) {
|
||||
out.score = r->tmpResult.getPoints();
|
||||
out.status = r->tmpResult.getStatus();
|
||||
out.time = r->tmpResult.getRunningTime();
|
||||
}
|
||||
else {
|
||||
if (context.controlId.second == oPunch::PunchFinish) {
|
||||
out.score = r->getRogainingPoints(false);
|
||||
out.status = r->getStatus();
|
||||
out.time = r->getRunningTime();
|
||||
}
|
||||
else {
|
||||
out.score = 0; // Undefined
|
||||
r->getSplitTime(context.controlId.second, out.status, out.time);
|
||||
}
|
||||
}
|
||||
|
||||
if (out.status == StatusUnknown && out.time > 0)
|
||||
out.status = StatusOK;
|
||||
|
||||
if (out.status == StatusUnknown)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -42,8 +42,6 @@ protected:
|
||||
|
||||
enum PrincipalSort {None, ClassWise, CourseWise};
|
||||
|
||||
virtual PrincipalSort getPrincipalSort() const {return ClassWise;}
|
||||
|
||||
virtual int score(oTeam &team, RunnerStatus st, int time, int points) const;
|
||||
virtual RunnerStatus deduceStatus(oTeam &team) const;
|
||||
virtual int deduceTime(oTeam &team) const;
|
||||
@ -64,6 +62,82 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
struct BaseResultContext {
|
||||
private:
|
||||
int leg;
|
||||
bool useModule;
|
||||
pair<int,int> controlId; // Start - finish
|
||||
bool totalResults;
|
||||
mutable map<int, pair<int, int> > resIntervalCache;
|
||||
|
||||
friend class GeneralResult;
|
||||
};
|
||||
|
||||
struct GeneralResultInfo {
|
||||
oAbstractRunner *src;
|
||||
int time;
|
||||
RunnerStatus status;
|
||||
int score;
|
||||
int place;
|
||||
|
||||
int getNumSubresult(const BaseResultContext &context) const;
|
||||
bool getSubResult(const BaseResultContext &context, int ix, GeneralResultInfo &out) const;
|
||||
|
||||
inline bool compareResult(const GeneralResultInfo &o) const {
|
||||
if (status != o.status)
|
||||
return RunnerStatusOrderMap[status] < RunnerStatusOrderMap[o.status];
|
||||
|
||||
if (place != o.place)
|
||||
return place < o.place;
|
||||
|
||||
const wstring &name = src->getName();
|
||||
const wstring &oname = o.src->getName();
|
||||
|
||||
return CompareString(LOCALE_USER_DEFAULT, 0,
|
||||
name.c_str(), name.length(),
|
||||
oname.c_str(), oname.length()) == CSTR_LESS_THAN;
|
||||
}
|
||||
|
||||
bool operator<(const GeneralResultInfo &o) const {
|
||||
pClass cls = src->getClassRef(true);
|
||||
pClass ocls = o.src->getClassRef(true);
|
||||
|
||||
if (cls != ocls) {
|
||||
int so = cls ? cls->getSortIndex() : 0;
|
||||
int oso = ocls ? ocls->getSortIndex() : 0;
|
||||
if (so != oso)
|
||||
return so < oso;
|
||||
|
||||
// Use id as fallback
|
||||
so = cls ? cls->getId() : 0;
|
||||
oso = ocls ? ocls->getId() : 0;
|
||||
if (so != oso)
|
||||
return so < oso;
|
||||
}
|
||||
return compareResult(o);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void calculateIndividualResults(vector<pRunner> &runners,
|
||||
const pair<int, int> &controlId,
|
||||
bool totalResults,
|
||||
const string &resTag,
|
||||
oListInfo::ResultType resType,
|
||||
int inputNumber,
|
||||
oEvent &oe,
|
||||
vector<GeneralResultInfo> &results);
|
||||
|
||||
static shared_ptr<BaseResultContext> calculateTeamResults(vector<pTeam> &teams,
|
||||
int leg,
|
||||
const pair<int, int> &controlId,
|
||||
bool totalResults,
|
||||
const string &resTag,
|
||||
oListInfo::ResultType resType,
|
||||
int inputNumber,
|
||||
oEvent &oe,
|
||||
vector<GeneralResultInfo> &results);
|
||||
|
||||
void setContext(const oListParam *context);
|
||||
void clearContext();
|
||||
|
||||
|
||||
300
code/html1.htm
Normal file
300
code/html1.htm
Normal file
@ -0,0 +1,300 @@
|
||||
<h1>Documentation of MeOS REST API</h1>
|
||||
|
||||
<h2>Competition</h2>
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=competition">/meos?get=competition</a></pre>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>MOP Competition XML</p>
|
||||
|
||||
<b>Example:</b>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*competition date="2015-09-06" organizer="Orienteringsklubben Linné" homepage="http://www.oklinne.nu">Stafett-DM, Uppland*/competition>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<h2>Classes</h2>
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=class">/meos?get=class</a></pre>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>MOP Classes XML</p>
|
||||
|
||||
<b>Example:</b>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*cls id="1" ord="10" radio="90,130;90,130;90,130">D21*/cls>
|
||||
*cls id="100" ord="1000" radio="90,130">M7*/cls>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<b>Remarks:</b> The attribute <i>ord</i> should be used to sort classes. The attribute <i>radio</i>
|
||||
lists the MeOS default radio control for each class and leg.
|
||||
Each leg of the class is separated by ';' and each radio control within a leg with ','.
|
||||
Note that you may query for results at any control; the listed
|
||||
controls are only for convenience.
|
||||
|
||||
<h2>Controls</h2>
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=control">/meos?get=control</a></pre>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>MOP Controls XML</p>
|
||||
|
||||
<b>Example:</b>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*control id="31">[31]*/control>
|
||||
*control id="32">[32]*/control>
|
||||
*control id="50">Radio 1*/control>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<h2>Competitors</h2>
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=competitor">/meos?get=competitor</a></pre>
|
||||
<pre>/meos?get=competitor#class=*c1>,*c2>,...</pre>
|
||||
|
||||
<b>Arguments:</b>
|
||||
<ul><li><i>class</i> A list of one or more class id:s, separated by comma. The default is all classes.
|
||||
</li></ul>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>MOP Competitors XML</p>
|
||||
|
||||
<b>Example:</b>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*cmp id="3565">
|
||||
*base org="570" cls="5" stat="1" st="360000" rt="20580">Elsa Winter*/base>
|
||||
*input it="20340" tstat="1"/>
|
||||
*/cmp>
|
||||
*cmp id="55851">
|
||||
*base org="134" cls="7" stat="1" st="380710" rt="46910">Anna Spring*/base>
|
||||
*/cmp>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<b>Remarks:</b>
|
||||
Please refer to the MOP documentation for a complete description of all attributes. Below is a quick reference.
|
||||
<ul>
|
||||
<li><i>stat</i> Status code. 1 is OK, 0 is unknown. Higher codes are used for disqualifications.</li>
|
||||
<li><i>st</i> Start time. In 1/10 seconds after 00:00:00.</li>
|
||||
<li><i>rt</i> Running time. In 1/10 seconds.</li>
|
||||
<li><i>input/it</i> Input running time accumulated from earlier races. In 1/10 seconds.</li>
|
||||
<li><i>input/st</i> Input status from earlier races.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Teams</h2>
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=team">/meos?get=team</a></pre>
|
||||
<pre>/meos?get=team#class=*c1>,*c2>,...</pre>
|
||||
|
||||
<b>Arguments:</b>
|
||||
<ul><li><i>class</i> A list of one or more class id:s, separated by comma. The default is all classes.
|
||||
</li></ul>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>MOP Teams XML</p>
|
||||
|
||||
<b>Example:</b>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*tm id="2928771">
|
||||
*base org="396" cls="5" stat="1" st="360000" rt="65770">IF Thor 1*/base>
|
||||
*r>34346;48866,866,0;32609*/r>
|
||||
*/tm>
|
||||
*tm id="2928346">
|
||||
*base org="134" cls="5" stat="1" st="360000" rt="99660">OK Enen 1*/base>
|
||||
*r>42020;55851;35732*/r>
|
||||
*/tm>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<b>Remarks:</b>
|
||||
Please refer to the MOP documentation for a complete description of all attributes. Below is a quick reference.
|
||||
<ul>
|
||||
<li><i>stat</i> Status code. 1 is OK, 0 is unknown. Higher codes are used for disqualifications.</li>
|
||||
<li><i>st</i> Start time. In 1/10 seconds after 00:00:00.</li>
|
||||
<li><i>rt</i> Running time (At finish, last leg). In 1/10 seconds.</li>
|
||||
<li><i>r</i> List of runners in the team. A ';' is used to separate the legs, a ',' within a legs
|
||||
are used to list paralell runners. A '0' indicates a vacant leg, which may or may
|
||||
not be valid for the team, depending on the rules.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Organizations and Clubs</h2>
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=organization">/meos?get=organization</a></pre>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>MOP Organization XML</p>
|
||||
|
||||
<b>Example:</b>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*org id="1012">BAOC*/org>
|
||||
*org id="598">Dalaportens OL*/org>
|
||||
*org id="133">Enebybergs IF*/org>
|
||||
*org id="140">Falkenbergs OK*/org>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<h2>Results</h2>
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=result">/meos?get=result</a></pre>
|
||||
<pre>/meos?get=result#class=*c1>,*c2>,...</pre>
|
||||
<pre>/meos?get=result#to=*c1></pre>
|
||||
<pre>/meos?get=result#from=*c1></pre>
|
||||
<pre>/meos?get=result#leg=*leg></pre>
|
||||
<pre>/meos?get=result#module=*module></pre>
|
||||
<pre>/meos?get=result#module=*module>#argument=*arg></pre>
|
||||
<pre><a href="/meos?get=result&limit=1">/meos?get=result#limit=*limit></a></pre>
|
||||
<pre><a href="/meos?get=result&total=true">/meos?get=result#total=*true/false></a></pre>
|
||||
<pre><a href="/meos?get=result&type=GlobalIndividual">/meos?get=result#type=*type></a></pre>
|
||||
|
||||
<b>Arguments:</b>
|
||||
<ul>
|
||||
<li><i>class</i> A list of one or more class id:s, separated by comma. The default is all classes.</li>
|
||||
<li><i>from</i> Returns the result measuring time from a specific control. If a specified class
|
||||
does not visit the control, an empty result set is returned; no error is given.
|
||||
The default is the start.</li>
|
||||
<li><i>to</i> Returns the result at a specific control. If a specified class does not visit the control,
|
||||
an empty result set is returned; no error is given. The default is the finish.</li>
|
||||
|
||||
<li><i>leg</i> In a team competition, returns result for a specified leg. If the leg is parallel,
|
||||
the result is for the completed parallel leg. The leg number refer to the flat view in
|
||||
MeOS class settings, i.e., for a setup "1, 2a, 2b, 2c, 3", correspons to flat leg numbers,
|
||||
"1, 2, 3, 4, 5". The default is the last leg.</li>
|
||||
<li><i>module</i> The result module tag to use for the result calculation.
|
||||
The support of the leg and control options depends on result module. The default is no module.</li>
|
||||
<li><i>argument</i> A numeric argument, defined and used by the result module.</li>
|
||||
|
||||
<li><i>limit</i> Limit the number of results per class. If there is a tie, the number of returned results
|
||||
may be higher than the requested. The default is no limit.</li>
|
||||
<li><i>total</i> Set to <b>true</b> if you want to calculate total results, i.e., results including earliers stages.</li>
|
||||
|
||||
<li><i>type</i> Use one of <b>ClassIndividual</b> (default for individual classes), <b>CourseIndividual</b>, <b>GlobalIndividual</b>, or
|
||||
<b>LegIndividual</b> to calculate individual results. <b>CourseIndividual</b> calculates result
|
||||
per course, ignoring class. <b>GlobalIndividual</b> calculates results without
|
||||
considering classes, <b>LegIndividual</b> calculates results considering classes and legs.
|
||||
Use one of <b>ClassTeam</b> (default for team classes) or <b>GlobalTeam</b> to calculate team
|
||||
results. <b>GlobalTeam</b> calculates team results without considering classes.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>MOP Individual or Team Result XML. The result list is sorted according to the result. Note than disqualified
|
||||
competitors are also included; for example a competitor with status *DNS> will be returned with this status for
|
||||
all radio controls. You may want to filter out such entries, depending on your application.
|
||||
</p>
|
||||
|
||||
|
||||
<b>Examples:</b>
|
||||
|
||||
<p>Individual results at the finish.</p>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*results location="Finish">
|
||||
*person cls="100" stat="1" st="387240" rt="21880" place="1">
|
||||
*name id="134940">Isac Ulvesson*/name>
|
||||
*org id="2184">BOIC*/org>
|
||||
*/person>
|
||||
|
||||
*person cls="100" stat="1" st="387700" rt="22720" place="2">
|
||||
*name id="134923">Anne Brahe*/name>
|
||||
*org id="2253">IFA*/org>
|
||||
*/person>
|
||||
|
||||
*person cls="100" stat="1" st="382570" rt="23260" place="3">
|
||||
*name id="134914">Dan Andersson*/name>
|
||||
*org id="5938">OK Kompassen*/org>
|
||||
*/person>
|
||||
*/results>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<p>Team results, leg 2 at Radio 1, leg has three parallel runners.</p>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*results leg="2" location="Radio 1">
|
||||
*team cls="6" stat="1" st="372000" rt="32030" place="1">
|
||||
*name id="2927509">OK Linné 1*/name>
|
||||
*org id="84">OK Linné*/org>
|
||||
*person cls="6" leg="2" stat="1" st="392720" rt="11310">
|
||||
*name id="52054">John Woods*/name>
|
||||
*org id="84">OK Linné*/club>
|
||||
*/person>
|
||||
|
||||
*person cls="6" leg="3" stat="3" st="392720">
|
||||
*name id="134850">Ralph Audoro*/name>
|
||||
*org id="84">OK Linné*/org>
|
||||
*/person>
|
||||
|
||||
*person cls="6" leg="4" stat="1" st="392720" rt="12850">
|
||||
*name id="134851">Niel Success*/name>
|
||||
*club id="84">OK Linné*/club>
|
||||
*/person>
|
||||
*/team>
|
||||
*/results>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<p>Roganing results, Invoke with argument module=rogaining, which is a built in module.</p>
|
||||
<pre>
|
||||
*MOPComplete>
|
||||
*results module="rogaining" location="Finish">
|
||||
*person cls="1" stat="1" score="26" st="324000" rt="72550" place="1">
|
||||
*name id="4">Omar Rue*/name>
|
||||
*/person>
|
||||
|
||||
*person cls="1" stat="1" score="25" st="324000" rt="72730" place="2">
|
||||
*name id="3">Oscar Wilde*/name>
|
||||
*/person>
|
||||
|
||||
*person cls="1" stat="1" score="25" st="324000" rt="72780" place="3">
|
||||
*name id="5">Alice Alison*/name>
|
||||
*/person>
|
||||
|
||||
*person cls="1" stat="5" score="26" st="324000" rt="72590">
|
||||
*name id="6">Reimund Rossinger*/name>
|
||||
*/person>
|
||||
*/results>
|
||||
*/MOPComplete>
|
||||
</pre>
|
||||
|
||||
<b>Remarks:</b>
|
||||
When and only when the type is <b>CourseIndividual</b>, the attribute <i>course/i> is included.
|
||||
<pre>
|
||||
*person cls="1" stat="1" st="324000" rt="72550" place="1" course=28>
|
||||
*name id="4">Jordan Griesmer*/name>
|
||||
*/person>
|
||||
</pre>
|
||||
|
||||
<h2>IOF XML Results</h2>
|
||||
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=iofresult">/meos?get=iofresult</a></pre>
|
||||
<pre>/meos?get=iofresult#class=*c1>,*c2>,...</pre>
|
||||
|
||||
<b>Arguments:</b>
|
||||
<ul>
|
||||
<li><i>class</i> A list of one or more class id:s, separated by comma. The default is all classes.</li>
|
||||
</ul>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>IOF XML version 3.0 result list.</p>
|
||||
|
||||
<h2>IOF XML Startlist</h2>
|
||||
|
||||
<b>Syntax:</b>
|
||||
<pre><a href="/meos?get=iofstart">/meos?get=iofstart</a></pre>
|
||||
<pre>/meos?get=iofstart#class=*c1>,*c2>,...</pre>
|
||||
|
||||
<b>Arguments:</b>
|
||||
<ul>
|
||||
<li><i>class</i> A list of one or more class id:s, separated by comma. The default is all classes.</li>
|
||||
</ul>
|
||||
|
||||
<b>Returns:</b>
|
||||
<p>IOF XML version 3.0 start list.</p>
|
||||
@ -203,7 +203,7 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
|
||||
vector<pTeam> t;
|
||||
oe.getTeams(0, t, false);
|
||||
for (size_t k = 0; k < t.size(); k++) {
|
||||
if (!includeCls.count(t[k]->getClassId()))
|
||||
if (!includeCls.count(t[k]->getClassId(true)))
|
||||
continue;
|
||||
int wid = t[k]->getId();
|
||||
knownId.insert(wid);
|
||||
@ -228,7 +228,7 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
|
||||
vector<pRunner> r;
|
||||
oe.getRunners(0, 0, r, false);
|
||||
for (size_t k = 0; k < r.size(); k++) {
|
||||
if (!includeCls.count(r[k]->getClassId()))
|
||||
if (!includeCls.count(r[k]->getClassId(true)))
|
||||
continue;
|
||||
int wid = r[k]->getId();
|
||||
knownId.insert(wid);
|
||||
@ -397,7 +397,7 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
|
||||
ch = true;
|
||||
}
|
||||
|
||||
int cls = bc.getClassId();
|
||||
int cls = bc.getClassId(true);
|
||||
if (cls != classId) {
|
||||
classId = cls;
|
||||
ch = true;
|
||||
@ -463,8 +463,8 @@ bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
|
||||
bool ch = synchronize(useTotalResults, r);
|
||||
|
||||
vector<RadioTime> newRT;
|
||||
if (r.getClassId() > 0) {
|
||||
const vector<int> &radios = cmp.getControls(r.getClassId(), r.getLegNumber());
|
||||
if (r.getClassId(false) > 0) {
|
||||
const vector<int> &radios = cmp.getControls(r.getClassId(false), r.getLegNumber());
|
||||
for (size_t k = 0; k < radios.size(); k++) {
|
||||
RadioTime radioTime;
|
||||
RunnerStatus s_split;
|
||||
@ -520,7 +520,7 @@ void InfoCompetitor::serialize(xmlbuffer &xml, bool diffOnly) const {
|
||||
bool InfoTeam::synchronize(oTeam &t) {
|
||||
bool ch = synchronizeBase(t);
|
||||
|
||||
const pClass cls = t.getClassRef();
|
||||
const pClass cls = t.getClassRef(true);
|
||||
if (cls) {
|
||||
vector< vector<int> > r;
|
||||
|
||||
|
||||
@ -127,12 +127,13 @@ class InfoClass : public InfoBase {
|
||||
class InfoOrganization : public InfoBase {
|
||||
protected:
|
||||
wstring name;
|
||||
bool synchronize(oClub &c);
|
||||
void serialize(xmlbuffer &xml, bool diffOnly) const;
|
||||
public:
|
||||
InfoOrganization(int id);
|
||||
virtual ~InfoOrganization() {}
|
||||
|
||||
bool synchronize(oClub &c);
|
||||
void serialize(xmlbuffer &xml, bool diffOnly) const;
|
||||
|
||||
friend class InfoCompetition;
|
||||
};
|
||||
|
||||
@ -183,9 +184,10 @@ class InfoTeam : public InfoBaseCompetitor {
|
||||
protected:
|
||||
// The outer level holds legs, the inner level holds (parallel/patrol) runners on each leg.
|
||||
vector< vector<int> > competitors;
|
||||
public:
|
||||
bool synchronize(oTeam &t);
|
||||
void serialize(xmlbuffer &xml, bool diffOnly) const;
|
||||
public:
|
||||
|
||||
InfoTeam(int id);
|
||||
virtual ~InfoTeam() {}
|
||||
friend class InfoCompetition;
|
||||
|
||||
@ -335,7 +335,7 @@ void IOF30Interface::personCourseAssignment(gdioutput &gdi, xmlList &xAssignment
|
||||
xPAssignment.getObjectString("ClassName", cls);
|
||||
multimap<wstring, pRunner>::const_iterator res = name2Runner.find(person);
|
||||
while (res != name2Runner.end() && person == res->first) {
|
||||
if (cls.empty() || res->second->getClass() == cls) {
|
||||
if (cls.empty() || res->second->getClass(false) == cls) {
|
||||
r = res->second;
|
||||
break;
|
||||
}
|
||||
@ -386,7 +386,7 @@ void IOF30Interface::teamCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
||||
if (!bib.empty())
|
||||
bib2Team[bib] = allT[k];
|
||||
|
||||
nameClass2Team[make_pair(allT[k]->getName(), allT[k]->getClass())] = allT[k];
|
||||
nameClass2Team[make_pair(allT[k]->getName(), allT[k]->getClass(false))] = allT[k];
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < xAssignment.size(); k++) {
|
||||
@ -426,7 +426,7 @@ void IOF30Interface::teamCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
||||
void IOF30Interface::assignTeamCourse(gdioutput &gdi, oTeam &team, xmlList &xAssignment,
|
||||
const map<wstring, pCourse> &courses) {
|
||||
|
||||
if (!team.getClassRef())
|
||||
if (!team.getClassRef(false))
|
||||
return;
|
||||
for (size_t k = 0; k <xAssignment.size(); k++) {
|
||||
|
||||
@ -443,11 +443,11 @@ void IOF30Interface::assignTeamCourse(gdioutput &gdi, oTeam &team, xmlList &xAss
|
||||
if (xLegOrder)
|
||||
legorder = xLegOrder.getInt() - 1;
|
||||
|
||||
int legId = team.getClassRef()->getLegNumberLinear(leg, legorder);
|
||||
int legId = team.getClassRef(false)->getLegNumberLinear(leg, legorder);
|
||||
if (legId>=0) {
|
||||
pRunner r = team.getRunner(legId);
|
||||
if (r == 0) {
|
||||
r = oe.addRunner(lang.tl(L"N.N."), team.getClubId(), team.getClassId(), 0, 0, false);
|
||||
r = oe.addRunner(lang.tl(L"N.N."), team.getClubId(), team.getClassId(false), 0, 0, false);
|
||||
if (r) {
|
||||
r->setEntrySource(entrySourceId);
|
||||
r->flagEntryTouched(true);
|
||||
@ -460,7 +460,7 @@ void IOF30Interface::assignTeamCourse(gdioutput &gdi, oTeam &team, xmlList &xAss
|
||||
}
|
||||
}
|
||||
else
|
||||
gdi.addString("", 0, L"Bantilldelning för 'X' hänvisar till en sträcka som inte finns#" + team.getClass()).setColor(colorRed);
|
||||
gdi.addString("", 0, L"Bantilldelning för 'X' hänvisar till en sträcka som inte finns#" + team.getClass(false)).setColor(colorRed);
|
||||
}
|
||||
else {
|
||||
wstring name;
|
||||
@ -543,8 +543,8 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
|
||||
for (bibIterT it = range.first; it != range.second; ++it) {
|
||||
int ln = it->second->getLegNumber();
|
||||
int rLegNumber = 0, rLegOrder = 0;
|
||||
if (it->second->getClassRef())
|
||||
it->second->getClassRef()->splitLegNumberParallel(ln, rLegNumber, rLegOrder);
|
||||
if (it->second->getClassRef(false))
|
||||
it->second->getClassRef(false)->splitLegNumberParallel(ln, rLegNumber, rLegOrder);
|
||||
bool match = true;
|
||||
if (leg != 0 && leg != rLegNumber+1)
|
||||
match = false;
|
||||
@ -569,14 +569,14 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
|
||||
vector<pTeam> t;
|
||||
oe.getTeams(0, t);
|
||||
for (size_t i = 0; i < t.size(); i++)
|
||||
clsName2Team[make_pair(t[i]->getClass(), t[i]->getName())] = t[i];
|
||||
clsName2Team[make_pair(t[i]->getClass(false), t[i]->getName())] = t[i];
|
||||
c2TeamInit = true;
|
||||
}
|
||||
|
||||
teamIterT res = clsName2Team.find(make_pair(className, teamName));
|
||||
|
||||
if (res != clsName2Team.end()) {
|
||||
pClass cls = res->second->getClassRef();
|
||||
pClass cls = res->second->getClassRef(false);
|
||||
if (cls) {
|
||||
int ln = cls->getLegNumberLinear(leg, legOrder);
|
||||
pRunner r = res->second->getRunner(ln);
|
||||
@ -863,7 +863,7 @@ void IOF30Interface::readEntryList(gdioutput &gdi, xmlobject &xo, bool removeNon
|
||||
key[j] = it->second[j].second;
|
||||
|
||||
sort(key.begin(), key.end());
|
||||
classLegEqClasses[t->getClassId()].insert(key);
|
||||
classLegEqClasses[t->getClassId(false)].insert(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1326,7 +1326,7 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
|
||||
map<int, vector<LegInfo> > localTeamClassConfig;
|
||||
pClass pc = readClass(xTeam.getObject("Class"), localTeamClassConfig);
|
||||
|
||||
if (pc && (t->getClassId() == 0 || !t->hasFlag(oAbstractRunner::FlagUpdateClass)) ) {
|
||||
if (pc && (t->getClassId(false) == 0 || !t->hasFlag(oAbstractRunner::FlagUpdateClass)) ) {
|
||||
t->setClassId(pc->getId(), false);
|
||||
}
|
||||
wstring bib;
|
||||
@ -1392,7 +1392,7 @@ pTeam IOF30Interface::readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
|
||||
return 0;
|
||||
|
||||
// Class
|
||||
if (pc && (t->getClassId() == 0 || !t->hasFlag(oAbstractRunner::FlagUpdateClass)) )
|
||||
if (pc && (t->getClassId(false) == 0 || !t->hasFlag(oAbstractRunner::FlagUpdateClass)) )
|
||||
t->setClassId(pc->getId(), false);
|
||||
|
||||
wstring bib;
|
||||
@ -1534,7 +1534,7 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
|
||||
|
||||
if (cardNo > 0 && r == 0 && team) {
|
||||
// We got no person, but a card number. Add the runner anonymously.
|
||||
r = oe.addRunner(lang.tl(L"N.N."), team->getClubId(), team->getClassId(), cardNo, 0, false);
|
||||
r = oe.addRunner(lang.tl(L"N.N."), team->getClubId(), team->getClassId(false), cardNo, 0, false);
|
||||
r->flagEntryTouched(true);
|
||||
r->setEntrySource(entrySourceId);
|
||||
r->synchronize();
|
||||
@ -1555,21 +1555,21 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
|
||||
map<int, vector<LegInfo> > localTeamClassConfig;
|
||||
pClass pc = readClass(xo.getObject("Class"), localTeamClassConfig);
|
||||
|
||||
if (pc && (r->getClassId() == 0 || !r->hasFlag(oAbstractRunner::FlagUpdateClass)) )
|
||||
if (pc && (r->getClassId(false) == 0 || !r->hasFlag(oAbstractRunner::FlagUpdateClass)) )
|
||||
r->setClassId(pc->getId(), false);
|
||||
|
||||
if (team) {
|
||||
int leg = xo.getObjectInt("Leg");
|
||||
int legorder = xo.getObjectInt("LegOrder");
|
||||
int legindex = max(0, leg - 1);
|
||||
map<int, vector<LegInfo> >::const_iterator res = teamClassConfig.find(team->getClassId());
|
||||
map<int, vector<LegInfo> >::const_iterator res = teamClassConfig.find(team->getClassId(false));
|
||||
if (res != teamClassConfig.end()) {
|
||||
legindex = getIndexFromLegPos(leg, legorder, res->second);
|
||||
}
|
||||
|
||||
if (personId2TeamLeg.find(r->getId()) == personId2TeamLeg.end()) {
|
||||
if (team->getClassRef())
|
||||
legindex = team->getClassRef()->getLegRunner(legindex);
|
||||
if (team->getClassRef(false))
|
||||
legindex = team->getClassRef(false)->getLegRunner(legindex);
|
||||
|
||||
// Ensure unique
|
||||
team->setRunner(legindex, r, false);
|
||||
@ -1676,7 +1676,7 @@ pRunner IOF30Interface::readPersonStart(gdioutput &gdi, pClass pc, xmlobject &xo
|
||||
int leg = starts[k].getObjectInt("Leg");
|
||||
int legorder = starts[k].getObjectInt("LegOrder");
|
||||
int legindex = max(0, leg - 1);
|
||||
map<int, vector<LegInfo> >::const_iterator res = teamClassConfig.find(team->getClassId());
|
||||
map<int, vector<LegInfo> >::const_iterator res = teamClassConfig.find(team->getClassId(false));
|
||||
if (res != teamClassConfig.end()) {
|
||||
legindex = getIndexFromLegPos(leg, legorder, res->second);
|
||||
}
|
||||
@ -1698,7 +1698,7 @@ pRunner IOF30Interface::readPersonStart(gdioutput &gdi, pClass pc, xmlobject &xo
|
||||
}
|
||||
}
|
||||
|
||||
if (pc && (r->getClassId() == 0 || !r->hasFlag(oAbstractRunner::FlagUpdateClass)) )
|
||||
if (pc && (r->getClassId(false) == 0 || !r->hasFlag(oAbstractRunner::FlagUpdateClass)) )
|
||||
r->setClassId(pc->getId(), true);
|
||||
|
||||
r->synchronize();
|
||||
@ -1961,7 +1961,7 @@ void IOF30Interface::writeAssignedFee(xmlparser &xml, const oAbstractRunner &tr,
|
||||
if (paid >= paidForCard) {
|
||||
paid -= paidForCard; // Included in card service fee
|
||||
}
|
||||
const pClass pc = tr.getClassRef();
|
||||
const oClass *pc = tr.getClassRef(false);
|
||||
if (!splitLateFee || !pc || !tr.hasLateEntryFee()) {
|
||||
xml.startTag("AssignedFee");
|
||||
string type = tr.hasLateEntryFee() ? "Late" : "Normal";
|
||||
@ -2476,7 +2476,6 @@ void IOF30Interface::writeClass(xmlparser &xml, const oClass &c) {
|
||||
else if (stat == oClass::InvalidRefund)
|
||||
xml.write("Status", L"InvalidatedNoFee");
|
||||
|
||||
|
||||
xml.endTag();
|
||||
}
|
||||
|
||||
@ -2537,7 +2536,7 @@ void IOF30Interface::writePersonResult(xmlparser &xml, const oRunner &r,
|
||||
if (teamMember) {
|
||||
oRunner const *resultHolder = &r;
|
||||
cTeam t = r.getTeam();
|
||||
pClass cls = r.getClassRef();
|
||||
const oClass *cls = r.getClassRef(false);
|
||||
|
||||
if (t && cls) {
|
||||
int leg = r.getLegNumber();
|
||||
@ -2614,9 +2613,9 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
||||
xml.write("TimeBehind", after);
|
||||
}
|
||||
|
||||
if (r.getClassRef()) {
|
||||
if (r.getClassRef(false)) {
|
||||
|
||||
if (r.statusOK() && r.getClassRef()->getNoTiming() == false) {
|
||||
if (r.statusOK() && r.getClassRef(false)->getNoTiming() == false) {
|
||||
if (!teamMember && r.getPlace() > 0 && r.getPlace() < 50000) {
|
||||
xml.write("Position", r.getPlace());
|
||||
}
|
||||
@ -2634,19 +2633,19 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
||||
|
||||
xml.write("Status", formatStatus(r.getStatus()));
|
||||
|
||||
if ( (r.getTeam() && r.getClassRef()->getClassType() != oClassPatrol && !teamsAsIndividual) || hasInputTime) {
|
||||
if ( (r.getTeam() && r.getClassRef(false)->getClassType() != oClassPatrol && !teamsAsIndividual) || hasInputTime) {
|
||||
xml.startTag("OverallResult");
|
||||
int rt = r.getTotalRunningTime();
|
||||
if (rt > 0)
|
||||
xml.write("Time", rt);
|
||||
|
||||
bool hasTiming = r.getClassRef()->getNoTiming() == false;
|
||||
bool hasTiming = r.getClassRef(false)->getNoTiming() == false;
|
||||
RunnerStatus stat = r.getTotalStatus();
|
||||
|
||||
int tleg = r.getLegNumber() >= 0 ? r.getLegNumber() : 0;
|
||||
|
||||
if (stat == StatusOK && hasTiming) {
|
||||
int after = r.getTotalRunningTime() - r.getClassRef()->getTotalLegLeaderTime(tleg, true);
|
||||
int after = r.getTotalRunningTime() - r.getClassRef(true)->getTotalLegLeaderTime(tleg, true);
|
||||
if (after >= 0)
|
||||
xml.write("TimeBehind", after);
|
||||
}
|
||||
@ -3100,7 +3099,7 @@ void IOF30Interface::writeStart(xmlparser &xml, const oRunner &r,
|
||||
void IOF30Interface::writeLegOrder(xmlparser &xml, const oRunner &r) const {
|
||||
// Team member race result
|
||||
int legNumber, legOrder;
|
||||
const pClass pc = r.getClassRef();
|
||||
const oClass *pc = r.getClassRef(false);
|
||||
if (pc) {
|
||||
bool par = pc->splitLegNumberParallel(r.getLegNumber(), legNumber, legOrder);
|
||||
xml.write("Leg", legNumber + 1);
|
||||
|
||||
@ -112,7 +112,7 @@ void LiveResult::showTimer(gdioutput &gdi, const oListInfo &liIn) {
|
||||
pair<int, int> key = make_pair(r->getId(), pp[k]->getControlId());
|
||||
processedPunches[key] = max(processedPunches[key], pp[k]->getAdjustedTime());
|
||||
|
||||
if (!li.getParam().selection.empty() && !li.getParam().selection.count(r->getClassId()))
|
||||
if (!li.getParam().selection.empty() && !li.getParam().selection.count(r->getClassId(true)))
|
||||
continue; // Filter class
|
||||
|
||||
if (pp[k]->getTypeCode() == fromPunch) {
|
||||
@ -182,7 +182,7 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
|
||||
if (!r)
|
||||
continue;
|
||||
|
||||
if (!li.getParam().selection.empty() && !li.getParam().selection.count(r->getClassId()))
|
||||
if (!li.getParam().selection.empty() && !li.getParam().selection.count(r->getClassId(true)))
|
||||
continue; // Filter class
|
||||
|
||||
pair<int, int> key = make_pair(r->getId(), pp[k]->getControlId());
|
||||
|
||||
@ -1149,6 +1149,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
delete gSI;
|
||||
gSI=0;
|
||||
|
||||
for (size_t k = 0; k < gdi_extra.size(); k++) {
|
||||
if (gdi_extra[k])
|
||||
gdi_extra[k]->clearPage(false, false);
|
||||
}
|
||||
|
||||
if (gEvent) {
|
||||
try {
|
||||
gEvent->save();
|
||||
|
||||
28
code/meos.rc
28
code/meos.rc
@ -28,10 +28,29 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
//
|
||||
|
||||
BMP_TEST BITMAP "bitmap1.bmp"
|
||||
|
||||
#endif // Neutral resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Neutral (Default) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD)
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Bitmap
|
||||
//
|
||||
|
||||
IDB_ECO BITMAP "bmp00001.bmp"
|
||||
|
||||
#endif // Neutral (Default) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
@ -48,6 +67,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
// remains consistent on all systems.
|
||||
IDI_MEOS ICON "meos.ICO"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
@ -160,6 +180,14 @@ BEGIN
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HTML
|
||||
//
|
||||
|
||||
IDR_HTML1 HTML "html1.htm"
|
||||
|
||||
#endif // Swedish (Sweden) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@ -1368,7 +1368,7 @@ static void decomposeClassName(const wstring &name, vector<wstring> &dec) {
|
||||
|
||||
for (size_t i = 0; i < name.size(); i++) {
|
||||
int bchar = toLowerStripped(name[i]);
|
||||
if (isspace(bchar) || bchar == '-' || bchar == 160) {
|
||||
if (myIsSpace(bchar) || bchar == '-' || bchar == 160) {
|
||||
if (!dec.back().empty())
|
||||
dec.push_back(wstring());
|
||||
continue;
|
||||
@ -1823,7 +1823,7 @@ void capitalize(wstring &str) {
|
||||
int getTimeZoneInfo(const wstring &date) {
|
||||
static wchar_t lastDate[16] = {0};
|
||||
static int lastValue = -1;
|
||||
// Local cacheing
|
||||
// Local caching
|
||||
if (lastValue != -1 && lastDate == date) {
|
||||
return lastValue;
|
||||
}
|
||||
@ -2161,8 +2161,14 @@ void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &
|
||||
}
|
||||
|
||||
void string2Wide(const string &in, wstring &out) {
|
||||
out.clear();
|
||||
out.insert(out.begin(), in.begin(), in.end());// XXX Simple extend
|
||||
int cp = 1252;
|
||||
if (in.empty()) {
|
||||
out = L"";
|
||||
return;
|
||||
}
|
||||
out.reserve(in.size() + 1);
|
||||
out.resize(in.size(), 0);
|
||||
MultiByteToWideChar(cp, MB_PRECOMPOSED, in.c_str(), in.size(), &out[0], out.size() * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
void wide2String(const wstring &in, string &out) {
|
||||
|
||||
@ -1906,7 +1906,7 @@ OpFailStatus MeosSQL::syncUpdate(oRunner *r, bool forceWriteAll)
|
||||
<< " StartTime=" << r->startTime << ", "
|
||||
<< " FinishTime=" << r->FinishTime << ", "
|
||||
<< " Course=" << r->getCourseId() << ", "
|
||||
<< " Class=" << r->getClassId() << ", "
|
||||
<< " Class=" << r->getClassId(false) << ", "
|
||||
<< " Club=" << r->getClubId() << ", "
|
||||
<< " Card=" << r->getCardId() << ", "
|
||||
<< " Status=" << r->status << ", "
|
||||
@ -2101,7 +2101,7 @@ OpFailStatus MeosSQL::syncUpdate(oTeam *t, bool forceWriteAll) {
|
||||
<< " Runners=" << quote << t->getRunners() << ", "
|
||||
<< " StartTime=" << t->startTime << ", "
|
||||
<< " FinishTime=" << t->FinishTime << ", "
|
||||
<< " Class=" << t->getClassId() << ", "
|
||||
<< " Class=" << t->getClassId(false) << ", "
|
||||
<< " Club=" << t->getClubId() << ", "
|
||||
<< " StartNo=" << t->getStartNo() << ", "
|
||||
<< " Status=" << t->status
|
||||
|
||||
@ -335,6 +335,7 @@
|
||||
<ClCompile Include="prefseditor.cpp" />
|
||||
<ClCompile Include="printer.cpp" />
|
||||
<ClCompile Include="progress.cpp" />
|
||||
<ClCompile Include="qualification_final.cpp" />
|
||||
<ClCompile Include="random.cpp">
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
@ -420,6 +421,7 @@
|
||||
<ClInclude Include="pdfwriter.h" />
|
||||
<ClInclude Include="prefseditor.h" />
|
||||
<ClInclude Include="Printer.h" />
|
||||
<ClInclude Include="qualification_final.h" />
|
||||
<ClInclude Include="recorder.h" />
|
||||
<ClInclude Include="restserver.h" />
|
||||
<ClInclude Include="RestService.h" />
|
||||
@ -482,6 +484,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="bitmap1.bmp" />
|
||||
<None Include="html1.htm">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
<None Include="meos.ico" />
|
||||
<None Include="small.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -27,9 +27,9 @@
|
||||
//V2: ABCDEFGHIHJKMN
|
||||
//V31: a
|
||||
//V33: abcde
|
||||
//V35: abc
|
||||
//V35: abcde
|
||||
int getMeosBuild() {
|
||||
string revision("$Rev: 621 $");
|
||||
string revision("$Rev: 634 $");
|
||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ int getMeosBuild() {
|
||||
//V33: abcdefghij
|
||||
//V34: abcdfg
|
||||
wstring getMeosDate() {
|
||||
wstring date(L"$Date: 2017-10-21 22:43:38 +0200 (lö, 21 okt 2017) $");
|
||||
wstring date(L"$Date: 2017-12-25 16:08:33 +0100 (må, 25 dec 2017) $");
|
||||
return date.substr(7,10);
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ void getSupporters(vector<string> &supp)
|
||||
supp.push_back("Oskarström OK");
|
||||
supp.push_back("Skogslöparna");
|
||||
supp.push_back("OK Milan");
|
||||
supp.push_back("GoIF Tjalve");
|
||||
supp.push_back("Tjalve IF");
|
||||
supp.push_back("OK Skärmen");
|
||||
supp.push_back("Østkredsen");
|
||||
supp.push_back("OK Roskilde");
|
||||
@ -177,4 +177,7 @@ void getSupporters(vector<string> &supp)
|
||||
supp.push_back("Åke Larsson, OK Hedströmmen");
|
||||
supp.push_back("Avesta OK");
|
||||
supp.push_back("Motionsorientering Göteborg");
|
||||
supp.push_back("OK Måsen");
|
||||
supp.push_back("IF Thor");
|
||||
supp.push_back("SOS Jindrichuv Hradec");
|
||||
}
|
||||
|
||||
@ -54,6 +54,7 @@ oBase::oBase(oEvent *poe)
|
||||
counter = 0;
|
||||
Modified.update();
|
||||
correctionNeeded = true;
|
||||
localObject = false;
|
||||
}
|
||||
|
||||
oBase::~oBase()
|
||||
@ -68,6 +69,8 @@ bool oBase::synchronize(bool writeOnly)
|
||||
}
|
||||
if (oe && oe->HasDBConnection && (changed || !writeOnly)) {
|
||||
correctionNeeded = false;
|
||||
if (localObject)
|
||||
return false;
|
||||
return oe->msSynchronize(this);
|
||||
}
|
||||
else {
|
||||
@ -79,17 +82,6 @@ bool oBase::synchronize(bool writeOnly)
|
||||
return true;
|
||||
}
|
||||
|
||||
void oBase::clearCombo(HWND hWnd)
|
||||
{
|
||||
SendMessage(hWnd, CB_RESETCONTENT, 0, 0);
|
||||
}
|
||||
|
||||
void oBase::addToCombo(HWND hWnd, const string &str, int data)
|
||||
{
|
||||
int index=SendMessage(hWnd, CB_ADDSTRING, 0, LPARAM(str.c_str()));
|
||||
SendMessage(hWnd, CB_SETITEMDATA, index, data);
|
||||
}
|
||||
|
||||
void oBase::setExtIdentifier(__int64 id)
|
||||
{
|
||||
getDI().setInt64("ExtId", id);
|
||||
|
||||
12
code/oBase.h
12
code/oBase.h
@ -75,7 +75,7 @@ private:
|
||||
void resetChangeStatus() {changed &= reChanged;}
|
||||
bool reChanged;
|
||||
bool changed;
|
||||
|
||||
bool localObject;
|
||||
const static unsigned long long BaseGenStringFlag = 1ull << 63;
|
||||
const static unsigned long long Base36StringFlag = 1ull << 62;
|
||||
const static unsigned long long ExtStringMask = ~(BaseGenStringFlag|Base36StringFlag);
|
||||
@ -106,15 +106,17 @@ protected:
|
||||
/** Change the id of the object */
|
||||
virtual void changeId(int newId);
|
||||
|
||||
//Used for handeling GUI combo boxes;
|
||||
static void clearCombo(HWND hWnd);
|
||||
static void addToCombo(HWND hWnd, const string &str, int data);
|
||||
|
||||
/** Get internal data buffers for DI */
|
||||
virtual oDataContainer &getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const = 0;
|
||||
virtual int getDISize() const = 0;
|
||||
|
||||
void setLocalObject() { localObject = true; }
|
||||
|
||||
public:
|
||||
|
||||
// Returns true if the object is local, not stored in DB/On disc
|
||||
bool isLocalObject() { return localObject; }
|
||||
|
||||
/// Returns textual information on the object
|
||||
virtual wstring getInfo() const = 0;
|
||||
|
||||
|
||||
313
code/oClass.cpp
313
code/oClass.cpp
@ -43,6 +43,8 @@
|
||||
#include "gdistructures.h"
|
||||
#include "meosexception.h"
|
||||
#include "random.h"
|
||||
#include "qualification_final.h"
|
||||
#include "generalresult.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
@ -64,6 +66,7 @@ oClass::oClass(oEvent *poe): oBase(poe)
|
||||
tCoursesChanged = false;
|
||||
tStatusRevision = 0;
|
||||
tShowMultiDialog = false;
|
||||
parentClass = 0;
|
||||
}
|
||||
|
||||
oClass::oClass(oEvent *poe, int id): oBase(poe)
|
||||
@ -73,7 +76,7 @@ oClass::oClass(oEvent *poe, int id): oBase(poe)
|
||||
if (id == 0)
|
||||
id = oe->getFreeClassId();
|
||||
Id=id;
|
||||
oe->qFreeClassId = max(id, oe->qFreeClassId);
|
||||
oe->qFreeClassId = max(id % MaxClassId, oe->qFreeClassId);
|
||||
tLeaderTime.resize(1);
|
||||
tNoTiming = -1;
|
||||
tIgnoreStartPunch = -1;
|
||||
@ -85,6 +88,8 @@ oClass::oClass(oEvent *poe, int id): oBase(poe)
|
||||
tCoursesChanged = false;
|
||||
tStatusRevision = 0;
|
||||
tShowMultiDialog = false;
|
||||
|
||||
parentClass = 0;
|
||||
}
|
||||
|
||||
oClass::~oClass()
|
||||
@ -359,7 +364,7 @@ int oClass::getNumRunners(bool checkFirstLeg, bool noCountVacant, bool noCountNo
|
||||
oRunnerList::iterator it;
|
||||
|
||||
for (it=oe->Runners.begin(); it != oe->Runners.end(); ++it) {
|
||||
if (it->getClassId()==Id) {
|
||||
if (it->getClassId(true)==Id) {
|
||||
if (it->skip())
|
||||
continue;
|
||||
if (checkFirstLeg && it->tLeg > 0)
|
||||
@ -412,7 +417,7 @@ void oClass::setName(const wstring &name)
|
||||
oDataContainer &oClass::getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const {
|
||||
data = (pvoid)oData;
|
||||
olddata = (pvoid)oDataOld;
|
||||
strData = 0;
|
||||
strData = const_cast< vector <vector<wstring> >* >(&oDataStr);
|
||||
return *oe->oClassData;
|
||||
}
|
||||
|
||||
@ -1067,13 +1072,14 @@ const vector< pair<wstring, size_t> > &oEvent::fillClasses(vector< pair<wstring,
|
||||
if (rit->isRemoved())
|
||||
continue;
|
||||
|
||||
if (rit->Class) {
|
||||
if (rit->Class->getNumStages() > 0 && rit->Class->getStartType(rit->tLeg) != STDrawn)
|
||||
pClass pc = rit->getClassRef(true);
|
||||
if (pc) {
|
||||
if (pc->getNumStages() > 0 && pc->getStartType(rit->tLeg) != STDrawn)
|
||||
needTime = false;
|
||||
}
|
||||
if (rit->tStartTime==0 && needTime)
|
||||
undrawn.insert(rit->getClassId());
|
||||
hasRunner.insert(rit->getClassId());
|
||||
undrawn.insert(rit->getClassId(true));
|
||||
hasRunner.insert(rit->getClassId(true));
|
||||
}
|
||||
}
|
||||
else if (extended == extraNumMaps)
|
||||
@ -1137,9 +1143,9 @@ void oEvent::getNotDrawnClasses(set<int> &classes, bool someMissing)
|
||||
synchronizeList(oLRunnerId);
|
||||
for (rit=Runners.begin(); rit != Runners.end(); ++rit) {
|
||||
if (rit->tStartTime>0)
|
||||
drawn.insert(rit->getClassId());
|
||||
drawn.insert(rit->getClassId(true));
|
||||
else if (someMissing)
|
||||
classes.insert(rit->getClassId());
|
||||
classes.insert(rit->getClassId(true));
|
||||
}
|
||||
|
||||
// Return all classe where some runner has no start time
|
||||
@ -1231,28 +1237,6 @@ bool oClass::isCourseUsed(int Id) const
|
||||
return false;
|
||||
}
|
||||
|
||||
string oClass::getClassResultStatus() const
|
||||
{
|
||||
list<oRunner>::iterator it;
|
||||
|
||||
int nrunner=0;
|
||||
int nrunner_finish=0;
|
||||
|
||||
for (it=oe->Runners.begin(); it!=oe->Runners.end();++it) {
|
||||
if (it->getClassId()==Id){
|
||||
nrunner++;
|
||||
|
||||
if (it->getStatus())
|
||||
nrunner_finish++;
|
||||
}
|
||||
}
|
||||
|
||||
char bf[128];
|
||||
sprintf_s(bf, "%d/%d", nrunner_finish, nrunner);
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
bool oClass::hasTrueMultiCourse() const {
|
||||
if (MultiCourse.empty())
|
||||
return false;
|
||||
@ -1516,7 +1500,7 @@ void oEvent::getNumClassRunners(int id, int leg, int &total, int &finished, int
|
||||
int maxleg = pc->getLastStageIndex();
|
||||
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (!it->skip() && it->getClassId()==id && it->getStatus() != StatusNotCompetiting) {
|
||||
if (!it->skip() && it->getClassId(true)==id && it->getStatus() != StatusNotCompetiting) {
|
||||
if (leg==0) {
|
||||
total++;
|
||||
|
||||
@ -1543,7 +1527,7 @@ void oEvent::getNumClassRunners(int id, int leg, int &total, int &finished, int
|
||||
oTeamList::const_iterator it;
|
||||
|
||||
for (it=Teams.begin(); it != Teams.end(); ++it) {
|
||||
if (it->getClassId()==id) {
|
||||
if (it->getClassId(true)==id) {
|
||||
total++;
|
||||
|
||||
if (it->tStatus!=StatusUnknown ||
|
||||
@ -2695,7 +2679,7 @@ void oClass::getStatistics(const set<int> &feeLock, int &entries, int &started)
|
||||
if (it->getStatus() == StatusNotCompetiting)
|
||||
continue;
|
||||
|
||||
if (it->getClassId()==Id) {
|
||||
if (it->getClassId(false)==Id) {
|
||||
if (feeLock.empty() || feeLock.count(it->getDCI().getInt("Fee"))) {
|
||||
entries++;
|
||||
if (it->getStatus()!= StatusUnknown && it->getStatus()!= StatusDNS && it->tStatus != StatusCANCEL)
|
||||
@ -2789,6 +2773,22 @@ void oClass::reinitialize()
|
||||
tMaxTime = oe->getMaximalTime();
|
||||
}
|
||||
|
||||
wstring wInfo = getDI().getString("Qualification");
|
||||
if (!wInfo.empty()) {
|
||||
if (!qualificatonFinal)
|
||||
qualificatonFinal = make_shared<QualificationFinal>(MaxClassId, Id);
|
||||
|
||||
qualificatonFinal->init(wInfo);
|
||||
virtualClasses.resize(getNumQualificationFinalClasses());
|
||||
|
||||
int nc = qualificatonFinal->getNumClasses();
|
||||
for (int i = 1; i <= nc; i++)
|
||||
getVirtualClass(i);
|
||||
}
|
||||
else {
|
||||
qualificatonFinal.reset();
|
||||
}
|
||||
|
||||
tNoTiming = -1;
|
||||
tIgnoreStartPunch = -1;
|
||||
}
|
||||
@ -3787,7 +3787,7 @@ void oClass::extractBibPatterns(oEvent &oe, map<int, pair<wstring, int> > &patte
|
||||
patterns.clear();
|
||||
wchar_t pattern[32];
|
||||
for (size_t k = t.size(); k > 0; k--) {
|
||||
int cls = t[k-1]->getClassId();
|
||||
int cls = t[k-1]->getClassId(true);
|
||||
if (cls == 0)
|
||||
continue;
|
||||
const wstring &bib = t[k-1]->getBib();
|
||||
@ -3806,7 +3806,7 @@ void oClass::extractBibPatterns(oEvent &oe, map<int, pair<wstring, int> > &patte
|
||||
for (size_t k = r.size(); k > 0; k--) {
|
||||
if (r[k-1]->getTeam() != 0)
|
||||
continue;
|
||||
int cls = r[k-1]->getClassId();
|
||||
int cls = r[k-1]->getClassId(true);
|
||||
if (cls == 0)
|
||||
continue;
|
||||
const wstring &bib = r[k-1]->getBib();
|
||||
@ -4061,7 +4061,7 @@ void oClass::drawSeeded(ClassSeedMethod seed, int leg, int firstStart,
|
||||
}
|
||||
}
|
||||
|
||||
bool oClass::hasClassGlobalDependance() const {
|
||||
bool oClass::hasClassGlobalDependence() const {
|
||||
for (size_t k = 0; k < legInfo.size(); k++) {
|
||||
if (legInfo[k].startMethod == STHunting)
|
||||
return true;
|
||||
@ -4139,6 +4139,8 @@ int oClass::getNextBaseLeg(int leg) const {
|
||||
}
|
||||
|
||||
int oClass::getPreceedingLeg(int leg) const {
|
||||
if (size_t(leg) >= legInfo.size())
|
||||
leg = legInfo.size() - 1;
|
||||
for (int k = leg; k > 0; k--) {
|
||||
if (!(legInfo[k].isParallel() || legInfo[k].isOptional()))
|
||||
return k-1;
|
||||
@ -4147,9 +4149,242 @@ int oClass::getPreceedingLeg(int leg) const {
|
||||
}
|
||||
|
||||
bool oClass::lockedForking() const {
|
||||
return getDCI().getInt("Locked") != 0;
|
||||
return (getDCI().getInt("Locked") & 1) == 1;
|
||||
}
|
||||
|
||||
void oClass::lockedForking(bool locked) {
|
||||
getDI().setInt("Locked", locked);
|
||||
int current = getDCI().getInt("Locked");
|
||||
getDI().setInt("Locked", locked ? (current | 1) : (current & ~1));
|
||||
}
|
||||
|
||||
bool oClass::lockedClassAssignment() const {
|
||||
return (getDCI().getInt("Locked") & 2) == 2;
|
||||
}
|
||||
|
||||
void oClass::lockedClassAssignment(bool locked) {
|
||||
int current = getDCI().getInt("Locked");
|
||||
getDI().setInt("Locked", locked ? (current | 2) : (current & ~2));
|
||||
}
|
||||
|
||||
oClass *oClass::getVirtualClass(int instance, bool allowCreation) {
|
||||
if (instance == 0)
|
||||
return this;
|
||||
if (parentClass)
|
||||
return parentClass->getVirtualClass(instance, allowCreation);
|
||||
|
||||
if (size_t(instance) < virtualClasses.size() && virtualClasses[instance])
|
||||
return virtualClasses[instance];
|
||||
|
||||
if (instance >= getNumQualificationFinalClasses())
|
||||
return this; // Invalid
|
||||
virtualClasses.resize(getNumQualificationFinalClasses());
|
||||
int virtId = Id + instance * MaxClassId;
|
||||
virtualClasses[instance] = oe->getClass(virtId);
|
||||
if (virtualClasses[instance]) {
|
||||
virtualClasses[instance]->parentClass = pClass(this);
|
||||
return virtualClasses[instance];
|
||||
}
|
||||
configureInstance(instance, allowCreation);
|
||||
if (virtualClasses[instance])
|
||||
return virtualClasses[instance];
|
||||
return this; // Fallback
|
||||
}
|
||||
|
||||
const oClass *oClass::getVirtualClass(int instance) const {
|
||||
if (instance == 0)
|
||||
return this;
|
||||
if (parentClass)
|
||||
return parentClass->getVirtualClass(instance);
|
||||
|
||||
if (size_t(instance) < virtualClasses.size() && virtualClasses[instance])
|
||||
return virtualClasses[instance];
|
||||
|
||||
if (instance >= getNumQualificationFinalClasses())
|
||||
return this; // Invalid
|
||||
virtualClasses.resize(getNumQualificationFinalClasses());
|
||||
|
||||
int virtId = Id + instance * MaxClassId;
|
||||
virtualClasses[instance] = oe->getClass(virtId);
|
||||
if (virtualClasses[instance]) {
|
||||
virtualClasses[instance]->parentClass = pClass(this);
|
||||
return virtualClasses[instance];
|
||||
}
|
||||
configureInstance(instance, false);
|
||||
if (virtualClasses[instance])
|
||||
return virtualClasses[instance];
|
||||
return this; // Fallback
|
||||
}
|
||||
|
||||
void oClass::configureInstance(int instance, bool allowCreation) const {
|
||||
int virtId = Id + instance * MaxClassId;
|
||||
virtualClasses[instance] = oe->getClass(virtId);
|
||||
if (virtualClasses[instance]) {
|
||||
virtualClasses[instance]->parentClass = pClass(this);
|
||||
return;
|
||||
}
|
||||
if (!allowCreation)
|
||||
return;
|
||||
|
||||
oClass copy(*this);
|
||||
copy.Id = Id + instance * MaxClassId;
|
||||
copy.setExtIdentifier(copy.Id);
|
||||
copy.Name += makeDash(L"-") + qualificatonFinal->getInstanceName(instance);
|
||||
copy.setLocalObject();
|
||||
copy.parentClass = pClass(this);
|
||||
copy.tSortIndex += instance;
|
||||
copy.getDI().setInt("SortIndex", copy.tSortIndex);
|
||||
copy.legInfo.clear();
|
||||
copy.MultiCourse.clear();
|
||||
copy.getDI().setString("Qualification", L"");
|
||||
virtualClasses[instance] = oe->addClass(copy);
|
||||
}
|
||||
|
||||
int oClass::getNumQualificationFinalClasses() const {
|
||||
if (qualificatonFinal)
|
||||
return qualificatonFinal->getNumClasses()+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void oClass::loadQualificationFinalScheme(const wstring &fileName) {
|
||||
auto qf = make_shared<QualificationFinal>(MaxClassId, Id);
|
||||
qf->import(fileName);
|
||||
wstring enc;
|
||||
qf->encode(enc);
|
||||
int ns = qf->getNumStages();
|
||||
setNumStages(ns);
|
||||
for (int i = 1; i < ns; i++) {
|
||||
setStartType(i, StartTypes::STDrawn, true);
|
||||
setLegType(i, LegTypes::LTNormal);
|
||||
setLegRunner(i, 0);
|
||||
}
|
||||
qualificatonFinal = qf;
|
||||
getDI().setString("Qualification", enc);
|
||||
for (int i = 0; i < qualificatonFinal->getNumClasses(); i++) {
|
||||
pClass inst = getVirtualClass(i+1, true);
|
||||
inst->synchronize();
|
||||
}
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void oClass::updateFinalClasses(oRunner *causingResult, bool updateStartNumbers) {
|
||||
if (!qualificatonFinal)
|
||||
return;
|
||||
assert(!causingResult || causingResult->Class == this);
|
||||
int instance = causingResult ? causingResult->classInstance() : 0;
|
||||
pClass currentInst = getVirtualClass(instance, false);
|
||||
if (instance == virtualClasses.size())
|
||||
return; // Final class
|
||||
int maxDepth = getNumStages();
|
||||
bool needIter = true;
|
||||
int limit = virtualClasses.size() - 1;
|
||||
|
||||
while (needIter && --maxDepth > 0) {
|
||||
needIter = false;
|
||||
if (size_t(instance) >= virtualClasses.size())
|
||||
break; // Final class
|
||||
|
||||
vector< vector<pRunner> > classSplit(virtualClasses.size());
|
||||
|
||||
for (oRunner &r : oe->Runners) {
|
||||
if (r.isRemoved() || !r.Class)
|
||||
continue;
|
||||
|
||||
if (r.Class != this && (r.Class->getId() % MaxClassId) != getId())
|
||||
continue;
|
||||
|
||||
int inst = r.Class == this ? r.classInstance() : (r.Class->getId() - getId()) & MaxClassId;
|
||||
|
||||
if (inst == 0 && r.tLeg > 0)
|
||||
continue; // Only allow base class for leg 0.
|
||||
|
||||
if (inst < instance || inst >= limit)
|
||||
continue;
|
||||
|
||||
classSplit[inst].push_back(&r);
|
||||
}
|
||||
|
||||
GeneralResult gr;
|
||||
|
||||
for (int i = instance; i < limit; i++) {
|
||||
if (classSplit[i].empty())
|
||||
continue;
|
||||
|
||||
if (i == 0 && qualificatonFinal->noQualification(i)) {
|
||||
set<int> allowed;
|
||||
qualificatonFinal->getBaseClassInstances(allowed);
|
||||
// Place all in this group
|
||||
for (pRunner r : classSplit[i]) {
|
||||
auto di = r->getDI();
|
||||
int oldHeat = di.getInt("Heat");
|
||||
if (allowed.count(oldHeat) || classSplit.size() < 2)
|
||||
continue;
|
||||
// Take the smallest gruop. User can set heat explicitly of other distribution is wanted.
|
||||
int heat = 1;
|
||||
for (int i : allowed) {
|
||||
if (size_t(i) < classSplit.size() &&
|
||||
classSplit[heat].size() > classSplit[i].size())
|
||||
heat = i;
|
||||
}
|
||||
if (heat != oldHeat) {
|
||||
bool lockedStartList = getVirtualClass(heat)->lockedClassAssignment() ||
|
||||
getVirtualClass(oldHeat)->lockedClassAssignment();
|
||||
|
||||
if (!lockedStartList) {
|
||||
pClass oldClass = r->getClassRef(true);
|
||||
oldClass->markSQLChanged(-1, 0);
|
||||
di.setInt("Heat", heat);
|
||||
r->classInstanceRev.first = -1;
|
||||
r->synchronize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gr.calculateIndividualResults(classSplit[i], oListInfo::Classwise, true, 0);
|
||||
int lastPlace = 0, orderPlace = 1;
|
||||
int numEqual = 0;
|
||||
for (size_t k = 0; k < classSplit[i].size(); k++) {
|
||||
auto &res = classSplit[i][k]->getTempResult();
|
||||
int heat = 0;
|
||||
if (res.getStatus() == StatusOK) {
|
||||
int place = res.getPlace();
|
||||
if (lastPlace == place)
|
||||
numEqual++;
|
||||
else
|
||||
numEqual = 0;
|
||||
|
||||
auto nextFinal = qualificatonFinal->getNextFinal(i, orderPlace, numEqual);
|
||||
heat = nextFinal.first;
|
||||
lastPlace = place;
|
||||
}
|
||||
orderPlace++;
|
||||
oRunner &thisRunner = *classSplit[i][k];
|
||||
pRunner runnerToChange = thisRunner.getMultiRunner(thisRunner.getRaceNo() + 1);
|
||||
|
||||
if (runnerToChange) {
|
||||
auto di = runnerToChange->getDI();
|
||||
int oldHeat = di.getInt("Heat");
|
||||
|
||||
if (heat != oldHeat) {
|
||||
bool lockedStartList = getVirtualClass(heat)->lockedClassAssignment() ||
|
||||
getVirtualClass(oldHeat)->lockedClassAssignment();
|
||||
|
||||
if (!lockedStartList) {
|
||||
pClass oldClass = runnerToChange->getClassRef(true);
|
||||
oldClass->markSQLChanged(-1, 0);
|
||||
di.setInt("Heat", heat);
|
||||
runnerToChange->classInstanceRev.first = -1;
|
||||
runnerToChange->synchronize();
|
||||
if (runnerToChange->getFinishTime() > 0)
|
||||
needIter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needIter) {
|
||||
instance = i+1; // Need not process last class again
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,8 @@ class oClass;
|
||||
typedef oClass* pClass;
|
||||
class oDataInterface;
|
||||
|
||||
const int MaxClassId = 1000000;
|
||||
|
||||
enum PersonSex;
|
||||
|
||||
enum StartTypes {
|
||||
@ -132,6 +134,7 @@ struct ClassResultInfo {
|
||||
int lastStartTime;
|
||||
};
|
||||
|
||||
class QualificationFinal;
|
||||
|
||||
enum ClassType {oClassIndividual=1, oClassPatrol=2,
|
||||
oClassRelay=3, oClassIndividRelay=4};
|
||||
@ -206,7 +209,7 @@ protected:
|
||||
|
||||
BYTE oData[dataSize];
|
||||
BYTE oDataOld[dataSize];
|
||||
|
||||
vector< vector<wstring> > oDataStr;
|
||||
//Multicourse data
|
||||
string codeMultiCourse() const;
|
||||
//Fill courseId with id:s of used courses.
|
||||
@ -258,14 +261,34 @@ protected:
|
||||
|
||||
static long long setupForkKey(const vector<int> indices, const vector< vector< vector<int> > > &courseKeys, vector<int> &ws);
|
||||
|
||||
mutable vector<pClass> virtualClasses;
|
||||
pClass parentClass;
|
||||
|
||||
shared_ptr<QualificationFinal> qualificatonFinal;
|
||||
|
||||
void configureInstance(int instance, bool allowCreation) const;
|
||||
public:
|
||||
|
||||
/** The master class in a qualification/final scheme. */
|
||||
const pClass getParentClass() const { return parentClass; }
|
||||
|
||||
const QualificationFinal *getQualificationFinal() const { return qualificatonFinal.get(); }
|
||||
|
||||
/** Returns the number of possible final classes.*/
|
||||
int getNumQualificationFinalClasses() const;
|
||||
void loadQualificationFinalScheme(const wstring &fileName);
|
||||
|
||||
void updateFinalClasses(oRunner *causingResult, bool updateStartNumbers);
|
||||
|
||||
static void initClassId(oEvent &oe);
|
||||
|
||||
// Return true if forking in the class is locked
|
||||
bool lockedForking() const;
|
||||
void lockedForking(bool locked);
|
||||
|
||||
bool lockedClassAssignment() const;
|
||||
void lockedClassAssignment(bool locked);
|
||||
|
||||
// Draw data
|
||||
int getDrawFirstStart() const;
|
||||
void setDrawFirstStart(int st);
|
||||
@ -286,7 +309,7 @@ public:
|
||||
void drawSeeded(ClassSeedMethod seed, int leg, int firstStart, int interval, const vector<int> &groups,
|
||||
bool noClubNb, bool reverse, int pairSize);
|
||||
/** Returns true if the class is setup so that changeing one runner can effect all others. (Pursuit)*/
|
||||
bool hasClassGlobalDependance() const;
|
||||
bool hasClassGlobalDependence() const;
|
||||
// Autoassign new bibs
|
||||
static void extractBibPatterns(oEvent &oe, map<int, pair<wstring, int> > &patterns);
|
||||
pair<int, wstring> getNextBib(map<int, pair<wstring, int> > &patterns); // Version that calculates next free bib from cached data (fast, no gap usage)
|
||||
@ -315,6 +338,9 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
oClass *getVirtualClass(int instance, bool allowCreation);
|
||||
const oClass *getVirtualClass(int instance) const;
|
||||
|
||||
ClassStatus getClassStatus() const;
|
||||
|
||||
ClassMetaType interpretClassType() const;
|
||||
@ -441,9 +467,6 @@ public:
|
||||
void setDirectResult(bool directResult);
|
||||
bool hasDirectResult() const;
|
||||
|
||||
|
||||
string getClassResultStatus() const;
|
||||
|
||||
bool isCourseUsed(int Id) const;
|
||||
wstring getLength(int leg) const;
|
||||
|
||||
@ -472,7 +495,7 @@ public:
|
||||
|
||||
void setNumStages(int no);
|
||||
|
||||
bool operator<(const oClass &b){return tSortIndex<b.tSortIndex;}
|
||||
bool operator<(const oClass &b) {return tSortIndex<b.tSortIndex || (tSortIndex == b.tSortIndex && Id < b.Id);}
|
||||
|
||||
// Get total number of runners running this class.
|
||||
// Use checkFirstLeg to only check the number of runners running leg 1.
|
||||
|
||||
@ -428,7 +428,6 @@ void oEvent::getClubs(vector<pClub> &c, bool sort) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void oEvent::viewClubMembers(gdioutput &gdi, int clubId)
|
||||
{
|
||||
sortRunners(ClassStartTime);
|
||||
@ -440,10 +439,12 @@ void oEvent::viewClubMembers(gdioutput &gdi, int clubId)
|
||||
int nt = 0;
|
||||
// Update teams
|
||||
for (oTeamList::iterator it = Teams.begin(); it!=Teams.end(); ++it) {
|
||||
if (it->skip())
|
||||
continue;
|
||||
if (it->getClubId() == clubId) {
|
||||
if (nt==0)
|
||||
gdi.addString("", 1, "Lag(flera)");
|
||||
gdi.addStringUT(0, it->getName() + L", " + it->getClass() );
|
||||
gdi.addStringUT(0, it->getName() + L", " + it->getClass(false) );
|
||||
nt++;
|
||||
}
|
||||
}
|
||||
@ -451,10 +452,12 @@ void oEvent::viewClubMembers(gdioutput &gdi, int clubId)
|
||||
gdi.dropLine();
|
||||
// Update runners
|
||||
for (oRunnerList::iterator it = Runners.begin(); it!=Runners.end(); ++it) {
|
||||
if (it->skip())
|
||||
continue;
|
||||
if (it->getClubId() == clubId) {
|
||||
if (nr==0)
|
||||
gdi.addString("", 1, "Löpare:");
|
||||
gdi.addStringUT(0, it->getName() + L", " + it->getClass() );
|
||||
gdi.addStringUT(0, it->getName() + L", " + it->getClass(true) );
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
@ -496,7 +499,7 @@ void oClub::addRunnerInvoiceLine(const pRunner r, bool inTeam,
|
||||
|
||||
wstring ts;
|
||||
if (!inTeam)
|
||||
line.addString(xs+data.clsPos, r->getClass());
|
||||
line.addString(xs+data.clsPos, r->getClass(true));
|
||||
|
||||
if (r->getStatus() == StatusUnknown)
|
||||
ts = L"-";
|
||||
@ -504,8 +507,8 @@ void oClub::addRunnerInvoiceLine(const pRunner r, bool inTeam,
|
||||
if (r->getStatus()==StatusOK) {
|
||||
ClassType type = oClassIndividual;
|
||||
cTeam t = r->getTeam();
|
||||
if (t && r->getClassRef())
|
||||
type = r->getClassRef()->getClassType();
|
||||
if (t && r->getClassRef(false))
|
||||
type = r->getClassRef(false)->getClassType();
|
||||
|
||||
if (type == oClassIndividRelay || type == oClassRelay) {
|
||||
int leg = r->getLegNumber();
|
||||
@ -541,7 +544,7 @@ void oClub::addRunnerInvoiceLine(const pRunner r, bool inTeam,
|
||||
if (res != definedPayModes.end())
|
||||
payMode = ", " + res->second;
|
||||
*/
|
||||
if (r->getClassRef() && r->getClassRef()->getClassStatus() == oClass::InvalidRefund) {
|
||||
if (r->getClassRef(false) && r->getClassRef(false)->getClassStatus() == oClass::InvalidRefund) {
|
||||
fee = 0;
|
||||
card = 0;
|
||||
}
|
||||
@ -574,7 +577,7 @@ void oClub::addTeamInvoiceLine(const pTeam t, const map<int, wstring> &definedPa
|
||||
return;
|
||||
|
||||
line.addString(xs, t->getName());
|
||||
line.addString(xs+data.clsPos, t->getClass());
|
||||
line.addString(xs+data.clsPos, t->getClass(false));
|
||||
wstring ts;
|
||||
|
||||
if (t->getStatus() == StatusUnknown)
|
||||
@ -588,7 +591,7 @@ void oClub::addTeamInvoiceLine(const pTeam t, const map<int, wstring> &definedPa
|
||||
}
|
||||
|
||||
|
||||
if (t->getClassRef() && t->getClassRef()->getClassStatus() == oClass::InvalidRefund) {
|
||||
if (t->getClassRef(false) && t->getClassRef(false)->getClassStatus() == oClass::InvalidRefund) {
|
||||
fee = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -998,3 +998,21 @@ void oControl::getClasses(vector<pClass> &cls) const {
|
||||
cls.push_back(pClass(&*it));
|
||||
}
|
||||
}
|
||||
|
||||
int oControl::getControlIdByName(const oEvent &oe, const string &name) {
|
||||
if (_stricmp(name.c_str(), "finish") == 0)
|
||||
return oPunch::PunchFinish;
|
||||
if (_stricmp(name.c_str(), "start") == 0)
|
||||
return oPunch::PunchStart;
|
||||
|
||||
vector<pControl> ac;
|
||||
oe.getControls(ac, true);
|
||||
wstring wname = oe.gdiBase().recodeToWide(name);
|
||||
for (pControl c : ac) {
|
||||
if (_wcsicmp(c->getName().c_str(), wname.c_str()) == 0)
|
||||
return c->getId();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -117,6 +117,7 @@ protected:
|
||||
void changedObject();
|
||||
|
||||
public:
|
||||
static int getControlIdByName(const oEvent &oe, const string &name);
|
||||
|
||||
// Returns true if controls is considered a radio control.
|
||||
bool isValidRadio() const;
|
||||
|
||||
@ -289,8 +289,7 @@ __int64 oDataContainer::getInt64(const void *data, const char *Name) const
|
||||
}
|
||||
}
|
||||
|
||||
bool oDataContainer::setString(oBase *ob, const char *name, const wstring &v)
|
||||
{
|
||||
bool oDataContainer::setString(oBase *ob, const char *name, const wstring &v) {
|
||||
oDataInfo *odi=findVariable(name);
|
||||
|
||||
if (!odi)
|
||||
|
||||
214
code/oEvent.cpp
214
code/oEvent.cpp
@ -441,6 +441,7 @@ oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
|
||||
oClassData->addVariableInt("Unordered", oDataContainer::oIS8U, "Oordnade parallella");
|
||||
oClassData->addVariableInt("Heat", oDataContainer::oIS8U, "Heat");
|
||||
oClassData->addVariableInt("Locked", oDataContainer::oIS8U, "Låst gaffling");
|
||||
oClassData->addVariableString("Qualification", "Kvalschema");
|
||||
|
||||
oTeamData = new oDataContainer(oTeam::dataSize);
|
||||
oTeamData->addVariableCurrency("Fee", "Anm. avgift");
|
||||
@ -1210,6 +1211,7 @@ bool oEvent::open(const xmlparser &xml) {
|
||||
}
|
||||
|
||||
toc("class");
|
||||
reinitializeClasses();
|
||||
|
||||
//Get clubs
|
||||
xo=xml.getObject("ClubList");
|
||||
@ -1839,7 +1841,7 @@ void oEvent::updateFreeId(oBase *obj)
|
||||
qFreeRunnerId=max(obj->Id, qFreeRunnerId);
|
||||
}
|
||||
else if (typeid(*obj)==typeid(oClass)){
|
||||
qFreeClassId=max(obj->Id, qFreeClassId);
|
||||
qFreeClassId=max(obj->Id % MaxClassId, qFreeClassId);
|
||||
}
|
||||
else if (typeid(*obj)==typeid(oCourse)){
|
||||
qFreeCourseId=max(obj->Id, qFreeCourseId);
|
||||
@ -1881,7 +1883,7 @@ void oEvent::updateFreeId()
|
||||
oClassList::iterator it;
|
||||
qFreeClassId=0;
|
||||
for (it=Classes.begin(); it != Classes.end(); ++it)
|
||||
qFreeClassId=max(qFreeClassId, it->Id);
|
||||
qFreeClassId=max(qFreeClassId, it->Id % MaxClassId);
|
||||
}
|
||||
{
|
||||
oCourseList::iterator it;
|
||||
@ -2553,17 +2555,27 @@ void oEvent::removeCourse(int Id)
|
||||
void oEvent::removeClass(int Id)
|
||||
{
|
||||
oClassList::iterator it;
|
||||
|
||||
for (it=Classes.begin(); it != Classes.end(); ++it){
|
||||
vector<int> subRemove;
|
||||
for (it = Classes.begin(); it != Classes.end(); ++it){
|
||||
if (it->Id==Id){
|
||||
if (it->getQualificationFinal()) {
|
||||
for (int n = 0; n < it->getNumQualificationFinalClasses(); n++) {
|
||||
const oClass *pc = it->getVirtualClass(n);
|
||||
if (pc && pc != &*it)
|
||||
subRemove.push_back(pc->getId());
|
||||
}
|
||||
}
|
||||
if (HasDBConnection)
|
||||
msRemove(&*it);
|
||||
Classes.erase(it);
|
||||
dataRevision++;
|
||||
updateTabs();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int id : subRemove) {
|
||||
removeClass(id);
|
||||
}
|
||||
}
|
||||
|
||||
void oEvent::removeControl(int Id)
|
||||
@ -2642,17 +2654,33 @@ bool oEvent::isCourseUsed(int Id) const
|
||||
|
||||
bool oEvent::isClassUsed(int Id) const
|
||||
{
|
||||
pClass cl = getClass(Id);
|
||||
if (cl && cl->parentClass) {
|
||||
if (isClassUsed(cl->parentClass->Id))
|
||||
return true;
|
||||
}
|
||||
|
||||
set<int> idToCheck;
|
||||
idToCheck.insert(Id);
|
||||
if (cl) {
|
||||
for (int i = 0; i < cl->getNumQualificationFinalClasses(); i++)
|
||||
idToCheck.insert(cl->getVirtualClass(i)->getId());
|
||||
}
|
||||
//Search runners
|
||||
oRunnerList::const_iterator it;
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (it->getClassId()==Id)
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (idToCheck.count(it->getClassId(false)))
|
||||
return true;
|
||||
}
|
||||
|
||||
//Search teams
|
||||
oTeamList::const_iterator tit;
|
||||
for (tit=Teams.begin(); tit != Teams.end(); ++tit){
|
||||
if (tit->getClassId()==Id)
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (idToCheck.count(tit->getClassId(false)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -2713,7 +2741,7 @@ bool oEvent::classHasResults(int Id) const
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if ( (Id == 0 || it->getClassId() == Id) && (it->getCard() || it->FinishTime))
|
||||
if ( (Id == 0 || it->getClassId(true) == Id) && (it->getCard() || it->FinishTime))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2722,10 +2750,16 @@ bool oEvent::classHasResults(int Id) const
|
||||
|
||||
bool oEvent::classHasTeams(int Id) const
|
||||
{
|
||||
oTeamList::const_iterator it;
|
||||
pClass pc = oe->getClass(Id);
|
||||
if (pc == 0)
|
||||
return false;
|
||||
|
||||
if (pc->getQualificationFinal() != 0)
|
||||
return false;
|
||||
|
||||
oTeamList::const_iterator it;
|
||||
for (it=Teams.begin(); it != Teams.end(); ++it)
|
||||
if (it->getClassId()==Id)
|
||||
if (!it->isRemoved() && it->getClassId(false)==Id)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -2768,8 +2802,8 @@ void oEvent::generateVacancyList(gdioutput &gdi, GUICALLBACK cb)
|
||||
if (it->skip() || !it->isVacant())
|
||||
continue;
|
||||
|
||||
if (it->getClassId() != Id) {
|
||||
Id=it->getClassId();
|
||||
if (it->getClassId(true) != Id) {
|
||||
Id=it->getClassId(true);
|
||||
y+=lh/2;
|
||||
|
||||
if (nRunner>=RunnersPerCol) {
|
||||
@ -2779,7 +2813,7 @@ void oEvent::generateVacancyList(gdioutput &gdi, GUICALLBACK cb)
|
||||
}
|
||||
|
||||
|
||||
gdi.addStringUT(y, x+dx[0], 1, it->getClass());
|
||||
gdi.addStringUT(y, x+dx[0], 1, it->getClass(true));
|
||||
y+=lh+lh/3;
|
||||
}
|
||||
|
||||
@ -2865,7 +2899,7 @@ void oEvent::generateInForestList(gdioutput &gdi, GUICALLBACK cb, GUICALLBACK cb
|
||||
}
|
||||
|
||||
if (unknown) {
|
||||
if (id != it->getClassId()) {
|
||||
if (id != it->getClassId(false)) {
|
||||
if (nr>0) {
|
||||
gdi.addString("", y, x, 0, "Antal: X#"+itos(nr));
|
||||
y+=lh;
|
||||
@ -2876,11 +2910,11 @@ void oEvent::generateInForestList(gdioutput &gdi, GUICALLBACK cb, GUICALLBACK cb
|
||||
y += lh;
|
||||
}
|
||||
y += lh;
|
||||
id = it->getClassId();
|
||||
gdi.addStringUT(y, x, 1, it->getClass());
|
||||
id = it->getClassId(false);
|
||||
gdi.addStringUT(y, x, 1, it->getClass(false));
|
||||
y += lh;
|
||||
}
|
||||
gdi.addStringUT(y, x, 0, it->getClass());
|
||||
gdi.addStringUT(y, x, 0, it->getClass(false));
|
||||
nr++;
|
||||
gdi.addStringUT(y, x+100, 0, it->getName(), 0, cb).setExtra(it->getId()).id = "T";
|
||||
y+=lh;
|
||||
@ -2920,15 +2954,15 @@ void oEvent::generateInForestList(gdioutput &gdi, GUICALLBACK cb, GUICALLBACK cb
|
||||
|
||||
if (it->tStatus == StatusUnknown) {
|
||||
|
||||
if (id != it->getClassId()) {
|
||||
if (id != it->getClassId(true)) {
|
||||
if (nr>0) {
|
||||
gdi.addString("", y, x, 0, "Antal: X#"+itos(nr));
|
||||
y+=lh;
|
||||
nr=0;
|
||||
}
|
||||
y += lh;
|
||||
id = it->getClassId();
|
||||
gdi.addStringUT(y, x, 1, it->getClass());
|
||||
id = it->getClassId(true);
|
||||
gdi.addStringUT(y, x, 1, it->getClass(true));
|
||||
y += lh;
|
||||
}
|
||||
|
||||
@ -2982,7 +3016,7 @@ void oEvent::generateInForestList(gdioutput &gdi, GUICALLBACK cb, GUICALLBACK cb
|
||||
gdi.addToolTip("", L"#" + punches + L". " + otherRunners, 0, &rc);
|
||||
}
|
||||
}
|
||||
gdi.addStringUT(y, x+dx[3], 0, it->getClass());
|
||||
gdi.addStringUT(y, x+dx[3], 0, it->getClass(true));
|
||||
y+=lh;
|
||||
}
|
||||
}
|
||||
@ -3126,7 +3160,7 @@ void oEvent::generateMinuteStartlist(gdioutput &gdi) {
|
||||
}
|
||||
|
||||
gdi.addStringUT(src_y, x+dx[2], fontMedium, r[0]->getClub(), dx[3]-dx[2]-4);
|
||||
gdi.addStringUT(src_y, x+dx[3], fontMedium, r[0]->getClass());
|
||||
gdi.addStringUT(src_y, x+dx[3], fontMedium, r[0]->getClass(true));
|
||||
y+=lh;
|
||||
}
|
||||
}
|
||||
@ -3689,7 +3723,7 @@ void oEvent::reEvaluateCourse(int CourseId, bool DoSync)
|
||||
set<int> classes;
|
||||
for(it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (it->getCourse(false) && it->getCourse(false)->getId()==CourseId){
|
||||
classes.insert(it->getClassId());
|
||||
classes.insert(it->getClassId(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3710,7 +3744,7 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
|
||||
}
|
||||
|
||||
for(oTeamList::iterator tit=Teams.begin();tit!=Teams.end();++tit) {
|
||||
if (!cls.empty() && cls.count(tit->getClassId()) == 0)
|
||||
if (!cls.empty() && cls.count(tit->getClassId(false)) == 0)
|
||||
continue;
|
||||
|
||||
tit->resetTmpStore();
|
||||
@ -3727,7 +3761,7 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
|
||||
oRunnerList::iterator it;
|
||||
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!cls.empty() && cls.count(it->getClassId()) == 0)
|
||||
if (!cls.empty() && cls.count(it->getClassId(true)) == 0)
|
||||
continue;
|
||||
|
||||
if (!it->tInTeam) {
|
||||
@ -3742,7 +3776,7 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
|
||||
while (needupdate) {
|
||||
needupdate = false;
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!cls.empty() && cls.count(it->getClassId()) == 0)
|
||||
if (!cls.empty() && cls.count(it->getClassId(true)) == 0)
|
||||
continue;
|
||||
|
||||
if (!it->isRemoved()) {
|
||||
@ -3760,7 +3794,7 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
|
||||
// Update team start times etc.
|
||||
for(oTeamList::iterator tit=Teams.begin();tit!=Teams.end();++tit) {
|
||||
if (!tit->isRemoved()) {
|
||||
if (!cls.empty() && cls.count(tit->getClassId()) == 0)
|
||||
if (!cls.empty() && cls.count(tit->getClassId(true)) == 0)
|
||||
continue;
|
||||
|
||||
tit->apply(false, 0, true);
|
||||
@ -3771,7 +3805,7 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
|
||||
}
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!it->isRemoved()) {
|
||||
if (!cls.empty() && cls.count(it->getClassId()) == 0)
|
||||
if (!cls.empty() && cls.count(it->getClassId(true)) == 0)
|
||||
continue;
|
||||
|
||||
if (!it->tInTeam)
|
||||
@ -3805,7 +3839,7 @@ void oEvent::reEvaluateChanged()
|
||||
it->clearSplitAnalysis();
|
||||
it->resetLeaderTime();
|
||||
it->reinitialize();
|
||||
resetClasses[it->getId()] = it->hasClassGlobalDependance();
|
||||
resetClasses[it->getId()] = it->hasClassGlobalDependence();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3833,11 +3867,11 @@ void oEvent::reEvaluateChanged()
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
|
||||
if (resetClasses.count(it->getClassId()))
|
||||
int clz = it->getClassId(true);
|
||||
if (resetClasses.count(clz))
|
||||
it->storeTimes();
|
||||
|
||||
if (!it->wasSQLChanged() && !resetClasses[it->getClassId()])
|
||||
if (!it->wasSQLChanged() && !resetClasses[clz])
|
||||
continue;
|
||||
|
||||
pTeam t = it->tInTeam;
|
||||
@ -3926,7 +3960,7 @@ void oEvent::reCalculateLeaderTimes(int classId)
|
||||
while (needupdate) {
|
||||
needupdate = false;
|
||||
for (oRunnerList::iterator it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!it->isRemoved() && (classId==0 || classId==it->getClassId())) {
|
||||
if (!it->isRemoved() && (classId==0 || classId==it->getClassId(true))) {
|
||||
if (it->tLeg == leg)
|
||||
it->storeTimes();
|
||||
else if (it->tLeg>leg)
|
||||
@ -4097,7 +4131,7 @@ int oEvent::getFirstStart(int classId) const {
|
||||
int minTime=3600*24;
|
||||
|
||||
while(it!=Runners.end()){
|
||||
if (!it->isRemoved() && classId==0 || it->getClassId()==classId)
|
||||
if (!it->isRemoved() && classId==0 || it->getClassId(true)==classId)
|
||||
if (it->tStartTime < minTime && it->tStatus!=StatusNotCompetiting && it->tStartTime>0)
|
||||
minTime = it->tStartTime;
|
||||
++it;
|
||||
@ -4168,17 +4202,26 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
||||
sortRunners(ClassStartTimeClub);
|
||||
oRunnerList::iterator it;
|
||||
|
||||
pClass cls = getClass(ClassId);
|
||||
if (cls == 0)
|
||||
throw meosException("Class not found");
|
||||
|
||||
if (cls->getParentClass())
|
||||
cls->getParentClass()->setBibMode(BibFree);
|
||||
|
||||
if (!firstNumber.empty()) {
|
||||
cls->setBibMode(BibFree);
|
||||
wchar_t pattern[32];
|
||||
int num = oClass::extractBibPattern(firstNumber, pattern);
|
||||
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if ( (ClassId==0 || it->getClassId()==ClassId) && it->legToRun()==leg) {
|
||||
if ( (ClassId==0 || it->getClassId(true)==ClassId) && (it->legToRun()==leg || leg == -1)) {
|
||||
wchar_t bib[32];
|
||||
swprintf_s(bib, pattern, num);
|
||||
it->setBib(bib, num, true, false);
|
||||
pClass pc = it->getClassRef(true);
|
||||
it->setBib(bib, num, pc ? !pc->lockedForking() : true, false);
|
||||
num++;
|
||||
it->synchronize();
|
||||
}
|
||||
@ -4188,7 +4231,7 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
||||
for(it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (ClassId==0 || it->getClassId()==ClassId) {
|
||||
if (ClassId==0 || it->getClassId(true)==ClassId) {
|
||||
it->getDI().setString("Bib", L"");//Update only bib
|
||||
it->synchronize();
|
||||
}
|
||||
@ -4206,8 +4249,8 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
||||
for (it=Teams.begin(); it != Teams.end(); ++it) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (ClassId==0 || it->getClassId()==ClassId) {
|
||||
if (it->getClassRef() && it->getClassRef()->getBibMode() != BibFree) {
|
||||
if (ClassId==0 || it->getClassId(false)==ClassId) {
|
||||
if (it->getClassRef(false) && it->getClassRef(false)->getBibMode() != BibFree) {
|
||||
for (size_t i = 0; i < it->Runners.size(); i++) {
|
||||
if (it->Runners[i]) {
|
||||
//runnerStartNo[it->Runners[i]->getId()] = it->Runners[i]->getStartNo();
|
||||
@ -4232,7 +4275,7 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
|
||||
if (ClassId == 0 || it->getClassId() == ClassId) {
|
||||
if (ClassId == 0 || it->getClassId(false) == ClassId) {
|
||||
wchar_t bib[32];
|
||||
swprintf_s(bib, pattern, num);
|
||||
bool lockedStartNo = it->Class && it->Class->lockedForking();
|
||||
@ -4250,7 +4293,7 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
||||
}
|
||||
else {
|
||||
for(it=Teams.begin(); it != Teams.end(); ++it){
|
||||
if (ClassId==0 || it->getClassId()==ClassId) {
|
||||
if (ClassId==0 || it->getClassId(false)==ClassId) {
|
||||
it->getDI().setString("Bib", L""); //Update only bib
|
||||
it->apply(true, 0, false);
|
||||
}
|
||||
@ -4265,7 +4308,7 @@ void oEvent::addAutoBib() {
|
||||
int clsId = -1;
|
||||
int bibGap = oe->getBibClassGap();
|
||||
int interval = 1;
|
||||
|
||||
set<int> isTeamCls;
|
||||
wchar_t pattern[32] = {0};
|
||||
wchar_t storedPattern[32];
|
||||
wcscpy_s(storedPattern, L"%d");
|
||||
@ -4283,24 +4326,26 @@ void oEvent::addAutoBib() {
|
||||
for (oTeamList::iterator tit = Teams.begin(); tit != Teams.end(); ++tit) {
|
||||
if (tit->skip())
|
||||
continue;
|
||||
pClass cls = tit->getClassRef();
|
||||
pClass cls = tit->getClassRef(false);
|
||||
if (cls == 0)
|
||||
continue;
|
||||
teamStartNo[tit->getId()] = tit->getStartNo();
|
||||
|
||||
wstring bibInfo = cls->getDCI().getString("Bib");
|
||||
|
||||
bool teamAssign = !bibInfo.empty();
|
||||
bool teamAssign = !bibInfo.empty() && cls->getNumStages() > 1;
|
||||
|
||||
bool freeMode = cls->getBibMode()==BibFree;
|
||||
if (!teamAssign && freeMode)
|
||||
continue; // Manul or none
|
||||
|
||||
isTeamCls.insert(cls->getId());
|
||||
|
||||
bool addBib = bibInfo != L"-";
|
||||
|
||||
if (addBib && teamAssign)
|
||||
tit->setStartNo(0, false);
|
||||
|
||||
if (tit->getClassRef() && tit->getClassRef()->getBibMode() != BibFree) {
|
||||
if (tit->getClassRef(false) && tit->getClassRef(false)->getBibMode() != BibFree) {
|
||||
for (size_t i = 0; i < tit->Runners.size(); i++) {
|
||||
if (tit->Runners[i]) {
|
||||
if (addBib && teamAssign)
|
||||
@ -4318,15 +4363,15 @@ void oEvent::addAutoBib() {
|
||||
for (oTeamList::iterator tit = Teams.begin(); tit != Teams.end(); ++tit) {
|
||||
if (tit->skip())
|
||||
continue;
|
||||
int clsId = tit->getClassId();
|
||||
int clsId = tit->getClassId(false);
|
||||
cls2TeamList[clsId].push_back(&*tit);
|
||||
}
|
||||
|
||||
map<int, vector<pRunner> > cls2RunnerList;
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (it->skip() || !it->getClassId())
|
||||
if (it->isRemoved() || !it->getClassId(false))
|
||||
continue;
|
||||
int clsId = it->getClassId();
|
||||
int clsId = it->getClassId(true);
|
||||
cls2RunnerList[clsId].push_back(&*it);
|
||||
}
|
||||
|
||||
@ -4362,7 +4407,7 @@ void oEvent::addAutoBib() {
|
||||
number = oClass::extractBibPattern(bibInfo, pattern);
|
||||
}
|
||||
|
||||
if (cls->getNumStages() > 1) {
|
||||
if (isTeamCls.count(clsId)) {
|
||||
vector<pTeam> &tl = cls2TeamList[clsId];
|
||||
|
||||
if (cls->getBibMode() == BibAdd) {
|
||||
@ -4405,18 +4450,23 @@ void oEvent::addAutoBib() {
|
||||
tl[k]->apply(true, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
interval = 1;
|
||||
|
||||
vector<pRunner> &rl = cls2RunnerList[clsId];
|
||||
bool locked = cls->lockedForking();
|
||||
if (pattern[0] && cls->getParentClass()) {
|
||||
// Switch to free mode if bib set for subclass
|
||||
cls->getParentClass()->setBibMode(BibFree);
|
||||
cls->setBibMode(BibFree);
|
||||
}
|
||||
for (size_t k = 0; k < rl.size(); k++) {
|
||||
if (pattern[0]) {
|
||||
wchar_t buff[32];
|
||||
swprintf_s(buff, pattern, number);
|
||||
rl[k]->setBib(buff, number, true, false);
|
||||
rl[k]->setBib(buff, number, !locked, false);
|
||||
number += interval;
|
||||
}
|
||||
else {
|
||||
@ -4436,7 +4486,7 @@ void oEvent::checkOrderIdMultipleCourses(int ClassId)
|
||||
|
||||
//Find first free order
|
||||
for(it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (ClassId==0 || it->getClassId()==ClassId){
|
||||
if (ClassId==0 || it->getClassId(false)==ClassId){
|
||||
it->synchronize();//Ensure we are up-to-date
|
||||
order=max(order, it->StartNo);
|
||||
}
|
||||
@ -4444,7 +4494,7 @@ void oEvent::checkOrderIdMultipleCourses(int ClassId)
|
||||
|
||||
//Assign orders
|
||||
for(it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (ClassId==0 || it->getClassId()==ClassId)
|
||||
if (ClassId==0 || it->getClassId(false)==ClassId)
|
||||
if (it->StartNo==0){
|
||||
it->StartNo=++order;
|
||||
it->updateChanged(); //Mark as changed.
|
||||
@ -4610,7 +4660,7 @@ void oEvent::loadProperties(const wchar_t *file) {
|
||||
bool compareClubClassTeamName(const oRunner &a, const oRunner &b)
|
||||
{
|
||||
if (a.Club==b.Club) {
|
||||
if (a.Class==b.Class) {
|
||||
if (a.getClassId(true) == b.getClassId(true)) {
|
||||
if (a.tInTeam==b.tInTeam)
|
||||
return a.tRealName<b.tRealName;
|
||||
else if (a.tInTeam) {
|
||||
@ -4621,11 +4671,10 @@ bool compareClubClassTeamName(const oRunner &a, const oRunner &b)
|
||||
return b.tInTeam!=0;
|
||||
}
|
||||
else
|
||||
return a.getClass()<b.getClass();
|
||||
return a.getClass(true)<b.getClass(true);
|
||||
}
|
||||
else
|
||||
return a.getClub()<b.getClub();
|
||||
|
||||
}
|
||||
|
||||
void oEvent::assignCardInteractive(gdioutput &gdi, GUICALLBACK cb)
|
||||
@ -4656,7 +4705,7 @@ void oEvent::assignCardInteractive(gdioutput &gdi, GUICALLBACK cb)
|
||||
|
||||
wstring r;
|
||||
if (it->Class)
|
||||
r+=it->getClass()+L", ";
|
||||
r+=it->getClass(false)+L", ";
|
||||
|
||||
if (it->tInTeam) {
|
||||
r+=itow(it->tInTeam->getStartNo()); + L" " + it->tInTeam->getName();
|
||||
@ -5345,7 +5394,7 @@ void oEvent::applyEventFees(bool updateClassFromEvent,
|
||||
if (it->skip())
|
||||
continue;
|
||||
|
||||
if (allClass || classFilter.count(it->getClassId())) {
|
||||
if (allClass || classFilter.count(it->getClassId(true))) {
|
||||
it->addClassDefaultFee(true);
|
||||
it->synchronize(true);
|
||||
}
|
||||
@ -5451,7 +5500,7 @@ void oEvent::removeVacanies(int classId) {
|
||||
if (it->skip() || !it->isVacant())
|
||||
continue;
|
||||
|
||||
if (classId!=0 && it->getClassId()!=classId)
|
||||
if (classId!=0 && it->getClassId(false)!=classId)
|
||||
continue;
|
||||
|
||||
if (!isRunnerUsed(it->Id))
|
||||
@ -5472,7 +5521,7 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
|
||||
for (oRunnerList::iterator it = Runners.begin(); it!=Runners.end(); ++it) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (onlyThisClass > 0 && it->getClassId() != onlyThisClass)
|
||||
if (onlyThisClass > 0 && it->getClassId(false) != onlyThisClass)
|
||||
continue;
|
||||
if (it->sName.empty()) {
|
||||
if (!warnNoName) {
|
||||
@ -5502,7 +5551,7 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
|
||||
if (!warnNoTeam) {
|
||||
gdi.alert(L"Deltagaren 'X' deltar i stafettklassen 'Y' men saknar lag. Klassens start- "
|
||||
L"och resultatlistor kan därmed bli felaktiga.#" + it->getName() +
|
||||
L"#" + it->getClass());
|
||||
L"#" + it->getClass(false));
|
||||
warnNoTeam = true;
|
||||
}
|
||||
}
|
||||
@ -5510,7 +5559,7 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
|
||||
if (!warnNoPatrol) {
|
||||
gdi.alert(L"Deltagaren 'X' deltar i patrullklassen 'Y' men saknar patrull. Klassens start- "
|
||||
L"och resultatlistor kan därmed bli felaktiga.#" + it->getName() +
|
||||
+ L"#" + it->getClass());
|
||||
+ L"#" + it->getClass(false));
|
||||
warnNoPatrol = true;
|
||||
}
|
||||
}
|
||||
@ -5524,7 +5573,7 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
|
||||
if (onlyThisClass > 0 && it->getClassId() != onlyThisClass)
|
||||
if (onlyThisClass > 0 && it->getClassId(false) != onlyThisClass)
|
||||
continue;
|
||||
|
||||
if (it->sName.empty()) {
|
||||
@ -5549,7 +5598,7 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
|
||||
if (type == oClassIndividual) {
|
||||
if (!warnIndividualTeam) {
|
||||
gdi.alert(L"Laget 'X' deltar i individuella klassen 'Y'. Klassens start- och resultatlistor "
|
||||
L"kan därmed bli felaktiga.#" + it->getName() + L"#" + it->getClass());
|
||||
L"kan därmed bli felaktiga.#" + it->getName() + L"#" + it->getClass(true));
|
||||
warnIndividualTeam = true;
|
||||
}
|
||||
}
|
||||
@ -5571,6 +5620,9 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
|
||||
if (onlyThisClass > 0 && it->getId() != onlyThisClass)
|
||||
continue;
|
||||
|
||||
if (it->getQualificationFinal())
|
||||
continue;
|
||||
|
||||
if (it->hasMultiCourse()) {
|
||||
for (unsigned k=0;k<it->getNumStages(); k++) {
|
||||
StartTypes st = it->getStartType(k);
|
||||
@ -5786,7 +5838,7 @@ wstring oEvent::cloneCompetition(bool cloneRunners, bool cloneTimes,
|
||||
r.StartNo = it->StartNo;
|
||||
r.CardNo = it->CardNo;
|
||||
r.Club = ce.getClub(it->getClubId());
|
||||
r.Class = ce.getClass(it->getClassId());
|
||||
r.Class = ce.getClass(it->getClassId(false));
|
||||
|
||||
if (cloneCourses)
|
||||
r.Course = ce.getCourse(it->getCourseId());
|
||||
@ -5819,7 +5871,7 @@ wstring oEvent::cloneCompetition(bool cloneRunners, bool cloneTimes,
|
||||
t.sName = it->sName;
|
||||
t.StartNo = it->StartNo;
|
||||
t.Club = ce.getClub(it->getClubId());
|
||||
t.Class = ce.getClass(it->getClassId());
|
||||
t.Class = ce.getClass(it->getClassId(false));
|
||||
|
||||
if (cloneTimes)
|
||||
t.startTime = it->startTime;
|
||||
@ -5879,7 +5931,7 @@ bool checkTargetClass(pRunner target, pRunner source,
|
||||
if (changeClassMethod == oEvent::TransferAnyway)
|
||||
return true;
|
||||
|
||||
if (!compareClassName(target->getClass(), source->getClass())) {
|
||||
if (!compareClassName(target->getClass(false), source->getClass(false))) {
|
||||
// Store all vacant positions in the right class
|
||||
int targetClass = -1;
|
||||
|
||||
@ -5894,10 +5946,10 @@ bool checkTargetClass(pRunner target, pRunner source,
|
||||
for (oClassList::const_iterator cit = Classes.begin(); cit != Classes.end(); ++cit) {
|
||||
if (cit->isRemoved())
|
||||
continue;
|
||||
if (compareClassName(cit->getName(), source->getClass())) {
|
||||
if (compareClassName(cit->getName(), source->getClass(false))) {
|
||||
targetClass = cit->getId();
|
||||
|
||||
if (targetClass == source->getClassId() || cit->getName() == source->getClass())
|
||||
if (targetClass == source->getClassId(false) || cit->getName() == source->getClass(false))
|
||||
break; // Assume exact match
|
||||
}
|
||||
}
|
||||
@ -5907,7 +5959,7 @@ bool checkTargetClass(pRunner target, pRunner source,
|
||||
for (size_t j = 0; j < targetVacant.size(); j++) {
|
||||
if (!targetVacant[j])
|
||||
continue;
|
||||
if (targetVacant[j]->getClassId() == targetClass)
|
||||
if (targetVacant[j]->getClassId(false) == targetClass)
|
||||
vacantIx.insert(j);
|
||||
}
|
||||
int posToUse = -1;
|
||||
@ -5935,12 +5987,12 @@ bool checkTargetClass(pRunner target, pRunner source,
|
||||
int oldStart = target->getStartTime();
|
||||
wstring oldBib = target->getBib();
|
||||
int oldSN = target->getStartNo();
|
||||
int oldClass = target->getClassId();
|
||||
int oldClass = target->getClassId(false);
|
||||
pRunner tgt = targetVacant[posToUse];
|
||||
target->cloneStartTime(tgt);
|
||||
target->setBib(tgt->getBib(), 0, false, false);
|
||||
target->setStartNo(tgt->getStartNo(), false);
|
||||
target->setClassId(tgt->getClassId(), false);
|
||||
target->setClassId(tgt->getClassId(false), false);
|
||||
|
||||
tgt->setStartTime(oldStart, true, false);
|
||||
tgt->setBib(oldBib, 0, false, false);
|
||||
@ -6122,7 +6174,7 @@ void oEvent::transferResult(oEvent &ce,
|
||||
for (size_t j = 0; j < cnd.size(); j++) {
|
||||
pRunner src = remainingRunners[cnd[j]];
|
||||
int p = 0;
|
||||
if (src->getClass() == it->getClass())
|
||||
if (src->getClass(false) == it->getClass(false))
|
||||
p += 1;
|
||||
if (src->getBirthYear() == it->getBirthYear())
|
||||
p += 2;
|
||||
@ -6165,7 +6217,7 @@ void oEvent::transferResult(oEvent &ce,
|
||||
}
|
||||
|
||||
pRunner targetVacant = ce.getRunner(src->getId(), 0);
|
||||
if (targetVacant && targetVacant->isVacant() && compareClassName(targetVacant->getClass(), src->getClass()) ) {
|
||||
if (targetVacant && targetVacant->isVacant() && compareClassName(targetVacant->getClass(false), src->getClass(false)) ) {
|
||||
targetVacant->setName(src->getName(), false);
|
||||
targetVacant->setClub(src->getClub());
|
||||
targetVacant->setCardNo(src->getCardNo(), false);
|
||||
@ -6173,13 +6225,13 @@ void oEvent::transferResult(oEvent &ce,
|
||||
assignedVacant.push_back(targetVacant);
|
||||
}
|
||||
else {
|
||||
pClass dstClass = ce.getClass(src->getClassId());
|
||||
if (dstClass && compareClassName(dstClass->getName(), src->getClass())) {
|
||||
if ( (!src->hasFlag(oAbstractRunner::FlagTransferSpecified) && allowNewEntries.count(src->getClassId()))
|
||||
pClass dstClass = ce.getClass(src->getClassId(false));
|
||||
if (dstClass && compareClassName(dstClass->getName(), src->getClass(false))) {
|
||||
if ( (!src->hasFlag(oAbstractRunner::FlagTransferSpecified) && allowNewEntries.count(src->getClassId(false)))
|
||||
|| src->hasFlag(oAbstractRunner::FlagTransferNew)) {
|
||||
if (src->getClubId() > 0)
|
||||
ce.getClubCreate(src->getClubId(), src->getClub());
|
||||
pRunner dst = ce.addRunner(src->getName(), src->getClubId(), src->getClassId(),
|
||||
pRunner dst = ce.addRunner(src->getName(), src->getClubId(), src->getClassId(false),
|
||||
src->getCardNo(), src->getBirthYear(), true);
|
||||
dst->cloneData(src);
|
||||
dst->setInputData(*src);
|
||||
@ -6188,7 +6240,7 @@ void oEvent::transferResult(oEvent &ce,
|
||||
else if (transferAllNoCompete) {
|
||||
if (src->getClubId() > 0)
|
||||
ce.getClubCreate(src->getClubId(), src->getClub());
|
||||
pRunner dst = ce.addRunner(src->getName(), src->getClubId(), src->getClassId(),
|
||||
pRunner dst = ce.addRunner(src->getName(), src->getClubId(), src->getClassId(false),
|
||||
0, src->getBirthYear(), true);
|
||||
dst->cloneData(src);
|
||||
dst->setInputData(*src);
|
||||
@ -6313,7 +6365,7 @@ void oEvent::transferResult(oEvent &ce,
|
||||
for (size_t j = 0; j < cnd.size(); j++) {
|
||||
pTeam src = remainingTeams[cnd[j]];
|
||||
int p = 0;
|
||||
if (src->getClass() == it->getClass())
|
||||
if (src->getClass(false) == it->getClass(false))
|
||||
p += 1;
|
||||
if (p > point) {
|
||||
winnerIx = cnd[j];
|
||||
|
||||
@ -447,7 +447,7 @@ protected:
|
||||
void exportIOFResults(xmlparser &xml, bool selfContained, const set<int> &classes, int leg, bool oldStylePatrol);
|
||||
void exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldStylePatrol);
|
||||
|
||||
/** Set up transient data in cassss */
|
||||
/** Set up transient data in classes */
|
||||
void reinitializeClasses();
|
||||
|
||||
/** Analyze the result status of each class*/
|
||||
@ -779,7 +779,7 @@ public:
|
||||
short partialCount;
|
||||
short legNumber;
|
||||
|
||||
inline int classId() const {return r->getClassId();}
|
||||
inline int classId() const {return r->getClassId(true);}
|
||||
inline int leg() const {return legNumber;}
|
||||
};
|
||||
|
||||
@ -917,8 +917,7 @@ public:
|
||||
bool empty() const;
|
||||
|
||||
void generateMinuteStartlist(gdioutput &gdi);
|
||||
void generateMinuteStartlist(const string &file);
|
||||
|
||||
|
||||
bool classHasTeams(int Id) const;
|
||||
bool classHasResults(int Id) const;
|
||||
bool isCourseUsed(int Id) const;
|
||||
@ -982,12 +981,14 @@ public:
|
||||
bool saveRunnerDatabase(const wchar_t *file, bool onlyLocal);
|
||||
|
||||
enum ResultType {RTClassResult, RTTotalResult, RTCourseResult, RTClassCourseResult};
|
||||
void calculateResults(ResultType result);
|
||||
void calculateResults(ResultType result, bool includePreliminary = false);
|
||||
void calculateRogainingResults();
|
||||
|
||||
void calculateResults(list<oSpeakerObject> &rl);
|
||||
void calculateTeamResults(bool totalMultiday);
|
||||
bool calculateTeamResults(int leg, bool totalMultiday);
|
||||
// Set results for specified classes to tempResult
|
||||
void calculateTeamResultAtControl(const set<int> &classId, int leg, int controlId, bool totalResults);
|
||||
|
||||
bool sortRunners(SortOrder so);
|
||||
/** If linear leg is true, leg is interpreted as actual leg numer, otherwise w.r.t to parallel legs. */
|
||||
|
||||
@ -565,13 +565,13 @@ void oEvent::optimizeStartOrder(vector< vector<pair<int, int> > > &StartField, D
|
||||
int relPos = relSt / di.baseInterval;
|
||||
|
||||
if (st>0 && relSt>=0 && relPos<3000 && (relSt%di.baseInterval) == 0) {
|
||||
if (otherClasses.count(it->getClassId())==0)
|
||||
if (otherClasses.count(it->getClassId(false))==0)
|
||||
continue;
|
||||
|
||||
if (!di.startName.empty() && it->Class && it->Class->getStart()!=di.startName)
|
||||
continue;
|
||||
|
||||
ClassInfo &ci = otherClasses[it->getClassId()];
|
||||
ClassInfo &ci = otherClasses[it->getClassId(false)];
|
||||
int k = 0;
|
||||
while(true) {
|
||||
if (k==StartField.size()) {
|
||||
@ -688,14 +688,18 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
||||
if (spec[k].vacances>0 && pc->getClassType()==oClassRelay)
|
||||
throw std::exception("Vakanser stöds ej i stafett.");
|
||||
|
||||
if (spec[k].vacances>0 && spec[k].leg>0)
|
||||
if (spec[k].vacances>0 && (spec[k].leg>0 || pc->getParentClass()))
|
||||
throw std::exception("Det går endast att sätta in vakanser på sträcka 1.");
|
||||
|
||||
if (size_t(spec[k].leg) < pc->legInfo.size()) {
|
||||
pc->legInfo[spec[k].leg].startMethod = STDrawn; //Automatically change start method
|
||||
}
|
||||
else if (spec[k].leg == -1) {
|
||||
for (size_t j = 0; j < pc->legInfo.size(); j++)
|
||||
pc->legInfo[j].startMethod = STDrawn; //Automatically change start method
|
||||
}
|
||||
clsId2Ix[spec[k].classID] = k;
|
||||
if (!multiDay && spec[k].leg == 0)
|
||||
if (!multiDay && spec[k].leg == 0 && pc->getParentClass() == 0)
|
||||
clsIdClearVac.insert(spec[k].classID);
|
||||
}
|
||||
|
||||
@ -709,7 +713,7 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
||||
vector<int> toRemove;
|
||||
//Remove old vacances
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (clsIdClearVac.count(it->getClassId())) {
|
||||
if (clsIdClearVac.count(it->getClassId(true))) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (it->tInTeam)
|
||||
@ -734,11 +738,12 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
||||
}
|
||||
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!it->isRemoved() && clsId2Ix.count(it->getClassId())) {
|
||||
int cid = it->getClassId(true);
|
||||
if (!it->isRemoved() && clsId2Ix.count(cid)) {
|
||||
if (it->getStatus() == StatusNotCompetiting)
|
||||
continue;
|
||||
int ix = clsId2Ix[it->getClassId()];
|
||||
if (it->legToRun() == spec[ix].leg ) {
|
||||
int ix = clsId2Ix[cid];
|
||||
if (it->legToRun() == spec[ix].leg || spec[ix].leg == -1) {
|
||||
runners.push_back(&*it);
|
||||
spec[ix].ntimes++;
|
||||
}
|
||||
@ -753,12 +758,12 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
||||
int baseInterval = 10*60;
|
||||
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!it->isRemoved() && clsId2Ix.count(it->getClassId())) {
|
||||
if (!it->isRemoved() && clsId2Ix.count(it->getClassId(true))) {
|
||||
if (it->getStatus() == StatusNotCompetiting)
|
||||
continue;
|
||||
|
||||
int st = it->getStartTime();
|
||||
int ix = clsId2Ix[it->getClassId()];
|
||||
int ix = clsId2Ix[it->getClassId(false)];
|
||||
|
||||
if (st>0) {
|
||||
first[ix] = min(first[ix], st);
|
||||
@ -839,7 +844,6 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
||||
nextFreeStartNo = max<int>(nextFreeStartNo, minStartNo + stimes.size());
|
||||
}
|
||||
|
||||
|
||||
void getLargestClub(map<int, vector<pRunner> > &clubRunner, vector<pRunner> &largest)
|
||||
{
|
||||
size_t maxClub=0;
|
||||
@ -1176,7 +1180,7 @@ void oEvent::automaticDrawAll(gdioutput &gdi, const wstring &firstStart,
|
||||
continue;
|
||||
if (it->tLeg != leg)
|
||||
continue;
|
||||
if (it->isVacant() && notDrawn.count(it->getClassId())==1)
|
||||
if (it->isVacant() && notDrawn.count(it->getClassId(false))==1)
|
||||
continue;
|
||||
pClass pc = it->Class;
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo)
|
||||
|
||||
for (it=Runners.begin(); it!=Runners.end(); ++it) {
|
||||
int st = 0;
|
||||
if (controlIdFrom > 0) {
|
||||
if (controlIdFrom > 0 && controlIdFrom != oPunch::PunchStart) {
|
||||
RunnerStatus stat;
|
||||
it->getSplitTime(controlIdFrom, stat, st);
|
||||
if (stat != StatusOK) {
|
||||
@ -56,7 +56,7 @@ void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (controlIdTo == 0) {
|
||||
if (controlIdTo == 0 || controlIdTo == oPunch::PunchFinish) {
|
||||
it->tempRT = max(0, it->FinishTime - (st + it->tStartTime) );
|
||||
if (it->tempRT > 0)
|
||||
it->tempRT += it->getTimeAdjustment();
|
||||
@ -79,8 +79,8 @@ void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo)
|
||||
int cTime=0;
|
||||
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (it->getClassId()!=cClassId){
|
||||
cClassId=it->getClassId();
|
||||
if (it->getClassId(true)!=cClassId){
|
||||
cClassId=it->getClassId(true);
|
||||
cPlace=0;
|
||||
vPlace=0;
|
||||
cTime=0;
|
||||
@ -105,7 +105,7 @@ void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo)
|
||||
}
|
||||
}
|
||||
|
||||
void oEvent::calculateResults(ResultType resultType) {
|
||||
void oEvent::calculateResults(ResultType resultType, bool includePreliminary) {
|
||||
const bool totalResults = resultType == RTTotalResult;
|
||||
const bool courseResults = resultType == RTCourseResult;
|
||||
const bool classCourseResults = resultType == RTClassCourseResult;
|
||||
@ -135,7 +135,7 @@ void oEvent::calculateResults(ResultType resultType) {
|
||||
// Start new "class"
|
||||
if (classCourseResults) {
|
||||
const pCourse crs = it->getCourse(false);
|
||||
int crsId = it->getClassId() * 997 + (crs ? crs->getId() : 0);
|
||||
int crsId = it->getClassId(true) * 997 + (crs ? crs->getId() : 0);
|
||||
if (crsId != cClassId) {
|
||||
cClassId = crsId;
|
||||
cPlace=0;
|
||||
@ -156,8 +156,8 @@ void oEvent::calculateResults(ResultType resultType) {
|
||||
cTime=0;
|
||||
}
|
||||
}
|
||||
else if (it->getClassId() != cClassId || it->tDuplicateLeg!=cDuplicateLeg || it->tLegEquClass != cLegEquClass) {
|
||||
cClassId=it->getClassId();
|
||||
else if (it->getClassId(true) != cClassId || it->tDuplicateLeg!=cDuplicateLeg || it->tLegEquClass != cLegEquClass) {
|
||||
cClassId=it->getClassId(true);
|
||||
useResults = it->Class ? !it->Class->getNoTiming() : false;
|
||||
cPlace=0;
|
||||
vPlace=0;
|
||||
@ -176,7 +176,7 @@ void oEvent::calculateResults(ResultType resultType) {
|
||||
else if (!totalResults) {
|
||||
int tPlace = 0;
|
||||
|
||||
if (it->tStatus==StatusOK){
|
||||
if (it->tStatus==StatusOK || (includePreliminary && it->tStatus == StatusUnknown && it->FinishTime > 0)){
|
||||
cPlace++;
|
||||
|
||||
int rt = it->getRunningTime() + it->getNumShortening() * 3600 * 24* 8;
|
||||
@ -200,7 +200,8 @@ void oEvent::calculateResults(ResultType resultType) {
|
||||
else {
|
||||
int tt = it->getTotalRunningTime(it->FinishTime, true);
|
||||
|
||||
if (it->getTotalStatus() == StatusOK && tt>0) {
|
||||
RunnerStatus totStat = it->getTotalStatus();
|
||||
if (totStat == StatusOK || (includePreliminary && totStat == StatusUnknown) && tt>0) {
|
||||
cPlace++;
|
||||
|
||||
if (tt > cTime)
|
||||
@ -236,8 +237,8 @@ void oEvent::calculateRogainingResults() {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
|
||||
if (it->getClassId()!=cClassId || it->tDuplicateLeg!=cDuplicateLeg) {
|
||||
cClassId = it->getClassId();
|
||||
if (it->getClassId(true)!=cClassId || it->tDuplicateLeg!=cDuplicateLeg) {
|
||||
cClassId = it->getClassId(true);
|
||||
useResults = it->Class ? !it->Class->getNoTiming() : false;
|
||||
cPlace = 0;
|
||||
vPlace = 0;
|
||||
@ -515,3 +516,81 @@ void oEvent::getGeneralResults(bool onlyEditable, vector< pair<int, pair<string,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TeamResultContainer {
|
||||
pTeam team;
|
||||
int runningTime;
|
||||
RunnerStatus status;
|
||||
|
||||
bool operator<(const TeamResultContainer &o) const {
|
||||
|
||||
pClass cls = team->getClassRef(false);
|
||||
pClass ocls = o.team->getClassRef(false);
|
||||
|
||||
if (cls != ocls) {
|
||||
int so = cls ? cls->getSortIndex() : 0;
|
||||
int oso = ocls ? ocls->getSortIndex() : 0;
|
||||
if (so != oso)
|
||||
return so < oso;
|
||||
}
|
||||
|
||||
if (status != o.status)
|
||||
return status < o.status;
|
||||
|
||||
if (runningTime != o.runningTime)
|
||||
return runningTime < o.runningTime;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void oEvent::calculateTeamResultAtControl(const set<int> &classId, int leg, int courseControlId, bool totalResults) {
|
||||
vector<TeamResultContainer> objs;
|
||||
objs.reserve(Teams.size());
|
||||
oSpeakerObject temp;
|
||||
for (auto &t : Teams) {
|
||||
if (t.isRemoved())
|
||||
continue;
|
||||
|
||||
if (!classId.empty() && !classId.count(t.getClassId(false)))
|
||||
continue;
|
||||
temp.reset();
|
||||
t.fillSpeakerObject(leg, courseControlId, -1, totalResults, temp);
|
||||
if (!temp.owner)
|
||||
continue;
|
||||
TeamResultContainer trc;
|
||||
trc.runningTime = temp.runningTime.time;
|
||||
trc.status = temp.status;
|
||||
trc.team = &t;
|
||||
objs.push_back(trc);
|
||||
}
|
||||
|
||||
sort(objs.begin(), objs.end());
|
||||
|
||||
int cClass = -1;
|
||||
int cPlace = -1;
|
||||
int placeCounter = -1;
|
||||
int cTime = 0;
|
||||
for (size_t i = 0; i < objs.size(); i++) {
|
||||
pTeam team = objs[i].team;
|
||||
int c = team->getClassId(false);
|
||||
if (c != cClass) {
|
||||
cClass = c;
|
||||
placeCounter = 1;
|
||||
cTime = -1;
|
||||
}
|
||||
else {
|
||||
placeCounter++;
|
||||
}
|
||||
|
||||
if (cTime != objs[i].runningTime) {
|
||||
cPlace = placeCounter;
|
||||
}
|
||||
|
||||
team->tmpResult.startTime = team->getStartTime();
|
||||
team->tmpResult.status = objs[i].status;
|
||||
team->tmpResult.runningTime = objs[i].runningTime;
|
||||
team->tmpResult.place = objs[i].status == StatusOK ? cPlace : 0;
|
||||
team->tmpResult.points = 0; // Not supported
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,6 +251,7 @@ bool oEvent::synchronizeList(oListId id, bool preSyncEvent, bool postSyncEvent)
|
||||
advanceInformationPunches.clear();
|
||||
|
||||
if (postSyncEvent) {
|
||||
reinitializeClasses();
|
||||
reEvaluateChanged();
|
||||
resetChangeStatus();
|
||||
return true;
|
||||
|
||||
@ -561,7 +561,7 @@ void oEvent::speakerList(gdioutput &gdi, int ClassId, int leg, int ControlId,
|
||||
if (classHasTeams(ClassId)) {
|
||||
oTeamList::iterator it=Teams.begin();
|
||||
while(it!=Teams.end()){
|
||||
if (it->getClassId()==ClassId && !it->skip()) {
|
||||
if (it->getClassId(true)==ClassId && !it->skip()) {
|
||||
oSpeakerObject so;
|
||||
it->fillSpeakerObject(leg, ControlId, PreviousControlId, totalResults, so);
|
||||
if (so.owner)
|
||||
@ -571,15 +571,23 @@ void oEvent::speakerList(gdioutput &gdi, int ClassId, int leg, int ControlId,
|
||||
}
|
||||
}
|
||||
else {
|
||||
oRunnerList::iterator it=Runners.begin();
|
||||
while(it!=Runners.end()){
|
||||
if (it->getClassId()==ClassId && !it->skip()) {
|
||||
pClass pc = getClass(ClassId);
|
||||
bool qfBaseClass = pc && pc->getQualificationFinal();
|
||||
bool qfFinalClass = pc && pc->getParentClass();
|
||||
|
||||
if (qfBaseClass || qfFinalClass)
|
||||
leg = 0;
|
||||
|
||||
for(auto &it : Runners){
|
||||
if (it.getClassId(true) == ClassId && !it.isRemoved()) {
|
||||
if (qfBaseClass && it.getLegNumber() > 0)
|
||||
continue;
|
||||
|
||||
oSpeakerObject so;
|
||||
it->fillSpeakerObject(leg, ControlId, PreviousControlId, totalResults, so);
|
||||
it.fillSpeakerObject(leg, ControlId, PreviousControlId, totalResults, so);
|
||||
if (so.owner)
|
||||
speakerList.push_back(so);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (speakerList.empty()) {
|
||||
@ -1089,9 +1097,9 @@ int oEvent::setupTimeLineEvents(int classId, int currentTime)
|
||||
if (false && startTimes.size() == 1) {
|
||||
oRunner &r = *started[firstNonEmpty][0];
|
||||
|
||||
oTimeLine tl(r.tStartTime, oTimeLine::TLTStart, oTimeLine::PHigh, r.getClassId(), 0, 0);
|
||||
oTimeLine tl(r.tStartTime, oTimeLine::TLTStart, oTimeLine::PHigh, r.getClassId(true), 0, 0);
|
||||
TimeLineIterator it = timeLineEvents.insert(pair<int, oTimeLine>(r.tStartTime, tl));
|
||||
it->second.setMessage(L"X har startat.#" + r.getClass());
|
||||
it->second.setMessage(L"X har startat.#" + r.getClass(true));
|
||||
}
|
||||
else {
|
||||
for (size_t j = 0; j<started.size(); j++) {
|
||||
@ -1106,15 +1114,15 @@ int oEvent::setupTimeLineEvents(int classId, int currentTime)
|
||||
prio = oTimeLine::PHigh;
|
||||
else if (p == 1)
|
||||
prio = oTimeLine::PMedium;
|
||||
oTimeLine tl(r.tStartTime, oTimeLine::TLTStart, prio, r.getClassId(), r.getId(), &r);
|
||||
oTimeLine tl(r.tStartTime, oTimeLine::TLTStart, prio, r.getClassId(true), r.getId(), &r);
|
||||
TimeLineIterator it = timeLineEvents.insert(pair<int, oTimeLine>(r.tStartTime + 1, tl));
|
||||
it->second.setMessage(L"har startat.");
|
||||
}
|
||||
else if (!startedClass) {
|
||||
// The entire class started
|
||||
oTimeLine tl(r.tStartTime, oTimeLine::TLTStart, oTimeLine::PHigh, r.getClassId(), 0, 0);
|
||||
oTimeLine tl(r.tStartTime, oTimeLine::TLTStart, oTimeLine::PHigh, r.getClassId(true), 0, 0);
|
||||
TimeLineIterator it = timeLineEvents.insert(pair<int, oTimeLine>(r.tStartTime, tl));
|
||||
it->second.setMessage(L"X har startat.#" + r.getClass());
|
||||
it->second.setMessage(L"X har startat.#" + r.getClass(true));
|
||||
startedClass = true;
|
||||
}
|
||||
}
|
||||
@ -1203,7 +1211,7 @@ void oEvent::timeLinePrognose(TempResultMap &results, TimeRunner &tr, int prelT,
|
||||
else if (p>6 + prio * 5)
|
||||
mp = oTimeLine::PLow;
|
||||
|
||||
oTimeLine tl(tr.time, oTimeLine::TLTExpected, mp, tr.runner->getClassId(), radioId, tr.runner);
|
||||
oTimeLine tl(tr.time, oTimeLine::TLTExpected, mp, tr.runner->getClassId(true), radioId, tr.runner);
|
||||
TimeLineIterator tlit = timeLineEvents.insert(pair<int, oTimeLine>(tl.getTime(), tl));
|
||||
tlit->second.setMessage(msg);
|
||||
}
|
||||
@ -1411,7 +1419,7 @@ int oEvent::setupTimeLineEvents(vector<pRunner> &started, const vector< pair<int
|
||||
else if (place <= 10)
|
||||
mp = oTimeLine::PMedium;
|
||||
|
||||
oTimeLine tl(radio[k].time, oTimeLine::TLTRadio, mp, r.getClassId(), rc[j].first, &r);
|
||||
oTimeLine tl(radio[k].time, oTimeLine::TLTRadio, mp, r.getClassId(true), rc[j].first, &r);
|
||||
TimeLineIterator tlit = timeLineEvents.insert(pair<int, oTimeLine>(tl.getTime(), tl));
|
||||
tlit->second.setMessage(msg).setDetail(detail);
|
||||
}
|
||||
@ -1509,7 +1517,7 @@ int oEvent::setupTimeLineEvents(vector<pRunner> &started, const vector< pair<int
|
||||
else if (place <= 20)
|
||||
mp = oTimeLine::PMedium;
|
||||
|
||||
oTimeLine tl(r.FinishTime, oTimeLine::TLTFinish, mp, r.getClassId(), r.getId(), &r);
|
||||
oTimeLine tl(r.FinishTime, oTimeLine::TLTFinish, mp, r.getClassId(true), r.getId(), &r);
|
||||
TimeLineIterator tlit = timeLineEvents.insert(pair<int, oTimeLine>(tl.getTime(), tl));
|
||||
tlit->second.setMessage(msg).setDetail(detail);
|
||||
}
|
||||
@ -1535,7 +1543,7 @@ int oEvent::setupTimeLineEvents(vector<pRunner> &started, const vector< pair<int
|
||||
else if (place <= 20)
|
||||
mp = oTimeLine::PMedium;
|
||||
|
||||
oTimeLine tl(r.FinishTime, oTimeLine::TLTFinish, mp, r.getClassId(), r.getId(), &r);
|
||||
oTimeLine tl(r.FinishTime, oTimeLine::TLTFinish, mp, r.getClassId(true), r.getId(), &r);
|
||||
TimeLineIterator tlit = timeLineEvents.insert(pair<int, oTimeLine>(t, tl));
|
||||
wstring msg;
|
||||
if (r.getStatus() != StatusDQ)
|
||||
@ -1558,7 +1566,7 @@ void oEvent::renderTimeLineEvents(gdioutput &gdi) const
|
||||
wstring msg = t>0 ? getAbsTime(t) : makeDash(L"--:--:--");
|
||||
oAbstractRunner *r = it->second.getSource(*this);
|
||||
if (r) {
|
||||
msg += L" (" + r->getClass() + L") ";
|
||||
msg += L" (" + r->getClass(true) + L") ";
|
||||
msg += r->getName() + L", " + r->getClub();
|
||||
}
|
||||
msg += L", " + lang.tl(it->second.getMessage());
|
||||
@ -1676,7 +1684,7 @@ void oEvent::getResultEvents(const set<int> &classFilter, const set<int> &punchF
|
||||
teamLegStatusOK.reserve(Teams.size() * 5);
|
||||
map<int, int> teamStatusPos;
|
||||
for (oTeamList::const_iterator it = Teams.begin(); it != Teams.end(); ++it) {
|
||||
if (!classFilter.count(it->getClassId()))
|
||||
if (!classFilter.count(it->getClassId(false)))
|
||||
continue;
|
||||
|
||||
int base = teamLegStatusOK.size();
|
||||
@ -1699,7 +1707,7 @@ void oEvent::getResultEvents(const set<int> &classFilter, const set<int> &punchF
|
||||
|
||||
for (oRunnerList::const_iterator it = Runners.begin(); it != Runners.end(); ++it) {
|
||||
const oRunner &r = *it;
|
||||
if (r.isRemoved() || !classFilter.count(r.getClassId()))
|
||||
if (r.isRemoved() || !classFilter.count(r.getClassId(true)))
|
||||
continue;
|
||||
if (r.prelStatusOK() || r.getStatus() != StatusUnknown) {
|
||||
RunnerStatus stat = r.prelStatusOK() ? StatusOK : r.getStatus();
|
||||
@ -1738,7 +1746,7 @@ void oEvent::getResultEvents(const set<int> &classFilter, const set<int> &punchF
|
||||
continue;
|
||||
|
||||
pRunner r = getRunner(fp.tRunnerId, 0);
|
||||
if (r == 0 || !classFilter.count(r->getClassId()) || r->getCard())
|
||||
if (r == 0 || !classFilter.count(r->getClassId(true)) || r->getCard())
|
||||
continue;
|
||||
|
||||
int courseControlId = oFreePunch::getControlIdFromHash(fp.iHashType, true);
|
||||
@ -1766,7 +1774,7 @@ void oEvent::getResultEvents(const set<int> &classFilter, const set<int> &punchF
|
||||
if (fp.isRemoved() || fp.tRunnerId == 0 || fp.Type == oPunch::PunchCheck || fp.Type == oPunch::PunchStart)
|
||||
continue;
|
||||
pRunner r = getRunner(fp.tRunnerId, 0);
|
||||
if (r == 0 || !classFilter.count(r->getClassId()))
|
||||
if (r == 0 || !classFilter.count(r->getClassId(true)))
|
||||
continue;
|
||||
int courseControlId = oFreePunch::getControlIdFromHash(fp.iHashType, true);
|
||||
int ctrl = oControl::getIdIndexFromCourseControlId(courseControlId).first;
|
||||
|
||||
@ -1037,7 +1037,7 @@ void oFreeImport::test(const oRunnerList &li)
|
||||
givenDB.insert(it->getGivenName().c_str());
|
||||
familyDB.insert(it->getFamilyName().c_str());
|
||||
clubDB.insert(it->getClub().c_str());
|
||||
classDB.insert(it->getClass().c_str());
|
||||
classDB.insert(it->getClass(true).c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -475,14 +475,14 @@ pFreePunch oEvent::addFreePunch(int time, int type, int card, bool updateStartFi
|
||||
if (tr && tr->getStatus() == StatusUnknown && time > 0) {
|
||||
tr->synchronize();
|
||||
if (type == oPunch::PunchStart) {
|
||||
if (tr->getClassRef() && !tr->getClassRef()->ignoreStartPunch())
|
||||
if (tr->getClassRef(false) && !tr->getClassRef(true)->ignoreStartPunch())
|
||||
tr->setStartTime(time, true, false);
|
||||
}
|
||||
else
|
||||
tr->setFinishTime(time);
|
||||
|
||||
// Direct result
|
||||
if (type == oPunch::PunchFinish && tr->getClassRef() && tr->getClassRef()->hasDirectResult()) {
|
||||
if (type == oPunch::PunchFinish && tr->getClassRef(false) && tr->getClassRef(true)->hasDirectResult()) {
|
||||
if (tr->getCourse(false) == 0 && tr->getCard() == 0) {
|
||||
tr->setStatus(StatusOK, true, false, true);
|
||||
}
|
||||
|
||||
@ -218,9 +218,9 @@ bool oEvent::exportOECSV(const wchar_t *file, int languageTypeIndex, bool includ
|
||||
row[OEclubcity] = gdibase.recodeToNarrow(it->getClub());
|
||||
}
|
||||
row[OEnat] = gdibase.recodeToNarrow(di.getString("Nationality"));
|
||||
row[OEclassno] = conv_is(it->getClassId());
|
||||
row[OEclassshortname] = gdibase.recodeToNarrow(it->getClass());
|
||||
row[OEclassname] = gdibase.recodeToNarrow(it->getClass());
|
||||
row[OEclassno] = conv_is(it->getClassId(true));
|
||||
row[OEclassshortname] = gdibase.recodeToNarrow(it->getClass(true));
|
||||
row[OEclassname] = gdibase.recodeToNarrow(it->getClass(true));
|
||||
|
||||
row[OErent] = conv_is(di.getInt("CardFee"));
|
||||
row[OEfee] = conv_is(di.getInt("Fee"));
|
||||
@ -300,7 +300,7 @@ void oEvent::importXML_EntryData(gdioutput &gdi, const wstring &file,
|
||||
vector< pair<int, int> > runnersInTeam;
|
||||
for (oRunnerList::iterator it = Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!it->isRemoved() && it->tInTeam) {
|
||||
runnersInTeam.push_back(make_pair(it->getId(), it->getClassId()) );
|
||||
runnersInTeam.push_back(make_pair(it->getId(), it->getClassId(false)) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,7 +597,7 @@ void oEvent::importXML_EntryData(gdioutput &gdi, const wstring &file,
|
||||
int id = runnersInTeam[k].first;
|
||||
int classId = runnersInTeam[k].second;
|
||||
pRunner r = getRunner(id, 0);
|
||||
if (r && !r->tInTeam && r->getClassId() == classId) {
|
||||
if (r && !r->tInTeam && r->getClassId(false) == classId) {
|
||||
toRemove.push_back(r->getId());
|
||||
}
|
||||
}
|
||||
@ -2048,7 +2048,7 @@ void oClass::exportIOFStart(xmlparser &xml) {
|
||||
|
||||
if (getClassType() == oClassIndividual || getClassType() == oClassIndividRelay) {
|
||||
for (oRunnerList::iterator it = oe->Runners.begin(); it!=oe->Runners.end(); ++it) {
|
||||
if (it->getClassId() != getId() || it->isRemoved())
|
||||
if (it->getClassId(true) != getId() || it->isRemoved())
|
||||
continue;
|
||||
|
||||
xml.startTag("PersonStart");
|
||||
@ -2096,7 +2096,7 @@ void oClass::exportIOFStart(xmlparser &xml) {
|
||||
bool writeTeamName = !useEventor || getClassType() != oClassPatrol;
|
||||
|
||||
for (oTeamList::iterator it = oe->Teams.begin(); it!=oe->Teams.end(); ++it) {
|
||||
if (it->getClassId() != getId() || it->isRemoved())
|
||||
if (it->getClassId(true) != getId() || it->isRemoved())
|
||||
continue;
|
||||
|
||||
xml.startTag("TeamStart");
|
||||
@ -2218,7 +2218,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (it->Runners.size()>=2 && it->Runners[0] && it->Runners[1]) {
|
||||
if (it->getClassId()!=Id) {
|
||||
if (it->getClassId(true)!=Id) {
|
||||
if (ClassStarted) xml.endTag();
|
||||
|
||||
if (!it->Class || it->Class->getClassType()!=oClassPatrol) {
|
||||
@ -2227,7 +2227,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!classes.empty() && classes.count(it->getClassId()) == 0) || leg != -1) {
|
||||
if ((!classes.empty() && classes.count(it->getClassId(true)) == 0) || leg != -1) {
|
||||
skipClass=true;
|
||||
ClassStarted=false;
|
||||
continue;
|
||||
@ -2236,9 +2236,9 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
skipClass=false;
|
||||
xml.startTag("ClassResult");
|
||||
ClassStarted=true;
|
||||
Id=it->getClassId();
|
||||
Id=it->getClassId(true);
|
||||
|
||||
xml.write("ClassShortName", it->getClass());
|
||||
xml.write("ClassShortName", it->getClass(true));
|
||||
}
|
||||
|
||||
if (skipClass)
|
||||
@ -2315,7 +2315,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
if (it->isRemoved() || (leg != -1 && it->tLeg != leg) || it->isVacant())
|
||||
continue;
|
||||
|
||||
if (it->getClassId()!=Id) {
|
||||
if (it->getClassId(true)!=Id) {
|
||||
if (ClassStarted) xml.endTag();
|
||||
|
||||
if (!it->Class) {
|
||||
@ -2332,7 +2332,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( (!classes.empty() && classes.count(it->getClassId()) == 0) ) {
|
||||
if ( (!classes.empty() && classes.count(it->getClassId(true)) == 0) ) {
|
||||
skipClass=true;
|
||||
ClassStarted=false;
|
||||
continue;
|
||||
@ -2341,9 +2341,9 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
xml.startTag("ClassResult");
|
||||
ClassStarted=true;
|
||||
skipClass=false;
|
||||
Id=it->getClassId();
|
||||
Id=it->getClassId(true);
|
||||
|
||||
xml.write("ClassShortName", it->getClass());
|
||||
xml.write("ClassShortName", it->getClass(true));
|
||||
}
|
||||
|
||||
if (skipClass)
|
||||
@ -2419,7 +2419,7 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldS
|
||||
for(oTeamList::iterator it=Teams.begin(); it != Teams.end(); ++it) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (it->getClassId()!=Id) {
|
||||
if (it->getClassId(true)!=Id) {
|
||||
if (ClassStarted) {
|
||||
xml.endTag();
|
||||
ClassStarted = false;
|
||||
@ -2442,7 +2442,7 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldS
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!classes.empty() && classes.count(it->getClassId()) == 0) {
|
||||
if (!classes.empty() && classes.count(it->getClassId(true)) == 0) {
|
||||
skipClass=true;
|
||||
continue;
|
||||
}
|
||||
@ -2450,9 +2450,9 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldS
|
||||
skipClass=false;
|
||||
xml.startTag("ClassResult");
|
||||
ClassStarted=true;
|
||||
Id=it->getClassId();
|
||||
Id=it->getClassId(true);
|
||||
|
||||
xml.write("ClassShortName", it->getClass());
|
||||
xml.write("ClassShortName", it->getClass(true));
|
||||
}
|
||||
|
||||
if (skipClass)
|
||||
|
||||
@ -396,9 +396,9 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
||||
continue;
|
||||
|
||||
// Case when runner/team has different class
|
||||
bool teamOK = it->getTeam() && clsSel.count(it->getTeam()->getClassId());
|
||||
bool teamOK = it->getTeam() && clsSel.count(it->getTeam()->getClassId(false));
|
||||
|
||||
if (!clsSel.empty() && (!teamOK && clsSel.count(it->getClassId()) == 0))
|
||||
if (!clsSel.empty() && (!teamOK && clsSel.count(it->getClassId(true)) == 0))
|
||||
continue;
|
||||
|
||||
totWord.clear();
|
||||
@ -417,7 +417,7 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
||||
}
|
||||
rout.clear();
|
||||
while (numIter-- > 0) {
|
||||
const wstring &out = oe->formatListString(pp, par, it->tInTeam, pRunner(&*it), it->Club, it->Class, c);
|
||||
const wstring &out = oe->formatListString(pp, par, it->tInTeam, pRunner(&*it), it->Club, pClass(it->getClassRef(true)), c);
|
||||
//row[k] = max(row[k], int(out.length()));
|
||||
if (out.length() > rout.length())
|
||||
rout = out;
|
||||
@ -474,7 +474,7 @@ const wstring & oEvent::formatListString(EPostType type, const pRunner r) const
|
||||
oListParam par;
|
||||
par.setLegNumberCoded(r->tLeg);
|
||||
pp.type = type;
|
||||
return formatListString(pp, par, r->tInTeam, r, r->Club, r->Class, ctr);
|
||||
return formatListString(pp, par, r->tInTeam, r, r->Club, r->getClassRef(true), ctr);
|
||||
}
|
||||
|
||||
const wstring & oEvent::formatListString(EPostType type, const pRunner r,
|
||||
@ -485,7 +485,7 @@ const wstring & oEvent::formatListString(EPostType type, const pRunner r,
|
||||
par.setLegNumberCoded(r->tLeg);
|
||||
pp.type = type;
|
||||
pp.text = format;
|
||||
return formatListString(pp, par, r->tInTeam, r, r->Club, r->Class, ctr);
|
||||
return formatListString(pp, par, r->tInTeam, r, r->Club, r->getClassRef(true), ctr);
|
||||
}
|
||||
|
||||
|
||||
@ -572,16 +572,16 @@ const wstring &oEvent::formatSpecialStringAux(const oPrintPost &pp, const oListP
|
||||
break;
|
||||
|
||||
case lRunnerLegNumberAlpha:
|
||||
if (t && t->getClassRef() && legIndex >= 0) {
|
||||
wstring legStr = t->getClassRef()->getLegNumber(legIndex);
|
||||
if (t && t->getClassRef(false) && legIndex >= 0) {
|
||||
wstring legStr = t->getClassRef(false)->getLegNumber(legIndex);
|
||||
wcscpy_s(bfw, legStr.c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case lRunnerLegNumber:
|
||||
if (t && t->getClassRef() && legIndex >= 0) {
|
||||
if (t && t->getClassRef(false) && legIndex >= 0) {
|
||||
int legNumber, legOrder;
|
||||
t->getClassRef()->splitLegNumberParallel(legIndex, legNumber, legOrder);
|
||||
t->getClassRef(false)->splitLegNumberParallel(legIndex, legNumber, legOrder);
|
||||
wsptr = &itow(legNumber+1);
|
||||
}
|
||||
break;
|
||||
@ -727,7 +727,7 @@ const wstring &oEvent::formatSpecialStringAux(const oPrintPost &pp, const oListP
|
||||
try {
|
||||
const wstring &res = formatListStringAux(pp, par, t, t ? t->getRunner(legIndex) : 0,
|
||||
t ? t->getClubRef() : 0,
|
||||
t ? t->getClassRef() : 0, counter);
|
||||
t ? t->getClassRef(false) : 0, counter);
|
||||
reentrantLock = false;
|
||||
return res;
|
||||
}
|
||||
@ -928,7 +928,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
||||
if (t) {
|
||||
pRunner r1 = t->getRunner(0);
|
||||
pRunner r2 = t->getRunner(1);
|
||||
if (r1 && r2) {
|
||||
if (r1 && r2 && r2->tParentRunner != r1) {
|
||||
swprintf_s(wbf, L"%s / %s", r1->getName().c_str(),r2->getName().c_str());
|
||||
}
|
||||
else if (r1) {
|
||||
@ -1375,7 +1375,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
||||
break;
|
||||
|
||||
case lRunnerCard:
|
||||
if (r && r->CardNo > 0)
|
||||
if (r && r->getCardNo() > 0)
|
||||
swprintf_s(wbf, L"%d", r->getCardNo());
|
||||
break;
|
||||
case lRunnerRank:
|
||||
@ -2212,7 +2212,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
if (it->isRemoved() || it->tStatus == StatusNotCompetiting)
|
||||
continue;
|
||||
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId())==0)
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId(false))==0)
|
||||
continue;
|
||||
it->apply(false, 0, true);
|
||||
}
|
||||
@ -2263,11 +2263,10 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
if (it->isRemoved() || it->tStatus == StatusNotCompetiting)
|
||||
continue;
|
||||
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId())==0)
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId(true))==0)
|
||||
continue;
|
||||
|
||||
//if (it->legToRun() != li.lp.legNumber && li.lp.legNumber!=-1)
|
||||
if (!li.lp.matchLegNumber(it->getClassRef(), it->legToRun()))
|
||||
if (!li.lp.matchLegNumber(it->getClassRef(false), it->legToRun()))
|
||||
continue;
|
||||
|
||||
if (li.filter(EFilterExcludeDNS))
|
||||
@ -2348,29 +2347,29 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
|
||||
wstring newKey;
|
||||
printPostInfo.par.relayLegIndex = -1;
|
||||
calculatePrintPostKey(li.subHead, gdi, li.lp, it->tInTeam, &*it, it->Club, it->Class, printPostInfo.counter, newKey);
|
||||
calculatePrintPostKey(li.subHead, gdi, li.lp, it->tInTeam, &*it, it->Club, it->getClassRef(true), printPostInfo.counter, newKey);
|
||||
|
||||
if (newKey != oldKey) {
|
||||
if (li.lp.pageBreak) {
|
||||
if (!oldKey.empty())
|
||||
gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, "");
|
||||
}
|
||||
gdi.addStringUT(pagePageInfo, it->getClass());
|
||||
gdi.addStringUT(pagePageInfo, it->getClass(true));
|
||||
|
||||
oldKey.swap(newKey);
|
||||
printPostInfo.counter.level2=0;
|
||||
printPostInfo.counter.level3=0;
|
||||
printPostInfo.reset();
|
||||
printPostInfo.par.relayLegIndex = -1;
|
||||
formatPrintPost(li.subHead, printPostInfo, it->tInTeam, &*it, it->Club, it->Class, 0, 0, -1);
|
||||
formatPrintPost(li.subHead, printPostInfo, it->tInTeam, &*it, it->Club, it->getClassRef(true), 0, 0, -1);
|
||||
}
|
||||
if (li.lp.filterMaxPer==0 || printPostInfo.counter.level2<li.lp.filterMaxPer) {
|
||||
printPostInfo.reset();
|
||||
printPostInfo.par.relayLegIndex = it->tLeg;
|
||||
formatPrintPost(li.listPost, printPostInfo, it->tInTeam, &*it, it->Club, it->Class, 0, 0, -1);
|
||||
formatPrintPost(li.listPost, printPostInfo, it->tInTeam, &*it, it->Club, it->getClassRef(true), 0, 0, -1);
|
||||
|
||||
if (li.listSubType==li.EBaseTypePunches) {
|
||||
listGeneratePunches(li.subListPost, gdi, li.lp, it->tInTeam, &*it, it->Club, it->Class);
|
||||
listGeneratePunches(li.subListPost, gdi, li.lp, it->tInTeam, &*it, it->Club, it->getClassRef(true));
|
||||
}
|
||||
}
|
||||
++printPostInfo.counter;
|
||||
@ -2397,7 +2396,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
if (it->isRemoved() || it->tStatus == StatusNotCompetiting)
|
||||
continue;
|
||||
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId())==0)
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId(true))==0)
|
||||
continue;
|
||||
tlist.push_back(&*it);
|
||||
}
|
||||
@ -2416,7 +2415,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
|
||||
for (size_t k = 0; k < tlist.size(); k++) {
|
||||
pTeam it = tlist[k];
|
||||
int linearLegSpec = li.lp.getLegNumber(it->getClassRef());
|
||||
int linearLegSpec = li.lp.getLegNumber(it->getClassRef(false));
|
||||
|
||||
if (gResult && it->getTempResult(0).getStatus() == StatusNotCompetiting)
|
||||
continue;
|
||||
@ -2475,12 +2474,12 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, "");
|
||||
}
|
||||
wstring legInfo;
|
||||
if (linearLegSpec >= 0 && it->getClassRef()) {
|
||||
if (linearLegSpec >= 0 && it->getClassRef(false)) {
|
||||
// Specified leg
|
||||
legInfo = lang.tl(L", Str. X#" + li.lp.getLegName());
|
||||
}
|
||||
|
||||
gdi.addStringUT(pagePageInfo, it->getClass() + legInfo); // Teamlist
|
||||
gdi.addStringUT(pagePageInfo, it->getClass(true) + legInfo); // Teamlist
|
||||
|
||||
oldKey.swap(newKey);
|
||||
printPostInfo.counter.level2=0;
|
||||
@ -2561,7 +2560,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
printPostInfo.keepToghether = suitableBreak;
|
||||
printPostInfo.par.relayLegIndex = tr[k] ? tr[k]->tLeg : -1;
|
||||
formatPrintPost(li.subListPost, printPostInfo, &*it, tr[k],
|
||||
it->Club, tr[k]->Class, 0, 0, -1);
|
||||
it->Club, tr[k]->getClassRef(true), 0, 0, -1);
|
||||
printPostInfo.counter.level3++;
|
||||
}
|
||||
}
|
||||
@ -2579,7 +2578,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
}
|
||||
else {
|
||||
formatPrintPost(li.subListPost, printPostInfo, &*it, tr[usedIx[k]],
|
||||
it->Club, tr[usedIx[k]]->Class, 0, 0, -1);
|
||||
it->Club, tr[usedIx[k]]->getClassRef(true), 0, 0, -1);
|
||||
}
|
||||
printPostInfo.counter.level3++;
|
||||
}
|
||||
@ -2632,16 +2631,15 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
}
|
||||
|
||||
bool startClub = false;
|
||||
pRunner pLeader = 0;
|
||||
|
||||
for (rit = Runners.begin(); rit != Runners.end(); ++rit) {
|
||||
if (rit->isRemoved() || rit->tStatus == StatusNotCompetiting)
|
||||
continue;
|
||||
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(rit->getClassId())==0)
|
||||
if (!li.lp.selection.empty() && li.lp.selection.count(rit->getClassId(true))==0)
|
||||
continue;
|
||||
|
||||
if (!li.lp.matchLegNumber(rit->getClassRef(), rit->legToRun()))
|
||||
if (!li.lp.matchLegNumber(rit->getClassRef(false), rit->legToRun()))
|
||||
continue;
|
||||
|
||||
if (li.filter(EFilterExcludeDNS))
|
||||
@ -2657,8 +2655,6 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pLeader || pLeader->Class != rit->Class)
|
||||
pLeader = &*rit;
|
||||
if (rit->Club == &*it) {
|
||||
if (!startClub) {
|
||||
if (li.lp.pageBreak) {
|
||||
@ -2680,7 +2676,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
printPostInfo.counter.level3=0;
|
||||
printPostInfo.reset();
|
||||
printPostInfo.par.relayLegIndex = rit->tLeg;
|
||||
formatPrintPost(li.listPost, printPostInfo, 0, &*rit, &*it, rit->Class, 0, 0, -1);
|
||||
formatPrintPost(li.listPost, printPostInfo, 0, &*rit, &*it, rit->getClassRef(true), 0, 0, -1);
|
||||
if (li.subListPost.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -294,6 +294,24 @@ class MetaListContainer;
|
||||
|
||||
struct oListParam {
|
||||
oListParam();
|
||||
|
||||
bool operator==(const oListParam& a) const {
|
||||
return a.listCode == listCode &&
|
||||
a.selection == selection &&
|
||||
a.useControlIdResultFrom == useControlIdResultFrom &&
|
||||
a.useControlIdResultTo == useControlIdResultTo &&
|
||||
a.filterMaxPer == filterMaxPer &&
|
||||
a.pageBreak == pageBreak &&
|
||||
a.showInterTimes == showInterTimes &&
|
||||
a.showSplitTimes == showSplitTimes &&
|
||||
a.inputNumber == inputNumber &&
|
||||
a.nextList == nextList &&
|
||||
a.previousList == previousList &&
|
||||
a.bgColor == bgColor &&
|
||||
a.bgColor2 == bgColor2 &&
|
||||
a.bgImage == bgImage &&
|
||||
a.legNumber == legNumber;
|
||||
}
|
||||
EStdListType listCode;
|
||||
GUICALLBACK cb;
|
||||
set<int> selection;
|
||||
@ -389,6 +407,7 @@ public:
|
||||
Global,
|
||||
Classwise,
|
||||
Legwise,
|
||||
Coursewise
|
||||
};
|
||||
|
||||
static bool addRunners(EBaseType t) {return t == EBaseTypeRunner || t == EBaseTypeClub;}
|
||||
|
||||
@ -405,7 +405,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
no_club.push_back(&*r_it);
|
||||
}
|
||||
|
||||
if (r_it->getClassId()==0)
|
||||
if (r_it->getClassId(false)==0)
|
||||
no_class.push_back(&*r_it);
|
||||
else if (needCourse && r_it->getCourse(false)==0)
|
||||
no_course.push_back(&*r_it);
|
||||
@ -481,7 +481,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
while(!no_course.empty() && ++i<20){
|
||||
pRunner r=no_course.front();
|
||||
no_course.pop_front();
|
||||
wstring name = r->getClass() + L": " + r->getName();
|
||||
wstring name = r->getClass(true) + L": " + r->getName();
|
||||
if (!r->getClub().empty())
|
||||
name += L" ("+ r->getClub()+ L")";
|
||||
gdi.addStringUT(0, name);
|
||||
@ -497,7 +497,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
while(!no_club.empty() && ++i<20){
|
||||
pRunner r=no_club.front();
|
||||
no_club.pop_front();
|
||||
gdi.addStringUT(0, r->getClass() + L": " + r->getName());
|
||||
gdi.addStringUT(0, r->getClass(true) + L": " + r->getName());
|
||||
}
|
||||
if (!no_club.empty()) gdi.addStringUT(1, Ellipsis);
|
||||
}
|
||||
@ -510,7 +510,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
while(!no_start.empty() && ++i<20){
|
||||
pRunner r=no_start.front();
|
||||
no_start.pop_front();
|
||||
wstring name = r->getClass() + L": " + r->getName();
|
||||
wstring name = r->getClass(true) + L": " + r->getName();
|
||||
if (!r->getClub().empty())
|
||||
name += L" (" + r->getClub() + L")";
|
||||
|
||||
@ -526,7 +526,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
while(!no_card.empty() && ++i<20){
|
||||
pRunner r=no_card.front();
|
||||
no_card.pop_front();
|
||||
wstring name = r->getClass() + L": " + r->getName();
|
||||
wstring name = r->getClass(true) + L": " + r->getName();
|
||||
if (!r->getClub().empty())
|
||||
name += L" (" + r->getClub() + L")";
|
||||
|
||||
@ -543,7 +543,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
while(!si_duplicate.empty() && ++i<50){
|
||||
pRunner r=si_duplicate.front();
|
||||
si_duplicate.pop_front();
|
||||
wstring name = r->getClass() + L" / " + r->getName();
|
||||
wstring name = r->getClass(true) + L" / " + r->getName();
|
||||
if (!r->getClub().empty())
|
||||
name += L" (" + r->getClub() + L")";
|
||||
name += L": " + itow(r->getCardNo());
|
||||
@ -566,7 +566,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
header = true;
|
||||
}
|
||||
|
||||
wstring name = r->getClass() + L" / " + r->getName();
|
||||
wstring name = r->getClass(true) + L" / " + r->getName();
|
||||
if (!r->getClub().empty())
|
||||
name += L" (" + r->getClub() + L")";
|
||||
name += L": " + itow(r->getCardNo());
|
||||
@ -589,7 +589,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
for (t_it=Teams.begin(); t_it != Teams.end(); ++t_it) {
|
||||
if (t_it->isRemoved())
|
||||
continue;
|
||||
pClass pc=getClass(t_it->getClassId());
|
||||
pClass pc=getClass(t_it->getClassId(true));
|
||||
|
||||
if (pc){
|
||||
for(unsigned i=0;i<pc->getNumStages();i++){
|
||||
@ -604,7 +604,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
bool any = false;
|
||||
for (r_it=Runners.begin(); r_it != Runners.end(); ++r_it){
|
||||
if (r_it->_objectmarker>1) {
|
||||
wstring name = r_it->getClass() + L": " + r_it->getName();
|
||||
wstring name = r_it->getClass(true) + L": " + r_it->getName();
|
||||
if (!r_it->getClub().empty())
|
||||
name += L" (" + r_it->getClub() + L")";
|
||||
|
||||
@ -626,7 +626,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
if (r_it->isRemoved())
|
||||
continue;
|
||||
if (r_it->_objectmarker==0){ //Only consider runners not in a team.
|
||||
gdi.addStringUT(y, x+tab[0], 0, r_it->getClass(), tab[1]-tab[0]);
|
||||
gdi.addStringUT(y, x+tab[0], 0, r_it->getClass(true), tab[1]-tab[0]);
|
||||
wstring name = r_it->getName();
|
||||
if (!r_it->getClub().empty())
|
||||
name += L" (" + r_it->getClub() + L")";
|
||||
@ -650,9 +650,9 @@ void oEvent::generatePreReport(gdioutput &gdi) {
|
||||
gdi.addString("", 1, "Lag(flera)");
|
||||
|
||||
for (t_it=Teams.begin(); t_it != Teams.end(); ++t_it){
|
||||
pClass pc=getClass(t_it->getClassId());
|
||||
pClass pc=getClass(t_it->getClassId(false));
|
||||
|
||||
gdi.addStringUT(0, t_it->getClass() + L": " + t_it->getName() + L" " + t_it->getStartTimeS());
|
||||
gdi.addStringUT(0, t_it->getClass(false) + L": " + t_it->getName() + L" " + t_it->getStartTimeS());
|
||||
|
||||
if (pc){
|
||||
for(unsigned i=0;i<pc->getNumStages();i++){
|
||||
|
||||
346
code/oRunner.cpp
346
code/oRunner.cpp
@ -44,6 +44,7 @@
|
||||
#include "socket.h"
|
||||
#include "MeOSFeatures.h"
|
||||
#include "oListInfo.h"
|
||||
#include "qualification_final.h"
|
||||
|
||||
oRunner::RaceIdFormatter oRunner::raceIdFormatter;
|
||||
|
||||
@ -420,8 +421,27 @@ void oAbstractRunner::setClassId(int id, bool isManualUpdate) {
|
||||
// Update all classes (for multirunner)
|
||||
void oRunner::setClassId(int id, bool isManualUpdate)
|
||||
{
|
||||
if (tParentRunner)
|
||||
tParentRunner->setClassId(id, isManualUpdate);
|
||||
if (Class && Class->getQualificationFinal() && isManualUpdate) {
|
||||
int heat = Class->getQualificationFinal()->getHeatFromClass(id, Class->getId());
|
||||
if (heat >= 0) {
|
||||
int oldHeat = getDI().getInt("Heat");
|
||||
|
||||
if (heat != oldHeat) {
|
||||
pClass oldHeatClass = getClassRef(true);
|
||||
getDI().setInt("Heat", heat);
|
||||
pClass newHeatClass = getClassRef(true);
|
||||
oldHeatClass->clearCache(true);
|
||||
newHeatClass->clearCache(true);
|
||||
tSplitRevision = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (tParentRunner) {
|
||||
assert(!isManualUpdate); // Do not support! This may be destroyed if calling tParentRunner->setClass
|
||||
return;
|
||||
}
|
||||
else {
|
||||
pClass pc = Class;
|
||||
pClass nPc = id>0 ? oe->getClass(id):0;
|
||||
@ -451,7 +471,7 @@ void oRunner::setClassId(int id, bool isManualUpdate)
|
||||
if (Class != 0 && Class != pc && tInTeam==0 &&
|
||||
Class->isSingleRunnerMultiStage()) {
|
||||
if (!isTemporaryObject) {
|
||||
pTeam t = oe->addTeam(getName(), getClubId(), getClassId());
|
||||
pTeam t = oe->addTeam(getName(), getClubId(), getClassId(false));
|
||||
t->setStartNo(StartNo, false);
|
||||
t->setRunner(0, this, true);
|
||||
}
|
||||
@ -765,91 +785,89 @@ pCourse oRunner::getCourse(bool useAdaptedCourse) const {
|
||||
if (Course)
|
||||
tCrs = Course;
|
||||
else if (Class) {
|
||||
if (Class->hasMultiCourse()) {
|
||||
const oClass *cls = getClassRef(true);
|
||||
|
||||
if (cls->hasMultiCourse()) {
|
||||
if (tInTeam) {
|
||||
if (size_t(tLeg) >= tInTeam->Runners.size() || tInTeam->Runners[tLeg] != this) {
|
||||
tInTeam->quickApply();
|
||||
}
|
||||
}
|
||||
|
||||
if (Class == cls) {
|
||||
if (tInTeam && Class->hasUnorderedLegs()) {
|
||||
vector< pair<int, pCourse> > group;
|
||||
Class->getParallelCourseGroup(tLeg, StartNo, group);
|
||||
|
||||
if (tInTeam && Class->hasUnorderedLegs()) {
|
||||
vector< pair<int, pCourse> > group;
|
||||
Class->getParallelCourseGroup(tLeg, StartNo, group);
|
||||
|
||||
if (group.size() == 1) {
|
||||
tCrs = group[0].second;
|
||||
if (group.size() == 1) {
|
||||
tCrs = group[0].second;
|
||||
}
|
||||
else {
|
||||
// Remove used courses
|
||||
int myStart = 0;
|
||||
|
||||
for (size_t k = 0; k < group.size(); k++) {
|
||||
if (group[k].first == tLeg)
|
||||
myStart = k;
|
||||
|
||||
pRunner tr = tInTeam->getRunner(group[k].first);
|
||||
if (tr && tr->Course) {
|
||||
// The course is assigned. Remove from group
|
||||
for (size_t j = 0; j < group.size(); j++) {
|
||||
if (group[j].second == tr->Course) {
|
||||
group[j].second = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out already preliminary assigned courses
|
||||
for (int k = 0; k < myStart; k++) {
|
||||
pRunner r = tInTeam->getRunner(group[k].first);
|
||||
if (r && !r->Course) {
|
||||
size_t j = k;
|
||||
while (j < group.size()) {
|
||||
if (group[j].second) {
|
||||
group[j].second = 0;
|
||||
break;
|
||||
}
|
||||
else j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < group.size(); j++) {
|
||||
int ix = (j + myStart) % group.size();
|
||||
pCourse gcrs = group[ix].second;
|
||||
if (gcrs) {
|
||||
tCrs = gcrs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tInTeam) {
|
||||
unsigned leg = legToRun();
|
||||
tCrs = Class->getCourse(leg, StartNo);
|
||||
}
|
||||
else {
|
||||
// Remove used courses
|
||||
int myStart = 0;
|
||||
|
||||
for (size_t k = 0; k < group.size(); k++) {
|
||||
if (group[k].first == tLeg)
|
||||
myStart = k;
|
||||
|
||||
pRunner tr = tInTeam->getRunner(group[k].first);
|
||||
if (tr && tr->Course) {
|
||||
// The course is assigned. Remove from group
|
||||
for (size_t j = 0; j < group.size(); j++) {
|
||||
if (group[j].second == tr->Course) {
|
||||
group[j].second = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out already preliminary assigned courses
|
||||
for (int k = 0; k < myStart; k++) {
|
||||
pRunner r = tInTeam->getRunner(group[k].first);
|
||||
if (r && !r->Course) {
|
||||
size_t j = k;
|
||||
while (j < group.size()) {
|
||||
if (group[j].second) {
|
||||
group[j].second = 0;
|
||||
break;
|
||||
}
|
||||
else j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < group.size(); j++) {
|
||||
int ix = (j + myStart) % group.size();
|
||||
pCourse gcrs = group[ix].second;
|
||||
if (gcrs) {
|
||||
tCrs = gcrs;
|
||||
break;
|
||||
if (unsigned(tDuplicateLeg) < Class->MultiCourse.size()) {
|
||||
vector<pCourse> &courses = Class->MultiCourse[tDuplicateLeg];
|
||||
if (courses.size() > 0) {
|
||||
int index = StartNo % courses.size();
|
||||
tCrs = courses[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tInTeam) {
|
||||
unsigned leg=legToRun();
|
||||
tCrs = Class->getCourse(leg, StartNo);
|
||||
/*if (leg<Class->MultiCourse.size()) {
|
||||
vector<pCourse> &courses=Class->MultiCourse[leg];
|
||||
if (courses.size()>0) {
|
||||
int index=StartNo;
|
||||
if (index>0)
|
||||
index = (index-1) % courses.size();
|
||||
|
||||
tCrs = courses[index];
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else {
|
||||
if (unsigned(tDuplicateLeg)<Class->MultiCourse.size()) {
|
||||
vector<pCourse> &courses=Class->MultiCourse[tDuplicateLeg];
|
||||
if (courses.size()>0) {
|
||||
int index=StartNo % courses.size();
|
||||
tCrs = courses[index];
|
||||
}
|
||||
}
|
||||
// Final / qualification classes
|
||||
tCrs = cls->getCourse(0, StartNo);
|
||||
}
|
||||
}
|
||||
else
|
||||
tCrs = Class->Course;
|
||||
tCrs = cls->Course;
|
||||
}
|
||||
|
||||
if (tCrs && useAdaptedCourse) {
|
||||
@ -1329,6 +1347,19 @@ bool oRunner::evaluateCard(bool doApply, vector<int> & MissingPunches,
|
||||
doAdjustTimes(course);
|
||||
|
||||
tRogainingPointsGross = tRogainingPoints;
|
||||
|
||||
if (oldStatus!=*refStatus || oldFT!=FinishTime) {
|
||||
clearSplitAnalysis = true;
|
||||
}
|
||||
|
||||
if ((inTeam || !tUseStartPunch) && doApply)
|
||||
apply(sync, 0, false); //Post apply. Update start times.
|
||||
|
||||
if (tCachedRunningTime != FinishTime - *refStartTime) {
|
||||
tCachedRunningTime = FinishTime - *refStartTime;
|
||||
clearSplitAnalysis = true;
|
||||
}
|
||||
|
||||
if (time_limit > 0) {
|
||||
int rt = getRunningTime();
|
||||
if (rt > 0) {
|
||||
@ -1342,17 +1373,7 @@ bool oRunner::evaluateCard(bool doApply, vector<int> & MissingPunches,
|
||||
}
|
||||
}
|
||||
|
||||
if (oldStatus!=*refStatus || oldFT!=FinishTime) {
|
||||
clearSplitAnalysis = true;
|
||||
}
|
||||
|
||||
if ((inTeam || !tUseStartPunch) && doApply)
|
||||
apply(sync, 0, false); //Post apply. Update start times.
|
||||
|
||||
if (tCachedRunningTime != FinishTime - *refStartTime) {
|
||||
tCachedRunningTime = FinishTime - *refStartTime;
|
||||
clearSplitAnalysis = true;
|
||||
}
|
||||
|
||||
// Clear split analysis data if necessary
|
||||
bool clear = splitTimes.size() != oldTimes.size() || clearSplitAnalysis;
|
||||
@ -1650,8 +1671,8 @@ int oRunner::getRaceRunningTime(int leg) const
|
||||
|
||||
bool oRunner::sortSplit(const oRunner &a, const oRunner &b)
|
||||
{
|
||||
int acid=a.getClassId();
|
||||
int bcid=b.getClassId();
|
||||
int acid=a.getClassId(true);
|
||||
int bcid=b.getClassId(true);
|
||||
if (acid!=bcid)
|
||||
return acid<bcid;
|
||||
else if (a.tempStatus != b.tempStatus)
|
||||
@ -1661,21 +1682,29 @@ bool oRunner::sortSplit(const oRunner &a, const oRunner &b)
|
||||
if (a.tempRT!=b.tempRT)
|
||||
return a.tempRT<b.tempRT;
|
||||
}
|
||||
return a.tRealName<b.tRealName;
|
||||
return CompareString(LOCALE_USER_DEFAULT, 0,
|
||||
a.tRealName.c_str(), a.tRealName.length(),
|
||||
b.tRealName.c_str(), b.tRealName.length()) == CSTR_LESS_THAN;
|
||||
}
|
||||
}
|
||||
|
||||
bool oRunner::operator <(const oRunner &c) {
|
||||
if (!Class || !c.Class)
|
||||
return size_t(Class)<size_t(c.Class);
|
||||
else if (Class == c.Class && Class->getClassStatus() != oClass::Normal)
|
||||
bool oRunner::operator<(const oRunner &c) const {
|
||||
const oClass * myClass = getClassRef(true);
|
||||
const oClass * cClass = c.getClassRef(true);
|
||||
if (!myClass || !cClass)
|
||||
return size_t(myClass)<size_t(cClass);
|
||||
else if (Class == cClass && Class->getClassStatus() != oClass::Normal)
|
||||
return CompareString(LOCALE_USER_DEFAULT, 0,
|
||||
tRealName.c_str(), tRealName.length(),
|
||||
c.tRealName.c_str(), c.tRealName.length()) == CSTR_LESS_THAN;
|
||||
|
||||
if (oe->CurrentSortOrder==ClassStartTime) {
|
||||
if (Class->Id != c.Class->Id)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass->Id != cClass->Id) {
|
||||
if (myClass->tSortIndex != cClass->tSortIndex)
|
||||
return myClass->tSortIndex < cClass->tSortIndex;
|
||||
else
|
||||
return myClass->Id < cClass->Id;
|
||||
}
|
||||
else if (tStartTime != c.tStartTime) {
|
||||
if (tStartTime <= 0 && c.tStartTime > 0)
|
||||
return false;
|
||||
@ -1697,8 +1726,8 @@ bool oRunner::operator <(const oRunner &c) {
|
||||
RunnerStatus stat = tStatus == StatusUnknown ? StatusOK : tStatus;
|
||||
RunnerStatus cstat = c.tStatus == StatusUnknown ? StatusOK : c.tStatus;
|
||||
|
||||
if (Class != c.Class)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass != cClass)
|
||||
return myClass->tSortIndex < cClass->tSortIndex || (myClass->tSortIndex == cClass->tSortIndex && myClass->Id < cClass->Id);
|
||||
else if (tLegEquClass != c.tLegEquClass)
|
||||
return tLegEquClass < c.tLegEquClass;
|
||||
else if (tDuplicateLeg != c.tDuplicateLeg)
|
||||
@ -1730,8 +1759,8 @@ bool oRunner::operator <(const oRunner &c) {
|
||||
}
|
||||
}
|
||||
else if (oe->CurrentSortOrder == ClassCourseResult) {
|
||||
if (Class != c.Class)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass != cClass)
|
||||
return myClass->tSortIndex < cClass->tSortIndex;
|
||||
|
||||
const pCourse crs1 = getCourse(false);
|
||||
const pCourse crs2 = c.getCourse(false);
|
||||
@ -1805,8 +1834,8 @@ bool oRunner::operator <(const oRunner &c) {
|
||||
return ft > cft;
|
||||
}
|
||||
else if (oe->CurrentSortOrder == ClassFinishTime){
|
||||
if (Class != c.Class)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass != cClass)
|
||||
return myClass->tSortIndex < cClass->tSortIndex || (myClass->tSortIndex == cClass->tSortIndex && myClass->Id < cClass->Id);
|
||||
if (tStatus != c.tStatus)
|
||||
return RunnerStatusOrderMap[tStatus] < RunnerStatusOrderMap[c.tStatus];
|
||||
else{
|
||||
@ -1834,8 +1863,8 @@ bool oRunner::operator <(const oRunner &c) {
|
||||
return et > cet;
|
||||
}
|
||||
else if (oe->CurrentSortOrder == ClassPoints) {
|
||||
if (Class != c.Class)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass != cClass)
|
||||
return myClass->tSortIndex < cClass->tSortIndex || (myClass->tSortIndex == cClass->tSortIndex && myClass->Id < cClass->Id);
|
||||
else if (tDuplicateLeg != c.tDuplicateLeg)
|
||||
return tDuplicateLeg < c.tDuplicateLeg;
|
||||
else if (tStatus != c.tStatus)
|
||||
@ -1852,8 +1881,8 @@ bool oRunner::operator <(const oRunner &c) {
|
||||
}
|
||||
}
|
||||
else if (oe->CurrentSortOrder==ClassTotalResult) {
|
||||
if (Class != c.Class)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass != cClass)
|
||||
return myClass->tSortIndex < cClass->tSortIndex || (myClass->tSortIndex == cClass->tSortIndex && myClass->Id < cClass->Id);
|
||||
else if (tDuplicateLeg != c.tDuplicateLeg)
|
||||
return tDuplicateLeg < c.tDuplicateLeg;
|
||||
else {
|
||||
@ -1902,8 +1931,8 @@ bool oRunner::operator <(const oRunner &c) {
|
||||
}
|
||||
}
|
||||
else if (oe->CurrentSortOrder==ClassStartTimeClub) {
|
||||
if (Class != c.Class)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass != cClass)
|
||||
return myClass->tSortIndex < cClass->tSortIndex || (myClass->tSortIndex == cClass->tSortIndex && myClass->Id < cClass->Id);
|
||||
else if (tStartTime != c.tStartTime) {
|
||||
if (tStartTime <= 0 && c.tStartTime > 0)
|
||||
return false;
|
||||
@ -1916,8 +1945,8 @@ bool oRunner::operator <(const oRunner &c) {
|
||||
}
|
||||
}
|
||||
else if (oe->CurrentSortOrder==ClassTeamLeg) {
|
||||
if (Class->Id != c.Class->Id)
|
||||
return Class->tSortIndex < c.Class->tSortIndex;
|
||||
if (myClass->Id != cClass->Id)
|
||||
return myClass->tSortIndex < cClass->tSortIndex || (myClass->tSortIndex == cClass->tSortIndex && myClass->Id < cClass->Id);
|
||||
else if (tInTeam != c.tInTeam) {
|
||||
if (tInTeam == 0)
|
||||
return true;
|
||||
@ -1959,7 +1988,7 @@ void oAbstractRunner::setClub(const wstring &clubName)
|
||||
updateChanged();
|
||||
if (Class) {
|
||||
// Vacant clubs have special logic
|
||||
Class->tResultInfo.clear();
|
||||
getClassRef(true)->tResultInfo.clear();
|
||||
}
|
||||
if (Club && Club->isVacant()) { // Clear entry date/time for vacant
|
||||
getDI().setInt("EntryDate", 0);
|
||||
@ -2326,7 +2355,7 @@ void oEvent::getRunners(int classId, int courseId, vector<pRunner> &r, bool sort
|
||||
continue;
|
||||
}
|
||||
|
||||
if (classId <= 0 || it->getClassId() == classId)
|
||||
if (classId <= 0 || it->getClassId(true) == classId)
|
||||
r.push_back(&*it);
|
||||
}
|
||||
}
|
||||
@ -2364,7 +2393,7 @@ pRunner oRunner::nextNeedReadout() const {
|
||||
// For a runner in a team, first the team for the card
|
||||
for (size_t k = 0; k < tInTeam->Runners.size(); k++) {
|
||||
pRunner tr = tInTeam->Runners[k];
|
||||
if (tr && tr->CardNo == CardNo && !tr->Card && !tr->statusOK())
|
||||
if (tr && tr->getCardNo() == CardNo && !tr->Card && !tr->statusOK())
|
||||
return tr;
|
||||
}
|
||||
}
|
||||
@ -2432,9 +2461,11 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, bool onlyWithNoCard, boo
|
||||
}
|
||||
else {
|
||||
if (time <= 0) { //No time specified. Card readout search
|
||||
|
||||
pRunner secondTry = 0;
|
||||
//First try runners with no card read or a different card read.
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (it->skip())
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
if (ignoreRunnersWithNoStart && (it->getStatus() == StatusDNS || it->getStatus() == StatusCANCEL))
|
||||
continue;
|
||||
@ -2442,9 +2473,15 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, bool onlyWithNoCard, boo
|
||||
continue;
|
||||
|
||||
pRunner ret;
|
||||
if (it->CardNo==cardNo && (ret = it->nextNeedReadout()) != 0)
|
||||
return ret;
|
||||
if (it->CardNo == cardNo && (ret = it->nextNeedReadout()) != 0) {
|
||||
if (!it->skip())
|
||||
return ret;
|
||||
else if (secondTry == 0 || secondTry->tLeg > ret->tLeg)
|
||||
secondTry = ret;
|
||||
}
|
||||
}
|
||||
if (secondTry)
|
||||
return secondTry;
|
||||
}
|
||||
else {
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
@ -2745,11 +2782,11 @@ const vector< pair<wstring, size_t> > &oEvent::fillRunners(vector< pair<wstring,
|
||||
if (compact) {
|
||||
swprintf_s(bf, L"%s, %s (%s)", it->getNameAndRace(true).c_str(),
|
||||
it->getClub().c_str(),
|
||||
it->getClass().c_str());
|
||||
it->getClass(true).c_str());
|
||||
|
||||
} else {
|
||||
swprintf_s(bf, L"%s\t%s\t%s", it->getNameAndRace(true).c_str(),
|
||||
it->getClass().c_str(),
|
||||
it->getClass(true).c_str(),
|
||||
it->getClub().c_str());
|
||||
}
|
||||
out.push_back(make_pair(bf, it->Id));
|
||||
@ -2769,7 +2806,7 @@ const vector< pair<wstring, size_t> > &oEvent::fillRunners(vector< pair<wstring,
|
||||
if ( it->getClubId() != lVacId || lVacId == 0)
|
||||
out.push_back(make_pair(it->getUIName(), it->Id));
|
||||
else {
|
||||
swprintf_s(bf, L"%s (%s)", it->getUIName().c_str(), it->getClass().c_str());
|
||||
swprintf_s(bf, L"%s (%s)", it->getUIName().c_str(), it->getClass(true).c_str());
|
||||
out.push_back(make_pair(bf, it->Id));
|
||||
}
|
||||
}
|
||||
@ -2879,7 +2916,7 @@ void oRunner::createMultiRunner(bool createMaster, bool sync)
|
||||
if (!multiRunner[k-1]) {
|
||||
update = true;
|
||||
multiRunner[k-1]=oe->addRunner(sName, getClubId(),
|
||||
getClassId(), 0, 0, false);
|
||||
getClassId(false), 0, 0, false);
|
||||
multiRunner[k-1]->tDuplicateLeg=k;
|
||||
multiRunner[k-1]->tParentRunner=this;
|
||||
|
||||
@ -2909,6 +2946,12 @@ pRunner oRunner::getPredecessor() const
|
||||
|
||||
bool oRunner::apply(bool sync, pRunner src, bool setTmpOnly) {
|
||||
createMultiRunner(false, sync);
|
||||
if (sync) {
|
||||
for (size_t k = 0; k < multiRunner.size(); k++) {
|
||||
if (multiRunner[k])
|
||||
multiRunner[k]->synchronize(true);
|
||||
}
|
||||
}
|
||||
tLeg = -1;
|
||||
tLegEquClass = 0;
|
||||
tUseStartPunch=true;
|
||||
@ -3045,7 +3088,7 @@ void oEvent::generateRunnerTableData(Table &table, oRunner *addRunner)
|
||||
oRunnerList::iterator it;
|
||||
table.reserve(Runners.size());
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it){
|
||||
if (!it->skip()){
|
||||
if (!it->isRemoved()){
|
||||
it->addTableRow(table);
|
||||
}
|
||||
}
|
||||
@ -3088,11 +3131,13 @@ void oRunner::addTableRow(Table &table) const
|
||||
table.set(row++, it, TID_ID, itow(getId()), false);
|
||||
table.set(row++, it, TID_MODIFIED, getTimeStamp(), false);
|
||||
|
||||
table.set(row++, it, TID_RUNNER, getUIName(), true);
|
||||
|
||||
table.set(row++, it, TID_CLASSNAME, getClass(), true, cellSelection);
|
||||
if (tParentRunner == 0)
|
||||
table.set(row++, it, TID_RUNNER, getUIName(), true);
|
||||
else
|
||||
table.set(row++, it, TID_RUNNER, getUIName() + L" (" + itow(tDuplicateLeg+1) + L")", false);
|
||||
table.set(row++, it, TID_CLASSNAME, getClass(true), true, cellSelection);
|
||||
table.set(row++, it, TID_COURSE, getCourseName(), true, cellSelection);
|
||||
table.set(row++, it, TID_CLUB, getClub(), true, cellCombo);
|
||||
table.set(row++, it, TID_CLUB, getClub(), tParentRunner == 0, cellCombo);
|
||||
|
||||
table.set(row++, it, TID_TEAM, tInTeam ? tInTeam->getName() : L"", false);
|
||||
table.set(row++, it, TID_LEG, tInTeam ? itow(tLeg+1) : L"" , false);
|
||||
@ -3138,7 +3183,7 @@ bool oRunner::inputData(int id, const wstring &input,
|
||||
throw std::exception("Tomt namn inte tillåtet.");
|
||||
|
||||
if (sName != input && tRealName != input) {
|
||||
updateFromDB(input, getClubId(), getClassId(), getCardNo(), getBirthYear());
|
||||
updateFromDB(input, getClubId(), getClassId(false), getCardNo(), getBirthYear());
|
||||
setName(input, true);
|
||||
synchronizeAll();
|
||||
}
|
||||
@ -3184,7 +3229,7 @@ bool oRunner::inputData(int id, const wstring &input,
|
||||
else
|
||||
pc = oe->getClubCreate(0, input);
|
||||
|
||||
updateFromDB(getName(), pc ? pc->getId():0, getClassId(), getCardNo(), getBirthYear());
|
||||
updateFromDB(getName(), pc ? pc->getId():0, getClassId(false), getCardNo(), getBirthYear());
|
||||
|
||||
setClub(pc ? pc->getName() : L"");
|
||||
synchronize(true);
|
||||
@ -3195,7 +3240,7 @@ bool oRunner::inputData(int id, const wstring &input,
|
||||
case TID_CLASSNAME:
|
||||
setClassId(inputId, true);
|
||||
synchronize(true);
|
||||
output = getClass();
|
||||
output = getClass(true);
|
||||
break;
|
||||
|
||||
case TID_STATUS: {
|
||||
@ -3258,7 +3303,7 @@ void oRunner::fillInput(int id, vector< pair<wstring, size_t> > &out, size_t &se
|
||||
else if (id==TID_CLASSNAME) {
|
||||
oe->fillClasses(out, oEvent::extraNone, oEvent::filterNone);
|
||||
out.push_back(make_pair(lang.tl(L"Ingen klass"), 0));
|
||||
selected = getClassId();
|
||||
selected = getClassId(true);
|
||||
}
|
||||
else if (id==TID_CLUB) {
|
||||
oe->fillClubs(out);
|
||||
@ -3378,7 +3423,7 @@ void oRunner::getSplitTime(int courseControlId, RunnerStatus &stat, int &rt) con
|
||||
{
|
||||
rt = 0;
|
||||
stat = StatusUnknown;
|
||||
int cardno = tParentRunner ? tParentRunner->CardNo : CardNo;
|
||||
int cardno = getCardNo();
|
||||
|
||||
if (courseControlId==oPunch::PunchFinish &&
|
||||
FinishTime>0 && tStatus!=StatusUnknown) {
|
||||
@ -3643,7 +3688,9 @@ const wstring &oAbstractRunner::getBib() const
|
||||
}
|
||||
|
||||
void oRunner::setBib(const wstring &bib, int bibNumerical, bool updateStartNo, bool tmpOnly) {
|
||||
if (tParentRunner)
|
||||
const bool freeBib = !Class || Class->getBibMode() == BibMode::BibFree;
|
||||
|
||||
if (tParentRunner && !freeBib)
|
||||
tParentRunner->setBib(bib, bibNumerical, updateStartNo, tmpOnly);
|
||||
else {
|
||||
if (updateStartNo)
|
||||
@ -3657,10 +3704,11 @@ void oRunner::setBib(const wstring &bib, int bibNumerical, bool updateStartNo, b
|
||||
if (oe)
|
||||
oe->bibStartNoToRunnerTeam.clear();
|
||||
}
|
||||
|
||||
for (size_t k=0;k<multiRunner.size();k++) {
|
||||
if (multiRunner[k]) {
|
||||
multiRunner[k]->getDI().setString("Bib", bib);
|
||||
if (!freeBib) {
|
||||
for (size_t k = 0; k < multiRunner.size(); k++) {
|
||||
if (multiRunner[k]) {
|
||||
multiRunner[k]->getDI().setString("Bib", bib);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3848,7 +3896,7 @@ void oRunner::printSplits(gdioutput &gdi) const {
|
||||
gdi.dropLine(0.5);
|
||||
pCourse pc = getCourse(true);
|
||||
|
||||
gdi.addStringUT(bnormal, getName() + L", " + getClass());
|
||||
gdi.addStringUT(bnormal, getName() + L", " + getClass(true));
|
||||
gdi.addStringUT(normal, getClub());
|
||||
gdi.dropLine(0.5);
|
||||
gdi.addStringUT(normal, lang.tl("Start: ") + getStartTimeS() + lang.tl(", Mål: ") + getFinishTimeS());
|
||||
@ -4175,7 +4223,7 @@ void oRunner::printStartInfo(gdioutput &gdi) const {
|
||||
if (!bib.empty())
|
||||
bib = bib + L": ";
|
||||
|
||||
gdi.addStringUT(boldSmall, bib + getName() + L", " + getClass());
|
||||
gdi.addStringUT(boldSmall, bib + getName() + L", " + getClass(true));
|
||||
gdi.addStringUT(fontSmall, getClub());
|
||||
gdi.dropLine(0.5);
|
||||
|
||||
@ -4274,7 +4322,7 @@ void oEvent::updateRunnersFromDB()
|
||||
|
||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!it->isVacant() && !it->isRemoved())
|
||||
it->updateFromDB(it->sName, it->getClubId(), it->getClassId(), it->getCardNo(), it->getBirthYear());
|
||||
it->updateFromDB(it->sName, it->getClubId(), it->getClassId(false), it->getCardNo(), it->getBirthYear());
|
||||
}
|
||||
}
|
||||
|
||||
@ -5258,6 +5306,10 @@ void oRunner::markClassChanged(int controlId) {
|
||||
assert(controlId < 4096);
|
||||
if (Class) {
|
||||
Class->markSQLChanged(tLeg, controlId);
|
||||
pClass cls2 = getClassRef(true);
|
||||
if (cls2 != Class)
|
||||
cls2->markSQLChanged(-1, controlId);
|
||||
|
||||
if (tInTeam && tInTeam->Class != Class && tInTeam->Class) {
|
||||
tInTeam->Class->markSQLChanged(tLeg, controlId);
|
||||
}
|
||||
@ -5535,10 +5587,13 @@ int oRunner::getRanking() const {
|
||||
}
|
||||
|
||||
void oAbstractRunner::hasManuallyUpdatedTimeStatus() {
|
||||
if (Class && Class->hasClassGlobalDependance()) {
|
||||
if (Class && Class->hasClassGlobalDependence()) {
|
||||
set<int> cls;
|
||||
oe->reEvaluateAll(cls, false);
|
||||
}
|
||||
if (Class) {
|
||||
Class->updateFinalClasses(dynamic_cast<oRunner *>(this), false);
|
||||
}
|
||||
}
|
||||
|
||||
bool oRunner::canShareCard(const pRunner other, int newCardNo) const {
|
||||
@ -5555,7 +5610,7 @@ bool oRunner::canShareCard(const pRunner other, int newCardNo) const {
|
||||
if (!getTeam() || other->getTeam() != getTeam())
|
||||
return false;
|
||||
|
||||
pClass tCls = getTeam()->getClassRef();
|
||||
const oClass * tCls = getTeam()->getClassRef(false);
|
||||
if (!tCls || tCls != Class)
|
||||
return false;
|
||||
|
||||
@ -5598,3 +5653,24 @@ bool oAbstractRunner::hasLateEntryFee() const {
|
||||
|
||||
return late;
|
||||
}
|
||||
|
||||
int oRunner::classInstance() const {
|
||||
if (classInstanceRev.first == oe->dataRevision)
|
||||
return classInstanceRev.second;
|
||||
classInstanceRev.second = getDCI().getInt("Heat");
|
||||
if (Class)
|
||||
classInstanceRev.second = min(classInstanceRev.second, Class->getNumQualificationFinalClasses());
|
||||
classInstanceRev.first = oe->dataRevision;
|
||||
return classInstanceRev.second;
|
||||
}
|
||||
|
||||
const wstring &oAbstractRunner::getClass(bool virtualClass) const {
|
||||
if (Class) {
|
||||
if (virtualClass)
|
||||
return Class->getVirtualClass(classInstance())->Name;
|
||||
else
|
||||
return Class->Name;
|
||||
}
|
||||
|
||||
else return _EmptyWString;
|
||||
}
|
||||
|
||||
@ -255,17 +255,28 @@ public:
|
||||
|
||||
const pClub getClubRef() const {return Club;}
|
||||
pClub getClubRef() {return Club;}
|
||||
virtual int classInstance() const = 0;
|
||||
|
||||
const pClass getClassRef() const {return Class;}
|
||||
pClass getClassRef() {return Class;}
|
||||
const oClass *getClassRef(bool virtualClass) const {
|
||||
return (virtualClass && Class) ? Class->getVirtualClass(classInstance()) : Class;
|
||||
}
|
||||
|
||||
pClass getClassRef(bool virtualClass) {
|
||||
return pClass((virtualClass && Class) ? Class->getVirtualClass(classInstance()) : Class);
|
||||
}
|
||||
|
||||
virtual const wstring &getClub() const {if (Club) return Club->name; else return _EmptyWString;}
|
||||
virtual int getClubId() const {if (Club) return Club->Id; else return 0;}
|
||||
virtual void setClub(const wstring &clubName);
|
||||
virtual pClub setClubId(int clubId);
|
||||
|
||||
virtual const wstring &getClass() const {if (Class) return Class->Name; else return _EmptyWString;}
|
||||
virtual int getClassId() const {if (Class) return Class->Id; else return 0;}
|
||||
const wstring &getClass(bool virtualClass) const;
|
||||
int getClassId(bool virtualClass) const {
|
||||
if (Class)
|
||||
return virtualClass ? Class->getVirtualClass(classInstance())->Id : Class->Id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void setClassId(int id, bool isManualUpdate);
|
||||
virtual int getStartNo() const {return StartNo;}
|
||||
virtual void setStartNo(int no, bool storeTmpOnly);
|
||||
@ -457,6 +468,8 @@ protected:
|
||||
// Running time as calculated by evalute. Used to detect changes.
|
||||
int tCachedRunningTime;
|
||||
|
||||
mutable pair<int, int> classInstanceRev;
|
||||
|
||||
void clearOnChangedRunningTime();
|
||||
|
||||
// Cached runner statistics
|
||||
@ -499,6 +512,8 @@ public:
|
||||
/** Get a runner reference (drawing) */
|
||||
pRunner getReference() const;
|
||||
|
||||
int classInstance() const override;
|
||||
|
||||
/**Set a runner reference*/
|
||||
void setReference(int runnerId);
|
||||
|
||||
@ -546,6 +561,9 @@ public:
|
||||
int getLegNumber() const {return tLeg;}
|
||||
int getSpeakerPriority() const;
|
||||
|
||||
RunnerStatus getTempStatus() const { return tempStatus; }
|
||||
int getTempTime() const { return tempRT; }
|
||||
|
||||
void remove();
|
||||
bool canRemove() const;
|
||||
|
||||
@ -703,7 +721,7 @@ public:
|
||||
pCard getCard() const {return Card;}
|
||||
int getCardId(){if (Card) return Card->Id; else return 0;}
|
||||
|
||||
bool operator<(const oRunner &c);
|
||||
bool operator<(const oRunner &c) const;
|
||||
bool static CompareSINumber(const oRunner &a, const oRunner &b){return a.CardNo<b.CardNo;}
|
||||
|
||||
bool evaluateCard(bool applyTeam, vector<int> &missingPunches, int addpunch=0, bool synchronize=false);
|
||||
@ -716,7 +734,7 @@ public:
|
||||
int getCourseId() const {if (Course) return Course->Id; else return 0;}
|
||||
void setCourseId(int id);
|
||||
|
||||
int getCardNo() const {return tParentRunner ? tParentRunner->CardNo : CardNo;}
|
||||
int getCardNo() const {return tParentRunner && CardNo == 0 ? tParentRunner->CardNo : CardNo;}
|
||||
void setCardNo(int card, bool matchCard, bool updateFromDatabase = false);
|
||||
/** Sets the card to a given card. An existing card is marked as unpaired.
|
||||
CardNo is updated. Returns id of old card (or 0).
|
||||
|
||||
@ -315,7 +315,7 @@ void oTeam::setRunnerInternal(int k, pRunner r)
|
||||
Runners[k]->tInTeam = this;
|
||||
Runners[k]->tLeg = k;
|
||||
if (Class && Class->getLegType(k) != LTGroup)
|
||||
Runners[k]->setClassId(getClassId(), false);
|
||||
Runners[k]->setClassId(getClassId(false), false);
|
||||
}
|
||||
updateChanged();
|
||||
}
|
||||
@ -698,7 +698,7 @@ bool oTeam::compareResult(const oTeam &a, const oTeam &b)
|
||||
{
|
||||
if (a.Class != b.Class) {
|
||||
if (a.Class) {
|
||||
if (b.Class) return a.Class->tSortIndex < b.Class->tSortIndex;
|
||||
if (b.Class) return a.Class->tSortIndex < b.Class->tSortIndex || (a.Class->tSortIndex == b.Class->tSortIndex && a.Class->Id < b.Class->Id);
|
||||
else return true;
|
||||
}
|
||||
else return false;
|
||||
@ -728,7 +728,8 @@ bool oTeam::compareStartTime(const oTeam &a, const oTeam &b)
|
||||
{
|
||||
if (a.Class != b.Class) {
|
||||
if (a.Class) {
|
||||
if (b.Class) return a.Class->tSortIndex<b.Class->tSortIndex;
|
||||
if (b.Class)
|
||||
return a.Class->tSortIndex<b.Class->tSortIndex || (a.Class->tSortIndex == b.Class->tSortIndex && a.Class->Id < b.Class->Id);
|
||||
else return true;
|
||||
}
|
||||
}
|
||||
@ -760,7 +761,8 @@ bool oTeam::compareSNO(const oTeam &a, const oTeam &b) {
|
||||
}
|
||||
else if (a.Class != b.Class) {
|
||||
if (a.Class) {
|
||||
if (b.Class) return a.Class->tSortIndex<b.Class->tSortIndex;
|
||||
if (b.Class)
|
||||
return a.Class->tSortIndex < b.Class->tSortIndex || (a.Class->tSortIndex == b.Class->tSortIndex && a.Class->Id < b.Class->Id);
|
||||
else return true;
|
||||
}
|
||||
}
|
||||
@ -928,6 +930,7 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
|
||||
}
|
||||
|
||||
if (Runners[i]) {
|
||||
pClass actualClass = Runners[i]->getClassRef(true);
|
||||
if (Runners[i]->tInTeam && Runners[i]->tInTeam!=this) {
|
||||
Runners[i]->tInTeam->correctRemove(Runners[i]);
|
||||
}
|
||||
@ -942,7 +945,8 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
|
||||
Runners[i]->tLegEquClass = i;
|
||||
}
|
||||
|
||||
Runners[i]->setStartNo(StartNo, setTmpOnly);
|
||||
if (actualClass == Class)
|
||||
Runners[i]->setStartNo(StartNo, setTmpOnly);
|
||||
if (!bib.empty() && Runners[i]->isChanged()) {
|
||||
if (bibMode == -1 && Class)
|
||||
bibMode = Class->getBibMode();
|
||||
@ -980,7 +984,7 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
|
||||
else
|
||||
lastStatus = Runners[i]->getStatus();
|
||||
|
||||
StartTypes st = pc->getStartType(i);
|
||||
StartTypes st = actualClass == pc ? pc->getStartType(i) : actualClass->getStartType(0);
|
||||
LegTypes lt = legType;
|
||||
|
||||
if ((lt==LTParallel || lt==LTParallelOptional) && i==0) {
|
||||
@ -1016,9 +1020,12 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
|
||||
}
|
||||
}
|
||||
if (!prs) {
|
||||
if (lt==LTNormal || lt==LTSum || lt == LTGroup)
|
||||
lastStartTime=pc->getStartData(i);
|
||||
|
||||
if (lt == LTNormal || lt == LTSum || lt == LTGroup) {
|
||||
if (actualClass == pc)
|
||||
lastStartTime = pc->getStartData(i);
|
||||
else
|
||||
lastStartTime = actualClass->getStartData(0); // Qualification/final classes
|
||||
}
|
||||
Runners[i]->setStartTime(lastStartTime, false, setTmpOnly);
|
||||
Runners[i]->tUseStartPunch=false;
|
||||
}
|
||||
@ -1740,7 +1747,7 @@ void oEvent::getTeams(int classId, vector<pTeam> &t, bool sort) {
|
||||
if (it->isRemoved())
|
||||
continue;
|
||||
|
||||
if (classId == 0 || it->getClassId() == classId)
|
||||
if (classId == 0 || it->getClassId(false) == classId)
|
||||
t.push_back(&*it);
|
||||
}
|
||||
}
|
||||
@ -1855,7 +1862,7 @@ void oTeam::addTableRow(Table &table) const {
|
||||
table.set(row++, it, TID_MODIFIED, getTimeStamp(), false);
|
||||
|
||||
table.set(row++, it, TID_NAME, getName(), true);
|
||||
table.set(row++, it, TID_CLASSNAME, getClass(), true, cellSelection);
|
||||
table.set(row++, it, TID_CLASSNAME, getClass(true), true, cellSelection);
|
||||
table.set(row++, it, TID_CLUB, getClub(), true, cellCombo);
|
||||
|
||||
table.set(row++, it, TID_START, getStartTimeS(), true);
|
||||
@ -1920,7 +1927,7 @@ bool oTeam::inputData(int id, const wstring &input,
|
||||
}
|
||||
else {
|
||||
if (isName && !input.empty() && Class) {
|
||||
pRunner r = oe->addRunner(input, getClubId(), getClassId(), 0, 0, false);
|
||||
pRunner r = oe->addRunner(input, getClubId(), getClassId(false), 0, 0, false);
|
||||
setRunner(ix, r, true);
|
||||
output = r->getName();
|
||||
}
|
||||
@ -1968,7 +1975,7 @@ bool oTeam::inputData(int id, const wstring &input,
|
||||
case TID_CLASSNAME:
|
||||
setClassId(inputId, true);
|
||||
synchronize(true);
|
||||
output = getClass();
|
||||
output = getClass(true);
|
||||
break;
|
||||
|
||||
case TID_STATUS: {
|
||||
@ -2033,7 +2040,7 @@ void oTeam::fillInput(int id, vector< pair<wstring, size_t> > &out, size_t &sele
|
||||
else if (id==TID_CLASSNAME) {
|
||||
oe->fillClasses(out, oEvent::extraNone, oEvent::filterOnlyMulti);
|
||||
out.push_back(make_pair(lang.tl(L"Ingen klass"), 0));
|
||||
selected = getClassId();
|
||||
selected = getClassId(true);
|
||||
}
|
||||
else if (id==TID_CLUB) {
|
||||
oe->fillClubs(out);
|
||||
|
||||
@ -105,6 +105,10 @@ public:
|
||||
|
||||
int getRanking() const;
|
||||
|
||||
int classInstance() const override {
|
||||
return 0; // Not supported
|
||||
}
|
||||
|
||||
void resetResultCalcCache() const;
|
||||
vector< vector<int> > &getResultCache(ResultCalcCacheSymbol symb) const;
|
||||
void setResultCache(ResultCalcCacheSymbol symb, int leg, vector<int> &data) const;
|
||||
|
||||
@ -102,7 +102,7 @@ const vector< pair<wstring, size_t> > &oEvent::fillTeams(vector< pair<wstring, s
|
||||
tn = dashes + it->getName();
|
||||
}
|
||||
if (it->Class)
|
||||
out.push_back(make_pair(tn + L" (" + it->getClass() + L")", it->Id));
|
||||
out.push_back(make_pair(tn + L" (" + it->getClass(true) + L")", it->Id));
|
||||
else
|
||||
out.push_back(make_pair(tn, it->Id));
|
||||
}
|
||||
@ -612,14 +612,14 @@ void oEvent::adjustTeamMultiRunners(pClass cls)
|
||||
if (cls) {
|
||||
bool multi = cls->getNumStages() > 1;
|
||||
for (oRunnerList::iterator it = Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (it->skip() || it->getClassId() != cls->getId())
|
||||
if (it->skip() || it->getClassId(false) != cls->getId())
|
||||
continue;
|
||||
if (multi && it->tInTeam == 0) {
|
||||
oe->autoAddTeam(&*it);
|
||||
}
|
||||
|
||||
if (!multi && it->tInTeam) {
|
||||
assert( it->tInTeam->getClassId() == cls->getId());
|
||||
assert( it->tInTeam->getClassId(false) == cls->getId());
|
||||
removeTeam(it->tInTeam->getId());
|
||||
}
|
||||
|
||||
@ -628,7 +628,7 @@ void oEvent::adjustTeamMultiRunners(pClass cls)
|
||||
|
||||
vector<int> tr;
|
||||
for (oTeamList::iterator it=Teams.begin(); it != Teams.end(); ++it) {
|
||||
if (!multi && !it->isRemoved() && it->getClassId() == cls->getId()) {
|
||||
if (!multi && !it->isRemoved() && it->getClassId(false) == cls->getId()) {
|
||||
tr.push_back(it->getId());
|
||||
}
|
||||
}
|
||||
@ -728,9 +728,9 @@ void oTeam::checkClassesWithReferences(oEvent &oe, std::set<int> &clsWithRef) {
|
||||
map<int, pair<int, int> > pairedUnpairedPerClass;
|
||||
for (size_t k = 0; k < r.size(); k++) {
|
||||
if (r[k]->getReference())
|
||||
++pairedUnpairedPerClass[r[k]->getClassId()].first;
|
||||
++pairedUnpairedPerClass[r[k]->getClassId(false)].first;
|
||||
else
|
||||
++pairedUnpairedPerClass[r[k]->getClassId()].second;
|
||||
++pairedUnpairedPerClass[r[k]->getClassId(false)].second;
|
||||
}
|
||||
|
||||
for (auto &it : pairedUnpairedPerClass) {
|
||||
@ -744,8 +744,8 @@ void oTeam::convertClassWithReferenceToPatrol(oEvent &oe, const std::set<int> &c
|
||||
oe.getRunners(-1, -1, r, true);
|
||||
|
||||
for(auto it : r) {
|
||||
if (clsWithRef.count(it->getClassId())) {
|
||||
pClass cls = it->getClassRef();
|
||||
if (clsWithRef.count(it->getClassId(false))) {
|
||||
pClass cls = it->getClassRef(false);
|
||||
|
||||
if (cls->getNumStages() == 0) {
|
||||
pCourse crs = cls->getCourse();
|
||||
|
||||
@ -45,11 +45,27 @@ class oSpeakerObject
|
||||
{
|
||||
public:
|
||||
struct RunningTime {
|
||||
void reset() { time = 0; preliminary = 0; }
|
||||
int time;
|
||||
int preliminary;
|
||||
RunningTime() : time(0), preliminary(0) {}
|
||||
};
|
||||
|
||||
void reset() {
|
||||
owner = 0;
|
||||
bib.clear();
|
||||
names.clear();
|
||||
outgoingnames.clear();
|
||||
resultRemark.clear();
|
||||
club.clear();
|
||||
startTimeS.clear();
|
||||
status = StatusUnknown;
|
||||
finishStatus = StatusUnknown;
|
||||
useSinceLast = 0;
|
||||
runningTime.reset();
|
||||
runningTimeLeg.reset();
|
||||
runningTimeSinceLast.reset();
|
||||
}
|
||||
oRunner *owner;
|
||||
wstring bib;
|
||||
vector<wstring> names;
|
||||
|
||||
298
code/qualification_final.cpp
Normal file
298
code/qualification_final.cpp
Normal file
@ -0,0 +1,298 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "qualification_final.h"
|
||||
|
||||
#include "meos_util.h"
|
||||
#include "meosexception.h"
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include "xmlparser.h"
|
||||
|
||||
pair<int, int> QualificationFinal::getNextFinal(int instance, int orderPlace, int numSharedPlaceNext) const {
|
||||
pair<int, int> key(instance, orderPlace);
|
||||
int iter = 0;
|
||||
while (numSharedPlaceNext >= 0) {
|
||||
auto res = sourcePlaceToFinalOrder.find(key);
|
||||
if (res != sourcePlaceToFinalOrder.end()) {
|
||||
if (iter >= 2) { // For three in a shared last place
|
||||
pair<int, int> key2 = key;
|
||||
int extraSub = ((iter + 1) % 2);
|
||||
key2.second -= extraSub;
|
||||
auto res2 = sourcePlaceToFinalOrder.find(key2);
|
||||
if (res2 != sourcePlaceToFinalOrder.end()) {
|
||||
auto ans = res2->second;
|
||||
ans.second += iter + extraSub;
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto ans = res->second;
|
||||
ans.second += iter;
|
||||
return ans;
|
||||
}
|
||||
--key.second;
|
||||
--numSharedPlaceNext;
|
||||
++iter;
|
||||
}
|
||||
|
||||
return make_pair(0, -1);
|
||||
}
|
||||
|
||||
bool QualificationFinal::noQualification(int instance) const {
|
||||
if (size_t(instance) >= classDefinition.size())
|
||||
return false;
|
||||
|
||||
return classDefinition[instance].qualificationMap.empty() &&
|
||||
classDefinition[instance].timeQualifications.empty();
|
||||
}
|
||||
|
||||
|
||||
void QualificationFinal::getBaseClassInstances(set<int> &base) const {
|
||||
for (size_t k = 0; k < classDefinition.size(); k++) {
|
||||
if (noQualification(k))
|
||||
base.insert(k+1);
|
||||
else break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QualificationFinal::import(const wstring &file) {
|
||||
xmlparser xml;
|
||||
xml.read(file);
|
||||
|
||||
auto qr = xml.getObject("QualificationRules");
|
||||
xmlList levels;
|
||||
qr.getObjects("Level", levels);
|
||||
map<int, int> idToIndex;
|
||||
map<int, set<int> > qualificationRelations;
|
||||
int numBaseLevels = 0;
|
||||
int iLevel = 0;
|
||||
for (size_t iLevel = 0; iLevel < levels.size(); iLevel++) {
|
||||
auto &level = levels[iLevel];
|
||||
xmlList classes;
|
||||
level.getObjects("Class", classes);
|
||||
for (auto &cls : classes) {
|
||||
wstring name;
|
||||
cls.getObjectString("Name", name);
|
||||
if (name.empty())
|
||||
throw meosException("Klassen måste ha ett namn.");
|
||||
int classId = cls.getObjectInt("id");
|
||||
if (!(classId>0))
|
||||
throw meosException("Id must be a positive integer.");
|
||||
if (idToIndex.count(classId))
|
||||
throw meosException("Duplicate class with id " + itos(classId));
|
||||
|
||||
xmlList rules;
|
||||
cls.getObjects("Qualification", rules);
|
||||
if (rules.empty())
|
||||
numBaseLevels = 1; // Instance zero is not used as qualification,
|
||||
|
||||
idToIndex[classId] = classDefinition.size() + numBaseLevels;
|
||||
classDefinition.push_back(Class());
|
||||
classDefinition.back().name = name;
|
||||
|
||||
for (auto &qf : rules) {
|
||||
int place = qf.getObjectInt("place");
|
||||
if (place > 0) {
|
||||
int id = qf.getObjectInt("id");
|
||||
if (id == 0 && iLevel == 0)
|
||||
classDefinition.back().qualificationMap.push_back(make_pair(0, place));
|
||||
else if (idToIndex.count(id)) {
|
||||
classDefinition.back().qualificationMap.push_back(make_pair(idToIndex[id], place));
|
||||
qualificationRelations[classId].insert(id);
|
||||
}
|
||||
else
|
||||
throw meosException("Unknown class with id " + itos(id));
|
||||
}
|
||||
else {
|
||||
string time;
|
||||
qf.getObjectString("place", time);
|
||||
if (time == "time") {
|
||||
string ids;
|
||||
qf.getObjectString("id", ids);
|
||||
vector<string> vid;
|
||||
split(ids, ",;", vid);
|
||||
vector<int> ivid;
|
||||
for (auto &s : vid) {
|
||||
int i = atoi(s.c_str());
|
||||
if (!idToIndex.count(i))
|
||||
throw meosException("Unknown class with id " + itos(i));
|
||||
ivid.push_back(idToIndex[i]);
|
||||
}
|
||||
|
||||
if (ivid.empty())
|
||||
throw meosException(L"Empty time qualification for " + name);
|
||||
classDefinition.back().timeQualifications.push_back(ivid);
|
||||
}
|
||||
else throw meosException("Unknown classification rule " + time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*classDefinition.resize(3);
|
||||
classDefinition[0].name = L"Semi A";
|
||||
classDefinition[1].name = L"Semi B";
|
||||
classDefinition[2].name = L"Final";
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
classDefinition[0].qualificationMap.push_back(make_pair(0, i * 2 + 1));
|
||||
classDefinition[1].qualificationMap.push_back(make_pair(0, i * 2 + 2));
|
||||
classDefinition[2].qualificationMap.push_back(make_pair(i%2+1, i/2 + 1));
|
||||
}
|
||||
*/
|
||||
initgmap(true);
|
||||
}
|
||||
|
||||
void QualificationFinal::init(const wstring &def) {
|
||||
vector <wstring> races, rtdef, rdef;
|
||||
split(def, L"|", races);
|
||||
classDefinition.resize(races.size());
|
||||
bool valid = true;
|
||||
bool first = true;
|
||||
for (size_t k = 0; k < races.size(); k++) {
|
||||
split(races[k], L"T", rtdef);
|
||||
classDefinition[k].qualificationMap.clear();
|
||||
classDefinition[k].timeQualifications.clear();
|
||||
|
||||
if (first && rtdef.empty())
|
||||
continue;
|
||||
|
||||
valid = rtdef.size() > 0;
|
||||
if (!valid)
|
||||
break;
|
||||
first = false;
|
||||
|
||||
split(rtdef[0], L";", rdef);
|
||||
valid = rdef.size() > 0 && rdef.size()%2 == 0;
|
||||
if (!valid)
|
||||
break;
|
||||
|
||||
for (size_t j = 0; j < rdef.size(); j+=2) {
|
||||
size_t src = _wtoi(rdef[j].c_str());
|
||||
if (src > k) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
const wstring &rd = rdef[j + 1];
|
||||
size_t d1 = _wtoi(rd.c_str());
|
||||
size_t d2 = d1;
|
||||
size_t range = rd.find_first_of('-', 0);
|
||||
if (range < rd.size())
|
||||
d2 = _wtoi(rd.c_str()+range+1);
|
||||
|
||||
if (d1 > d2) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
while (d1 <= d2) {
|
||||
classDefinition[k].qualificationMap.push_back(make_pair(int(src), int(d1)));
|
||||
d1++;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 1; valid && i < rtdef.size(); i++) {
|
||||
split(rtdef[i], L";", rdef);
|
||||
classDefinition[k].timeQualifications.push_back(vector<int>());
|
||||
for (size_t j = 0; valid && j < rdef.size(); j += 2) {
|
||||
size_t src = _wtoi(rdef[j].c_str());
|
||||
if (src > k) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
classDefinition[k].timeQualifications.back().push_back(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
classDefinition.clear();
|
||||
|
||||
initgmap(false);
|
||||
}
|
||||
|
||||
void QualificationFinal::encode(wstring &output) const {
|
||||
output.clear();
|
||||
|
||||
for (size_t k = 0; k < classDefinition.size(); k++) {
|
||||
if (k > 0)
|
||||
output.append(L"|");
|
||||
|
||||
auto &qm = classDefinition[k].qualificationMap;
|
||||
|
||||
for (size_t j = 0; j < qm.size(); j++) {
|
||||
if (j > 0)
|
||||
output.append(L";");
|
||||
|
||||
size_t i = j;
|
||||
while ((i + 1) < qm.size() && qm[i + 1].first == qm[i].first
|
||||
&& qm[i + 1].second == qm[i].second+1) {
|
||||
i++;
|
||||
}
|
||||
output.append(itow(qm[j].first) + L";");
|
||||
if (i <= j + 1) {
|
||||
output.append(itow(qm[j].second));
|
||||
}
|
||||
else {
|
||||
output.append(itow(qm[j].second) + L"-" + itow(qm[i].second));
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
|
||||
auto &tqm = classDefinition[k].timeQualifications;
|
||||
for (auto &source : tqm) {
|
||||
output.append(L"T");
|
||||
for (size_t i = 0; i < source.size(); i++) {
|
||||
if (i > 0)
|
||||
output.append(L";");
|
||||
output.append(itow(source[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int QualificationFinal::getNumStages(int stage) const {
|
||||
if (stage == 0 || classDefinition[stage-1].qualificationMap.empty())
|
||||
return 1;
|
||||
|
||||
set<int> races;
|
||||
for (auto &qm : classDefinition[stage - 1].qualificationMap) {
|
||||
if (qm.first == stage)
|
||||
throw meosException("Invalid qualification scheme");
|
||||
races.insert(qm.first);
|
||||
}
|
||||
|
||||
int def = 0;
|
||||
for (int r : races)
|
||||
def = max(def, 1 + getNumStages(r));
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
void QualificationFinal::initgmap(bool check) {
|
||||
sourcePlaceToFinalOrder.clear();
|
||||
|
||||
for (int ix = 0; ix < (int)classDefinition.size(); ix++) {
|
||||
auto &c = classDefinition[ix];
|
||||
|
||||
for (int k = 0; k < (int)c.qualificationMap.size(); k++) {
|
||||
const pair<int, int> &sd = c.qualificationMap[k];
|
||||
if (check && sourcePlaceToFinalOrder.count(sd))
|
||||
throw meosException(L"Inconsistent qualification rule, X#" + c.name + + L"/" + itow(sd.first));
|
||||
|
||||
sourcePlaceToFinalOrder[sd] = make_pair(ix+1, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int QualificationFinal::getHeatFromClass(int finalClassId, int baseClassId) const {
|
||||
if (baseClassId == baseId) {
|
||||
int fci = (finalClassId - baseId) / maxClassId;
|
||||
|
||||
if (fci * maxClassId + baseClassId == finalClassId)
|
||||
return fci;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
84
code/qualification_final.h
Normal file
84
code/qualification_final.h
Normal file
@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2017 Melin Software HB
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Melin Software HB - software@melin.nu - www.melin.nu
|
||||
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
class QualificationFinal {
|
||||
private:
|
||||
|
||||
int maxClassId;
|
||||
int baseId;
|
||||
|
||||
struct Class {
|
||||
wstring name;
|
||||
vector< pair<int, int> > qualificationMap;
|
||||
vector< vector<int> > timeQualifications;
|
||||
};
|
||||
|
||||
vector<Class> classDefinition;
|
||||
|
||||
map<pair<int, int>, pair<int, int>> sourcePlaceToFinalOrder;
|
||||
|
||||
void initgmap(bool check);
|
||||
|
||||
// Recursive implementation
|
||||
int getNumStages(int stage) const;
|
||||
public:
|
||||
|
||||
QualificationFinal(int maxClassId, int baseId) : maxClassId(maxClassId), baseId(baseId) {}
|
||||
|
||||
int getNumClasses() const {
|
||||
return classDefinition.size();
|
||||
}
|
||||
|
||||
const wstring getInstanceName(int inst) {
|
||||
return classDefinition.at(inst-1).name;
|
||||
}
|
||||
|
||||
// Count number of stages
|
||||
int getNumStages() const {
|
||||
return getNumStages(classDefinition.size());
|
||||
}
|
||||
|
||||
int getHeatFromClass(int finalClassId, int baseClassId) const;
|
||||
|
||||
void import(const wstring &file);
|
||||
|
||||
void init(const wstring &def);
|
||||
void encode(wstring &output) const;
|
||||
|
||||
/** Retuns the final class and the order within that class. */
|
||||
pair<int,int> getNextFinal(int instance, int orderPlace, int numSharedPlaceNext) const;
|
||||
|
||||
/** Returns true if all competitors are automatically qualified*/
|
||||
bool noQualification(int instance) const;
|
||||
|
||||
/** Fills in the set of no-qualification classes*/
|
||||
void getBaseClassInstances(set<int> &base) const;
|
||||
};
|
||||
@ -10,14 +10,16 @@
|
||||
#define IDI_SMALL 108
|
||||
#define IDC_MEOS 109
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDB_ECO 131
|
||||
#define IDR_HTML1 132
|
||||
#define IDC_STATIC -1
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 131
|
||||
#define _APS_NEXT_RESOURCE_VALUE 133
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 110
|
||||
|
||||
@ -31,11 +31,14 @@ Eksoppsv
|
||||
#include "infoserver.h"
|
||||
#include <chrono>
|
||||
|
||||
#include "oListInfo.h"
|
||||
#include "TabList.h"
|
||||
#include "generalresult.h"
|
||||
|
||||
using namespace restbed;
|
||||
|
||||
vector< shared_ptr<RestServer> > RestServer::startedServers;
|
||||
|
||||
|
||||
shared_ptr<RestServer> RestServer::construct() {
|
||||
shared_ptr<RestServer> obj(new RestServer());
|
||||
startedServers.push_back(obj);
|
||||
@ -43,7 +46,13 @@ shared_ptr<RestServer> RestServer::construct() {
|
||||
}
|
||||
|
||||
void RestServer::remove(shared_ptr<RestServer> server) {
|
||||
// xxx std::remove(startedServers.begin(), startedServers.end(), server);
|
||||
//std::remove(startedServers.begin(), startedServers.end(), server);
|
||||
for (size_t k = 0; k < startedServers.size(); k++) {
|
||||
if (startedServers[k] == server) {
|
||||
startedServers.erase(startedServers.begin() + k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RestServer::RestServer() : hasAnyRequest(false) {
|
||||
@ -142,21 +151,18 @@ void RestServer::compute(oEvent &ref) {
|
||||
auto rq = getRequest();
|
||||
if (!rq)
|
||||
return;
|
||||
if (rq->parameters.empty()) {
|
||||
rq->answer = "<html><head>"
|
||||
"<title>MeOS Information Service</title>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<h2>MeOS</h2>"
|
||||
"</body>"
|
||||
"</html>";
|
||||
|
||||
try {
|
||||
computeInternal(ref, rq);
|
||||
}
|
||||
else if (rq->parameters.count("get") > 0) {
|
||||
string what = rq->parameters.find("get")->second;
|
||||
getData(ref, what, rq->parameters, rq->answer);
|
||||
catch (meosException &ex) {
|
||||
rq->answer = "Error (MeOS): Error: " + ref.gdiBase().toUTF8(lang.tl(ex.wwhat()));
|
||||
}
|
||||
else {
|
||||
rq->answer = "Error (MeOS): Unknown request";
|
||||
catch (std::exception &ex) {
|
||||
rq->answer = "Error (MeOS): General Error: " + string(ex.what());
|
||||
}
|
||||
catch (...) {
|
||||
rq->answer = "Error (MeOS): Unknown internal error.";
|
||||
}
|
||||
|
||||
{
|
||||
@ -166,39 +172,594 @@ void RestServer::compute(oEvent &ref) {
|
||||
waitForCompletion.notify_all();
|
||||
}
|
||||
|
||||
|
||||
void RestServer::computeInternal(oEvent &ref, shared_ptr<RestServer::EventRequest> &rq) {
|
||||
if (rq->parameters.empty()) {
|
||||
rq->answer = "<html><head>"
|
||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset = UTF-8\">"
|
||||
"<title>MeOS Information Service</title>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<h2>MeOS</h2><p>" + ref.gdiBase().toUTF8(lang.tl(getMeosFullVersion())) + "<p>"
|
||||
"<ul>\n";
|
||||
|
||||
vector<oListParam> lists;
|
||||
TabList::getPublicLists(ref, lists);
|
||||
map<EStdListType, oListInfo> listMap;
|
||||
ref.getListTypes(listMap, false);
|
||||
for (auto &lp : lists) {
|
||||
wstring n = lp.getName();
|
||||
if (n.empty()) {
|
||||
n = listMap[lp.listCode].getName();
|
||||
}
|
||||
lp.setName(n);
|
||||
|
||||
int keyCand = lp.listCode * 100;
|
||||
bool done = false;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (!listCache.count(keyCand + i)) {
|
||||
keyCand += i;
|
||||
listCache[keyCand].first = lp;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
else if(listCache[keyCand + i].first == lp) {
|
||||
keyCand = keyCand + i;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
listCache[keyCand].first = lp;
|
||||
listCache[keyCand].second.reset();
|
||||
}
|
||||
|
||||
rq->answer += "<li><a href=\"?html=1&type=" + itos(keyCand) + "\">" + ref.gdiBase().toUTF8(n) + "</a></li>\n";
|
||||
}
|
||||
// "<li><a href=\"?html=1&result=1\">Resultat</a></li>"
|
||||
// "<li><a href=\"?html=1&startlist=1\">Startlista</a></li>"
|
||||
rq->answer += "</ul>\n";
|
||||
|
||||
HINSTANCE hInst = GetModuleHandle(0);
|
||||
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(132), RT_HTML);
|
||||
HGLOBAL res = LoadResource(hInst, hRes);
|
||||
char *html = (char *)LockResource(res);
|
||||
int resSize = SizeofResource(hInst, hRes);
|
||||
|
||||
if (html) {
|
||||
string htmlS;
|
||||
while (*html != 0 && resSize > 0) {
|
||||
if (*html == '*')
|
||||
htmlS += "<";
|
||||
else if (*html == '#')
|
||||
htmlS += "&";
|
||||
else
|
||||
htmlS += *html;
|
||||
++html;
|
||||
resSize--;
|
||||
}
|
||||
|
||||
rq->answer += htmlS;
|
||||
}
|
||||
|
||||
rq->answer += "\n</body></html>\n";
|
||||
}
|
||||
else if (rq->parameters.count("get") > 0) {
|
||||
string what = rq->parameters.find("get")->second;
|
||||
getData(ref, what, rq->parameters, rq->answer);
|
||||
}
|
||||
else if (rq->parameters.count("html") > 0) {
|
||||
string stype = rq->parameters.count("type") ? rq->parameters.find("type")->second : _EmptyString;
|
||||
int type = atoi(stype.c_str());
|
||||
auto res = listCache.find(type);
|
||||
|
||||
if (res != listCache.end()) {
|
||||
gdioutput gdiPrint("print", ref.gdiBase().getScale(), ref.gdiBase().getCP());
|
||||
gdiPrint.clearPage(false);
|
||||
|
||||
if (!res->second.second) {
|
||||
res->second.second = make_shared<oListInfo>();
|
||||
ref.generateListInfo(res->second.first, gdiPrint.getLineHeight(), *res->second.second);
|
||||
}
|
||||
ref.generateList(gdiPrint, true, *res->second.second, false);
|
||||
wstring exportFile = getTempFile();
|
||||
gdiPrint.writeHTML(exportFile, ref.getName(), 30);
|
||||
ifstream fin(exportFile.c_str());
|
||||
string rbf;
|
||||
while (std::getline(fin, rbf)) {
|
||||
rq->answer += rbf;
|
||||
}
|
||||
removeTempFile(exportFile);
|
||||
}
|
||||
else {
|
||||
rq->answer = "Error (MeOS): Unknown list";
|
||||
}
|
||||
}
|
||||
else {
|
||||
rq->answer = "Error (MeOS): Unknown request";
|
||||
}
|
||||
}
|
||||
|
||||
void writePerson(const GeneralResult::GeneralResultInfo &res,
|
||||
xmlbuffer &reslist,
|
||||
bool includeTeam,
|
||||
bool includeCourse,
|
||||
vector< pair<string, wstring> > &rProp) {
|
||||
int clsId = res.src->getClassId(true);
|
||||
rProp.push_back(make_pair("cls", itow(clsId)));
|
||||
if (includeCourse) {
|
||||
pRunner pr = dynamic_cast<pRunner>(res.src);
|
||||
if (pr && pr->getCourse(false))
|
||||
rProp.push_back(make_pair("course", itow(pr->getCourse(false)->getId())));
|
||||
}
|
||||
bool hasTeam = res.src->getTeam() != 0 &&
|
||||
clsId == res.src->getClassId(false) && // No Qualification/Final
|
||||
(clsId == 0 || res.src->getClassRef(false)->getQualificationFinal() == 0); // // No Qualification/Final
|
||||
|
||||
if (includeTeam && hasTeam)
|
||||
rProp.push_back(make_pair("team", itow(res.src->getTeam()->getId())));
|
||||
|
||||
if (hasTeam)
|
||||
rProp.push_back(make_pair("leg", itow(1+pRunner(res.src)->getLegNumber())));
|
||||
|
||||
rProp.push_back(make_pair("stat", itow(res.status)));
|
||||
|
||||
if (res.score > 0)
|
||||
rProp.push_back(make_pair("score", itow(res.score)));
|
||||
|
||||
rProp.push_back(make_pair("st", itow(10 * (res.src->getStartTime() + res.src->getEvent()->getZeroTimeNum()))));
|
||||
|
||||
if (res.src->getClassRef(false) == 0 || !res.src->getClassRef(true)->getNoTiming()) {
|
||||
if (res.time > 0)
|
||||
rProp.push_back(make_pair("rt", itow(10 * res.time)));
|
||||
if (res.place > 0)
|
||||
rProp.push_back(make_pair("place", itow(res.place)));
|
||||
}
|
||||
|
||||
auto &subTag = reslist.startTag("person", rProp);
|
||||
rProp.clear();
|
||||
rProp.push_back(make_pair("id", itow(res.src->getId())));
|
||||
subTag.write("name", rProp, res.src->getName());
|
||||
rProp.clear();
|
||||
|
||||
if (res.src->getClubRef()) {
|
||||
rProp.push_back(make_pair("id", itow(res.src->getClubId())));
|
||||
subTag.write("org", rProp, res.src->getClub());
|
||||
rProp.clear();
|
||||
}
|
||||
|
||||
subTag.endTag();
|
||||
}
|
||||
|
||||
void RestServer::getData(oEvent &oe, const string &what, const multimap<string, string> ¶m, string &answer) {
|
||||
xmlbuffer out;
|
||||
out.setComplete(true);
|
||||
bool okRequest = false;
|
||||
if (what == "iofresult") {
|
||||
wstring exportFile = getTempFile();
|
||||
bool useUTC = false;
|
||||
set<int> cls;
|
||||
if (param.count("class") > 0)
|
||||
getSelection(param.find("class")->second, cls);
|
||||
|
||||
if (what == "competition") {
|
||||
oe.exportIOFSplits(oEvent::IOF30, exportFile.c_str(), false, useUTC, cls, -1, false, false, true, false);
|
||||
ifstream fin(exportFile.c_str());
|
||||
string rbf;
|
||||
while (std::getline(fin, rbf)) {
|
||||
answer += rbf;
|
||||
}
|
||||
removeTempFile(exportFile);
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "iofstart") {
|
||||
wstring exportFile = getTempFile();
|
||||
bool useUTC = false;
|
||||
set<int> cls;
|
||||
if (param.count("class") > 0)
|
||||
getSelection(param.find("class")->second, cls);
|
||||
|
||||
oe.exportIOFStartlist(oEvent::IOF30, exportFile.c_str(), useUTC, cls, false, true, false);
|
||||
ifstream fin(exportFile.c_str());
|
||||
string rbf;
|
||||
while (std::getline(fin, rbf)) {
|
||||
answer += rbf;
|
||||
}
|
||||
removeTempFile(exportFile);
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "competition") {
|
||||
InfoCompetition cmp(0);
|
||||
cmp.synchronize(oe);
|
||||
cmp.serialize(out, false);
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "class") {
|
||||
vector<pClass> cls;
|
||||
oe.getClasses(cls, true);
|
||||
|
||||
set<int> ctrlW;
|
||||
vector<pControl> ctrl;
|
||||
oe.getControls(ctrl, true);
|
||||
for (size_t k = 0; k < ctrl.size(); k++) {
|
||||
if (ctrl[k]->isValidRadio()) {
|
||||
vector<int> cc;
|
||||
ctrl[k]->getCourseControls(cc);
|
||||
ctrlW.insert(cc.begin(), cc.end());
|
||||
}
|
||||
}
|
||||
for (auto c : cls) {
|
||||
InfoClass iCls(c->getId());
|
||||
set<int> ctrl;
|
||||
iCls.synchronize(*c, ctrl);
|
||||
iCls.synchronize(*c, ctrlW);
|
||||
iCls.serialize(out, false);
|
||||
}
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "organization") {
|
||||
vector<pClub> clb;
|
||||
oe.getClubs(clb, true);
|
||||
for (auto c : clb) {
|
||||
InfoOrganization iClb(c->getId());
|
||||
iClb.synchronize(*c);
|
||||
iClb.serialize(out, false);
|
||||
}
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "competitor") {
|
||||
vector<pRunner> r;
|
||||
set<int> selection;
|
||||
if (param.count("id") > 0)
|
||||
getSelection(param.find("id")->second, selection);
|
||||
if (param.count("class") > 0)
|
||||
getSelection(param.find("class")->second, selection);
|
||||
|
||||
oe.getRunners(selection.size() == 1 ? *selection.begin() : 0, -1, r, true);
|
||||
|
||||
{
|
||||
vector<pRunner> r2;
|
||||
r2.reserve(r.size());
|
||||
for (pRunner tr : r) {
|
||||
pClass cls = tr->getClassRef(true);
|
||||
if (cls && cls->getQualificationFinal() && tr->getLegNumber() != 0)
|
||||
continue;
|
||||
if (selection.empty() || (cls && selection.count(cls->getId())))
|
||||
r2.push_back(tr);
|
||||
}
|
||||
r.swap(r2);
|
||||
}
|
||||
|
||||
for (auto c : r) {
|
||||
InfoCompetitor iR(c->getId());
|
||||
iR.synchronize(false, *c);
|
||||
iR.serialize(out, false);
|
||||
}
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "team") {
|
||||
vector<pTeam> teams;
|
||||
set<int> selection;
|
||||
if (param.count("class") > 0)
|
||||
getSelection(param.find("class")->second, selection);
|
||||
|
||||
oe.getTeams(selection.size() == 1 ? *selection.begin() : 0, teams, true);
|
||||
|
||||
if (selection.size() > 1) {
|
||||
vector<pTeam> r2;
|
||||
r2.reserve(teams.size());
|
||||
for (pTeam tr : teams) {
|
||||
if (selection.count(tr->getClassId(false)))
|
||||
r2.push_back(tr);
|
||||
}
|
||||
teams.swap(r2);
|
||||
}
|
||||
|
||||
for (auto c : teams) {
|
||||
InfoTeam iT(c->getId());
|
||||
iT.synchronize(*c);
|
||||
iT.serialize(out, false);
|
||||
}
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "control") {
|
||||
vector<pControl> ctrl;
|
||||
oe.getControls(ctrl, true);
|
||||
vector< pair<string, wstring> > prop(1);
|
||||
prop[0].first = "id";
|
||||
for (pControl c : ctrl) {
|
||||
int nd = c->getNumberDuplicates();
|
||||
for (int k = 0; k < nd; k++) {
|
||||
prop[0].second = itow(oControl::getCourseControlIdFromIdIndex(c->getId(), k));
|
||||
if (nd > 1)
|
||||
out.write("control", prop, c->getName() + L"-" + itow(k+1));
|
||||
else
|
||||
out.write("control", prop, c->getName());
|
||||
}
|
||||
}
|
||||
okRequest = true;
|
||||
}
|
||||
else if (what == "result") {
|
||||
okRequest = true;
|
||||
vector<pRunner> r;
|
||||
set<int> selection;
|
||||
pClass sampleClass = 0;
|
||||
if (param.count("class") > 0) {
|
||||
getSelection(param.find("class")->second, selection);
|
||||
if (!selection.empty())
|
||||
sampleClass = oe.getClass(*selection.begin());
|
||||
}
|
||||
|
||||
if (sampleClass == 0) {
|
||||
vector<pClass> tt;
|
||||
oe.getClasses(tt, false);
|
||||
if (!tt.empty())
|
||||
sampleClass = tt[0];
|
||||
}
|
||||
|
||||
string resTag;
|
||||
if (param.count("module") > 0)
|
||||
resTag = param.find("module")->second;
|
||||
|
||||
pair<int,int> controlId(oPunch::PunchStart, oPunch::PunchFinish);
|
||||
bool totalResult = false;
|
||||
if (param.count("total")) {
|
||||
const string &tot = param.find("total")->second;
|
||||
totalResult = atoi(tot.c_str()) > 0 || _stricmp(tot.c_str(), "true") == 0;
|
||||
}
|
||||
|
||||
if (param.count("to")) {
|
||||
const string &cid = param.find("to")->second;
|
||||
|
||||
controlId.second = atoi(cid.c_str());
|
||||
if (controlId.second == 0)
|
||||
controlId.second = oControl::getControlIdByName(oe, cid);
|
||||
|
||||
if (controlId.second == 0)
|
||||
throw meosException("Unknown control: " + cid);
|
||||
}
|
||||
|
||||
if (param.count("from")) {
|
||||
const string &cid = param.find("from")->second;
|
||||
|
||||
controlId.first = atoi(cid.c_str());
|
||||
if (controlId.first == 0)
|
||||
controlId.first = oControl::getControlIdByName(oe, cid);
|
||||
|
||||
if (controlId.first == 0)
|
||||
throw meosException("Unknown control: " + cid);
|
||||
}
|
||||
|
||||
oListInfo::ResultType resType = oListInfo::Classwise;
|
||||
wstring resTypeStr = L"classindividual";
|
||||
|
||||
ClassType ct = sampleClass ? sampleClass->getClassType() : ClassType::oClassIndividual;
|
||||
bool team = ct == oClassPatrol || ct == oClassRelay;
|
||||
int limit = 100000;
|
||||
if (param.count("limit")) {
|
||||
limit = atoi(param.find("limit")->second.c_str());
|
||||
if (limit <= 0)
|
||||
throw meosException("Invalid limit: " + param.find("limit")->second);
|
||||
}
|
||||
|
||||
if (param.count("type")) {
|
||||
string type = param.find("type")->second;
|
||||
|
||||
if (type == "GlobalIndividual") {
|
||||
resType = oListInfo::Global;
|
||||
team = false;
|
||||
}
|
||||
else if (type == "ClassIndividual") {
|
||||
resType = oListInfo::Classwise;
|
||||
team = false;
|
||||
}
|
||||
else if (type == "CourseIndividual") {
|
||||
resType = oListInfo::Coursewise;
|
||||
team = false;
|
||||
}
|
||||
else if (type == "LegIndividual") {
|
||||
resType = oListInfo::Legwise;
|
||||
team = false;
|
||||
}
|
||||
else if (type == "GlobalTeam") {
|
||||
resType = oListInfo::Global;
|
||||
team = true;
|
||||
}
|
||||
else if (type == "ClassTeam") {
|
||||
resType = oListInfo::Classwise;
|
||||
team = true;
|
||||
}
|
||||
else
|
||||
throw meosException("Unknown type: " + type);
|
||||
|
||||
string2Wide(type, resTypeStr);
|
||||
resTypeStr = canonizeName(resTypeStr.c_str());
|
||||
}
|
||||
else if (team) {
|
||||
resTypeStr = L"classteam";
|
||||
}
|
||||
|
||||
int inputNumber = 0;
|
||||
|
||||
|
||||
if (param.count("argument")) {
|
||||
const string &arg = param.find("argument")->second;
|
||||
inputNumber = atoi(arg.c_str());
|
||||
}
|
||||
|
||||
vector<GeneralResult::GeneralResultInfo> results;
|
||||
vector< pair<string, wstring> > prop, noProp, rProp;
|
||||
|
||||
prop.push_back(make_pair("type", resTypeStr));
|
||||
|
||||
int leg = -1;
|
||||
if (param.count("leg") > 0) {
|
||||
string legs = param.find("leg")->second;
|
||||
leg = atoi(legs.c_str())-1;
|
||||
if (leg < 0 || leg > 32)
|
||||
throw meosException("Invalid leg: " + legs);
|
||||
}
|
||||
|
||||
if (ct == oClassRelay) {
|
||||
if (leg == -1)
|
||||
prop.push_back(make_pair("leg", L"Last"));
|
||||
else
|
||||
prop.push_back(make_pair("leg", itow(leg + 1)));
|
||||
}
|
||||
|
||||
if (!resTag.empty())
|
||||
prop.push_back(make_pair("module", oe.gdiBase().widen(resTag) + L"(" + itow(inputNumber) + L")"));
|
||||
|
||||
if (controlId.first != oPunch::PunchStart) {
|
||||
pair<int, int> idIx = oControl::getIdIndexFromCourseControlId(controlId.first);
|
||||
pControl ctrl = oe.getControl(idIx.first);
|
||||
if (ctrl == 0)
|
||||
throw meosException("Unknown control: " + itos(idIx.first));
|
||||
|
||||
wstring loc = ctrl->getName();
|
||||
if (idIx.second > 0)
|
||||
loc += L"-" + itow(idIx.second + 1);
|
||||
|
||||
prop.push_back(make_pair("from", loc));
|
||||
}
|
||||
|
||||
if (controlId.second == oPunch::PunchFinish)
|
||||
prop.push_back(make_pair("to", L"Finish"));
|
||||
else {
|
||||
pair<int, int> idIx = oControl::getIdIndexFromCourseControlId(controlId.second);
|
||||
pControl ctrl = oe.getControl(idIx.first);
|
||||
if (ctrl == 0)
|
||||
throw meosException("Unknown control: " + itos(idIx.first));
|
||||
|
||||
wstring loc = ctrl->getName();
|
||||
if (idIx.second > 0)
|
||||
loc += L"-" + itow(idIx.second+1);
|
||||
|
||||
prop.push_back(make_pair("to", loc));
|
||||
}
|
||||
|
||||
if (!team) {
|
||||
oe.getRunners(selection.size() == 1 ? *selection.begin() : 0, -1, r, false);
|
||||
|
||||
{
|
||||
vector<pRunner> r2;
|
||||
r2.reserve(r.size());
|
||||
for (pRunner tr : r) {
|
||||
pClass cls = tr->getClassRef(true);
|
||||
if (cls && cls->getQualificationFinal() && tr->getLegNumber() != 0)
|
||||
continue;
|
||||
if (selection.empty() || (cls && selection.count(cls->getId())))
|
||||
r2.push_back(tr);
|
||||
}
|
||||
r.swap(r2);
|
||||
}
|
||||
|
||||
GeneralResult::calculateIndividualResults(r, controlId, totalResult, resTag, resType, inputNumber, oe, results);
|
||||
|
||||
if (resType == oListInfo::Classwise)
|
||||
sort(results.begin(), results.end());
|
||||
/*else if (resType == oListInfo::Coursewise) {
|
||||
sort(results.begin(), results.end(),
|
||||
[](const GeneralResult::GeneralResultInfo &a, const GeneralResult::GeneralResultInfo &b)->
|
||||
bool {
|
||||
pCourse ac = dynamic_cast<const oRunner &>(*a.src).getCourse(false);
|
||||
pCourse bc = dynamic_cast<const oRunner &>(*b.src).getCourse(false);
|
||||
if (ac != bc)
|
||||
return ac->getId() < bc->getId();
|
||||
|
||||
return a.compareResult(b);
|
||||
}
|
||||
);
|
||||
}*/
|
||||
auto &reslist = out.startTag("results", prop);
|
||||
|
||||
int place = -1;
|
||||
int cClass = -1;
|
||||
int counter = 0;
|
||||
for (const auto &res : results) {
|
||||
if (res.src->getClassId(true) != cClass) {
|
||||
counter = 0;
|
||||
place = 1;
|
||||
cClass = res.src->getClassId(true);
|
||||
}
|
||||
if (++counter > limit && (place != res.place || res.status != StatusOK))
|
||||
continue;
|
||||
place = res.place;
|
||||
writePerson(res, reslist, true, resType == oListInfo::Coursewise, rProp);
|
||||
}
|
||||
reslist.endTag();
|
||||
}
|
||||
else {
|
||||
//Teams
|
||||
vector<pTeam> teams;
|
||||
oe.getTeams(selection.size() == 1 ? *selection.begin() : 0, teams, true);
|
||||
|
||||
if (selection.size() > 1) {
|
||||
vector<pTeam> r2;
|
||||
r2.reserve(teams.size());
|
||||
for (pTeam tr : teams) {
|
||||
if (selection.count(tr->getClassId(true)))
|
||||
r2.push_back(tr);
|
||||
}
|
||||
teams.swap(r2);
|
||||
}
|
||||
auto context = GeneralResult::calculateTeamResults(teams, leg, controlId, totalResult, resTag, resType, inputNumber, oe, results);
|
||||
|
||||
sort(results.begin(), results.end());
|
||||
auto &reslist = out.startTag("results", prop);
|
||||
|
||||
int place = -1;
|
||||
int cClass = -1;
|
||||
int counter = 0;
|
||||
for (const auto &res : results) {
|
||||
pTeam team = pTeam(res.src);
|
||||
if (leg >= team->getNumRunners())
|
||||
continue;
|
||||
|
||||
if (res.src->getClassId(true) != cClass) {
|
||||
counter = 0;
|
||||
place = 1;
|
||||
cClass = res.src->getClassId(true);
|
||||
}
|
||||
if (++counter > limit && (place != res.place || res.status != StatusOK))
|
||||
continue;
|
||||
place = res.place;
|
||||
|
||||
rProp.push_back(make_pair("cls", itow(res.src->getClassId(true))));
|
||||
rProp.push_back(make_pair("stat", itow(res.status)));
|
||||
if (res.score > 0)
|
||||
rProp.push_back(make_pair("score", itow(res.score)));
|
||||
|
||||
if (res.src->getStartTime() > 0)
|
||||
rProp.push_back(make_pair("st", itow(10 * (res.src->getStartTime() + oe.getZeroTimeNum()))));
|
||||
|
||||
if (res.src->getClassRef(false) == 0 || !res.src->getClassRef(true)->getNoTiming()) {
|
||||
if (res.time > 0)
|
||||
rProp.push_back(make_pair("rt", itow(10 * res.time)));
|
||||
if (res.place > 0)
|
||||
rProp.push_back(make_pair("place", itow(res.place)));
|
||||
}
|
||||
|
||||
auto &subTag = reslist.startTag("team", rProp);
|
||||
rProp.clear();
|
||||
rProp.push_back(make_pair("id", itow(res.src->getId())));
|
||||
subTag.write("name", rProp, res.src->getName());
|
||||
rProp.clear();
|
||||
|
||||
if (res.src->getClubRef()) {
|
||||
rProp.push_back(make_pair("id", itow(res.src->getClubId())));
|
||||
subTag.write("org", rProp, res.src->getClub());
|
||||
rProp.clear();
|
||||
}
|
||||
|
||||
int subRes = res.getNumSubresult(*context);
|
||||
GeneralResult::GeneralResultInfo out;
|
||||
|
||||
for (int k = 0; k < subRes; k++) {
|
||||
if (res.getSubResult(*context, k, out)) {
|
||||
writePerson(out, subTag, false, false, rProp);
|
||||
}
|
||||
}
|
||||
|
||||
subTag.endTag();
|
||||
}
|
||||
reslist.endTag();
|
||||
|
||||
}
|
||||
}
|
||||
if (out.size() > 0) {
|
||||
xmlparser mem;
|
||||
@ -208,7 +769,7 @@ void RestServer::getData(oEvent &oe, const string &what, const multimap<string,
|
||||
mem.endTag();
|
||||
mem.getMemoryOutput(answer);
|
||||
}
|
||||
else {
|
||||
else if (!okRequest) {
|
||||
answer = "Error (MeOS): Unknown command '" + what + "'";
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +75,11 @@ private:
|
||||
|
||||
RestServer(const RestServer &);
|
||||
RestServer & operator=(const RestServer &) const;
|
||||
|
||||
|
||||
void computeInternal(oEvent &ref, shared_ptr<RestServer::EventRequest> &rq);
|
||||
|
||||
map<int, pair<oListParam, shared_ptr<oListInfo> > > listCache;
|
||||
public:
|
||||
|
||||
~RestServer();
|
||||
|
||||
@ -194,7 +194,7 @@ void SpeakerMonitor::renderResult(gdioutput &gdi,
|
||||
|
||||
int dx = 0;
|
||||
if (showClass) {
|
||||
pClass pc = res.r->getClassRef();
|
||||
pClass pc = res.r->getClassRef(true);
|
||||
if (pc) {
|
||||
gdi.addStringUT(yp, xp + timeWidth, fontMediumPlus, pc->getName());
|
||||
dx = classWidth;
|
||||
@ -243,7 +243,7 @@ void SpeakerMonitor::renderResult(gdioutput &gdi,
|
||||
}
|
||||
else {
|
||||
if (showClass) {
|
||||
pClass pc = res.r->getClassRef();
|
||||
pClass pc = res.r->getClassRef(true);
|
||||
if (pc)
|
||||
msg += L" (" + pc->getName() + L") ";
|
||||
else
|
||||
@ -412,7 +412,7 @@ wstring getTimeDesc(int t1, int t2) {
|
||||
|
||||
void SpeakerMonitor::getMessage(const oEvent::ResultEvent &res,
|
||||
wstring &message, deque<wstring> &details) {
|
||||
pClass cls = res.r->getClassRef();
|
||||
pClass cls = res.r->getClassRef(true);
|
||||
if (!cls)
|
||||
return;
|
||||
|
||||
@ -605,10 +605,10 @@ void SpeakerMonitor::getMessage(const oEvent::ResultEvent &res,
|
||||
details.push_back(share);
|
||||
}
|
||||
}
|
||||
if (changeover && res.r->getTeam() && res.r->getTeam()->getClassRef() != 0) {
|
||||
if (changeover && res.r->getTeam() && res.r->getTeam()->getClassRef(true) != 0) {
|
||||
wstring vxl = L"skickar ut X.#";
|
||||
pTeam t = res.r->getTeam();
|
||||
pClass cls = t->getClassRef();
|
||||
pClass cls = t->getClassRef(true);
|
||||
bool second = false;
|
||||
int nextLeg = cls->getNextBaseLeg(res.r->getLegNumber());
|
||||
if (nextLeg > 0) {
|
||||
|
||||
@ -2279,3 +2279,19 @@ ask:updatetimes = Vill du behålla nuvarande starttider, om möjligt? Svara nej
|
||||
X har en tid (Y) som inte är kompatibel med förändringen = X har en tid (Y) som inte är kompatibel med förändringen
|
||||
warn:latestarttime = Att använda starttider mer än X timmar efter nolltiden rekommenderas inte eftersom äldre SI brickor endast har en 12-timmarsklocka.\n\nVill du ändå använda starttiden?
|
||||
Anm. tid = Anm. tid
|
||||
Ekonomihantering, X = Ekonomihantering, X
|
||||
Manuellt gjorda justeringar = Manuellt gjorda justeringar
|
||||
Antal förfrågningar: X = Antal förfrågningar: X
|
||||
Genomsnittlig svarstid: X ms = Genomsnittlig svarstid: X ms
|
||||
Informationsserver = Informationsserver
|
||||
Längsta svarstid: X ms = Längsta svarstid: X ms
|
||||
MeOS Informationsserver REST-API = MeOS Informationsserver REST-API
|
||||
RestService = RestService
|
||||
Server startad på port X = Server startad på port X
|
||||
Testa servern = Testa servern
|
||||
help:rest = MeOS REST API låter dig komma åt tävlingsdata via en webbanslutning. Du kan visa resultatlistor direkt i en webbläsare, men du kan också komma åt tävlingsdata och resultat i XML-format för vidare behandling andra program och appar.
|
||||
Server startad på X = Server startad på X
|
||||
Inconsistent qualification rule, X = Inkonsekvent kvalifikationsregel, X
|
||||
help:LockStartList = MeOS uppdaterar inte löparna i en låst klass även om kvalificeringsresultaten ändras.
|
||||
Kval-Final-Schema = Kval-Final-Schema
|
||||
Lås startlista = Lås startlista
|
||||
|
||||
Loading…
Reference in New Issue
Block a user