MeOS version 3.6.1069
This commit is contained in:
parent
e8e5e499f2
commit
55d526c3e4
@ -46,6 +46,8 @@ void RestService::save(oEvent &oe, gdioutput &gdi) {
|
|||||||
|
|
||||||
int xport = gdi.getTextNo("Port");
|
int xport = gdi.getTextNo("Port");
|
||||||
if (xport > 0 && xport < 65536) {
|
if (xport > 0 && xport < 65536) {
|
||||||
|
oe.setProperty("ServicePort", xport);
|
||||||
|
|
||||||
port = xport;
|
port = xport;
|
||||||
server->startService(port);
|
server->startService(port);
|
||||||
}
|
}
|
||||||
@ -53,6 +55,12 @@ void RestService::save(oEvent &oe, gdioutput &gdi) {
|
|||||||
throw meosException("Invalid port number");
|
throw meosException("Invalid port number");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gdi.isChecked("MapRoot")) {
|
||||||
|
rootMap = gdi.recodeToNarrow(gdi.getText("RootMap"));
|
||||||
|
server->setRootMap(rootMap);
|
||||||
|
oe.setProperty("ServiceRootMap", gdi.getText("RootMap"));
|
||||||
|
}
|
||||||
|
|
||||||
if (gdi.isChecked("AllowEntry")) {
|
if (gdi.isChecked("AllowEntry")) {
|
||||||
RestServer::EntryPermissionType pt = (RestServer::EntryPermissionType)gdi.getSelectedItem("PermissionPerson").first;
|
RestServer::EntryPermissionType pt = (RestServer::EntryPermissionType)gdi.getSelectedItem("PermissionPerson").first;
|
||||||
RestServer::EntryPermissionClass pc = (RestServer::EntryPermissionClass)gdi.getSelectedItem("PermissionClass").first;
|
RestServer::EntryPermissionClass pc = (RestServer::EntryPermissionClass)gdi.getSelectedItem("PermissionClass").first;
|
||||||
@ -67,9 +75,10 @@ void RestService::save(oEvent &oe, gdioutput &gdi) {
|
|||||||
void ListIpAddresses(vector<string>& ip);
|
void ListIpAddresses(vector<string>& ip);
|
||||||
|
|
||||||
void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||||
if (port == -1)
|
if (port == -1) {
|
||||||
port = oe.getPropertyInt("ServicePort", 2009);
|
port = oe.getPropertyInt("ServicePort", 2009);
|
||||||
|
rootMap = oe.getPropertyString("ServiceRootMap", "");
|
||||||
|
}
|
||||||
settingsTitle(gdi, "MeOS Informationsserver REST-API");
|
settingsTitle(gdi, "MeOS Informationsserver REST-API");
|
||||||
|
|
||||||
//gdi.fillRight();
|
//gdi.fillRight();
|
||||||
@ -87,10 +96,15 @@ void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
|||||||
bool disablePermisson = true;
|
bool disablePermisson = true;
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
|
gdi.addCheckbox("MapRoot", "Mappa rootadresssen (http:///localhost:port/) till funktion:", nullptr, !rootMap.empty()).setHandler(this);
|
||||||
|
gdi.addInput("RootMap", gdi.recodeToWide(rootMap));
|
||||||
|
gdi.setInputStatus("RootMap", !rootMap.empty());
|
||||||
|
|
||||||
startCancelInterval(gdi, "Save", created, IntervalNone, L"");
|
startCancelInterval(gdi, "Save", created, IntervalNone, L"");
|
||||||
|
|
||||||
if (!server)
|
if (!server) {
|
||||||
gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"#http://localhost:[PORT]/meos");
|
gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"#http://localhost:[PORT]/meos");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
gdi.addString("", 0, "Server startad på X#" + itos(port));
|
gdi.addString("", 0, "Server startad på X#" + itos(port));
|
||||||
auto per = server->getEntryPermission();
|
auto per = server->getEntryPermission();
|
||||||
@ -180,6 +194,9 @@ void RestService::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
|
|||||||
gdi.setInputStatus("PermissionPerson", gdi.isChecked(bi.id));
|
gdi.setInputStatus("PermissionPerson", gdi.isChecked(bi.id));
|
||||||
gdi.setInputStatus("PermissionClass", gdi.isChecked(bi.id));
|
gdi.setInputStatus("PermissionClass", gdi.isChecked(bi.id));
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "MapRoot") {
|
||||||
|
gdi.setInputStatus("RootMap", gdi.isChecked(bi.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type == GUI_LINK) {
|
else if (type == GUI_LINK) {
|
||||||
wstring url = ((TextInfo &)info).text;
|
wstring url = ((TextInfo &)info).text;
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class RestService :
|
|||||||
{
|
{
|
||||||
int port;
|
int port;
|
||||||
shared_ptr<RestServer> server;
|
shared_ptr<RestServer> server;
|
||||||
|
string rootMap;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void save(oEvent &oe, gdioutput &gdi) override;
|
void save(oEvent &oe, gdioutput &gdi) override;
|
||||||
|
|||||||
@ -1040,7 +1040,7 @@ void PunchMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
|||||||
auto pc = r->getCourse(false);
|
auto pc = r->getCourse(false);
|
||||||
if (radio < 10 || pc->hasControlCode(radio)) {
|
if (radio < 10 || pc->hasControlCode(radio)) {
|
||||||
pp.clear();
|
pp.clear();
|
||||||
oe->getPunchesForRunner(r->getId(), pp);
|
oe->getPunchesForRunner(r->getId(), false, pp);
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
for (auto p : pp) {
|
for (auto p : pp) {
|
||||||
if (p->getTypeCode() == radio)
|
if (p->getTypeCode() == radio)
|
||||||
|
|||||||
@ -467,9 +467,11 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
oe->setupRelay(*pc, newType, nstages, st);
|
oe->setupRelay(*pc, newType, nstages, st);
|
||||||
|
|
||||||
if (gdi.hasField("MAdd")) {
|
if (gdi.hasField("MAdd")) {
|
||||||
gdi.enableInput("MAdd");
|
for (const char *s : {"MCourses", "StageCourses", "MAdd", "MRemove", "MUp", "MDown"}) {
|
||||||
gdi.enableInput("MCourses");
|
if (gdi.hasField(s)) {
|
||||||
gdi.enableInput("MRemove");
|
gdi.enableInput(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pc->forceShowMultiDialog(true);
|
pc->forceShowMultiDialog(true);
|
||||||
selectClass(gdi, pc->getId());
|
selectClass(gdi, pc->getId());
|
||||||
@ -506,11 +508,21 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
if (gdi.getSelectedItem("MCourses", lbi)) {
|
if (gdi.getSelectedItem("MCourses", lbi)) {
|
||||||
int courseid=lbi.data;
|
int courseid=lbi.data;
|
||||||
|
|
||||||
pc->addStageCourse(currentStage, courseid);
|
int ix = -1;
|
||||||
|
ListBoxInfo selS;
|
||||||
|
if (gdi.getSelectedItem("StageCourses", selS)) {
|
||||||
|
ix = selS.index+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc->addStageCourse(currentStage, courseid, ix);
|
||||||
pc->fillStageCourses(gdi, currentStage, "StageCourses");
|
pc->fillStageCourses(gdi, currentStage, "StageCourses");
|
||||||
|
if (ix != -1)
|
||||||
|
gdi.selectItemByIndex("StageCourses", ix);
|
||||||
|
|
||||||
pc->synchronize();
|
pc->synchronize();
|
||||||
oe->checkOrderIdMultipleCourses(cid);
|
oe->checkOrderIdMultipleCourses(cid);
|
||||||
|
|
||||||
|
setLockForkingState(gdi, *pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EditChanged=true;
|
EditChanged=true;
|
||||||
@ -530,18 +542,67 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
ListBoxInfo lbi;
|
ListBoxInfo lbi;
|
||||||
if (gdi.getSelectedItem("StageCourses", lbi)) {
|
if (gdi.getSelectedItem("StageCourses", lbi)) {
|
||||||
int courseid=lbi.data;
|
int courseid=lbi.data;
|
||||||
pc->removeStageCourse(currentStage, courseid, lbi.index);
|
int ix = lbi.index;
|
||||||
|
pc->removeStageCourse(currentStage, courseid, ix);
|
||||||
pc->synchronize();
|
pc->synchronize();
|
||||||
pc->fillStageCourses(gdi, currentStage, "StageCourses");
|
pc->fillStageCourses(gdi, currentStage, "StageCourses");
|
||||||
|
if (ix > 0)
|
||||||
|
gdi.selectItemByIndex("StageCourses", ix-1);
|
||||||
|
|
||||||
|
|
||||||
|
setLockForkingState(gdi, *pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (bi.id == "MUp" || bi.id == "MDown") {
|
||||||
|
DWORD cid = ClassId;
|
||||||
|
if (!checkClassSelected(gdi))
|
||||||
|
return false;
|
||||||
|
pClass pc = oe->getClass(cid);
|
||||||
|
|
||||||
|
if (!pc)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (currentStage >= 0) {
|
||||||
|
int ix = -1;
|
||||||
|
ListBoxInfo selS;
|
||||||
|
if (gdi.getSelectedItem("StageCourses", selS)) {
|
||||||
|
ix = selS.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ix != -1) {
|
||||||
|
int off = bi.id == "MUp" ? -1 : 1;
|
||||||
|
pc->moveStageCourse(currentStage, ix, off);
|
||||||
|
pc->synchronize();
|
||||||
|
pc->fillStageCourses(gdi, currentStage, "StageCourses");
|
||||||
|
gdi.selectItemByIndex("StageCourses", ix + off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setLockForkingState(gdi, *pc);
|
||||||
|
EditChanged = true;
|
||||||
}
|
}
|
||||||
EditChanged=true;
|
EditChanged=true;
|
||||||
}
|
}
|
||||||
|
else if (type == GUI_LISTBOXSELECT) {
|
||||||
|
const ListBoxInfo &bi = *(ListBoxInfo *)data;
|
||||||
|
if (bi.id == "MCourses") {
|
||||||
|
gdi.sendCtrlMessage("MAdd");
|
||||||
|
}
|
||||||
|
else if (bi.id == "StageCourses") {
|
||||||
|
//gdi.sendCtrlMessage("MRemove");
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (type==GUI_LISTBOX) {
|
else if (type==GUI_LISTBOX) {
|
||||||
ListBoxInfo bi=*(ListBoxInfo *)data;
|
ListBoxInfo bi=*(ListBoxInfo *)data;
|
||||||
|
|
||||||
if (bi.id.substr(0, 7)=="LegType") {
|
if (bi.id == "StageCourses") {
|
||||||
|
pClass pc = oe->getClass(ClassId);
|
||||||
|
if (!pc)
|
||||||
|
return false;
|
||||||
|
setLockForkingState(gdi, *pc);
|
||||||
|
}
|
||||||
|
else if (bi.id.substr(0, 7)=="LegType") {
|
||||||
LegTypes lt = LegTypes(bi.data);
|
LegTypes lt = LegTypes(bi.data);
|
||||||
|
|
||||||
int i=atoi(bi.id.substr(7).c_str());
|
int i=atoi(bi.id.substr(7).c_str());
|
||||||
@ -956,7 +1017,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
vector<pClass> cls;
|
vector<pClass> cls;
|
||||||
oe->getClasses(cls, true);
|
oe->getClasses(cls, true);
|
||||||
for (size_t k = 0; k < cls.size(); k++) {
|
for (size_t k = 0; k < cls.size(); k++) {
|
||||||
if (cls[k]->getStart() == start)
|
if (cls[k]->getStart() == start && !cls[k]->hasFreeStart())
|
||||||
lst.insert(cls[k]->getId());
|
lst.insert(cls[k]->getId());
|
||||||
}
|
}
|
||||||
gdi.setSelection("Classes", lst);
|
gdi.setSelection("Classes", lst);
|
||||||
@ -1805,6 +1866,18 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
int tot, fin, dns;
|
int tot, fin, dns;
|
||||||
oe->getNumClassRunners(pc->getId(), 0, tot, fin, dns);
|
oe->getNumClassRunners(pc->getId(), 0, tot, fin, dns);
|
||||||
|
if (pc->isQualificationFinalBaseClass()) {
|
||||||
|
set<int> base;
|
||||||
|
pc->getQualificationFinal()->getBaseClassInstances(base);
|
||||||
|
for (int i : base) {
|
||||||
|
if (pc->getVirtualClass(i)) {
|
||||||
|
int tot2 = 0;
|
||||||
|
oe->getNumClassRunners(pc->getVirtualClass(i)->getId(), 0, tot2, fin, dns);
|
||||||
|
tot += tot2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gdi.addString("", fontMediumPlus, "Antal deltagare: X#" + itos(tot));
|
gdi.addString("", fontMediumPlus, "Antal deltagare: X#" + itos(tot));
|
||||||
gdi.dropLine(1.2);
|
gdi.dropLine(1.2);
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
@ -1826,9 +1899,6 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
for (int i : base) {
|
for (int i : base) {
|
||||||
if (pc->getVirtualClass(i)) {
|
if (pc->getVirtualClass(i)) {
|
||||||
gdi.addStringUT(0, pc->getVirtualClass(i)->getName());
|
gdi.addStringUT(0, pc->getVirtualClass(i)->getName());
|
||||||
int tot2 = 0;
|
|
||||||
oe->getNumClassRunners(pc->getVirtualClass(i)->getId(), 0, tot2, fin, dns);
|
|
||||||
tot += tot2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numSplitDef = base.size();
|
numSplitDef = base.size();
|
||||||
@ -1844,7 +1914,6 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.selectFirstItem("SplitInput");
|
gdi.selectFirstItem("SplitInput");
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSplitDistribution(gdi, numSplitDef, tot);
|
updateSplitDistribution(gdi, numSplitDef, tot);
|
||||||
@ -2260,58 +2329,77 @@ void TabClass::showClassSettings(gdioutput &gdi)
|
|||||||
|
|
||||||
int y = 0;
|
int y = 0;
|
||||||
int xp = gdi.getCX();
|
int xp = gdi.getCX();
|
||||||
const int width = 80;
|
const int width = gdi.scaleLength(80);
|
||||||
|
int classW = gdi.scaleLength(300);
|
||||||
|
vector<wstring> str(cInfo.size());
|
||||||
|
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||||
|
auto &ci = cInfo[k];
|
||||||
|
wchar_t bf1[128];
|
||||||
|
wchar_t bf2[128];
|
||||||
|
int cstart = ci.firstStart + (ci.nRunners - 1) * ci.interval;
|
||||||
|
wstring first = oe->getAbsTime(ci.firstStart*drawInfo.baseInterval + drawInfo.firstStart);
|
||||||
|
wstring last = oe->getAbsTime((cstart)*drawInfo.baseInterval + drawInfo.firstStart);
|
||||||
|
pClass pc = oe->getClass(ci.classId);
|
||||||
|
|
||||||
|
swprintf_s(bf1, L"%s, %d", pc ? pc->getName().c_str() : L"-", ci.nRunners);
|
||||||
|
swprintf_s(bf2, L"%d-[%d]-%d (%s-%s)", ci.firstStart, ci.interval, cstart, first.c_str(), last.c_str());
|
||||||
|
str[k] = L"X platser. Startar Y#" + wstring(bf1) + L"#" + bf2;
|
||||||
|
|
||||||
|
TextInfo ti;
|
||||||
|
ti.xp = 0;
|
||||||
|
ti.yp = 0;
|
||||||
|
ti.format = 0;
|
||||||
|
ti.text = str[k];
|
||||||
|
gdi.calcStringSize(ti);
|
||||||
|
classW = max(classW, ti.realWidth + gdi.scaleLength(10));
|
||||||
|
}
|
||||||
|
|
||||||
if (!cInfo.empty()) {
|
if (!cInfo.empty()) {
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
|
|
||||||
y = gdi.getCY();
|
y = gdi.getCY();
|
||||||
gdi.addString("", y, xp, 1, "Sammanställning, klasser:");
|
gdi.addString("", y, xp, 1, "Sammanställning, klasser:");
|
||||||
gdi.addString("", y, xp+300, 0, "Första start:");
|
gdi.addString("", y, xp + classW, 0, "Första start:");
|
||||||
gdi.addString("", y, xp+300+width, 0, "Intervall:");
|
gdi.addString("", y, xp + classW + width, 0, "Intervall:");
|
||||||
gdi.addString("", y, xp+300+width*2, 0, "Vakanser:");
|
gdi.addString("", y, xp + classW + width * 2, 0, "Vakanser:");
|
||||||
gdi.addString("", y, xp+300+width*3, 0, "Reserverade:");
|
gdi.addString("", y, xp + classW + width * 3, 0, "Reserverade:");
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
for (size_t k=0;k<cInfo.size();k++) {
|
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||||
const ClassInfo &ci = cInfo[k];
|
const ClassInfo &ci = cInfo[k];
|
||||||
wchar_t bf1[128];
|
int cstart = ci.firstStart + (ci.nRunners - 1) * ci.interval;
|
||||||
wchar_t bf2[128];
|
wstring first = oe->getAbsTime(ci.firstStart*drawInfo.baseInterval + drawInfo.firstStart);
|
||||||
int cstart = ci.firstStart + (ci.nRunners-1) * ci.interval;
|
wstring last = oe->getAbsTime((cstart)*drawInfo.baseInterval + drawInfo.firstStart);
|
||||||
wstring first=oe->getAbsTime(ci.firstStart*drawInfo.baseInterval+drawInfo.firstStart);
|
pClass pc = oe->getClass(ci.classId);
|
||||||
wstring last=oe->getAbsTime((cstart)*drawInfo.baseInterval+drawInfo.firstStart);
|
|
||||||
pClass pc=oe->getClass(ci.classId);
|
|
||||||
swprintf_s(bf1, L"%s, %d", pc ? pc->getName().c_str() : L"-", ci.nRunners);
|
|
||||||
swprintf_s(bf2, L"%d-[%d]-%d (%s-%s)", ci.firstStart, ci.interval, cstart, first.c_str(), last.c_str());
|
|
||||||
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
|
|
||||||
int id = ci.classId;
|
int id = ci.classId;
|
||||||
GDICOLOR clr = ci.hasFixedTime || ci.nExtraSpecified || ci.nVacantSpecified ? colorDarkGreen : colorBlack;
|
GDICOLOR clr = ci.hasFixedTime || ci.nExtraSpecified || ci.nVacantSpecified ? colorDarkGreen : colorBlack;
|
||||||
|
|
||||||
gdi.addString("C" + itos(id), 0, L"X platser. Startar Y#" + wstring(bf1) + L"#" + bf2).setColor(clr).setExtra(clr);
|
gdi.addString("C" + itos(id), 0, str[k]).setColor(clr).setExtra(clr);
|
||||||
|
|
||||||
y = gdi.getCY();
|
y = gdi.getCY();
|
||||||
InputInfo *ii;
|
InputInfo *ii;
|
||||||
GDICOLOR fixedColor = colorLightGreen;
|
GDICOLOR fixedColor = colorLightGreen;
|
||||||
ii = &gdi.addInput(xp+300, y, "S"+itos(id), first, 7, DrawClassesCB);
|
ii = &gdi.addInput(xp + classW, y, "S" + itos(id), first, 7, DrawClassesCB);
|
||||||
if (ci.hasFixedTime) {
|
if (ci.hasFixedTime) {
|
||||||
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
||||||
}
|
}
|
||||||
ii = &gdi.addInput(xp+300+width, y, "I"+itos(id), formatTime(ci.interval*drawInfo.baseInterval), 7, DrawClassesCB);
|
ii = &gdi.addInput(xp + classW + width, y, "I" + itos(id), formatTime(ci.interval*drawInfo.baseInterval), 7, DrawClassesCB);
|
||||||
if (ci.hasFixedTime) {
|
if (ci.hasFixedTime) {
|
||||||
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
||||||
}
|
}
|
||||||
ii = &gdi.addInput(xp+300+width*2, y, "V"+itos(id), itow(ci.nVacant), 7, DrawClassesCB);
|
ii = &gdi.addInput(xp + classW + width * 2, y, "V" + itos(id), itow(ci.nVacant), 7, DrawClassesCB);
|
||||||
if (ci.nVacantSpecified) {
|
if (ci.nVacantSpecified) {
|
||||||
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
||||||
}
|
}
|
||||||
ii = &gdi.addInput(xp+300+width*3, y, "R"+itos(id), itow(ci.nExtra), 7, DrawClassesCB);
|
ii = &gdi.addInput(xp + classW + width * 3, y, "R" + itos(id), itow(ci.nExtra), 7, DrawClassesCB);
|
||||||
if (ci.nExtraSpecified) {
|
if (ci.nExtraSpecified) {
|
||||||
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
||||||
}
|
}
|
||||||
if (k%5 == 4)
|
if (k % 5 == 4)
|
||||||
gdi.dropLine(1);
|
gdi.dropLine(1);
|
||||||
|
|
||||||
gdi.dropLine(1.6);
|
gdi.dropLine(1.6);
|
||||||
@ -2414,7 +2502,8 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
|||||||
gdi.check("LockStartList", false);
|
gdi.check("LockStartList", false);
|
||||||
gdi.setInputStatus("LockStartList", false);
|
gdi.setInputStatus("LockStartList", false);
|
||||||
}
|
}
|
||||||
gdi.check("NoTiming", false);
|
if (gdi.hasField("NoTiming"))
|
||||||
|
gdi.check("NoTiming", false);
|
||||||
|
|
||||||
ClassId=cid;
|
ClassId=cid;
|
||||||
EditChanged=false;
|
EditChanged=false;
|
||||||
@ -2455,7 +2544,8 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gdi.check("AllowQuickEntry", pc->getAllowQuickEntry());
|
gdi.check("AllowQuickEntry", pc->getAllowQuickEntry());
|
||||||
gdi.check("NoTiming", pc->getNoTiming());
|
if (gdi.hasField("NoTiming"))
|
||||||
|
gdi.check("NoTiming", pc->getNoTiming());
|
||||||
|
|
||||||
if (gdi.hasField("FreeStart"))
|
if (gdi.hasField("FreeStart"))
|
||||||
gdi.check("FreeStart", pc->hasFreeStart());
|
gdi.check("FreeStart", pc->hasFreeStart());
|
||||||
@ -2890,7 +2980,8 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
|
|||||||
pc->lockedForking(gdi.isChecked("LockForking"));
|
pc->lockedForking(gdi.isChecked("LockForking"));
|
||||||
|
|
||||||
pc->setAllowQuickEntry(gdi.isChecked("AllowQuickEntry"));
|
pc->setAllowQuickEntry(gdi.isChecked("AllowQuickEntry"));
|
||||||
pc->setNoTiming(gdi.isChecked("NoTiming"));
|
if (gdi.hasField("NoTiming"))
|
||||||
|
pc->setNoTiming(gdi.isChecked("NoTiming"));
|
||||||
|
|
||||||
if (gdi.hasField("FreeStart"))
|
if (gdi.hasField("FreeStart"))
|
||||||
pc->setFreeStart(gdi.isChecked("FreeStart"));
|
pc->setFreeStart(gdi.isChecked("FreeStart"));
|
||||||
@ -2901,7 +2992,8 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
|
|||||||
if (gdi.hasField("DirectResult")) {
|
if (gdi.hasField("DirectResult")) {
|
||||||
bool withDirect = gdi.isChecked("DirectResult");
|
bool withDirect = gdi.isChecked("DirectResult");
|
||||||
|
|
||||||
if (withDirect && !pc->hasDirectResult() && !hasWarnedDirect) {
|
if (withDirect && !pc->hasDirectResult() && !hasWarnedDirect &&
|
||||||
|
!oe->getMeOSFeatures().hasFeature(MeOSFeatures::NoCourses)) {
|
||||||
if (gdi.ask(L"warning:direct_result"))
|
if (gdi.ask(L"warning:direct_result"))
|
||||||
hasWarnedDirect = true;
|
hasWarnedDirect = true;
|
||||||
else
|
else
|
||||||
@ -3135,20 +3227,24 @@ bool TabClass::loadPage(gdioutput &gdi)
|
|||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.dropLine(3.5);
|
gdi.dropLine(3.5);
|
||||||
gdi.addCheckbox("AllowQuickEntry", "Tillåt direktanmälan", 0);
|
gdi.addCheckbox("AllowQuickEntry", "Tillåt direktanmälan", 0);
|
||||||
gdi.addCheckbox("NoTiming", "Utan tidtagning", 0);
|
if (showAdvanced || !oe->getMeOSFeatures().hasFeature(MeOSFeatures::NoCourses)) {
|
||||||
|
gdi.addCheckbox("NoTiming", "Utan tidtagning", 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (showAdvanced) {
|
if (showAdvanced) {
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.addCheckbox("FreeStart", "Fri starttid", 0, false, "Klassen lottas inte, startstämpling");
|
gdi.addCheckbox("FreeStart", "Fri starttid", 0, false, "Klassen lottas inte, startstämpling");
|
||||||
gdi.addCheckbox("IgnoreStart", "Ignorera startstämpling", 0, false, "Uppdatera inte starttiden vid startstämpling");
|
gdi.addCheckbox("IgnoreStart", "Ignorera startstämpling", 0, false, "Uppdatera inte starttiden vid startstämpling");
|
||||||
|
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showAdvanced || oe->getMeOSFeatures().hasFeature(MeOSFeatures::NoCourses)) {
|
||||||
gdi.addCheckbox("DirectResult", "Resultat vid målstämpling", 0, false,
|
gdi.addCheckbox("DirectResult", "Resultat vid målstämpling", 0, false,
|
||||||
"help:DirectResult");
|
"help:DirectResult");
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
@ -3794,7 +3890,7 @@ void TabClass::simultaneous(int classId, const wstring &time) {
|
|||||||
pCourse crs = pc->getCourse();
|
pCourse crs = pc->getCourse();
|
||||||
pc->setNumStages(1);
|
pc->setNumStages(1);
|
||||||
if (crs)
|
if (crs)
|
||||||
pc->addStageCourse(0, crs->getId());
|
pc->addStageCourse(0, crs->getId(), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pc->setStartType(0, STTime, false);
|
pc->setStartType(0, STTime, false);
|
||||||
@ -3845,18 +3941,23 @@ void TabClass::selectCourses(gdioutput &gdi, int legNo) {
|
|||||||
}
|
}
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
int x1=gdi.getCX();
|
int x1=gdi.getCX();
|
||||||
gdi.addListBox("StageCourses", 180, 200, MultiCB, getCourseLabel(pc->hasCoursePool())).ignore(true);
|
gdi.addListBox("StageCourses", 240, 200, MultiCB, getCourseLabel(pc->hasCoursePool())).ignore(true);
|
||||||
pc->fillStageCourses(gdi, currentStage, "StageCourses");
|
pc->fillStageCourses(gdi, currentStage, "StageCourses");
|
||||||
int x2=gdi.getCX();
|
int x2=gdi.getCX();
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addListBox("MCourses", 180, 200, MultiCB, L"Banor:").ignore(true);
|
gdi.addListBox("MCourses", 240, 200, MultiCB, L"Banor:").ignore(true);
|
||||||
oe->fillCourses(gdi, "MCourses", true);
|
oe->fillCourses(gdi, "MCourses", true);
|
||||||
|
|
||||||
gdi.setCX(x1);
|
gdi.setCX(x1);
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
|
|
||||||
gdi.addButton("MRemove", "Ta bort markerad >>", MultiCB);
|
gdi.addButton("MRemove", "Ta bort markerad >>", MultiCB);
|
||||||
gdi.setCX(x2);
|
gdi.addButton(gdi.getCX(), gdi.getCY(), gdi.scaleLength(30), "MUp", L"#▲", MultiCB, L"Flytta upp", false, false);
|
||||||
|
gdi.addButton(gdi.getCX(), gdi.getCY(), gdi.scaleLength(30), "MDown", L"#▼", MultiCB, L"Flytta ner", false, false);
|
||||||
|
gdi.disableInput("MUp");
|
||||||
|
gdi.disableInput("MDown");
|
||||||
|
|
||||||
|
gdi.setCX(max(x2, gdi.getCY()));
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
|
|
||||||
gdi.addButton("MAdd", "<< Lägg till", MultiCB);
|
gdi.addButton("MAdd", "<< Lägg till", MultiCB);
|
||||||
@ -4331,6 +4432,10 @@ void TabClass::writeDrawInfo(gdioutput &gdi, const DrawInfo &drawInfoIn) {
|
|||||||
gdi.setText("FirstStart", oe->getAbsTime(drawInfoIn.firstStart));
|
gdi.setText("FirstStart", oe->getAbsTime(drawInfoIn.firstStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabClass::setLockForkingState(gdioutput &gdi, const oClass &c) {
|
||||||
|
setLockForkingState(gdi, c.hasCoursePool(), c.lockedForking());
|
||||||
|
}
|
||||||
|
|
||||||
void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockState) {
|
void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockState) {
|
||||||
if (gdi.hasField("DefineForking"))
|
if (gdi.hasField("DefineForking"))
|
||||||
gdi.setInputStatus("DefineForking", !lockState && !poolState);
|
gdi.setInputStatus("DefineForking", !lockState && !poolState);
|
||||||
@ -4348,6 +4453,27 @@ void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockStat
|
|||||||
gdi.setInputStatus(s, !lockState || poolState);
|
gdi.setInputStatus(s, !lockState || poolState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool moveUp = false;
|
||||||
|
bool moveDown = false;
|
||||||
|
|
||||||
|
if (gdi.hasField("MCourses")) {
|
||||||
|
ListBoxInfo lbi;
|
||||||
|
if (gdi.getSelectedItem("StageCourses", lbi)) {
|
||||||
|
if (lbi.index > 0)
|
||||||
|
moveUp = true;
|
||||||
|
int numItem = gdi.getNumItems("StageCourses");
|
||||||
|
if (lbi.index < numItem - 1)
|
||||||
|
moveDown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gdi.hasField("MUp")) {
|
||||||
|
gdi.setInputStatus("MUp", (!lockState || poolState) && moveUp);
|
||||||
|
}
|
||||||
|
if (gdi.hasField("MDown")) {
|
||||||
|
gdi.setInputStatus("MDown", (!lockState || poolState) && moveDown);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabClass::warnDrawStartTime(gdioutput &gdi, const wstring &firstStart) {
|
bool TabClass::warnDrawStartTime(gdioutput &gdi, const wstring &firstStart) {
|
||||||
|
|||||||
@ -150,6 +150,7 @@ class TabClass :
|
|||||||
static vector< pair<wstring, size_t> > getPairOptions();
|
static vector< pair<wstring, size_t> > getPairOptions();
|
||||||
|
|
||||||
void setLockForkingState(gdioutput &gdi, bool poolState, bool lockState);
|
void setLockForkingState(gdioutput &gdi, bool poolState, bool lockState);
|
||||||
|
void setLockForkingState(gdioutput &gdi, const oClass &c);
|
||||||
|
|
||||||
void loadBasicDrawSetup(gdioutput &gdi, int &bx, int &by, const wstring& firstStart,
|
void loadBasicDrawSetup(gdioutput &gdi, int &bx, int &by, const wstring& firstStart,
|
||||||
int maxNumControl, const wstring& minInterval, const wstring& vacances, const set<int> &clsId);
|
int maxNumControl, const wstring& minInterval, const wstring& vacances, const set<int> &clsId);
|
||||||
|
|||||||
@ -383,6 +383,9 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
wstring url = ti.text;
|
wstring url = ti.text;
|
||||||
ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
else if (ti.id == "fnpath") {
|
||||||
|
ShellExecute(NULL, L"open", ti.text.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type==GUI_BUTTON) {
|
else if (type==GUI_BUTTON) {
|
||||||
ButtonInfo bi=*(ButtonInfo *)data;
|
ButtonInfo bi=*(ButtonInfo *)data;
|
||||||
@ -558,17 +561,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
else if (bi.id=="Test") {
|
else if (bi.id=="Test") {
|
||||||
vector< pair<wstring, wstring> > cpp;
|
checkRentCards(gdi);
|
||||||
cpp.push_back(make_pair(L"Source", L"*.cpp"));
|
|
||||||
int ix = 0;
|
|
||||||
wstring fn = gdi.browseForSave(cpp, L".cpp", ix);
|
|
||||||
if (!fn.empty())
|
|
||||||
gdi.getRecorder().saveRecordings(gdi.narrow(fn));
|
|
||||||
else {
|
|
||||||
TestMeOS tm(oe, "base");
|
|
||||||
tm.runAll();
|
|
||||||
tm.publish(gdi);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (bi.id=="Report") {
|
else if (bi.id=="Report") {
|
||||||
gdi.clearPage(true);
|
gdi.clearPage(true);
|
||||||
@ -2076,7 +2069,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
// Construct runner from database
|
// Construct runner from database
|
||||||
oRunner sRunner(oe, 0);
|
oRunner sRunner(oe, 0);
|
||||||
sRunner.init(*dbr);
|
sRunner.init(*dbr, false);
|
||||||
pRunner added = oe->addRunnerFromDB(&sRunner, classId, true);
|
pRunner added = oe->addRunnerFromDB(&sRunner, classId, true);
|
||||||
if (added)
|
if (added)
|
||||||
added->synchronize();
|
added->synchronize();
|
||||||
@ -2375,8 +2368,25 @@ void TabCompetition::copyrightLine(gdioutput &gdi) const
|
|||||||
void TabCompetition::loadAboutPage(gdioutput &gdi) const
|
void TabCompetition::loadAboutPage(gdioutput &gdi) const
|
||||||
{
|
{
|
||||||
gdi.clearPage(false);
|
gdi.clearPage(false);
|
||||||
gdi.addString("", 2, makeDash(L"Om MeOS - ett Mycket Enkelt OrienteringsSystem")).setColor(colorDarkBlue);
|
gdi.addString("", textImage, "513");
|
||||||
gdi.dropLine(2);
|
|
||||||
|
gdi.addString("", fontMediumPlus, makeDash(L"Om MeOS - ett Mycket Enkelt OrienteringsSystem")).setColor(colorDarkBlue);
|
||||||
|
gdi.dropLine(1);
|
||||||
|
|
||||||
|
wchar_t FileNamePath[260];
|
||||||
|
getUserFile(FileNamePath, L"");
|
||||||
|
gdi.pushX();
|
||||||
|
gdi.fillRight();
|
||||||
|
gdi.addString("", 0, "MeOS lokala datakatalog är: ");
|
||||||
|
gdi.fillDown();
|
||||||
|
gdi.addString("fnpath", 0, FileNamePath, CompetitionCB);
|
||||||
|
gdi.popX();
|
||||||
|
gdi.dropLine(0.5);
|
||||||
|
RECT rc = { gdi.getCX(), gdi.getCY(), gdi.getPageX(), gdi.getCY() + 2 };
|
||||||
|
gdi.addRectangle(rc, colorBlack);
|
||||||
|
gdi.dropLine(1.5);
|
||||||
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
|
||||||
|
|
||||||
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2019 Melin Software HB"));
|
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2019 Melin Software HB"));
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
|
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
|
||||||
@ -4115,3 +4125,34 @@ void TabCompetition::checkReadyForResultExport(gdioutput &gdi, const set<int> &c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabCompetition::checkRentCards(gdioutput &gdi) {
|
||||||
|
gdi.clearPage(false);
|
||||||
|
|
||||||
|
wstring fn = gdi.browseForOpen({ make_pair(L"csv", L"*.csv") }, L"csv");
|
||||||
|
if (!fn.empty()) {
|
||||||
|
csvparser csv;
|
||||||
|
list<vector<wstring>> data;
|
||||||
|
csv.parse(fn, data);
|
||||||
|
set<int> rentCards;
|
||||||
|
for (auto &c : data) {
|
||||||
|
if (c.size() > 0) {
|
||||||
|
int cn = _wtoi(c[0].c_str());
|
||||||
|
rentCards.insert(cn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<pRunner> runners;
|
||||||
|
oe->getRunners(0, 0, runners);
|
||||||
|
int bcf = oe->getBaseCardFee();
|
||||||
|
for (pRunner r : runners) {
|
||||||
|
if (rentCards.count(r->getCardNo()) && r->getDCI().getInt("CardFee") == 0) {
|
||||||
|
gdi.addStringUT(0, r->getCompleteIdentification());
|
||||||
|
r->getDI().setInt("CardFee", bcf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.addButton("Cancel", "OK", CompetitionCB);
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
|||||||
@ -139,6 +139,10 @@ class TabCompetition :
|
|||||||
void createCompetition(gdioutput &gdi);
|
void createCompetition(gdioutput &gdi);
|
||||||
|
|
||||||
void listBackups(gdioutput &gdi);
|
void listBackups(gdioutput &gdi);
|
||||||
|
|
||||||
|
|
||||||
|
void checkRentCards(gdioutput &gdi);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void clearCompetitionData();
|
void clearCompetitionData();
|
||||||
|
|
||||||
|
|||||||
@ -914,7 +914,7 @@ void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (size_t i = 0; i<cls[k]->getNumStages(); i++)
|
for (size_t i = 0; i<cls[k]->getNumStages(); i++)
|
||||||
cls[k]->addStageCourse(i, res->second->getId());
|
cls[k]->addStageCourse(i, res->second->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -939,7 +939,7 @@ void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (size_t i = 0; i<bestClass->getNumStages(); i++)
|
for (size_t i = 0; i<bestClass->getNumStages(); i++)
|
||||||
bestClass->addStageCourse(i, crs[k]->getId());
|
bestClass->addStageCourse(i, crs[k]->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,13 @@
|
|||||||
const static int CUSTOM_OFFSET = 10;
|
const static int CUSTOM_OFFSET = 10;
|
||||||
const static int NUMTEXTSAMPLE = 13;
|
const static int NUMTEXTSAMPLE = 13;
|
||||||
|
|
||||||
|
const static int ForcePageBreak = 1024;
|
||||||
|
const static int IgnoreLimitPer = 512;
|
||||||
|
const static int AddTeamClasses = 4;
|
||||||
|
const static int AddPatrolClasses = 3;
|
||||||
|
const static int AddRogainingClasses = 2;
|
||||||
|
const static int AddAllClasses = 1;
|
||||||
|
|
||||||
TabList::TabList(oEvent *poe):TabBase(poe)
|
TabList::TabList(oEvent *poe):TabBase(poe)
|
||||||
{
|
{
|
||||||
listEditor = 0;
|
listEditor = 0;
|
||||||
@ -209,9 +216,12 @@ void TabList::generateList(gdioutput &gdi, bool forceUpdate)
|
|||||||
gdi.getData("GeneralList", storedWidth);
|
gdi.getData("GeneralList", storedWidth);
|
||||||
gdi.restoreNoUpdate("GeneralList");
|
gdi.restoreNoUpdate("GeneralList");
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
gdi.clearPage(false);
|
gdi.clearPage(false);
|
||||||
|
if (currentList.getParam().filterMaxPer > 0 && !ownWindow && !gdi.isFullScreen()) {
|
||||||
|
gdi.addInfoBox("infofilter", L"Visar de X bästa#" + itow(currentList.getParam().filterMaxPer), 6000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
gdi.setRestorePoint("GeneralList");
|
gdi.setRestorePoint("GeneralList");
|
||||||
|
|
||||||
currentList.setCallback(ownWindow ? 0 : openRunnerTeamCB);
|
currentList.setCallback(ownWindow ? 0 : openRunnerTeamCB);
|
||||||
@ -519,10 +529,12 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
else if (bi.id == "RemoveSaved") {
|
else if (bi.id == "RemoveSaved") {
|
||||||
ListBoxInfo lbi;
|
ListBoxInfo lbi;
|
||||||
if (gdi.getSelectedItem("SavedInstance", lbi)) {
|
if (gdi.getSelectedItem("SavedInstance", lbi)) {
|
||||||
oe->synchronize(false);
|
if (gdi.ask(L"Vill du ta bort 'X'?#" + lbi.text)) {
|
||||||
oe->getListContainer().removeParam(lbi.data);
|
oe->synchronize(false);
|
||||||
oe->synchronize(true);
|
oe->getListContainer().removeParam(lbi.data);
|
||||||
loadPage(gdi);
|
oe->synchronize(true);
|
||||||
|
loadPage(gdi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -888,6 +900,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
par.back().listCode = EIndCourseList;
|
par.back().listCode = EIndCourseList;
|
||||||
par.back().showInterTitle = false;
|
par.back().showInterTitle = false;
|
||||||
|
par.back().setLegNumberCoded(-1);
|
||||||
cnf.getIndividual(par.back().selection);
|
cnf.getIndividual(par.back().selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,13 +951,22 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
bi.id.substr(0, 7) == "StartL:" ||
|
bi.id.substr(0, 7) == "StartL:" ||
|
||||||
bi.id.substr(0, 7) == "GenLst:") {
|
bi.id.substr(0, 7) == "GenLst:") {
|
||||||
bool isReport = bi.id.substr(0, 7) == "GenLst:";
|
bool isReport = bi.id.substr(0, 7) == "GenLst:";
|
||||||
bool allClasses = bi.getExtraInt() == 1;
|
int baseType = bi.getExtraInt() & 0xFF;
|
||||||
bool rogaining = bi.getExtraInt() == 2;
|
int flags = bi.getExtraInt() & 0xFF00;
|
||||||
bool patrol = bi.getExtraInt() == 3;
|
bool isStartList = bi.id.substr(0, 7) == "StartL:";
|
||||||
|
bool allClasses = baseType == AddAllClasses;
|
||||||
|
bool rogaining = baseType == AddRogainingClasses;
|
||||||
|
bool patrol = baseType == AddPatrolClasses;
|
||||||
|
bool team = baseType == AddTeamClasses;
|
||||||
oe->sanityCheck(gdi, bi.id.substr(0, 7) == "Result:");
|
oe->sanityCheck(gdi, bi.id.substr(0, 7) == "Result:");
|
||||||
oListParam par;
|
oListParam par;
|
||||||
par.listCode = oe->getListContainer().getType(bi.id.substr(7));
|
par.listCode = oe->getListContainer().getType(bi.id.substr(7));
|
||||||
readSettings(gdi, par, true);
|
readSettings(gdi, par, !isStartList);
|
||||||
|
if ((flags & IgnoreLimitPer) == IgnoreLimitPer || isReport)
|
||||||
|
par.filterMaxPer = 0;
|
||||||
|
|
||||||
|
if ((flags & ForcePageBreak) == ForcePageBreak)
|
||||||
|
par.pageBreak = true;
|
||||||
|
|
||||||
par.setLegNumberCoded(-1);
|
par.setLegNumberCoded(-1);
|
||||||
if (patrol) {
|
if (patrol) {
|
||||||
@ -957,6 +979,11 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
oe->getClassConfigurationInfo(cnf);
|
oe->getClassConfigurationInfo(cnf);
|
||||||
cnf.getRogaining(par.selection);
|
cnf.getRogaining(par.selection);
|
||||||
}
|
}
|
||||||
|
else if (team) {
|
||||||
|
ClassConfigInfo cnf;
|
||||||
|
oe->getClassConfigurationInfo(cnf);
|
||||||
|
cnf.getRelay(par.selection);
|
||||||
|
}
|
||||||
else if (!isReport && !allClasses) {
|
else if (!isReport && !allClasses) {
|
||||||
ClassConfigInfo cnf;
|
ClassConfigInfo cnf;
|
||||||
oe->getClassConfigurationInfo(cnf);
|
oe->getClassConfigurationInfo(cnf);
|
||||||
@ -1872,20 +1899,20 @@ namespace {
|
|||||||
gdi.addString("", 0, info);
|
gdi.addString("", 0, info);
|
||||||
gdi.dropLine(0.3);
|
gdi.dropLine(0.3);
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addInput("Margin", itow(tmpSettingsParam.margin) + L" %", 5, 0, L"Marginal:");
|
gdi.addInput("Margin", itow(tmpSettingsParam.margin) + L" %", 5, 0, L"Marginal:").setHandler(&htmlClass);
|
||||||
gdi.addInput("Scale", itow(int(tmpSettingsParam.htmlScale*100)) + L" %", 5, 0, L"Skalfaktor:");
|
gdi.addInput("Scale", itow(int(tmpSettingsParam.htmlScale*100)) + L" %", 5, 0, L"Skalfaktor:").setHandler(&htmlClass);
|
||||||
if (tmpSettingsParam.nColumns <= 0)
|
if (tmpSettingsParam.nColumns <= 0)
|
||||||
tmpSettingsParam.nColumns = 1;
|
tmpSettingsParam.nColumns = 1;
|
||||||
|
|
||||||
gdi.addInput("Columns", itow(tmpSettingsParam.nColumns), 5, 0, L"Kolumner:");
|
gdi.addInput("Columns", itow(tmpSettingsParam.nColumns), 5, 0, L"Kolumner:").setHandler(&htmlClass);
|
||||||
gdi.addInput("Time", itow(tmpSettingsParam.timePerPage) + L"ms", 5, 0, L"Visningstid:");
|
gdi.addInput("Time", itow(tmpSettingsParam.timePerPage) + L"ms", 5, 0, L"Visningstid:").setHandler(&htmlClass);
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.dropLine(3.4);
|
gdi.dropLine(3.4);
|
||||||
|
|
||||||
gdi.addCheckbox("UseRows", "Begränsa antal rader per sida", 0, tmpSettingsParam.htmlRows>0).setHandler(&htmlClass);
|
gdi.addCheckbox("UseRows", "Begränsa antal rader per sida", 0, tmpSettingsParam.htmlRows>0).setHandler(&htmlClass);
|
||||||
gdi.dropLine(-0.4);
|
gdi.dropLine(-0.4);
|
||||||
gdi.addInput("Rows", itow(tmpSettingsParam.htmlRows), 5);
|
gdi.addInput("Rows", itow(tmpSettingsParam.htmlRows), 5).setHandler(&htmlClass);
|
||||||
gdi.setInputStatus("Rows", tmpSettingsParam.htmlRows > 0);
|
gdi.setInputStatus("Rows", tmpSettingsParam.htmlRows > 0);
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
@ -1893,13 +1920,13 @@ namespace {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addInput("Scale", itow(int(tmpSettingsParam.htmlScale * 100)) + L" %", 5, 0, L"Skalfaktor:");
|
gdi.addInput("Scale", itow(int(tmpSettingsParam.htmlScale * 100)) + L" %", 5, 0, L"Skalfaktor:").setHandler(&htmlClass);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.dropLine(3.4);
|
gdi.dropLine(3.4);
|
||||||
|
|
||||||
gdi.addCheckbox("Reload", "Automatisk omladdning", 0, tmpSettingsParam.timePerPage>999).setHandler(&htmlClass);
|
gdi.addCheckbox("Reload", "Automatisk omladdning", 0, tmpSettingsParam.timePerPage>999).setHandler(&htmlClass);
|
||||||
gdi.dropLine(-0.4);
|
gdi.dropLine(-0.4);
|
||||||
gdi.addInput("ReloadTime", itow(tmpSettingsParam.timePerPage/1000) + L" s", 5);
|
gdi.addInput("ReloadTime", itow(tmpSettingsParam.timePerPage/1000) + L" s", 5).setHandler(&htmlClass);
|
||||||
gdi.setInputStatus("Reload", tmpSettingsParam.timePerPage>999);
|
gdi.setInputStatus("Reload", tmpSettingsParam.timePerPage>999);
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
@ -1907,6 +1934,8 @@ namespace {
|
|||||||
}
|
}
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addButton("ApplyList", "Lagra inställningar").setHandler(&htmlClass);
|
gdi.addButton("ApplyList", "Lagra inställningar").setHandler(&htmlClass);
|
||||||
|
if (tmpSettingsParam.sourceParam != -1)
|
||||||
|
gdi.disableInput("ApplyList");
|
||||||
gdi.addButton("Automatic", "Automatisera", 0, "Skriv ut eller exportera listan automatiskt.").setHandler(&htmlClass);
|
gdi.addButton("Automatic", "Automatisera", 0, "Skriv ut eller exportera listan automatiskt.").setHandler(&htmlClass);
|
||||||
gdi.addButton("HTML", "Exportera").setHandler(&htmlClass);
|
gdi.addButton("HTML", "Exportera").setHandler(&htmlClass);
|
||||||
}
|
}
|
||||||
@ -2021,6 +2050,7 @@ void TabList::handleHTMLSettings(gdioutput &gdi, BaseInfo &info, GuiEventType ty
|
|||||||
else {
|
else {
|
||||||
dest_gdi.sendCtrlMessage("Remember");
|
dest_gdi.sendCtrlMessage("Remember");
|
||||||
}
|
}
|
||||||
|
gdi.disableInput("ApplyList");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (lastHtmlTarget.empty()) {
|
if (lastHtmlTarget.empty()) {
|
||||||
@ -2055,18 +2085,24 @@ void TabList::handleHTMLSettings(gdioutput &gdi, BaseInfo &info, GuiEventType ty
|
|||||||
}
|
}
|
||||||
else if (bi.id == "UseRows") {
|
else if (bi.id == "UseRows") {
|
||||||
gdi.setInputStatus("Rows", gdi.isChecked(bi.id));
|
gdi.setInputStatus("Rows", gdi.isChecked(bi.id));
|
||||||
|
gdi.enableInput("ApplyList");
|
||||||
}
|
}
|
||||||
else if (bi.id == "Reload") {
|
else if (bi.id == "Reload") {
|
||||||
gdi.setInputStatus("ReloadTime", gdi.isChecked(bi.id));
|
gdi.setInputStatus("ReloadTime", gdi.isChecked(bi.id));
|
||||||
|
gdi.enableInput("ApplyList");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == GUI_LISTBOX) {
|
else if (type == GUI_LISTBOX) {
|
||||||
ListBoxInfo lbi = dynamic_cast<ListBoxInfo &>(info);
|
ListBoxInfo lbi = dynamic_cast<ListBoxInfo &>(info);
|
||||||
if (lbi.id == "Format") {
|
if (lbi.id == "Format") {
|
||||||
htmlDetails(gdi, tmpSettingsParam, html2IdToInfo[lbi.data], lbi.data > 5);
|
htmlDetails(gdi, tmpSettingsParam, html2IdToInfo[lbi.data], lbi.data > 5);
|
||||||
|
gdi.enableInput("ApplyList");
|
||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (type == GUI_INPUTCHANGE) {
|
||||||
|
gdi.enableInput("ApplyList");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
|
void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
|
||||||
@ -2345,7 +2381,7 @@ bool TabList::loadPage(gdioutput &gdi)
|
|||||||
}
|
}
|
||||||
if (cnf.hasPatrol()) {
|
if (cnf.hasPatrol()) {
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
gdi.addButton("StartL:patrolstart", "Patrull", ListsCB).setExtra(3);
|
gdi.addButton("StartL:patrolstart", "Patrull", ListsCB).setExtra(AddPatrolClasses);
|
||||||
}
|
}
|
||||||
for (size_t k = 0; k < cnf.raceNStart.size(); k++) {
|
for (size_t k = 0; k < cnf.raceNStart.size(); k++) {
|
||||||
if (cnf.raceNStart[k].size() > 0) {
|
if (cnf.raceNStart[k].size() > 0) {
|
||||||
@ -2386,7 +2422,7 @@ bool TabList::loadPage(gdioutput &gdi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cnf.hasPatrol()) {
|
if (cnf.hasPatrol()) {
|
||||||
gdi.addButton("Result:patrolresult", "Patrull", ListsCB).setExtra(3);
|
gdi.addButton("Result:patrolresult", "Patrull", ListsCB).setExtra(AddPatrolClasses);
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2395,7 +2431,7 @@ bool TabList::loadPage(gdioutput &gdi)
|
|||||||
gdi.addButton("Result:liveresultradio", "Liveresultat", ListsCB);
|
gdi.addButton("Result:liveresultradio", "Liveresultat", ListsCB);
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
|
|
||||||
gdi.addButton("Result:latestresult", "Latest Results", ListsCB).setExtra(1);
|
gdi.addButton("Result:latestresult", "Latest Results", ListsCB).setExtra(AddAllClasses);
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
|
|
||||||
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
|
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
|
||||||
@ -2457,8 +2493,7 @@ bool TabList::loadPage(gdioutput &gdi)
|
|||||||
|
|
||||||
if (cnf.hasRogaining()) {
|
if (cnf.hasRogaining()) {
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
//gdi.addButton("RogainingResultList", "Rogaining", ListsCB);
|
gdi.addButton("Result:rogainingind", "Rogaining", ListsCB).setExtra(AddRogainingClasses);
|
||||||
gdi.addButton("Result:rogainingind", "Rogaining", ListsCB).setExtra(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
@ -2519,24 +2554,33 @@ bool TabList::loadPage(gdioutput &gdi)
|
|||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
|
|
||||||
gdi.addButton("InForestList", "Kvar-i-skogen", ListsCB, "tooltip:inforest");
|
gdi.addButton("InForestList", "Kvar-i-skogen", ListsCB, "tooltip:inforest").setExtra(IgnoreLimitPer);
|
||||||
if (cnf.hasIndividual()) {
|
if (cnf.hasIndividual()) {
|
||||||
gdi.addButton("PriceList", "Prisutdelningslista", ListsCB);
|
gdi.addButton("PriceList", "Prisutdelningslista", ListsCB);
|
||||||
}
|
}
|
||||||
gdi.addButton("PreReport", "Kör kontroll inför tävlingen...", ListsCB);
|
gdi.addButton("PreReport", "Kör kontroll inför tävlingen...", ListsCB);
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
|
|
||||||
|
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy) && cnf.hasIndividual()) {
|
||||||
|
gdi.addButton("GenLst:unexpectedfee", "Unexpected Fee", ListsCB);
|
||||||
|
checkWidth(gdi);
|
||||||
|
}
|
||||||
|
|
||||||
if (cnf.hasMultiCourse) {
|
if (cnf.hasMultiCourse) {
|
||||||
gdi.addButton("CourseReport", "Bantilldelning", ListsCB);
|
gdi.addButton("CourseReport", "Bantilldelning", ListsCB).setExtra(IgnoreLimitPer);
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
|
|
||||||
if (cnf.hasTeamClass()) {
|
if (cnf.hasTeamClass()) {
|
||||||
gdi.addButton("GenLst:courseteamtable", "Gafflingar i tabellformat", ListsCB,
|
gdi.addButton("GenLst:courseteamtable", "Gafflingar i tabellformat", ListsCB,
|
||||||
"Från den här listan kan man skapa etiketter att klistra på kartor");
|
"Från den här listan kan man skapa etiketter att klistra på kartor");
|
||||||
checkWidth(gdi);
|
checkWidth(gdi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cnf.hasTeamClass()) {
|
||||||
|
gdi.addButton("GenLst:teamchanges", "Lagändringblankett", ListsCB).setExtra(AddTeamClasses | ForcePageBreak);
|
||||||
|
checkWidth(gdi);
|
||||||
|
}
|
||||||
bool hasVac = false;
|
bool hasVac = false;
|
||||||
bool hasAPIEntry = false;
|
bool hasAPIEntry = false;
|
||||||
{
|
{
|
||||||
@ -2579,7 +2623,7 @@ bool TabList::loadPage(gdioutput &gdi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cnf.hasRentedCard)
|
if (cnf.hasRentedCard)
|
||||||
gdi.addButton("HiredCards", "Hyrbricksrapport", ListsCB);
|
gdi.addButton("HiredCards", "Hyrbricksrapport", ListsCB).setExtra(IgnoreLimitPer);
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
@ -3055,9 +3099,6 @@ void TabList::getPublicLists(oEvent &oe, vector<oListParam> &lists) {
|
|||||||
getResultPatrol(oe, lists.back(), cnf);
|
getResultPatrol(oe, lists.back(), cnf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cnf.hasRogaining()) {
|
|
||||||
//gdi.addButton("Result:rogainingind", "Rogaining", ListsCB).setExtra(2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaListContainer &lc = oe.getListContainer();
|
MetaListContainer &lc = oe.getListContainer();
|
||||||
|
|||||||
@ -1089,6 +1089,10 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
pRunner r = oe->getRunner(runnerId, 0);
|
pRunner r = oe->getRunner(runnerId, 0);
|
||||||
if (r) {
|
if (r) {
|
||||||
warnDuplicateCard(gdi, cardNo, r);
|
warnDuplicateCard(gdi, cardNo, r);
|
||||||
|
|
||||||
|
if (ii.changedInput() && oe->hasHiredCardData()) {
|
||||||
|
gdi.check("RentCard", oe->isHiredCard(cardNo));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1369,7 +1373,6 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
|
|||||||
ButtonInfo bi=*(ButtonInfo *)data;
|
ButtonInfo bi=*(ButtonInfo *)data;
|
||||||
TabSI &tsi = dynamic_cast<TabSI &>(*gdi.getTabs().get(TSITab));
|
TabSI &tsi = dynamic_cast<TabSI &>(*gdi.getTabs().get(TSITab));
|
||||||
|
|
||||||
|
|
||||||
if (bi.id == "VacancyAdd") {
|
if (bi.id == "VacancyAdd") {
|
||||||
showVacancyList(gdi, "add");
|
showVacancyList(gdi, "add");
|
||||||
}
|
}
|
||||||
@ -1509,9 +1512,12 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabRunner::setCardNo(gdioutput &gdi, int cardNo)
|
void TabRunner::setCardNo(gdioutput &gdi, int cardNo) {
|
||||||
{
|
pRunner db_r=oe->dbLookUpByCard(cardNo);
|
||||||
pRunner db_r=oe->dbLookUpByCard(cardNo);
|
|
||||||
|
if (cardNo > 0 && oe->hasHiredCardData()) {
|
||||||
|
gdi.check("RentCard", oe->isHiredCard(cardNo));
|
||||||
|
}
|
||||||
|
|
||||||
if (db_r) {
|
if (db_r) {
|
||||||
gdi.setText("Name", db_r->getName());
|
gdi.setText("Name", db_r->getName());
|
||||||
@ -1810,7 +1816,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vector<pFreePunch> punches;
|
vector<pFreePunch> punches;
|
||||||
oe.getPunchesForRunner(r->getId(), punches);
|
oe.getPunchesForRunner(r->getId(), true, punches);
|
||||||
|
|
||||||
int lastT = r->getStartTime();
|
int lastT = r->getStartTime();
|
||||||
for (size_t k = 0; k < punches.size(); k++) {
|
for (size_t k = 0; k < punches.size(); k++) {
|
||||||
@ -1953,7 +1959,7 @@ void TabRunner::showVacancyList(gdioutput &gdi, const string &method, int classI
|
|||||||
lastFee = tsi.storedInfo.storedFee;
|
lastFee = tsi.storedInfo.storedFee;
|
||||||
|
|
||||||
gdi.addCombo("Fee", 60, 150, 0, L"Avgift:");
|
gdi.addCombo("Fee", 60, 150, 0, L"Avgift:");
|
||||||
oe->fillFees(gdi, "Fee", true);
|
oe->fillFees(gdi, "Fee", false, true);
|
||||||
gdi.autoGrow("Fee");
|
gdi.autoGrow("Fee");
|
||||||
|
|
||||||
if (!lastFee.empty() && lastFee != L"@") {
|
if (!lastFee.empty() && lastFee != L"@") {
|
||||||
@ -2097,11 +2103,12 @@ void TabRunner::listRunners(gdioutput &gdi, const vector<pRunner> &r, bool filte
|
|||||||
for (size_t k=0; k<r.size(); k++) {
|
for (size_t k=0; k<r.size(); k++) {
|
||||||
if (filterVacant && r[k]->isVacant())
|
if (filterVacant && r[k]->isVacant())
|
||||||
continue;
|
continue;
|
||||||
|
out.clear();
|
||||||
sprintf_s(bf, "%d.", k+1);
|
sprintf_s(bf, "%d.", k+1);
|
||||||
gdi.addStringUT(yp, xp, 0, bf);
|
gdi.addStringUT(yp, xp, 0, bf);
|
||||||
gdi.addStringUT(yp, xp+40, 0, r[k]->getNameAndRace(true), 190);
|
gdi.addStringUT(yp, xp+gdi.scaleLength(40), 0, r[k]->getNameAndRace(true), gdi.scaleLength(190));
|
||||||
gdi.addStringUT(yp, xp+200, 0, r[k]->getClass(true), 140);
|
gdi.addStringUT(yp, xp+gdi.scaleLength(200), 0, r[k]->getClass(true), gdi.scaleLength(140));
|
||||||
gdi.addStringUT(yp, xp+350, 0, r[k]->getClub(), 190);
|
gdi.addStringUT(yp, xp + gdi.scaleLength(350), 0, r[k]->getClub(), +gdi.scaleLength(190));
|
||||||
int c = r[k]->getCardNo();
|
int c = r[k]->getCardNo();
|
||||||
if (c>0) {
|
if (c>0) {
|
||||||
{
|
{
|
||||||
@ -2113,10 +2120,10 @@ void TabRunner::listRunners(gdioutput &gdi, const vector<pRunner> &r, bool filte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (out.size() <= 1) {
|
if (out.size() <= 1) {
|
||||||
gdi.addStringUT(yp, xp+550, 0, "(" + itos(c) + ")", 190);
|
gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, "(" + itos(c) + ")", 190);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TextInfo &ti = gdi.addStringUT(yp, xp+550, 0, L"(" + itow(c) + lang.tl(", reused card") + L")", 100);
|
TextInfo &ti = gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, L"(" + itow(c) + lang.tl(", reused card") + L")", gdi.scaleLength(100));
|
||||||
wstring tt;
|
wstring tt;
|
||||||
for (size_t j = 0; j < out.size(); j++) {
|
for (size_t j = 0; j < out.size(); j++) {
|
||||||
if (out[j] == r[k]->getMultiRunner(0))
|
if (out[j] == r[k]->getMultiRunner(0))
|
||||||
@ -2793,6 +2800,8 @@ void TabRunner::fillRunnerList(gdioutput &gdi) {
|
|||||||
|
|
||||||
bool TabRunner::canSetStart(pRunner r) const {
|
bool TabRunner::canSetStart(pRunner r) const {
|
||||||
pClass pc = r->getTeam() ? r->getTeam()->getClassRef(false) : r->getClassRef(true);
|
pClass pc = r->getTeam() ? r->getTeam()->getClassRef(false) : r->getClassRef(true);
|
||||||
|
if (r->getTeam() && pc->isQualificationFinalBaseClass())
|
||||||
|
pc = r->getClassRef(true);
|
||||||
|
|
||||||
if (pc && pc->getNumStages() > 0) {
|
if (pc && pc->getNumStages() > 0) {
|
||||||
StartTypes st = pc->getStartType(r->getLegNumber());
|
StartTypes st = pc->getStartType(r->getLegNumber());
|
||||||
|
|||||||
193
code/TabSI.cpp
193
code/TabSI.cpp
@ -933,12 +933,14 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.restore("EntryLine");
|
gdi.restore("EntryLine");
|
||||||
|
|
||||||
wchar_t bf[256];
|
wchar_t bf[256];
|
||||||
|
wstring cno = r->getCardNo() > 0 ? L"(" + itow(r->getCardNo()) + L"), " : L"";
|
||||||
|
|
||||||
if (r->getClubId() != 0) {
|
if (r->getClubId() != 0) {
|
||||||
swprintf_s(bf, L"(%d), %s, %s", r->getCardNo(), r->getClub().c_str(),
|
swprintf_s(bf, L"%s%s, %s", cno.c_str(), r->getClub().c_str(),
|
||||||
r->getClass(true).c_str());
|
r->getClass(true).c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
swprintf_s(bf, L"(%d), %s", r->getCardNo(), r->getClass(true).c_str());
|
swprintf_s(bf, L"%s%s", cno.c_str(), r->getClass(true).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring info(bf);
|
wstring info(bf);
|
||||||
@ -1035,6 +1037,84 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.setInputStatus("StatusOK", !dnf);
|
gdi.setInputStatus("StatusOK", !dnf);
|
||||||
gdi.check("StatusOK", !dnf);
|
gdi.check("StatusOK", !dnf);
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "RHCClear") {
|
||||||
|
if (gdi.ask(L"Vill du tömma listan med hyrbrickor?")) {
|
||||||
|
oe->clearHiredCards();
|
||||||
|
loadPage(gdi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bi.id == "RHCImport") {
|
||||||
|
wstring fn = gdi.browseForOpen({ make_pair(L"Semikolonseparerad (csv)", L"*.csv") }, L"csv");
|
||||||
|
if (!fn.empty()) {
|
||||||
|
csvparser csv;
|
||||||
|
list<vector<wstring>> data;
|
||||||
|
csv.parse(fn, data);
|
||||||
|
set<int> rentCards;
|
||||||
|
for (auto &c : data) {
|
||||||
|
for (wstring wc : c) {
|
||||||
|
int cn = _wtoi(wc.c_str());
|
||||||
|
if (cn > 0) {
|
||||||
|
oe->setHiredCard(cn, true);
|
||||||
|
gdi.addStringUT(0, itos(cn)).setHandler(getResetHiredCardHandler());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gdi.scrollToBottom();
|
||||||
|
gdi.refresh();
|
||||||
|
vector<pRunner> runners;
|
||||||
|
oe->getRunners(0, 0, runners);
|
||||||
|
if (!runners.empty() && gdi.ask(L"Vill du sätta hyrbricka på befintliga löpare med dessa brickor?")) {
|
||||||
|
int bcf = oe->getBaseCardFee();
|
||||||
|
for (pRunner r : runners) {
|
||||||
|
if (rentCards.count(r->getCardNo()) && r->getDCI().getInt("CardFee") == 0) {
|
||||||
|
gdi.addStringUT(0, r->getCompleteIdentification());
|
||||||
|
r->getDI().setInt("CardFee", bcf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadPage(gdi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bi.id == "RHCExport") {
|
||||||
|
int ix = 0;
|
||||||
|
wstring fn = gdi.browseForSave({ make_pair(L"Semikolonseparerad (csv)", L"*.csv") }, L"csv", ix);
|
||||||
|
if (!fn.empty()) {
|
||||||
|
oe->synchronizeList(oListId::oLPunchId);
|
||||||
|
|
||||||
|
auto hc = oe->getHiredCards();
|
||||||
|
csvparser csv;
|
||||||
|
csv.openOutput(fn);
|
||||||
|
for (int c : hc)
|
||||||
|
csv.outputRow(itos(c));
|
||||||
|
csv.closeOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bi.id == "RHCPrint") {
|
||||||
|
gdioutput gdiPrint("print", gdi.getScale());
|
||||||
|
gdiPrint.clearPage(false);
|
||||||
|
|
||||||
|
gdiPrint.addString("", boldLarge, "Hyrbricksrapport");
|
||||||
|
|
||||||
|
oe->synchronizeList(oListId::oLPunchId);
|
||||||
|
auto hc = oe->getHiredCards();
|
||||||
|
int dc = gdiPrint.scaleLength(70);
|
||||||
|
int col = 0;
|
||||||
|
gdiPrint.dropLine(2);
|
||||||
|
int cx = gdiPrint.getCX();
|
||||||
|
int cy = gdiPrint.getCY();
|
||||||
|
|
||||||
|
for (int h : hc) {
|
||||||
|
if (col >= 8) {
|
||||||
|
col = 0;
|
||||||
|
cy += gdiPrint.getLineHeight() * 2;
|
||||||
|
}
|
||||||
|
gdiPrint.addStringUT(cy, cx + col * dc, 0, itow(h));
|
||||||
|
col++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdiPrint.refresh();
|
||||||
|
gdiPrint.print(oe);
|
||||||
|
}
|
||||||
else if (bi.id == "CCSClear") {
|
else if (bi.id == "CCSClear") {
|
||||||
if (gdi.ask(L"Vill du göra om avbockningen från början igen?")) {
|
if (gdi.ask(L"Vill du göra om avbockningen från början igen?")) {
|
||||||
checkedCardFlags.clear();
|
checkedCardFlags.clear();
|
||||||
@ -1138,6 +1218,9 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
|||||||
else if (mode == ModeCheckCards) {
|
else if (mode == ModeCheckCards) {
|
||||||
showCheckCardStatus(gdi, "init");
|
showCheckCardStatus(gdi, "init");
|
||||||
}
|
}
|
||||||
|
else if (mode == ModeRegisterCards) {
|
||||||
|
showRegisterHiredCards(gdi);
|
||||||
|
}
|
||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
else if (bi.id=="Fee") {
|
else if (bi.id=="Fee") {
|
||||||
@ -1385,12 +1468,17 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
|||||||
if (runnerMatchedId != -1 && gdi.isChecked("AutoTie") && cardNo>0)
|
if (runnerMatchedId != -1 && gdi.isChecked("AutoTie") && cardNo>0)
|
||||||
gdi.addTimeoutMilli(50, "TieCard", SportIdentCB).setExtra(runnerMatchedId);
|
gdi.addTimeoutMilli(50, "TieCard", SportIdentCB).setExtra(runnerMatchedId);
|
||||||
}
|
}
|
||||||
else if (cardNo>0 && gdi.getText("Name").empty()) {
|
else if (cardNo>0) {
|
||||||
SICard sic(ConvertedTimeStatus::Hour24);
|
if (ii.changedInput() && oe->hasHiredCardData())
|
||||||
sic.clear(0);
|
gdi.check("RentCard", oe->isHiredCard(cardNo));
|
||||||
sic.CardNumber = cardNo;
|
|
||||||
|
|
||||||
entryCard(gdi, sic);
|
if (gdi.getText("Name").empty()) {
|
||||||
|
SICard sic(ConvertedTimeStatus::Hour24);
|
||||||
|
sic.clear(0);
|
||||||
|
sic.CardNumber = cardNo;
|
||||||
|
|
||||||
|
entryCard(gdi, sic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ii.id[0]=='*') {
|
else if (ii.id[0]=='*') {
|
||||||
@ -1644,6 +1732,7 @@ bool TabSI::loadPage(gdioutput &gdi) {
|
|||||||
gdi.addItem("ReadType", lang.tl("Avläsning/radiotider"), ModeReadOut);
|
gdi.addItem("ReadType", lang.tl("Avläsning/radiotider"), ModeReadOut);
|
||||||
gdi.addItem("ReadType", lang.tl("Tilldela hyrbrickor"), ModeAssignCards);
|
gdi.addItem("ReadType", lang.tl("Tilldela hyrbrickor"), ModeAssignCards);
|
||||||
gdi.addItem("ReadType", lang.tl("Avstämning hyrbrickor"), ModeCheckCards);
|
gdi.addItem("ReadType", lang.tl("Avstämning hyrbrickor"), ModeCheckCards);
|
||||||
|
gdi.addItem("ReadType", lang.tl("Registrera hyrbrickor"), ModeRegisterCards);
|
||||||
gdi.addItem("ReadType", lang.tl("Anmälningsläge"), ModeEntry);
|
gdi.addItem("ReadType", lang.tl("Anmälningsläge"), ModeEntry);
|
||||||
gdi.addItem("ReadType", lang.tl("Print card data"), ModeCardData);
|
gdi.addItem("ReadType", lang.tl("Print card data"), ModeCardData);
|
||||||
|
|
||||||
@ -1709,7 +1798,9 @@ bool TabSI::loadPage(gdioutput &gdi) {
|
|||||||
else if (mode == ModeCheckCards) {
|
else if (mode == ModeCheckCards) {
|
||||||
showCheckCardStatus(gdi, "init");
|
showCheckCardStatus(gdi, "init");
|
||||||
}
|
}
|
||||||
|
else if (mode == ModeRegisterCards) {
|
||||||
|
showRegisterHiredCards(gdi);
|
||||||
|
}
|
||||||
|
|
||||||
// Unconditional clear
|
// Unconditional clear
|
||||||
activeSIC.clear(0);
|
activeSIC.clear(0);
|
||||||
@ -1783,7 +1874,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
|||||||
DWORD loaded;
|
DWORD loaded;
|
||||||
bool pageLoaded=gdi.getData("SIPageLoaded", loaded);
|
bool pageLoaded=gdi.getData("SIPageLoaded", loaded);
|
||||||
|
|
||||||
if (pageLoaded && manualInput)
|
if (pageLoaded && manualInput && mode == ModeReadOut)
|
||||||
gdi.restore("ManualInput");
|
gdi.restore("ManualInput");
|
||||||
|
|
||||||
if (!pageLoaded && !insertCardNumberField.empty()) {
|
if (!pageLoaded && !insertCardNumberField.empty()) {
|
||||||
@ -1816,6 +1907,16 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
|||||||
checkCard(gdi, sic, true);
|
checkCard(gdi, sic, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (mode == ModeRegisterCards) {
|
||||||
|
if (!pageLoaded) {
|
||||||
|
CardQueue.push_back(sic);
|
||||||
|
gdi.addInfoBox("SIREAD", L"Inläst bricka ställd i kö");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
registerHiredCard(gdi, sic);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (mode == ModeCardData) {
|
else if (mode == ModeCardData) {
|
||||||
if (sic.convertedTime == ConvertedTimeStatus::Hour12) {
|
if (sic.convertedTime == ConvertedTimeStatus::Hour12) {
|
||||||
int locTime = getLocalAbsTime();
|
int locTime = getLocalAbsTime();
|
||||||
@ -2549,6 +2650,9 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
|
|||||||
{
|
{
|
||||||
gdi.setText("CardNo", sic.CardNumber);
|
gdi.setText("CardNo", sic.CardNumber);
|
||||||
|
|
||||||
|
if (oe->hasHiredCardData())
|
||||||
|
gdi.check("RentCard", oe->isHiredCard(sic.CardNumber));
|
||||||
|
|
||||||
wstring name;
|
wstring name;
|
||||||
wstring club;
|
wstring club;
|
||||||
int age = 0;
|
int age = 0;
|
||||||
@ -2582,6 +2686,9 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
|
|||||||
if (cls && age > 0) {
|
if (cls && age > 0) {
|
||||||
directEntryGUI.updateFees(gdi, cls, age);
|
directEntryGUI.updateFees(gdi, cls, age);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
updateEntryInfo(gdi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabSI::assignCard(gdioutput &gdi, const SICard &sic)
|
void TabSI::assignCard(gdioutput &gdi, const SICard &sic)
|
||||||
@ -2690,7 +2797,7 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r) {
|
|||||||
|
|
||||||
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy)) {
|
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy)) {
|
||||||
gdi.addCombo("Fee", 60, 150, SportIdentCB, L"Anm. avgift:");
|
gdi.addCombo("Fee", 60, 150, SportIdentCB, L"Anm. avgift:");
|
||||||
oe->fillFees(gdi, "Fee", false);
|
oe->fillFees(gdi, "Fee", true, false);
|
||||||
|
|
||||||
if (!storedInfo.storedFee.empty() && storedInfo.storedFee != L"@")
|
if (!storedInfo.storedFee.empty() && storedInfo.storedFee != L"@")
|
||||||
gdi.setText("Fee", storedInfo.storedFee);
|
gdi.setText("Fee", storedInfo.storedFee);
|
||||||
@ -3503,6 +3610,35 @@ wstring TabSI::getCardInfo(bool param, vector<int> &count) const {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabSI::showRegisterHiredCards(gdioutput &gdi) {
|
||||||
|
gdi.disableInput("Interactive");
|
||||||
|
gdi.disableInput("Database");
|
||||||
|
gdi.disableInput("PrintSplits");
|
||||||
|
gdi.disableInput("UseManualInput");
|
||||||
|
|
||||||
|
gdi.fillDown();
|
||||||
|
gdi.addString("", 10, "help:registerhiredcards");
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.fillRight();
|
||||||
|
gdi.pushX();
|
||||||
|
gdi.addButton("RHCClear", "Nollställ", SportIdentCB);
|
||||||
|
gdi.addButton("RHCImport", "Importera...", SportIdentCB);
|
||||||
|
gdi.addButton("RHCExport", "Exportera...", SportIdentCB);
|
||||||
|
gdi.addButton("RHCPrint", "Skriv ut...", SportIdentCB);
|
||||||
|
gdi.popX();
|
||||||
|
gdi.dropLine(3);
|
||||||
|
gdi.fillDown();
|
||||||
|
|
||||||
|
oe->synchronizeList(oListId::oLPunchId);
|
||||||
|
auto &hiredCards = oe->getHiredCards();
|
||||||
|
for (int i : hiredCards) {
|
||||||
|
gdi.addStringUT(0, itos(i)).setExtra(i).setHandler(getResetHiredCardHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
|
void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
|
||||||
vector<pRunner> r;
|
vector<pRunner> r;
|
||||||
const int cx = gdi.getCX();
|
const int cx = gdi.getCX();
|
||||||
@ -3514,6 +3650,7 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
|
|||||||
gdi.disableInput("Database");
|
gdi.disableInput("Database");
|
||||||
gdi.disableInput("PrintSplits");
|
gdi.disableInput("PrintSplits");
|
||||||
gdi.disableInput("UseManualInput");
|
gdi.disableInput("UseManualInput");
|
||||||
|
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addString("", 10, "help:checkcards");
|
gdi.addString("", 10, "help:checkcards");
|
||||||
|
|
||||||
@ -3640,6 +3777,42 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
|
|||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ResetHiredCard : public GuiHandler {
|
||||||
|
oEvent *oe;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
|
||||||
|
if (type == GuiEventType::GUI_LINK) {
|
||||||
|
TextInfo &ti = dynamic_cast<TextInfo &>(info);
|
||||||
|
int c = _wtoi(ti.text.c_str());
|
||||||
|
if (gdi.ask(L"Vill du ta bort brickan från hyrbrickslistan?")) {
|
||||||
|
oe->setHiredCard(c, false);
|
||||||
|
ti.text = L"-";
|
||||||
|
ti.setHandler(nullptr);
|
||||||
|
gdi.refreshFast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetHiredCard(oEvent *oe) : oe(oe) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
GuiHandler *TabSI::getResetHiredCardHandler() {
|
||||||
|
if (!resetHiredCardHandler)
|
||||||
|
resetHiredCardHandler = make_shared<ResetHiredCard>(oe);
|
||||||
|
|
||||||
|
return resetHiredCardHandler.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabSI::registerHiredCard(gdioutput &gdi, const SICard &sic) {
|
||||||
|
if (!oe->isHiredCard(sic.CardNumber))
|
||||||
|
oe->setHiredCard(sic.CardNumber, true);
|
||||||
|
gdi.addStringUT(0, itos(sic.CardNumber)).setHandler(getResetHiredCardHandler());
|
||||||
|
gdi.scrollToBottom();
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
void TabSI::checkCard(gdioutput &gdi, const SICard &card, bool updateAll) {
|
void TabSI::checkCard(gdioutput &gdi, const SICard &card, bool updateAll) {
|
||||||
bool wasChecked = (checkedCardFlags[card.CardNumber] & CNFChecked) != 0 && updateAll;
|
bool wasChecked = (checkedCardFlags[card.CardNumber] & CNFChecked) != 0 && updateAll;
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,8 @@ public:
|
|||||||
ModeAssignCards,
|
ModeAssignCards,
|
||||||
ModeCheckCards,
|
ModeCheckCards,
|
||||||
ModeEntry,
|
ModeEntry,
|
||||||
ModeCardData
|
ModeCardData,
|
||||||
|
ModeRegisterCards,
|
||||||
};
|
};
|
||||||
|
|
||||||
void setMode(SIMode m) { mode = m; }
|
void setMode(SIMode m) { mode = m; }
|
||||||
@ -73,6 +74,9 @@ private:
|
|||||||
|
|
||||||
set<int> warnedClassOutOfMaps;
|
set<int> warnedClassOutOfMaps;
|
||||||
|
|
||||||
|
shared_ptr<GuiHandler> resetHiredCardHandler;
|
||||||
|
GuiHandler *getResetHiredCardHandler();
|
||||||
|
|
||||||
int runnerMatchedId;
|
int runnerMatchedId;
|
||||||
bool printErrorShown;
|
bool printErrorShown;
|
||||||
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
|
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
|
||||||
@ -94,6 +98,7 @@ private:
|
|||||||
int inputId;
|
int inputId;
|
||||||
|
|
||||||
void showCheckCardStatus(gdioutput &gdi, const string &cmd);
|
void showCheckCardStatus(gdioutput &gdi, const string &cmd);
|
||||||
|
void showRegisterHiredCards(gdioutput &gdi);
|
||||||
|
|
||||||
wstring getCardInfo(bool param, vector<int> &count) const;
|
wstring getCardInfo(bool param, vector<int> &count) const;
|
||||||
// Formatting for card tick off
|
// Formatting for card tick off
|
||||||
@ -119,6 +124,7 @@ private:
|
|||||||
|
|
||||||
map<int, CardNumberFlags> checkedCardFlags;
|
map<int, CardNumberFlags> checkedCardFlags;
|
||||||
void checkCard(gdioutput &gdi, const SICard &sic, bool updateAll);
|
void checkCard(gdioutput &gdi, const SICard &sic, bool updateAll);
|
||||||
|
void registerHiredCard(gdioutput &gdi, const SICard &sic);
|
||||||
|
|
||||||
void showReadPunches(gdioutput &gdi, vector<PunchInfo> &punches, set<string> &dates);
|
void showReadPunches(gdioutput &gdi, vector<PunchInfo> &punches, set<string> &dates);
|
||||||
void showReadCards(gdioutput &gdi, vector<SICard> &cards);
|
void showReadCards(gdioutput &gdi, vector<SICard> &cards);
|
||||||
|
|||||||
@ -979,15 +979,15 @@ bool TabSpeaker::loadPage(gdioutput &gdi) {
|
|||||||
int h,w;
|
int h,w;
|
||||||
gdi.getTargetDimension(w, h);
|
gdi.getTargetDimension(w, h);
|
||||||
|
|
||||||
int bw=gdi.scaleLength(100);
|
int bw = gdi.scaleLength(100);
|
||||||
int nbtn=max((w-80)/bw, 1);
|
int numBtn = max((w - gdi.scaleLength(80)) / bw, 1);
|
||||||
bw=(w-80)/nbtn;
|
bw = (w - 80) / numBtn;
|
||||||
int basex = SPEAKER_BASE_X;
|
int basex = SPEAKER_BASE_X;
|
||||||
int basey=gdi.getCY();
|
int basey=gdi.getCY();
|
||||||
|
|
||||||
int cx=basex;
|
int cx=basex;
|
||||||
int cy=basey;
|
int cy=basey;
|
||||||
int cb=1;
|
|
||||||
vector<pClass> clsToWatch;
|
vector<pClass> clsToWatch;
|
||||||
for (int cid : classesToWatch) {
|
for (int cid : classesToWatch) {
|
||||||
pClass pc = oe->getClass(cid);
|
pClass pc = oe->getClass(cid);
|
||||||
@ -998,18 +998,29 @@ bool TabSpeaker::loadPage(gdioutput &gdi) {
|
|||||||
|
|
||||||
sort(clsToWatch.begin(), clsToWatch.end(), [](const pClass &a, const pClass &b) {return *a < *b; });
|
sort(clsToWatch.begin(), clsToWatch.end(), [](const pClass &a, const pClass &b) {return *a < *b; });
|
||||||
|
|
||||||
|
int bwCls = bw;
|
||||||
|
TextInfo ti;
|
||||||
|
for (auto pc : clsToWatch) {
|
||||||
|
ti.xp = 0;
|
||||||
|
ti.yp = 0;
|
||||||
|
ti.format = 0;
|
||||||
|
ti.text = pc->getName();
|
||||||
|
gdi.calcStringSize(ti);
|
||||||
|
bwCls = max(bwCls, ti.realWidth+ gdi.scaleLength(10));
|
||||||
|
}
|
||||||
|
int limitX = w - bw / 3;
|
||||||
|
|
||||||
for (auto pc : clsToWatch) {
|
for (auto pc : clsToWatch) {
|
||||||
char classid[32];
|
char classid[32];
|
||||||
sprintf_s(classid, "cid%d", pc->getId());
|
sprintf_s(classid, "cid%d", pc->getId());
|
||||||
gdi.addButton(cx, cy, bw, classid, L"#" + pc->getName(), tabSpeakerCB, L"", false, false);
|
|
||||||
cx+=bw;
|
|
||||||
cb++;
|
|
||||||
|
|
||||||
if (cb>nbtn) {
|
if (cx > basex && (cx + bwCls) >= limitX) {
|
||||||
cb=1;
|
cx = basex;
|
||||||
cx=basex;
|
cy += gdi.getButtonHeight() + 4;
|
||||||
cy+=gdi.getButtonHeight()+4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdi.addButton(cx, cy, bwCls-2, classid, L"#" + pc->getName(), tabSpeakerCB, L"", false, false);
|
||||||
|
cx += bwCls;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pm = false;
|
bool pm = false;
|
||||||
@ -1021,20 +1032,21 @@ bool TabSpeaker::loadPage(gdioutput &gdi) {
|
|||||||
cx=gdi.getCX();
|
cx=gdi.getCX();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
|
cx = basex; db = 0;
|
||||||
|
cy += gdi.getButtonHeight() + 4;
|
||||||
|
}
|
||||||
gdi.addButton(cx+db, cy, bw-2, "Events", "Händelser", tabSpeakerCB, "Löpande information om viktiga händelser i tävlingen", false, false);
|
gdi.addButton(cx+db, cy, bw-2, "Events", "Händelser", tabSpeakerCB, "Löpande information om viktiga händelser i tävlingen", false, false);
|
||||||
if (++cb>nbtn) {
|
db += bw;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight()+4;
|
|
||||||
} else db += bw;
|
|
||||||
pm = true;
|
pm = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.addButton(cx + db, cy, bw - 2, "Report", "Rapportläge", tabSpeakerCB, "Visa detaljerad rapport för viss deltagare", false, false);
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
if (++cb>nbtn) {
|
cx = basex; db = 0;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight() + 4;
|
cy += gdi.getButtonHeight() + 4;
|
||||||
}
|
}
|
||||||
else db += bw;
|
gdi.addButton(cx + db, cy, bw - 2, "Report", "Rapportläge", tabSpeakerCB, "Visa detaljerad rapport för viss deltagare", false, false);
|
||||||
|
db += bw;
|
||||||
|
|
||||||
if (pm) {
|
if (pm) {
|
||||||
gdi.addButton(cx + db, cy, bw / 5, "ZoomIn", "+", tabSpeakerCB, "Zooma in (Ctrl + '+')", false, false);
|
gdi.addButton(cx + db, cy, bw / 5, "ZoomIn", "+", tabSpeakerCB, "Zooma in (Ctrl + '+')", false, false);
|
||||||
@ -1043,62 +1055,69 @@ bool TabSpeaker::loadPage(gdioutput &gdi) {
|
|||||||
db += bw / 5 + 2;
|
db += bw / 5 + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
|
cx = basex; db = 0;
|
||||||
|
cy += gdi.getButtonHeight() + 4;
|
||||||
|
}
|
||||||
gdi.addButton(cx+db, cy, bw-2, "Settings", "Inställningar...", tabSpeakerCB, "Välj vilka klasser och kontroller som bevakas", false, false);
|
gdi.addButton(cx+db, cy, bw-2, "Settings", "Inställningar...", tabSpeakerCB, "Välj vilka klasser och kontroller som bevakas", false, false);
|
||||||
if (++cb>nbtn) {
|
db += bw;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight()+4;
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
} else db += bw;
|
cx = basex; db = 0;
|
||||||
|
cy += gdi.getButtonHeight() + 4;
|
||||||
|
}
|
||||||
gdi.addButton(cx+db, cy, bw-2, "Manual", "Tidsinmatning", tabSpeakerCB, "Mata in radiotider manuellt", false, false);
|
gdi.addButton(cx+db, cy, bw-2, "Manual", "Tidsinmatning", tabSpeakerCB, "Mata in radiotider manuellt", false, false);
|
||||||
if (++cb>nbtn) {
|
db += bw;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight()+4;
|
|
||||||
} else db += bw;
|
|
||||||
|
|
||||||
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
|
cx = basex; db = 0;
|
||||||
|
cy += gdi.getButtonHeight() + 4;
|
||||||
|
}
|
||||||
gdi.addButton(cx+db, cy, bw-2, "PunchTable", "Stämplingar", tabSpeakerCB, "Visa en tabell över alla stämplingar", false, false);
|
gdi.addButton(cx+db, cy, bw-2, "PunchTable", "Stämplingar", tabSpeakerCB, "Visa en tabell över alla stämplingar", false, false);
|
||||||
if (++cb>nbtn) {
|
db += bw;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight()+4;
|
|
||||||
} else db += bw;
|
|
||||||
|
|
||||||
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
|
cx = basex; db = 0;
|
||||||
|
cy += gdi.getButtonHeight() + 4;
|
||||||
|
}
|
||||||
gdi.addButton(cx+db, cy, bw-2, "LiveResult", "Direkt tidtagning", tabSpeakerCB, "Visa rullande tider mellan kontroller i helskärmsläge", false, false);
|
gdi.addButton(cx+db, cy, bw-2, "LiveResult", "Direkt tidtagning", tabSpeakerCB, "Visa rullande tider mellan kontroller i helskärmsläge", false, false);
|
||||||
if (++cb>nbtn) {
|
db += bw;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight()+4;
|
|
||||||
} else db += bw;
|
|
||||||
|
|
||||||
if (!ownWindow) {
|
if (!ownWindow) {
|
||||||
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
|
cx = basex; db = 0;
|
||||||
|
cy += gdi.getButtonHeight() + 4;
|
||||||
|
}
|
||||||
gdi.addButton(cx+db, cy, bw-2, "Priority", "Prioritering", tabSpeakerCB, "Välj löpare att prioritera bevakning för", false, false);
|
gdi.addButton(cx+db, cy, bw-2, "Priority", "Prioritering", tabSpeakerCB, "Välj löpare att prioritera bevakning för", false, false);
|
||||||
if (++cb>nbtn) {
|
db += bw;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight()+4;
|
|
||||||
} else db += bw;
|
|
||||||
|
|
||||||
|
|
||||||
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
|
cx = basex; db = 0;
|
||||||
|
cy += gdi.getButtonHeight() + 4;
|
||||||
|
}
|
||||||
gdi.addButton(cx+db, cy, bw-2, "Window", "Nytt fönster", tabSpeakerCB, "", false, false);
|
gdi.addButton(cx+db, cy, bw-2, "Window", "Nytt fönster", tabSpeakerCB, "", false, false);
|
||||||
if (++cb>nbtn) {
|
db += bw;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight()+4;
|
|
||||||
} else db += bw;
|
|
||||||
|
|
||||||
|
|
||||||
if (getExtraWindows().size() == 1) {
|
if (getExtraWindows().size() == 1) {
|
||||||
wstring sf = getSpeakerSettingsFile();
|
wstring sf = getSpeakerSettingsFile();
|
||||||
if (fileExist(sf.c_str())) {
|
if (fileExist(sf.c_str())) {
|
||||||
gdi.addButton(cx + db, cy, bw - 2, "LoadWindows", "Återskapa", tabSpeakerCB, "Återskapa tidigare sparade fönster- och speakerinställningar", false, false);
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
if (++cb > nbtn) {
|
cx = basex; db = 0;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight() + 4;
|
cy += gdi.getButtonHeight() + 4;
|
||||||
}
|
}
|
||||||
else db += bw;
|
gdi.addButton(cx + db, cy, bw - 2, "LoadWindows", "Återskapa", tabSpeakerCB, "Återskapa tidigare sparade fönster- och speakerinställningar", false, false);
|
||||||
|
db += bw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gdi.addButton(cx + db, cy, bw - 2, "SaveWindows", "Spara", tabSpeakerCB, "Spara fönster- och speakerinställningar på datorn", false, false);
|
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||||
if (++cb > nbtn) {
|
cx = basex; db = 0;
|
||||||
cb = 1, cx = basex, db = 0;
|
|
||||||
cy += gdi.getButtonHeight() + 4;
|
cy += gdi.getButtonHeight() + 4;
|
||||||
}
|
}
|
||||||
else db += bw;
|
gdi.addButton(cx + db, cy, bw - 2, "SaveWindows", "Spara", tabSpeakerCB, "Spara fönster- och speakerinställningar på datorn", false, false);
|
||||||
|
db += bw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -442,7 +442,6 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
|||||||
r->setName(name, true);
|
r->setName(name, true);
|
||||||
}
|
}
|
||||||
r->setCardNo(cardNo, true);
|
r->setCardNo(cardNo, true);
|
||||||
|
|
||||||
if (gdi.isChecked("RENT" + itos(i)))
|
if (gdi.isChecked("RENT" + itos(i)))
|
||||||
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||||
else
|
else
|
||||||
@ -461,10 +460,15 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
r=oe->addRunner(name, t->getClubId(), t->getClassId(false), cardNo, 0, false);
|
r = oe->addRunner(name, t->getClubId(), t->getClassId(false), cardNo, 0, false);
|
||||||
|
|
||||||
r->setName(name, true);
|
r->setName(name, true);
|
||||||
r->setCardNo(cardNo, true);
|
r->setCardNo(cardNo, true);
|
||||||
|
if (gdi.isChecked("RENT" + itos(i)))
|
||||||
|
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||||
|
else
|
||||||
|
r->getDI().setInt("CardFee", 0);
|
||||||
|
|
||||||
r->synchronize();
|
r->synchronize();
|
||||||
t->setRunner(i, r, true);
|
t->setRunner(i, r, true);
|
||||||
}
|
}
|
||||||
@ -1065,8 +1069,11 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ii.id == "DirName" || ii.id == "DirCard") {
|
if (ii.id == "DirName" || ii.id == "DirCard") {
|
||||||
gdi.setInputStatus("DirOK", !gdi.getText("DirName").empty() &&
|
int cno = gdi.getTextNo("DirCard");
|
||||||
gdi.getTextNo("DirCard") > 0);
|
if (cno > 0 && oe->hasHiredCardData()) {
|
||||||
|
gdi.check("DirRent", oe->isHiredCard(cno));
|
||||||
|
}
|
||||||
|
gdi.setInputStatus("DirOK", !gdi.getText("DirName").empty() && cno > 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1135,12 +1142,16 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
pClass pc=oe->getClass(classId);
|
pClass pc=oe->getClass(classId);
|
||||||
if (pc) {
|
if (pc) {
|
||||||
for(unsigned i=0;i<pc->getNumStages();i++){
|
for (unsigned i = 0; i < pc->getNumStages(); i++) {
|
||||||
if (ii.id == "SI" + itos(i)) {
|
if (ii.id == "SI" + itos(i)) {
|
||||||
int cardNo = _wtoi(ii.text.c_str());
|
int cardNo = _wtoi(ii.text.c_str());
|
||||||
pTeam t = oe->getTeam(teamId);
|
pTeam t = oe->getTeam(teamId);
|
||||||
if (t) {
|
if (t) {
|
||||||
warnDuplicateCard(gdi, ii.id, cardNo, t->getRunner(i));
|
pRunner r = t->getRunner(i);
|
||||||
|
if (ii.changedInput() && oe->hasHiredCardData()) {
|
||||||
|
gdi.check("RENT" + itos(i), oe->isHiredCard(cardNo));
|
||||||
|
}
|
||||||
|
warnDuplicateCard(gdi, ii.id, cardNo, r);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -209,11 +209,11 @@ void Table::addRow(int rowId, oBase *object)
|
|||||||
|
|
||||||
Data[0].cells[i].canEdit=false;
|
Data[0].cells[i].canEdit=false;
|
||||||
Data[0].cells[i].type=cellEdit;
|
Data[0].cells[i].type=cellEdit;
|
||||||
Data[0].cells[i].owner=0;
|
Data[0].cells[i].ownerRef.reset();
|
||||||
|
|
||||||
Data[1].cells[i].canEdit=false;
|
Data[1].cells[i].canEdit=false;
|
||||||
Data[1].cells[i].type=cellEdit;
|
Data[1].cells[i].type=cellEdit;
|
||||||
Data[1].cells[i].owner=0;
|
Data[1].cells[i].ownerRef.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -236,7 +236,7 @@ void Table::set(int column, oBase &owner, int id, const wstring &data, bool canE
|
|||||||
TableRow &row=Data[dataPointer];
|
TableRow &row=Data[dataPointer];
|
||||||
TableCell &cell=row.cells[column];
|
TableCell &cell=row.cells[column];
|
||||||
cell.contents=data;
|
cell.contents=data;
|
||||||
cell.owner=&owner;
|
cell.ownerRef = owner.getReference();
|
||||||
cell.id=id;
|
cell.id=id;
|
||||||
cell.canEdit=canEdit;
|
cell.canEdit=canEdit;
|
||||||
cell.type=type;
|
cell.type=type;
|
||||||
@ -725,7 +725,8 @@ void Table::selection(gdioutput &gdi, const wstring &text, int data) {
|
|||||||
|
|
||||||
TableCell &cell = Data[selectionRow].cells[selectionCol];
|
TableCell &cell = Data[selectionRow].cells[selectionCol];
|
||||||
int id = Data[selectionRow].id;
|
int id = Data[selectionRow].id;
|
||||||
cell.owner->inputData(cell.id, text, data, cell.contents, false);
|
if (cell.hasOwner())
|
||||||
|
cell.getOwner()->inputData(cell.id, text, data, cell.contents, false);
|
||||||
reloadRow(id);
|
reloadRow(id);
|
||||||
RECT rc;
|
RECT rc;
|
||||||
getRowRect(selectionRow, rc);
|
getRowRect(selectionRow, rc);
|
||||||
@ -913,7 +914,7 @@ bool Table::editCell(gdioutput &gdi, int row, int col) {
|
|||||||
|
|
||||||
if (cell.type == cellAction) {
|
if (cell.type == cellAction) {
|
||||||
ReleaseCapture();
|
ReleaseCapture();
|
||||||
gdi.makeEvent("CellAction", internalName, cell.id, cell.owner ? cell.owner->getId() : 0, false);
|
gdi.makeEvent("CellAction", internalName, cell.id, cell.hasOwner() ? cell.getOwner()->getId() : 0, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -934,7 +935,8 @@ bool Table::editCell(gdioutput &gdi, int row, int col) {
|
|||||||
|
|
||||||
vector< pair<wstring, size_t> > out;
|
vector< pair<wstring, size_t> > out;
|
||||||
size_t selected = 0;
|
size_t selected = 0;
|
||||||
cell.owner->fillInput(cell.id, out, selected);
|
if (cell.hasOwner())
|
||||||
|
cell.getOwner()->fillInput(cell.id, out, selected);
|
||||||
|
|
||||||
int width = 40;
|
int width = 40;
|
||||||
for (size_t k = 0; k<out.size(); k++)
|
for (size_t k = 0; k<out.size(); k++)
|
||||||
@ -1593,7 +1595,8 @@ void Table::setTableText(gdioutput &gdi, int editRow, int editCol, const wstring
|
|||||||
|
|
||||||
wstring output;
|
wstring output;
|
||||||
TableCell &cell=Data[editRow].cells[editCol];
|
TableCell &cell=Data[editRow].cells[editCol];
|
||||||
cell.owner->inputData(cell.id, bf, 0, output, false);
|
if (cell.hasOwner())
|
||||||
|
cell.getOwner()->inputData(cell.id, bf, 0, output, false);
|
||||||
cell.contents = output;
|
cell.contents = output;
|
||||||
if (hEdit != 0)
|
if (hEdit != 0)
|
||||||
DestroyWindow(hEdit);
|
DestroyWindow(hEdit);
|
||||||
@ -2108,7 +2111,8 @@ void Table::importClipboard(gdioutput &gdi)
|
|||||||
if (cell.type==cellSelection || cell.type==cellCombo) {
|
if (cell.type==cellSelection || cell.type==cellCombo) {
|
||||||
vector< pair<wstring, size_t> > out;
|
vector< pair<wstring, size_t> > out;
|
||||||
size_t selected = 0;
|
size_t selected = 0;
|
||||||
cell.owner->fillInput(cell.id, out, selected);
|
if (cell.hasOwner())
|
||||||
|
cell.getOwner()->fillInput(cell.id, out, selected);
|
||||||
index = -1;
|
index = -1;
|
||||||
for (size_t i = 0; i<out.size() && index == -1; i++) {
|
for (size_t i = 0; i<out.size() && index == -1; i++) {
|
||||||
if (_wcsicmp(out[i].first.c_str(), table[k][j].c_str()) == 0)
|
if (_wcsicmp(out[i].first.c_str(), table[k][j].c_str()) == 0)
|
||||||
@ -2117,11 +2121,13 @@ void Table::importClipboard(gdioutput &gdi)
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
cell.owner->inputData(cell.id, table[k][j], index, output, false);
|
if (cell.hasOwner())
|
||||||
|
cell.getOwner()->inputData(cell.id, table[k][j], index, output, false);
|
||||||
cell.contents = output;
|
cell.contents = output;
|
||||||
}
|
}
|
||||||
else if (cell.type == cellCombo) {
|
else if (cell.type == cellCombo) {
|
||||||
cell.owner->inputData(cell.id, table[k][j], index, output, false);
|
if (cell.hasOwner())
|
||||||
|
cell.getOwner()->inputData(cell.id, table[k][j], index, output, false);
|
||||||
cell.contents = output;
|
cell.contents = output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2158,13 +2164,13 @@ int Table::deleteRows(int row1, int row2)
|
|||||||
if ( k >= sortIndex.size())
|
if ( k >= sortIndex.size())
|
||||||
throw std::exception("Index out of range");
|
throw std::exception("Index out of range");
|
||||||
const TableRow &tr = Data[sortIndex[k].index];
|
const TableRow &tr = Data[sortIndex[k].index];
|
||||||
oBase *ob = tr.cells[0].owner;
|
oBase *ob = tr.cells[0].getOwner();
|
||||||
if (!ob)
|
if (ob) {
|
||||||
throw std::exception("Null pointer exception");
|
if (ob->canRemove())
|
||||||
if (ob->canRemove())
|
ob->remove();
|
||||||
ob->remove();
|
else
|
||||||
else
|
failed++;
|
||||||
failed++;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCellSelection(0);
|
clearCellSelection(0);
|
||||||
@ -2323,8 +2329,8 @@ int Table::getNumDataRows() const {
|
|||||||
void TableRow::setObject(oBase &obj) {
|
void TableRow::setObject(oBase &obj) {
|
||||||
ob = &obj;
|
ob = &obj;
|
||||||
for (size_t k = 0; k < cells.size(); k++) {
|
for (size_t k = 0; k < cells.size(); k++) {
|
||||||
if (cells[k].owner != 0)
|
if (cells[k].hasOwner())
|
||||||
cells[k].owner = &obj;
|
cells[k].ownerRef = obj.getReference();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,10 @@ class TableCell
|
|||||||
RECT absPos;
|
RECT absPos;
|
||||||
|
|
||||||
DWORD id;
|
DWORD id;
|
||||||
oBase *owner;
|
|
||||||
|
bool hasOwner() const { return ownerRef && ownerRef->get() != nullptr; };
|
||||||
|
oBase *getOwner() const { return ownerRef ? ownerRef->get() : nullptr; }
|
||||||
|
shared_ptr<oBase::oBaseReference> ownerRef;
|
||||||
bool canEdit;
|
bool canEdit;
|
||||||
CellType type;
|
CellType type;
|
||||||
|
|
||||||
|
|||||||
@ -642,7 +642,7 @@ bool csvparser::importOCAD_CSV(oEvent &event, const wstring &file, bool addClass
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (size_t i = 0; i<cls->getNumStages(); i++)
|
for (size_t i = 0; i<cls->getNumStages(); i++)
|
||||||
cls->addStageCourse(i, pc->getId());
|
cls->addStageCourse(i, pc->getId(), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cls->synchronize();
|
cls->synchronize();
|
||||||
|
|||||||
@ -2315,3 +2315,97 @@ xml-data = XML data
|
|||||||
Year of birth = Førdselsår
|
Year of birth = Førdselsår
|
||||||
Zooma in (Ctrl + '+') = Zoom ind (Ctrl + '+')
|
Zooma in (Ctrl + '+') = Zoom ind (Ctrl + '+')
|
||||||
Zooma ut (Ctrl + '-') = Zoom ud (Ctrl + '-')
|
Zooma ut (Ctrl + '-') = Zoom ud (Ctrl + '-')
|
||||||
|
AllPunches = Alle stemplinger
|
||||||
|
Anmäl andra = Tilmeld andre
|
||||||
|
Anmälan mottagen = Tilmelding modtaget
|
||||||
|
Anmälan måste hanteras manuellt = Tilmelding skal håndteres manuelt.
|
||||||
|
Anyone = Enhver
|
||||||
|
Automatisk omladdning = Automatisk opdatering
|
||||||
|
Begränsa antal rader per sida = Begræns antal rækker per side
|
||||||
|
Bricknummer = Si brik nummer
|
||||||
|
ClassKnockoutTotalResult = Klasse, knock-out, samlet resultat
|
||||||
|
ClassLiveResult = Live resultater (radio tider), klassevis
|
||||||
|
Classes together = Klasser samlet
|
||||||
|
CoursePunches = Stemplinger (for bane)
|
||||||
|
Database is used and cannot be deleted = Databasen er i brug og kan ikke slettes
|
||||||
|
Direkt tidtagning = Direkte tidtagning
|
||||||
|
EFilterAPIEntry = Indtastning via API
|
||||||
|
Ej omstart = Ej omstart
|
||||||
|
Endast grundläggande (enklast möjligt) = Kund grundlæggende(så simpelt som muligt)
|
||||||
|
Endast tidtagning = Kun tidtagning
|
||||||
|
Endast tidtagning (utan banor) = Kun tidtagning (uden baner)
|
||||||
|
Endast tidtagning (utan banor), stafett = Kun tidtagning (uden baner), stafet
|
||||||
|
Externa adresser = Eksterne adresser
|
||||||
|
Felaktigt datum 'X' (Använd YYYY-MM-DD) = Forkert dato format 'X' (Brug YYYY-MM-DD)
|
||||||
|
Felaktigt rankingformat i X. Förväntat: Y = Forkert format på ranking i X \nForventet format: Y
|
||||||
|
FilterAnyResult = Med radiotider/resultat
|
||||||
|
FilterNamedControl = Med angivne poster
|
||||||
|
FilterNotFinish = Udeluk ikke gennemført
|
||||||
|
Finish order = Målrækkefølge
|
||||||
|
First to finish = Først gennemført
|
||||||
|
Från löpardatabasen = Fra løberdatabase
|
||||||
|
Från löpardatabasen i befintliga klubbar = Fra løber database fra klubber der er kendt
|
||||||
|
Färre slingor = Færre sløjfer
|
||||||
|
Förhindra att laget deltar i någon omstart = Udeluk at holdet deltager i omstart
|
||||||
|
Förhindra omstart = Udeluk omstart
|
||||||
|
HTML Export = HTML Export
|
||||||
|
HTML Export för 'X' = HTML export af 'X'
|
||||||
|
HTML formaterad genom listinställningar = HTML formateret ud fra liste indstillinger
|
||||||
|
Hittar inte klass X = Kan ikke finde klasse X
|
||||||
|
Importerar RAID patrull csv-fil = Importerer RAID patrulje .csv data
|
||||||
|
Importerar ranking = Importer ranking
|
||||||
|
Individual result by finish time = Individuelle resultater ud fra måltid
|
||||||
|
Individuellt = Individuelt
|
||||||
|
Klart. X värden tilldelade = Klar, X værdier er tildelt.
|
||||||
|
Klassen X är listad flera gånger = Klassen X er angivet flere gange
|
||||||
|
Klassval för 'X' = Valg af klasse for 'X'
|
||||||
|
Knockout total = Knock-out samlet
|
||||||
|
Kolumner = Kolonner
|
||||||
|
Lag och stafett = Hold og stafet
|
||||||
|
Lagra inställningar = Gem indstillinger
|
||||||
|
LineBreak = Linieskift
|
||||||
|
Liveresultat, radiotider = Live resultater med radiotider
|
||||||
|
MeOS utvecklinsstöd = Støtte til MeOS udvikling
|
||||||
|
Med direktanmälan = Med tilmelding på stævneplads
|
||||||
|
Ogiltig starttid X = Ugyldig starttid X
|
||||||
|
Ogiltigt startintervall X = Ugyldigt start interval X
|
||||||
|
Pages with columns = Sider med kolonner
|
||||||
|
Pages with columns, no header = Sider med kolonner, uden overskrift
|
||||||
|
PunchAbsTime = Stempling rigtig tid
|
||||||
|
PunchName = Stempling, post benævnelse
|
||||||
|
PunchNamedSplit = Tid siden seneste nævnte post
|
||||||
|
PunchSplitTime = Tid siden seneste post (mellemtid)
|
||||||
|
PunchTimeSinceLast = Tid mellem poster
|
||||||
|
PunchTotalTime = Samlet tid ved post
|
||||||
|
PunchTotalTimeAfter = Samlet efter ved post
|
||||||
|
Rad X är ogiltig = Række X er ugyldig
|
||||||
|
Rader = Rækker
|
||||||
|
RunnerCheck = Tidspunkt for check stempling
|
||||||
|
RunnerGrossTime = Løbers tid før korrektion
|
||||||
|
RunnerId = Løbers eksterne ID
|
||||||
|
Slå ihop med befintlig lista = Slå sammen med eksisterende liste
|
||||||
|
StartTimeClass = Start tid, klasse
|
||||||
|
Support intermediate legs = Understøt angivne stafet stræk
|
||||||
|
TeamGrossTime = Holdets tid før korrektion
|
||||||
|
Till vilka klasser = Til hvilke klasser
|
||||||
|
Tillåt anmälan = Tillad tilmelding
|
||||||
|
Timekeeping = Tidtagning
|
||||||
|
Varning: Följande deltagare har ett osäkert resultat = Advarsel: tildeling er uklar for følgende løbere.
|
||||||
|
Varning: Kartorna är slut = Advarsel: Der er ikke flere kort
|
||||||
|
Varning: deltagare med blankt namn påträffad. MeOS kräver att alla deltagare har ett namn, och tilldelar namnet 'N.N.' = Advarsel: Der er fundet en løber uden tildelt navn. MeOS kræver at alle løbere har et navn. MeOS har tildelt navnet 'N.N.'
|
||||||
|
Varning: lag utan namn påträffat. MeOS kräver att alla lag har ett namn, och tilldelar namnet 'N.N.' = Advarsel: Der er fundet et hold uden tildelt navn. MeOS kræver at hold har et navn og har tildelt navnet 'N.N.'
|
||||||
|
Varvräkning = Tæl omgange
|
||||||
|
Varvräkning med mellantid = Tæl omgange med mellemtider
|
||||||
|
Vem får anmäla sig = Hvem kan tilmelde sig
|
||||||
|
Vill du ta bort schemat? = Vil du fjerne skemaet?
|
||||||
|
Visa detaljerad rapport för viss deltagare = Vis detaljeret rapport for en specifik deltager
|
||||||
|
Visa rubrik = Vis overskrift
|
||||||
|
Visa rubrik mellan listorna = Vis overskrift imellem listerne
|
||||||
|
Without courses = Uden baner
|
||||||
|
X går vidare, klass enligt ranking = X går videre, klasse ifølge ranking
|
||||||
|
ask:outofmaps = Der er ikke flere kort. Vil du alligevel tilføje denne løber?
|
||||||
|
ask:removescheme = Resultater slettes hvis du sletter dette skema. Vil du fortsætte?
|
||||||
|
help:custom_text_lines = Du kan indsætte egne data ved at skrive [Symbol Name]. De mulige tegn kan ses i listen til højre.\n\nExample: Well done [Løbernavn]!
|
||||||
|
htmlhelp = HTML kan eksporteres som en struktureret tabel eller som et frit formateret dokument (mere i stil med MeOS lister). Du kan også bruge eksporter skabeloner med egen formatering: kolonner, JavaScript base page flips, automatisk rulning, o.s.v. Det er muligt at tilføje egne skabeloner ved at tilføje '.template' filer i MeOS mappen. Hvis du bruger skabeloner er der et antal parametre der skal angives, se nedenfor. Den præcise fortolkning af parametrene afhænger af skabelonen.\n\nHvis du vælger <Store Settings> bliver listen og dens opsætning gemt permanent i løbet. Du kan så tilgå listen ved at bruge MeOS som Web server (Tjenesten 'Information Server') eller ved at eksportere listen ved jævne mellemrum.
|
||||||
|
info:pageswithcolumns = Vis listen en side af gangen med det angivne antal kolonner. Genindlæs listen automatisk efter hvert gennemløb.
|
||||||
|
Övrigt = Øvrigt
|
||||||
|
|||||||
@ -2392,7 +2392,7 @@ Bricknummer = Card number
|
|||||||
Anmäl andra = New entry
|
Anmäl andra = New entry
|
||||||
Anmälan mottagen = Accepted entry
|
Anmälan mottagen = Accepted entry
|
||||||
Automatisk omladdning = Automatic update
|
Automatisk omladdning = Automatic update
|
||||||
Till vilka klasser = To which classes
|
Till vilka klasser = To what classes
|
||||||
Vem får anmäla sig = Who may enter
|
Vem får anmäla sig = Who may enter
|
||||||
Anmälan måste hanteras manuellt = Your entry requires manual processing.
|
Anmälan måste hanteras manuellt = Your entry requires manual processing.
|
||||||
EFilterAPIEntry = Entries via API
|
EFilterAPIEntry = Entries via API
|
||||||
@ -2407,3 +2407,24 @@ info:pageswithcolumns = Show the list one page at the time, with the specified n
|
|||||||
Pages with columns = Pages with columns
|
Pages with columns = Pages with columns
|
||||||
Pages with columns, no header = Pages with columns, no header
|
Pages with columns, no header = Pages with columns, no header
|
||||||
Externa adresser = External links
|
Externa adresser = External links
|
||||||
|
info:advanceinfo = Starting the service for instant result transfer failed. Results will be recieved with a few seconds delay. This is expected behaviour if more than one MeOS process is started on this computer.
|
||||||
|
Klassen är full = The class is full
|
||||||
|
Flytta upp = Move up
|
||||||
|
Flytta ner = Move down
|
||||||
|
EFilterWrongFee = Unexpected fee
|
||||||
|
RunnerExpectedFee = Competitors expected fee
|
||||||
|
Unexpected Fee = Unexpected entry fees
|
||||||
|
Anmälningsdatum = Entry date
|
||||||
|
Förväntad = Expected
|
||||||
|
Registrera hyrbrickor = Register rental cards
|
||||||
|
Vill du sätta hyrbricka på befintliga löpare med dessa brickor? = Do you want to apply rental card data on existing runners?
|
||||||
|
Vill du ta bort brickan från hyrbrickslistan? = Do you want to remove the card from the rental card list?
|
||||||
|
Vill du tömma listan med hyrbrickor? = Do you want to clear the rental card list?
|
||||||
|
prefsLastExportTarget = Last export target
|
||||||
|
prefsServiceRootMap = Standard function for web server root
|
||||||
|
prefsshowheader = Show page headers
|
||||||
|
help:registerhiredcards = Preregister punching cards as rental cards to get automatic hired card status when the card is assigned.
|
||||||
|
Lagändringblankett = Team Change Form
|
||||||
|
Mappa rootadresssen (http:///localhost:port/) till funktion = Map root address (http:///localhost:port/) to function
|
||||||
|
ClassAvailableMaps = Available maps for class
|
||||||
|
ClassTotalMaps = Total number of maps for class
|
||||||
|
|||||||
@ -1016,14 +1016,11 @@ ButtonInfo &gdioutput::addButton(int x, int y, const string &id, const wstring &
|
|||||||
HANDLE bm = 0;
|
HANDLE bm = 0;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
if (text[0] == '@') {
|
if (text[0] == '@') {
|
||||||
HINSTANCE hInst = GetModuleHandle(0);//(HINSTANCE)GetWindowLong(hWndTarget, GWL_HINSTANCE);
|
HINSTANCE hInst = GetModuleHandle(0); int ir = _wtoi(text.c_str() + 1);
|
||||||
int ir = _wtoi(text.c_str() + 1);
|
bm = LoadBitmap(hInst, MAKEINTRESOURCE(ir));
|
||||||
// bm = LoadImage(hInst, MAKEINTRESOURCE(ir), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
|
||||||
bm = LoadBitmap(hInst, MAKEINTRESOURCE(ir));// , IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
|
||||||
|
|
||||||
SIZE size;
|
SIZE size;
|
||||||
size.cx = 24;
|
size.cx = 24;
|
||||||
//GetBitmapDimensionEx(bm, &size);
|
|
||||||
width = size.cx+4;
|
width = size.cx+4;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1031,6 +1028,13 @@ ButtonInfo &gdioutput::addButton(int x, int y, const string &id, const wstring &
|
|||||||
HDC hDC = GetDC(hWndTarget);
|
HDC hDC = GetDC(hWndTarget);
|
||||||
SelectObject(hDC, getGUIFont());
|
SelectObject(hDC, getGUIFont());
|
||||||
wstring ttext = lang.tl(text);
|
wstring ttext = lang.tl(text);
|
||||||
|
int tts = ttext.size();
|
||||||
|
if (tts > 2 && ttext[0] == '<' && ttext[1] == '<') {
|
||||||
|
ttext = L"◀" + ttext.substr(2);
|
||||||
|
}
|
||||||
|
else if (tts > 2 && ttext[tts-1] == '>' && ttext[tts-2] == '>') {
|
||||||
|
ttext = ttext.substr(0, tts-2) + L"▶";
|
||||||
|
}
|
||||||
if (lang.capitalizeWords())
|
if (lang.capitalizeWords())
|
||||||
capitalizeWords(ttext);
|
capitalizeWords(ttext);
|
||||||
GetTextExtentPoint32(hDC, ttext.c_str(), ttext.length(), &size);
|
GetTextExtentPoint32(hDC, ttext.c_str(), ttext.length(), &size);
|
||||||
@ -1100,6 +1104,13 @@ ButtonInfo &gdioutput::addButton(int x, int y, int w, const string &id,
|
|||||||
|
|
||||||
ButtonInfo bi;
|
ButtonInfo bi;
|
||||||
wstring ttext = lang.tl(text);
|
wstring ttext = lang.tl(text);
|
||||||
|
int tts = ttext.size();
|
||||||
|
if (tts > 2 && ttext[0] == '<' && ttext[1] == '<') {
|
||||||
|
ttext = L"◀" + ttext.substr(2);
|
||||||
|
}
|
||||||
|
else if (tts > 2 && ttext[tts - 1] == '>' && ttext[tts - 2] == '>') {
|
||||||
|
ttext = ttext.substr(0, tts - 2) + L"▶";
|
||||||
|
}
|
||||||
if (lang.capitalizeWords())
|
if (lang.capitalizeWords())
|
||||||
capitalizeWords(ttext);
|
capitalizeWords(ttext);
|
||||||
int height = getButtonHeight();
|
int height = getButtonHeight();
|
||||||
@ -1779,6 +1790,26 @@ bool gdioutput::getSelectedItem(ListBoxInfo &lbi) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gdioutput::getNumItems(const char *id) {
|
||||||
|
for (auto &lbi : LBI) {
|
||||||
|
if (lbi.id == id) {
|
||||||
|
if (lbi.IsCombo) {
|
||||||
|
return SendMessage(lbi.hWnd, CB_GETCOUNT, 0, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return SendMessage(lbi.hWnd, LB_GETCOUNT, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
string err = string("Internal Error, identifier not found: X#") + id;
|
||||||
|
throw std::exception(err.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int gdioutput::getItemDataByName(const char *id, const char *name) const{
|
int gdioutput::getItemDataByName(const char *id, const char *name) const{
|
||||||
wstring wname = recodeToWide(name);
|
wstring wname = recodeToWide(name);
|
||||||
list<ListBoxInfo>::const_iterator it;
|
list<ListBoxInfo>::const_iterator it;
|
||||||
@ -1872,6 +1903,61 @@ bool gdioutput::selectItemByData(const char *id, int data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool gdioutput::selectItemByIndex(const char *id, int index) {
|
||||||
|
for (auto it = LBI.begin(); it != LBI.end(); ++it) {
|
||||||
|
if (it->id == id) {
|
||||||
|
if (it->IsCombo) {
|
||||||
|
if (index == -1) {
|
||||||
|
SendMessage(it->hWnd, CB_SETCURSEL, -1, 0);
|
||||||
|
it->data = 0;
|
||||||
|
it->text = L"";
|
||||||
|
it->original = L"";
|
||||||
|
it->originalIdx = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SendMessage(it->hWnd, CB_SETCURSEL, index, 0);
|
||||||
|
int data = SendMessage(it->hWnd, CB_GETITEMDATA, index, 0);
|
||||||
|
it->data = data;
|
||||||
|
it->originalIdx = data;
|
||||||
|
TCHAR bf[1024];
|
||||||
|
if (SendMessage(it->hWnd, CB_GETLBTEXT, index, LPARAM(bf)) != CB_ERR) {
|
||||||
|
it->text = bf;
|
||||||
|
it->original = bf;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (index == -1) {
|
||||||
|
SendMessage(it->hWnd, LB_SETCURSEL, -1, 0);
|
||||||
|
it->data = 0;
|
||||||
|
it->text = L"";
|
||||||
|
it->original = L"";
|
||||||
|
it->originalIdx = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SendMessage(it->hWnd, LB_SETCURSEL, index, 0);
|
||||||
|
int data = SendMessage(it->hWnd, LB_GETITEMDATA, index, 0);
|
||||||
|
|
||||||
|
it->data = data;
|
||||||
|
it->originalIdx = data;
|
||||||
|
TCHAR bf[1024];
|
||||||
|
if (SendMessage(it->hWnd, LB_GETTEXT, index, LPARAM(bf)) != LB_ERR) {
|
||||||
|
it->text = bf;
|
||||||
|
it->original = bf;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool gdioutput::autoGrow(const char *id) {
|
bool gdioutput::autoGrow(const char *id) {
|
||||||
list<ListBoxInfo>::iterator it;
|
list<ListBoxInfo>::iterator it;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|||||||
@ -549,6 +549,8 @@ public:
|
|||||||
|
|
||||||
int getItemDataByName(const char *id, const char *name) const;
|
int getItemDataByName(const char *id, const char *name) const;
|
||||||
bool selectItemByData(const char *id, int data);
|
bool selectItemByData(const char *id, int data);
|
||||||
|
bool selectItemByIndex(const char *id, int index);
|
||||||
|
|
||||||
void removeSelected(const char *id);
|
void removeSelected(const char *id);
|
||||||
|
|
||||||
bool selectItemByData(const string &id, int data) {
|
bool selectItemByData(const string &id, int data) {
|
||||||
@ -579,6 +581,9 @@ public:
|
|||||||
/** Return a selected item*/
|
/** Return a selected item*/
|
||||||
bool getSelectedItem(const string &id, ListBoxInfo &lbi);
|
bool getSelectedItem(const string &id, ListBoxInfo &lbi);
|
||||||
|
|
||||||
|
/** Get number of items in a list box.'*/
|
||||||
|
int getNumItems(const char *id);
|
||||||
|
|
||||||
/** Return the selected data in first, second indicates if data was available*/
|
/** Return the selected data in first, second indicates if data was available*/
|
||||||
pair<int, bool> getSelectedItem(const string &id);
|
pair<int, bool> getSelectedItem(const string &id);
|
||||||
pair<int, bool> getSelectedItem(const char *id);
|
pair<int, bool> getSelectedItem(const char *id);
|
||||||
|
|||||||
@ -251,7 +251,9 @@ public:
|
|||||||
InputInfo &setFont(gdioutput &gdi, gdiFonts font);
|
InputInfo &setFont(gdioutput &gdi, gdiFonts font);
|
||||||
GDICOLOR getBgColor() const {return bgColor;}
|
GDICOLOR getBgColor() const {return bgColor;}
|
||||||
GDICOLOR getFgColor() const {return fgColor;}
|
GDICOLOR getFgColor() const {return fgColor;}
|
||||||
|
/** Return the previously stored text */
|
||||||
|
const wstring &getPreviousText() const { return focusText; }
|
||||||
|
bool changedInput() const { return text != focusText; }
|
||||||
InputInfo &setPassword(bool pwd);
|
InputInfo &setPassword(bool pwd);
|
||||||
|
|
||||||
HWND getControlWindow() const {return hWnd;}
|
HWND getControlWindow() const {return hWnd;}
|
||||||
@ -276,7 +278,7 @@ private:
|
|||||||
bool isEditControl;
|
bool isEditControl;
|
||||||
bool writeLock;
|
bool writeLock;
|
||||||
wstring original;
|
wstring original;
|
||||||
wstring focusText; // Test when got focus
|
wstring focusText; // Text when got focus
|
||||||
bool ignoreCheck; // True if changed-state should be ignored
|
bool ignoreCheck; // True if changed-state should be ignored
|
||||||
friend class gdioutput;
|
friend class gdioutput;
|
||||||
};
|
};
|
||||||
|
|||||||
190
code/html1.htm
190
code/html1.htm
@ -272,6 +272,196 @@ When and only when the type is <b>CourseIndividual</b>, the attribute <i>course<
|
|||||||
*/person>
|
*/person>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Status</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre><a href="/meos?get=status">/meos?get=status</a></pre>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
<p>MeOS Status Data. Includes MeOS version and competition name id, which also is the name of the database used, if any.</p>
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
<pre>
|
||||||
|
*MOPComplete>
|
||||||
|
*status version="3.6.1029" eventNameId="meos_20190223_212818_2FD" onDatabase="1"/>
|
||||||
|
*/MOPComplete>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Entry Classes</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre><a href="/meos?get=entryclass">/meos?get=entryclass</a></pre>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
<p>Classes where entry is allowed via the API.</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
*EntryClasses>
|
||||||
|
*Class id="5">
|
||||||
|
*Name>U1*Name>
|
||||||
|
*Fee>70 kr*/Fee>
|
||||||
|
*MaxAge>16*/MaxAge>
|
||||||
|
*Start>Start 1*/Start>
|
||||||
|
*AvailableStarts>30*/AvailableStarts>
|
||||||
|
*/Class>
|
||||||
|
*/EntryClasses>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Lookup competitor</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre><a href="/meos?lookup=competitor&id=%runnerid%">/meos?lookup=competitor&id=*id></a></pre>
|
||||||
|
<pre><a href="/meos?lookup=competitor&card=%card%">/meos?lookup=competitor&card=*card></a></pre>
|
||||||
|
<pre><a href="/meos?lookup=competitor&bib=%bib%">/meos?lookup=competitor&bib=*bib></a></pre>
|
||||||
|
<pre><a href="/meos?lookup=competitor&name=%name%&club=%club%">/meos?lookup=competitor&name=*name>&club=*club></a></pre>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
<p>Competitor including individual result.</p>
|
||||||
|
|
||||||
|
<b>Arguments:</b>
|
||||||
|
<ul>
|
||||||
|
<li><i>id</i> Competitor id. MeOS internal id.</li>
|
||||||
|
<li><i>card</i> Card number.</li>
|
||||||
|
<li><i>bib</i> Bib or start number.</li>
|
||||||
|
<li><i>name</i> Name of competitor.</li>
|
||||||
|
<li><i>club</i> Name of club.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
*Competitors>
|
||||||
|
*Competitor id="85">
|
||||||
|
*Name>Nils Bor*/Name>
|
||||||
|
*ExternalId>1234*/ExternalId>
|
||||||
|
*Club id="84">OK Linné*/Club>
|
||||||
|
*Class id="204">Men*/Class>
|
||||||
|
*Card>16733*/Card>
|
||||||
|
*Status code="1">OK*/Status>
|
||||||
|
*Start>17:38:00*/Start>
|
||||||
|
*Finish>18:22:21*/Finish>
|
||||||
|
*RunningTime>44:21*/RunningTime>
|
||||||
|
*Place>7*/Place>
|
||||||
|
*TimeAfter>13:04*/TimeAfter>
|
||||||
|
*Team id="26">OK Linné 2*/Team>
|
||||||
|
*Leg>1*/Leg>
|
||||||
|
*Splits>
|
||||||
|
*Control number="1">
|
||||||
|
*Name>[31]*/Name>
|
||||||
|
*Time>6:25*/Time>
|
||||||
|
*Analysis lost="1:11" behind="1:11" mistake="" leg="5" total="3"/>
|
||||||
|
*/Control>
|
||||||
|
*Control number="2">
|
||||||
|
*Name>Radio*/Name>
|
||||||
|
*Time>12:50*/Time>
|
||||||
|
*Analysis lost="1:10" behind="2:21" mistake="1:20" leg="3" total="3"/>
|
||||||
|
*/Control>
|
||||||
|
...
|
||||||
|
*/Splits>
|
||||||
|
*/Competitor>
|
||||||
|
*/Competitors>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Lookup Database Competitor</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre><a href="/meos?lookup=dbcompetitor&id=%runnerextid%">/meos?lookup=dbcompetitor&id=*id></a></pre>
|
||||||
|
<pre><a href="/meos?lookup=dbcompetitor&card=%card%">/meos?lookup=dbcompetitor&card=*card></a></pre>
|
||||||
|
<pre><a href="/meos?lookup=dbcompetitor&name=%dbname%&club=%dbclub%">/meos?lookup=dbcompetitor&name=*name>&club=*club></a></pre>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
<p>Competitor from runner database. Note that a partial name may be submitted, and that several matching result may be returned, sorted by relevance.
|
||||||
|
This query is suitable for auto complete functionality.</p>
|
||||||
|
|
||||||
|
<b>Arguments:</b>
|
||||||
|
<ul>
|
||||||
|
<li><i>id</i> External id from runner database.</li>
|
||||||
|
<li><i>card</i> Card number.</li>
|
||||||
|
<li><i>name</i> Name of competitor. Possibly a partial name.</li>
|
||||||
|
<li><i>club</i> Name of club.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
*DatabaseCompetitors>
|
||||||
|
*Competitor id="15393">
|
||||||
|
*Name>Anskar Dahl*/Name>
|
||||||
|
*Club id="575">IFK Mora OK*/Club>
|
||||||
|
*Card>79709*/Card>
|
||||||
|
*Nationality>SWE*/Nationality>
|
||||||
|
*Sex>M*/Sex>
|
||||||
|
*BirthYear>1957*/BirthYear>
|
||||||
|
*/Competitor>
|
||||||
|
*/DatabaseCompetitors>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Lookup Database Club</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre><a href="/meos?lookup=dbclub&id=%clubid%">/meos?lookup=dbclub&id=*id></a></pre>
|
||||||
|
<pre><a href="/meos?lookup=dbclub&name=%club%">/meos?lookup=dbclub&name=*name></a></pre>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
<p>Club from club database. Note that a partial name may be submitted, and that several matching result may be returned, sorted by relevance.
|
||||||
|
This query is suitable for auto complete functionality.</p>
|
||||||
|
|
||||||
|
<b>Arguments:</b>
|
||||||
|
<ul>
|
||||||
|
<li><i>id</i> External id from club database.</li>
|
||||||
|
<li><i>name</i> Name of club. Possibly a partial name.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
*DatabaseClubs>
|
||||||
|
*Club id="134">
|
||||||
|
*Name>OK Enen*/Name>
|
||||||
|
*/Club>
|
||||||
|
*/DatabaseClubs>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>API New Entry</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre>/meos?entry&id=*id>&class=*classid>&card=*card></pre>
|
||||||
|
<pre>/meos?entry&name=*name>&club=*club>&class=*classid>&card=*card></pre>
|
||||||
|
|
||||||
|
<b>Arguments:</b>
|
||||||
|
<ul>
|
||||||
|
<li><i>id</i> External id of runner from runner database.</li>
|
||||||
|
<li><i>name</i> Name of runner.</li>
|
||||||
|
<li><i>club</i> Name of runner's club.</li>
|
||||||
|
<li><i>class</i> Id of class.</li>
|
||||||
|
<li><i>card</i> Card number.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
Status.
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
*Answer>
|
||||||
|
*Status>OK*/Status>
|
||||||
|
*Fee>130*/Fee>
|
||||||
|
*Info>Open Long, Rudolf Minowski (OK Tisaren)*/Info>
|
||||||
|
*/Answer>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
*Answer>
|
||||||
|
*Status>Failed*/Status>
|
||||||
|
*Info>Out of maps.*/Info>
|
||||||
|
*/Answer>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Page template</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre>/meos?page=*page></pre>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
Installed template file with the specified tag.
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Image</h2>
|
||||||
|
<b>Syntax:</b>
|
||||||
|
<pre>/meos?image=*image></pre>
|
||||||
|
|
||||||
|
<b>Returns:</b>
|
||||||
|
Image, *image>.png, if installed in MeOS datafolder. MeOS logo if *image> is meos.
|
||||||
|
|
||||||
<h2>IOF XML Results</h2>
|
<h2>IOF XML Results</h2>
|
||||||
|
|
||||||
<b>Syntax:</b>
|
<b>Syntax:</b>
|
||||||
|
|||||||
@ -269,7 +269,7 @@ void IOF30Interface::classCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
|||||||
if (pc->hasMultiCourse()) {
|
if (pc->hasMultiCourse()) {
|
||||||
for (size_t k = 0; k < pc->getNumStages(); k++) {
|
for (size_t k = 0; k < pc->getNumStages(); k++) {
|
||||||
for (size_t j = 0; j < pCrs.size(); j++)
|
for (size_t j = 0; j < pCrs.size(); j++)
|
||||||
pc->addStageCourse(k, pCrs[j]);
|
pc->addStageCourse(k, pCrs[j], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -277,7 +277,7 @@ void IOF30Interface::classCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
|||||||
}
|
}
|
||||||
else if (leg == 0 && pCrs.size() == 1) {
|
else if (leg == 0 && pCrs.size() == 1) {
|
||||||
if (pc->hasMultiCourse())
|
if (pc->hasMultiCourse())
|
||||||
pc->addStageCourse(0, pCrs[0]);
|
pc->addStageCourse(0, pCrs[0], -1);
|
||||||
else
|
else
|
||||||
pc->setCourse(pCrs[0]);
|
pc->setCourse(pCrs[0]);
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ void IOF30Interface::classCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
|||||||
pc->setNumStages(leg+1);
|
pc->setNumStages(leg+1);
|
||||||
|
|
||||||
for (size_t j = 0; j < pCrs.size(); j++)
|
for (size_t j = 0; j < pCrs.size(); j++)
|
||||||
pc->addStageCourse(leg, pCrs[j]);
|
pc->addStageCourse(leg, pCrs[j], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,7 +620,7 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
|
|||||||
c[k]->setNumStages(1);
|
c[k]->setNumStages(1);
|
||||||
c[k]->clearStageCourses(0);
|
c[k]->clearStageCourses(0);
|
||||||
for (size_t j = 0; j < crsFam.size(); j++)
|
for (size_t j = 0; j < crsFam.size(); j++)
|
||||||
c[k]->addStageCourse(0, crsFam[j]->getId());
|
c[k]->addStageCourse(0, crsFam[j]->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -628,7 +628,7 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
|
|||||||
for (int i = 0; i < nl; i++) {
|
for (int i = 0; i < nl; i++) {
|
||||||
c[k]->clearStageCourses(i);
|
c[k]->clearStageCourses(i);
|
||||||
for (int j = 0; j < nFam; j++)
|
for (int j = 0; j < nFam; j++)
|
||||||
c[k]->addStageCourse(i, crsFam[(j + i)%nFam]->getId());
|
c[k]->addStageCourse(i, crsFam[(j + i)%nFam]->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assigned = true;
|
assigned = true;
|
||||||
@ -648,7 +648,7 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
|
|||||||
const vector<pCourse> &crsFam = coursesFamilies.find(*fit)->second;
|
const vector<pCourse> &crsFam = coursesFamilies.find(*fit)->second;
|
||||||
int nFam = crsFam.size();
|
int nFam = crsFam.size();
|
||||||
for (int j = 0; j < nFam; j++)
|
for (int j = 0; j < nFam; j++)
|
||||||
c[k]->addStageCourse(i, crsFam[j]->getId());
|
c[k]->addStageCourse(i, crsFam[j]->getId(), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
assigned = true;
|
assigned = true;
|
||||||
@ -667,7 +667,7 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
|
|||||||
for (int i = 0; i < nl; i++) {
|
for (int i = 0; i < nl; i++) {
|
||||||
c[k]->clearStageCourses(i);
|
c[k]->clearStageCourses(i);
|
||||||
for (int j = 0; j < nCrs; j++)
|
for (int j = 0; j < nCrs; j++)
|
||||||
c[k]->addStageCourse(i, crs[(j + i)%nCrs]->getId());
|
c[k]->addStageCourse(i, crs[(j + i)%nCrs]->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -739,6 +739,8 @@ void IOF30Interface::readEntryList(gdioutput &gdi, xmlobject &xo, bool removeNon
|
|||||||
int &entRead, int &entFail, int &entRemoved) {
|
int &entRead, int &entFail, int &entRemoved) {
|
||||||
string ver;
|
string ver;
|
||||||
entRemoved = 0;
|
entRemoved = 0;
|
||||||
|
bool wasEmpty = oe.getNumRunners() == 0;
|
||||||
|
|
||||||
xo.getObjectString("iofVersion", ver);
|
xo.getObjectString("iofVersion", ver);
|
||||||
if (!ver.empty() && ver > "3.0")
|
if (!ver.empty() && ver > "3.0")
|
||||||
gdi.addString("", 0, "Varning, okänd XML-version X#" + ver);
|
gdi.addString("", 0, "Varning, okänd XML-version X#" + ver);
|
||||||
@ -962,8 +964,95 @@ void IOF30Interface::readEntryList(gdioutput &gdi, xmlobject &xo, bool removeNon
|
|||||||
if (!rids.empty())
|
if (!rids.empty())
|
||||||
oe.removeRunner(rids);
|
oe.removeRunner(rids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wasEmpty) {
|
||||||
|
vector<pClass> allCls;
|
||||||
|
oe.getClasses(allCls, false);
|
||||||
|
set<int> fees;
|
||||||
|
set<int> redFees;
|
||||||
|
set<double> factor;
|
||||||
|
for (pClass cls : allCls) {
|
||||||
|
int cf = cls->getDCI().getInt("ClassFee");
|
||||||
|
int cfRed = cls->getDCI().getInt("ClassFeeRed");
|
||||||
|
if (cf > 0)
|
||||||
|
fees.insert(cf);
|
||||||
|
|
||||||
|
if (cfRed != 0 && cfRed != cf)
|
||||||
|
redFees.insert(cfRed);
|
||||||
|
|
||||||
|
int cfLate = cls->getDCI().getInt("HighClassFee");
|
||||||
|
|
||||||
|
if (cfLate > cf && cf > 0) {
|
||||||
|
factor.insert(double(cfLate) / double(cf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int youthFee = numeric_limits<int>::max();
|
||||||
|
if (!fees.empty())
|
||||||
|
youthFee = min(youthFee, *fees.begin());
|
||||||
|
if (!redFees.empty())
|
||||||
|
youthFee = min(youthFee, *redFees.begin());
|
||||||
|
|
||||||
|
int eliteFee = numeric_limits<int>::max();
|
||||||
|
if (!fees.empty())
|
||||||
|
eliteFee = *fees.rbegin();
|
||||||
|
|
||||||
|
int normalFee = eliteFee;
|
||||||
|
for (int f : fees) {
|
||||||
|
if (f != youthFee && f != eliteFee) {
|
||||||
|
normalFee = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (youthFee != numeric_limits<int>::max()) {
|
||||||
|
oe.getDI().setInt("YouthFee", youthFee);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eliteFee != numeric_limits<int>::max()) {
|
||||||
|
oe.getDI().setInt("EliteFee", eliteFee);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalFee != numeric_limits<int>::max()) {
|
||||||
|
oe.getDI().setInt("EntryFee", normalFee);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (factor.size() > 0) {
|
||||||
|
double f = *factor.rbegin();
|
||||||
|
wstring fs = std::to_wstring(int((f - 1.0) * 100.0)) + L" %";
|
||||||
|
oe.getDI().setString("LateEntryFactor", fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOF30Interface::readServiceRequestList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail) {
|
||||||
|
string ver;
|
||||||
|
xo.getObjectString("iofVersion", ver);
|
||||||
|
if (!ver.empty() && ver > "3.0")
|
||||||
|
gdi.addString("", 0, "Varning, okänd XML-version X#" + ver);
|
||||||
|
|
||||||
|
xmlList req;
|
||||||
|
xo.getObjects("PersonServiceRequest", req);
|
||||||
|
entrySourceId = 0;
|
||||||
|
|
||||||
|
for (auto &rx : req) {
|
||||||
|
xmlobject xPers = rx.getObject("Person");
|
||||||
|
pRunner r = 0;
|
||||||
|
if (xPers)
|
||||||
|
r = readPerson(gdi, xPers);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
auto xreq = rx.getObject("ServiceRequest");
|
||||||
|
if (xreq) {
|
||||||
|
auto xServ = xreq.getObject("Service");
|
||||||
|
string type;
|
||||||
|
if (xServ && xServ.getObjectString("type", type)=="StartGroup") {
|
||||||
|
int id = xServ.getObjectInt("Id");
|
||||||
|
r->getDI().setInt("Heat", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IOF30Interface::readStartList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail) {
|
void IOF30Interface::readStartList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail) {
|
||||||
string ver;
|
string ver;
|
||||||
@ -1149,10 +1238,13 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
|
|||||||
if (date) {
|
if (date) {
|
||||||
wstring dateStr;
|
wstring dateStr;
|
||||||
date.getObjectString("Date", dateStr);
|
date.getObjectString("Date", dateStr);
|
||||||
oe.setDate(dateStr);
|
|
||||||
wstring timeStr;
|
wstring timeStr;
|
||||||
date.getObjectString("Time", timeStr);
|
date.getObjectString("Time", timeStr);
|
||||||
if (!timeStr.empty()) {
|
if (!timeStr.empty()) {
|
||||||
|
wstring tDate, tTime;
|
||||||
|
getLocalDateTime(dateStr, timeStr, tDate, tTime);
|
||||||
|
dateStr.swap(tDate);
|
||||||
|
timeStr.swap(tTime);
|
||||||
int t = convertAbsoluteTimeISO(timeStr);
|
int t = convertAbsoluteTimeISO(timeStr);
|
||||||
if (t >= 0 && oe.getNumRunners() == 0) {
|
if (t >= 0 && oe.getNumRunners() == 0) {
|
||||||
int zt = t - 3600;
|
int zt = t - 3600;
|
||||||
@ -1161,6 +1253,9 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
|
|||||||
oe.setZeroTime(formatTimeHMS(zt));
|
oe.setZeroTime(formatTimeHMS(zt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oe.setDate(dateStr);
|
||||||
|
|
||||||
//oe.setZeroTime(...);
|
//oe.setZeroTime(...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,12 +1441,12 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
|
|||||||
if (newTeam) {
|
if (newTeam) {
|
||||||
wstring entryTime;
|
wstring entryTime;
|
||||||
xTeam.getObjectString("EntryTime", entryTime);
|
xTeam.getObjectString("EntryTime", entryTime);
|
||||||
di.setDate("EntryDate", entryTime);
|
|
||||||
|
|
||||||
size_t tpos = entryTime.find_first_of(L"T");
|
wstring date, time;
|
||||||
if (tpos != -1) {
|
getLocalDateTime(entryTime, date, time);
|
||||||
wstring timeString = entryTime.substr(tpos+1);
|
di.setDate("EntryDate", date);
|
||||||
int t = convertAbsoluteTimeISO(timeString);
|
if (time.length() > 0) {
|
||||||
|
int t = convertAbsoluteTimeISO(time);
|
||||||
if (t >= 0)
|
if (t >= 0)
|
||||||
di.setInt("EntryTime", t);
|
di.setInt("EntryTime", t);
|
||||||
}
|
}
|
||||||
@ -1450,7 +1545,8 @@ pTeam IOF30Interface::getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool
|
|||||||
if (!t)
|
if (!t)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
t->setEntrySource(entrySourceId);
|
if (entrySourceId > 0)
|
||||||
|
t->setEntrySource(entrySourceId);
|
||||||
t->flagEntryTouched(true);
|
t->flagEntryTouched(true);
|
||||||
if (t->getName().empty() || !t->hasFlag(oAbstractRunner::FlagUpdateName))
|
if (t->getName().empty() || !t->hasFlag(oAbstractRunner::FlagUpdateName))
|
||||||
t->setName(name, false);
|
t->setName(name, false);
|
||||||
@ -1608,16 +1704,16 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
|
|||||||
|
|
||||||
wstring entryTime;
|
wstring entryTime;
|
||||||
xo.getObjectString("EntryTime", entryTime);
|
xo.getObjectString("EntryTime", entryTime);
|
||||||
di.setDate("EntryDate", entryTime);
|
|
||||||
size_t tpos = entryTime.find_first_of(L"T");
|
wstring date, time;
|
||||||
if (tpos != -1) {
|
getLocalDateTime(entryTime, date, time);
|
||||||
wstring timeString = entryTime.substr(tpos+1);
|
di.setDate("EntryDate", date);
|
||||||
int t = convertAbsoluteTimeISO(timeString);
|
if (time.length() > 0) {
|
||||||
|
int t = convertAbsoluteTimeISO(time);
|
||||||
if (t >= 0)
|
if (t >= 0)
|
||||||
di.setInt("EntryTime", t);
|
di.setInt("EntryTime", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double fee = 0, paid = 0, taxable = 0, percentage = 0;
|
double fee = 0, paid = 0, taxable = 0, percentage = 0;
|
||||||
wstring currency;
|
wstring currency;
|
||||||
xmlList xAssigned;
|
xmlList xAssigned;
|
||||||
@ -1836,7 +1932,8 @@ pRunner IOF30Interface::readPerson(gdioutput &gdi, const xmlobject &person) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r->setEntrySource(entrySourceId);
|
if (entrySourceId > 0)
|
||||||
|
r->setEntrySource(entrySourceId);
|
||||||
r->flagEntryTouched(true);
|
r->flagEntryTouched(true);
|
||||||
|
|
||||||
if (!r->hasFlag(oAbstractRunner::FlagUpdateName)) {
|
if (!r->hasFlag(oAbstractRunner::FlagUpdateName)) {
|
||||||
@ -2115,16 +2212,20 @@ void IOF30Interface::getAgeLevels(const vector<FeeInfo> &fees, const vector<int>
|
|||||||
redIx = ix[k];
|
redIx = ix[k];
|
||||||
if (fees[normalIx] < fees[ix[k]])
|
if (fees[normalIx] < fees[ix[k]])
|
||||||
normalIx = ix[k];
|
normalIx = ix[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t k = 0; k < ix.size(); k++) {
|
||||||
const wstring &to = fees[ix[k]].toBirthDate;
|
const wstring &to = fees[ix[k]].toBirthDate;
|
||||||
const wstring &from = fees[ix[k]].fromBirthDate;
|
const wstring &from = fees[ix[k]].fromBirthDate;
|
||||||
|
|
||||||
if (!from.empty() && (youthLimit.empty() || youthLimit > from))
|
if (!from.empty() && (youthLimit.empty() || youthLimit > from) && fees[ix[k]].fee == fees[redIx].fee)
|
||||||
youthLimit = from;
|
youthLimit = from;
|
||||||
|
|
||||||
if (!to.empty() && (seniorLimit.empty() || seniorLimit > to))
|
if (!to.empty() && (seniorLimit.empty() || seniorLimit > to) && fees[ix[k]].fee == fees[redIx].fee)
|
||||||
seniorLimit = to;
|
seniorLimit = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2395,6 +2496,123 @@ int IOF30Interface::parseISO8601Time(const xmlobject &xo) {
|
|||||||
return oe.getRelativeTime(date, time, zone);
|
return oe.getRelativeTime(date, time, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOF30Interface::getLocalDateTime(const string &date, const string &time,
|
||||||
|
string &dateOut, string &timeOut) {
|
||||||
|
int zIx = -1;
|
||||||
|
for (size_t k = 0; k < time.length(); k++) {
|
||||||
|
if (time[k] == '+' || time[k] == '-' || time[k] == 'Z') {
|
||||||
|
if (zIx == -1)
|
||||||
|
zIx = k;
|
||||||
|
else;
|
||||||
|
// Bad format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zIx == -1) {
|
||||||
|
dateOut = date;
|
||||||
|
timeOut = time;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string timePart = time.substr(0, zIx);
|
||||||
|
string zone = time.substr(zIx);
|
||||||
|
wstring wTime(timePart.begin(), timePart.end());
|
||||||
|
|
||||||
|
SYSTEMTIME st;
|
||||||
|
memset(&st, 0, sizeof(SYSTEMTIME));
|
||||||
|
|
||||||
|
int atime = convertAbsoluteTimeISO(wTime);
|
||||||
|
int idate = convertDateYMS(date, st, true);
|
||||||
|
if (idate != -1) {
|
||||||
|
if (zone == "Z" || zone == "z") {
|
||||||
|
st.wHour = atime / 3600;
|
||||||
|
st.wMinute = (atime / 60) % 60;
|
||||||
|
st.wSecond = atime % 60;
|
||||||
|
|
||||||
|
SYSTEMTIME localTime;
|
||||||
|
memset(&localTime, 0, sizeof(SYSTEMTIME));
|
||||||
|
SystemTimeToTzSpecificLocalTime(0, &st, &localTime);
|
||||||
|
|
||||||
|
char bf[64];
|
||||||
|
sprintf(bf, "%02d:%02d:%02d", localTime.wHour, localTime.wMinute, localTime.wSecond);
|
||||||
|
timeOut = bf;
|
||||||
|
sprintf(bf, "%d-%02d-%02d", localTime.wYear, localTime.wMonth, localTime.wDay);
|
||||||
|
dateOut = bf;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dateOut = date;
|
||||||
|
timeOut = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOF30Interface::getLocalDateTime(const wstring &datetime, wstring &dateOut, wstring &timeOut) {
|
||||||
|
size_t t = datetime.find_first_of('T');
|
||||||
|
if (t != dateOut.npos) {
|
||||||
|
wstring date = datetime.substr(0, t);
|
||||||
|
wstring time = datetime.substr(t + 1);
|
||||||
|
getLocalDateTime(date, time, dateOut, timeOut);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dateOut = datetime;
|
||||||
|
timeOut = L"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOF30Interface::getLocalDateTime(const wstring &date, const wstring &time,
|
||||||
|
wstring &dateOut, wstring &timeOut) {
|
||||||
|
int zIx = -1;
|
||||||
|
for (size_t k = 0; k < time.length(); k++) {
|
||||||
|
if (time[k] == '+' || time[k] == '-' || time[k] == 'Z') {
|
||||||
|
if (zIx == -1)
|
||||||
|
zIx = k;
|
||||||
|
else;
|
||||||
|
// Bad format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zIx == -1) {
|
||||||
|
dateOut = date;
|
||||||
|
timeOut = time;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring timePart = time.substr(0, zIx);
|
||||||
|
wstring zone = time.substr(zIx);
|
||||||
|
wstring wTime(timePart.begin(), timePart.end());
|
||||||
|
|
||||||
|
SYSTEMTIME st;
|
||||||
|
memset(&st, 0, sizeof(SYSTEMTIME));
|
||||||
|
|
||||||
|
int atime = convertAbsoluteTimeISO(wTime);
|
||||||
|
int idate = convertDateYMS(date, st, true);
|
||||||
|
if (idate != -1) {
|
||||||
|
if (zone == L"Z" || zone == L"z") {
|
||||||
|
st.wHour = atime / 3600;
|
||||||
|
st.wMinute = (atime / 60) % 60;
|
||||||
|
st.wSecond = atime % 60;
|
||||||
|
|
||||||
|
SYSTEMTIME localTime;
|
||||||
|
memset(&localTime, 0, sizeof(SYSTEMTIME));
|
||||||
|
SystemTimeToTzSpecificLocalTime(0, &st, &localTime);
|
||||||
|
|
||||||
|
atime = localTime.wHour * 3600 + localTime.wMinute * 60 + localTime.wSecond;
|
||||||
|
wchar_t bf[64];
|
||||||
|
wsprintf(bf, L"%02d:%02d:%02d", localTime.wHour, localTime.wMinute, localTime.wSecond);
|
||||||
|
timeOut = bf;
|
||||||
|
wsprintf(bf, L"%d-%02d-%02d", localTime.wYear, localTime.wMonth, localTime.wDay);
|
||||||
|
dateOut = bf;
|
||||||
|
//dateOut = itow(localTime.wYear) + L"-" + itow(localTime.wMonth) + L"-" + itow(localTime.wDay);
|
||||||
|
//timeOut = itow(localTime.wHour) + L":" + itow(localTime.wMinute) + L":" + itow(localTime.wSecond);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dateOut = date;
|
||||||
|
timeOut = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void IOF30Interface::getProps(vector<wstring> &props) const {
|
void IOF30Interface::getProps(vector<wstring> &props) const {
|
||||||
props.push_back(L"xmlns");
|
props.push_back(L"xmlns");
|
||||||
props.push_back(L"http://www.orienteering.org/datastandard/3.0");
|
props.push_back(L"http://www.orienteering.org/datastandard/3.0");
|
||||||
@ -3601,7 +3819,7 @@ void IOF30Interface::bindClassCourse(oClass &pc, const vector< vector<pCourse> >
|
|||||||
for (size_t k = 0; k < crs.size(); k++) {
|
for (size_t k = 0; k < crs.size(); k++) {
|
||||||
pc.clearStageCourses(k);
|
pc.clearStageCourses(k);
|
||||||
for (size_t j = 0; j < crs[k].size(); j++) {
|
for (size_t j = 0; j < crs[k].size(); j++) {
|
||||||
pc.addStageCourse(k, crs[k][j]->getId());
|
pc.addStageCourse(k, crs[k][j]->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -274,6 +274,13 @@ public:
|
|||||||
IOF30Interface(oEvent *oe, bool forceSplitFee);
|
IOF30Interface(oEvent *oe, bool forceSplitFee);
|
||||||
virtual ~IOF30Interface() {}
|
virtual ~IOF30Interface() {}
|
||||||
|
|
||||||
|
static void getLocalDateTime(const wstring &datetime, wstring &dateOut, wstring &timeOut);
|
||||||
|
|
||||||
|
static void getLocalDateTime(const wstring &date, const wstring &time,
|
||||||
|
wstring &dateOut, wstring &timeOut);
|
||||||
|
static void getLocalDateTime(const string &date, const string &time,
|
||||||
|
string &dateOut, string &timeOut);
|
||||||
|
|
||||||
void getIdTypes(vector<string> &types);
|
void getIdTypes(vector<string> &types);
|
||||||
void setPreferredIdType(const string &type);
|
void setPreferredIdType(const string &type);
|
||||||
|
|
||||||
@ -287,6 +294,8 @@ public:
|
|||||||
|
|
||||||
void readStartList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
void readStartList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||||
|
|
||||||
|
void readServiceRequestList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||||
|
|
||||||
void readClassList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
void readClassList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||||
|
|
||||||
void readCompetitorList(gdioutput &gdi, const xmlobject &xo, int &personCount);
|
void readCompetitorList(gdioutput &gdi, const xmlobject &xo, int &personCount);
|
||||||
|
|||||||
@ -1214,6 +1214,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
if (autoTask)
|
if (autoTask)
|
||||||
autoTask->synchronize(gdi_extra);
|
autoTask->synchronize(gdi_extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_USER + 5:
|
||||||
|
if (gdi_main)
|
||||||
|
gdi_main->addInfoBox("ainfo", L"info:advanceinfo", 10000);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
wmId = LOWORD(wParam);
|
wmId = LOWORD(wParam);
|
||||||
wmEvent = HIWORD(wParam);
|
wmEvent = HIWORD(wParam);
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
//V35: abcdef
|
//V35: abcdef
|
||||||
//V36: abcdef
|
//V36: abcdef
|
||||||
int getMeosBuild() {
|
int getMeosBuild() {
|
||||||
string revision("$Rev: 859 $");
|
string revision("$Rev: 895 $");
|
||||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,12 +42,12 @@ int getMeosBuild() {
|
|||||||
//V33: abcdefghij
|
//V33: abcdefghij
|
||||||
//V34: abcdfge
|
//V34: abcdfge
|
||||||
wstring getMeosDate() {
|
wstring getMeosDate() {
|
||||||
wstring date(L"$Date: 2019-03-19 21:52:12 +0100 (ti, 19 mar 2019) $");
|
wstring date(L"$Date: 2019-05-11 07:26:35 +0200 (lö, 11 maj 2019) $");
|
||||||
return date.substr(7,10);
|
return date.substr(7,10);
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getBuildType() {
|
wstring getBuildType() {
|
||||||
return L"RC1"; // No parantheses (...)
|
return L""; // No parantheses (...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getMajorVersion() {
|
wstring getMajorVersion() {
|
||||||
@ -128,5 +128,7 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
|||||||
supp.emplace_back(L"Ligue PACA");
|
supp.emplace_back(L"Ligue PACA");
|
||||||
supp.emplace_back(L"SC vebr-sport");
|
supp.emplace_back(L"SC vebr-sport");
|
||||||
supp.emplace_back(L"IP Skogen Göteborg");
|
supp.emplace_back(L"IP Skogen Göteborg");
|
||||||
|
supp.emplace_back(L"Smedjebackens Orientering");
|
||||||
|
supp.emplace_back(L"Gudhems IF");
|
||||||
reverse(supp.begin(), supp.end());
|
reverse(supp.begin(), supp.end());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1654,6 +1654,8 @@ void MetaList::initSymbols() {
|
|||||||
typeToSymbol[lClassStartTimeRange] = L"StartTimeForClassRange";
|
typeToSymbol[lClassStartTimeRange] = L"StartTimeForClassRange";
|
||||||
typeToSymbol[lClassLength] = L"ClassLength";
|
typeToSymbol[lClassLength] = L"ClassLength";
|
||||||
typeToSymbol[lClassResultFraction] = L"ClassResultFraction";
|
typeToSymbol[lClassResultFraction] = L"ClassResultFraction";
|
||||||
|
typeToSymbol[lClassAvailableMaps] = L"ClassAvailableMaps";
|
||||||
|
typeToSymbol[lClassTotalMaps] = L"ClassTotalMaps";
|
||||||
typeToSymbol[lCourseLength] = L"CourseLength";
|
typeToSymbol[lCourseLength] = L"CourseLength";
|
||||||
typeToSymbol[lCourseName] = L"CourseName";
|
typeToSymbol[lCourseName] = L"CourseName";
|
||||||
typeToSymbol[lCourseClimb] = L"CourseClimb";
|
typeToSymbol[lCourseClimb] = L"CourseClimb";
|
||||||
@ -1712,6 +1714,7 @@ void MetaList::initSymbols() {
|
|||||||
typeToSymbol[lRunnerNationality] = L"RunnerNationality";
|
typeToSymbol[lRunnerNationality] = L"RunnerNationality";
|
||||||
typeToSymbol[lRunnerPhone] = L"RunnerPhone";
|
typeToSymbol[lRunnerPhone] = L"RunnerPhone";
|
||||||
typeToSymbol[lRunnerFee] = L"RunnerFee";
|
typeToSymbol[lRunnerFee] = L"RunnerFee";
|
||||||
|
typeToSymbol[lRunnerExpectedFee] = L"RunnerExpectedFee";
|
||||||
typeToSymbol[lRunnerPaid] = L"RunnerPaid";
|
typeToSymbol[lRunnerPaid] = L"RunnerPaid";
|
||||||
typeToSymbol[lRunnerPayMethod] = L"RunnerPayMethod";
|
typeToSymbol[lRunnerPayMethod] = L"RunnerPayMethod";
|
||||||
typeToSymbol[lRunnerEntryDate] = L"RunnerEntryDate";
|
typeToSymbol[lRunnerEntryDate] = L"RunnerEntryDate";
|
||||||
@ -1881,6 +1884,7 @@ void MetaList::initSymbols() {
|
|||||||
filterToSymbol[EFilterHasNoCard] = "FilterNoCard";
|
filterToSymbol[EFilterHasNoCard] = "FilterNoCard";
|
||||||
filterToSymbol[EFilterAnyResult] = "FilterAnyResult";
|
filterToSymbol[EFilterAnyResult] = "FilterAnyResult";
|
||||||
filterToSymbol[EFilterAPIEntry] = "EFilterAPIEntry";
|
filterToSymbol[EFilterAPIEntry] = "EFilterAPIEntry";
|
||||||
|
filterToSymbol[EFilterWrongFee] = "EFilterWrongFee";
|
||||||
|
|
||||||
for (map<EFilterList, string>::iterator it = filterToSymbol.begin();
|
for (map<EFilterList, string>::iterator it = filterToSymbol.begin();
|
||||||
it != filterToSymbol.end(); ++it) {
|
it != filterToSymbol.end(); ++it) {
|
||||||
|
|||||||
@ -536,7 +536,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
wstring str;
|
wstring str;
|
||||||
try {
|
try {
|
||||||
st = currentResult->deduceStatus(*rr[k]);
|
st = currentResult->deduceStatus(*rr[k]);
|
||||||
str = oe->formatStatus(st);
|
str = oe->formatStatus(st, false);
|
||||||
}
|
}
|
||||||
catch (meosException &ex) {
|
catch (meosException &ex) {
|
||||||
err = ex.wwhat();
|
err = ex.wwhat();
|
||||||
@ -638,7 +638,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
wstring str;
|
wstring str;
|
||||||
try {
|
try {
|
||||||
st = currentResult->deduceStatus(*tr[k]);
|
st = currentResult->deduceStatus(*tr[k]);
|
||||||
str = oe->formatStatus(st);
|
str = oe->formatStatus(st, false);
|
||||||
}
|
}
|
||||||
catch (meosException &ex) {
|
catch (meosException &ex) {
|
||||||
err = ex.wwhat();
|
err = ex.wwhat();
|
||||||
@ -964,7 +964,7 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
|
|||||||
st = currentResult->deduceStatus(r);
|
st = currentResult->deduceStatus(r);
|
||||||
currentResult->debugDumpVariables(gdi, true);
|
currentResult->debugDumpVariables(gdi, true);
|
||||||
|
|
||||||
gdi.addStringUT(1, L"ComputedStatus: " + oe->formatStatus(st)).setColor(colorGreen);
|
gdi.addStringUT(1, L"ComputedStatus: " + oe->formatStatus(st, false)).setColor(colorGreen);
|
||||||
}
|
}
|
||||||
catch (meosException &ex) {
|
catch (meosException &ex) {
|
||||||
currentResult->debugDumpVariables(gdi, true);
|
currentResult->debugDumpVariables(gdi, true);
|
||||||
@ -1018,7 +1018,7 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
|
|||||||
st = currentResult->deduceStatus(t);
|
st = currentResult->deduceStatus(t);
|
||||||
currentResult->debugDumpVariables(gdi, true);
|
currentResult->debugDumpVariables(gdi, true);
|
||||||
|
|
||||||
gdi.addStringUT(1, L"ComputedStatus: " + oe->formatStatus(st)).setColor(colorGreen);
|
gdi.addStringUT(1, L"ComputedStatus: " + oe->formatStatus(st, false)).setColor(colorGreen);
|
||||||
}
|
}
|
||||||
catch (meosException &ex) {
|
catch (meosException &ex) {
|
||||||
currentResult->debugDumpVariables(gdi, true);
|
currentResult->debugDumpVariables(gdi, true);
|
||||||
|
|||||||
@ -44,8 +44,7 @@ static char THIS_FILE[]=__FILE__;
|
|||||||
|
|
||||||
char RunnerStatusOrderMap[100];
|
char RunnerStatusOrderMap[100];
|
||||||
|
|
||||||
oBase::oBase(oEvent *poe)
|
oBase::oBase(oEvent *poe) {
|
||||||
{
|
|
||||||
Removed = false;
|
Removed = false;
|
||||||
oe = poe;
|
oe = poe;
|
||||||
Id = 0;
|
Id = 0;
|
||||||
@ -57,8 +56,14 @@ oBase::oBase(oEvent *poe)
|
|||||||
localObject = false;
|
localObject = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
oBase::~oBase()
|
oBase::~oBase(){
|
||||||
{
|
if (myReference)
|
||||||
|
myReference->ref = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void oBase::remove() {
|
||||||
|
if (myReference)
|
||||||
|
myReference->ref = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oBase::synchronize(bool writeOnly)
|
bool oBase::synchronize(bool writeOnly)
|
||||||
|
|||||||
25
code/oBase.h
25
code/oBase.h
@ -34,6 +34,7 @@
|
|||||||
#include "TimeStamp.h"
|
#include "TimeStamp.h"
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class oEvent;
|
class oEvent;
|
||||||
class gdioutput;
|
class gdioutput;
|
||||||
@ -72,8 +73,18 @@ enum SortOrder {ClassStartTime,
|
|||||||
Custom,
|
Custom,
|
||||||
SortEnumLastItem};
|
SortEnumLastItem};
|
||||||
|
|
||||||
class oBase
|
class oBase {
|
||||||
{
|
public:
|
||||||
|
class oBaseReference {
|
||||||
|
private:
|
||||||
|
oBase * ref = nullptr;
|
||||||
|
public:
|
||||||
|
oBase * get() {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class oBase;
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
void storeChangeStatus() {reChanged = changed;}
|
void storeChangeStatus() {reChanged = changed;}
|
||||||
void resetChangeStatus() {changed &= reChanged;}
|
void resetChangeStatus() {changed &= reChanged;}
|
||||||
@ -83,6 +94,7 @@ private:
|
|||||||
const static unsigned long long BaseGenStringFlag = 1ull << 63;
|
const static unsigned long long BaseGenStringFlag = 1ull << 63;
|
||||||
const static unsigned long long Base36StringFlag = 1ull << 62;
|
const static unsigned long long Base36StringFlag = 1ull << 62;
|
||||||
const static unsigned long long ExtStringMask = ~(BaseGenStringFlag|Base36StringFlag);
|
const static unsigned long long ExtStringMask = ~(BaseGenStringFlag|Base36StringFlag);
|
||||||
|
shared_ptr<oBaseReference> myReference;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int Id;
|
int Id;
|
||||||
@ -118,6 +130,15 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Get a safe reference to this object
|
||||||
|
const shared_ptr<oBaseReference> &getReference() {
|
||||||
|
if (!myReference) {
|
||||||
|
myReference = make_shared<oBaseReference>();
|
||||||
|
myReference->ref = this;
|
||||||
|
}
|
||||||
|
return myReference;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if the object is local, not stored in DB/On disc
|
// Returns true if the object is local, not stored in DB/On disc
|
||||||
bool isLocalObject() { return localObject; }
|
bool isLocalObject() { return localObject; }
|
||||||
|
|
||||||
|
|||||||
@ -706,16 +706,10 @@ void oCard::getPunches(vector<pPunch> &punchesOut) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oCard::comparePunchTime(oPunch *p1, oPunch *p2) {
|
|
||||||
return p1->Time < p2->Time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void oCard::setupFromRadioPunches(oRunner &r) {
|
void oCard::setupFromRadioPunches(oRunner &r) {
|
||||||
oe->synchronizeList(oListId::oLPunchId);
|
oe->synchronizeList(oListId::oLPunchId);
|
||||||
vector<pFreePunch> p;
|
vector<pFreePunch> p;
|
||||||
oe->getPunchesForRunner(r.getId(), p);
|
oe->getPunchesForRunner(r.getId(), true, p);
|
||||||
|
|
||||||
sort(p.begin(), p.end(), comparePunchTime);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < p.size(); k++)
|
for (size_t k = 0; k < p.size(); k++)
|
||||||
addPunch(p[k]->Type, p[k]->Time, 0);
|
addPunch(p[k]->Type, p[k]->Time, 0);
|
||||||
|
|||||||
101
code/oClass.cpp
101
code/oClass.cpp
@ -644,21 +644,44 @@ bool oClass::fillStageCourses(gdioutput &gdi, int stage,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oClass::addStageCourse(int iStage, int courseId)
|
bool oClass::addStageCourse(int iStage, int courseId, int index)
|
||||||
{
|
{
|
||||||
return addStageCourse(iStage, oe->getCourse(courseId));
|
return addStageCourse(iStage, oe->getCourse(courseId), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool oClass::addStageCourse(int iStage, pCourse pc)
|
bool oClass::addStageCourse(int iStage, pCourse pc, int index)
|
||||||
{
|
{
|
||||||
if (unsigned(iStage)>=MultiCourse.size())
|
if (unsigned(iStage)>=MultiCourse.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
vector<pCourse> &Stage=MultiCourse[iStage];
|
vector<pCourse> &stage=MultiCourse[iStage];
|
||||||
|
|
||||||
if (pc) {
|
if (pc) {
|
||||||
tCoursesChanged = true;
|
tCoursesChanged = true;
|
||||||
Stage.push_back(pc);
|
if (index == -1 || size_t(index) >= stage.size())
|
||||||
|
stage.push_back(pc);
|
||||||
|
else {
|
||||||
|
stage.insert(stage.begin() + index, pc);
|
||||||
|
}
|
||||||
|
updateChanged();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool oClass::moveStageCourse(int stage, int index, int offset) {
|
||||||
|
if (unsigned(stage) >= MultiCourse.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vector<pCourse> &stages = MultiCourse[stage];
|
||||||
|
|
||||||
|
if (offset == -1 && size_t(index) < stages.size() && index > 0) {
|
||||||
|
swap(stages[index - 1], stages[index]);
|
||||||
|
updateChanged();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (offset == 1 && size_t(index + 1) < stages.size() && index >= 0) {
|
||||||
|
swap(stages[index + 1], stages[index]);
|
||||||
updateChanged();
|
updateChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2622,11 +2645,8 @@ int oClass::getNumRemainingMaps(bool forceRecalculate) const {
|
|||||||
numMaps = Course->tMapsRemaining;
|
numMaps = Course->tMapsRemaining;
|
||||||
else
|
else
|
||||||
numMaps = min(numMaps, Course->tMapsRemaining);
|
numMaps = min(numMaps, Course->tMapsRemaining);
|
||||||
|
|
||||||
return numMaps;
|
|
||||||
}
|
}
|
||||||
else
|
return numMaps;
|
||||||
return numMaps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void oClass::setNumberMaps(int nm) {
|
void oClass::setNumberMaps(int nm) {
|
||||||
@ -2648,39 +2668,19 @@ int oClass::getNumberMaps(bool rawAttribute) const {
|
|||||||
void oEvent::getStartBlocks(vector<int> &blocks, vector<wstring> &starts) const
|
void oEvent::getStartBlocks(vector<int> &blocks, vector<wstring> &starts) const
|
||||||
{
|
{
|
||||||
oClassList::const_iterator it;
|
oClassList::const_iterator it;
|
||||||
map<int, wstring> bs;
|
set<pair<wstring, int>> bs;
|
||||||
for (it = Classes.begin(); it != Classes.end(); ++it) {
|
for (it = Classes.begin(); it != Classes.end(); ++it) {
|
||||||
if (it->isRemoved())
|
if (it->isRemoved())
|
||||||
continue;
|
continue;
|
||||||
map<int, wstring>::iterator v = bs.find(it->getBlock());
|
|
||||||
|
|
||||||
if (v!=bs.end() && v->first!=0 && v->second!=it->getStart()) {
|
bs.emplace(it->getStart(), it->getBlock());
|
||||||
wstring msg = L"Ett startblock spänner över flera starter: X/Y#" + it->getStart() + L"#" + v->second;
|
|
||||||
throw meosException(msg.c_str());
|
|
||||||
}
|
|
||||||
bs[it->getBlock()] = it->getStart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks.clear();
|
blocks.clear();
|
||||||
starts.clear();
|
starts.clear();
|
||||||
|
|
||||||
if (bs.size() > 1) {
|
for (auto &v : bs) {
|
||||||
for (map<int, wstring>::iterator v = bs.begin(); v != bs.end(); ++v) {
|
blocks.push_back(v.second);
|
||||||
blocks.push_back(v->first);
|
starts.push_back(v.first);
|
||||||
starts.push_back(v->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (bs.size() == 1) {
|
|
||||||
set<wstring> s;
|
|
||||||
for (it = Classes.begin(); it != Classes.end(); ++it) {
|
|
||||||
if (it->isRemoved())
|
|
||||||
continue;
|
|
||||||
s.insert(it->getStart());
|
|
||||||
}
|
|
||||||
for (set<wstring>::iterator v = s.begin(); v != s.end(); ++v) {
|
|
||||||
blocks.push_back(bs.begin()->first);
|
|
||||||
starts.push_back(*v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2861,20 +2861,24 @@ void oClass::addClassDefaultFee(bool resetFee) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oClass::reinitialize() {
|
void oClass::reinitialize(bool force) const {
|
||||||
int ix = getDI().getInt("SortIndex");
|
if (!force && isInitialized)
|
||||||
|
return;
|
||||||
|
isInitialized = true; // Prevent recursion
|
||||||
|
|
||||||
|
int ix = getDCI().getInt("SortIndex");
|
||||||
if (ix == 0) {
|
if (ix == 0) {
|
||||||
ix = getSortIndex(getId()*10);
|
ix = getSortIndex(getId()*10);
|
||||||
getDI().setInt("SortIndex", ix);
|
const_cast<oClass*>(this)->getDI().setInt("SortIndex", ix);
|
||||||
}
|
}
|
||||||
tSortIndex = ix;
|
tSortIndex = ix;
|
||||||
|
|
||||||
tMaxTime = getDI().getInt("MaxTime");
|
tMaxTime = getDCI().getInt("MaxTime");
|
||||||
if (tMaxTime == 0 && oe) {
|
if (tMaxTime == 0 && oe) {
|
||||||
tMaxTime = oe->getMaximalTime();
|
tMaxTime = oe->getMaximalTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring wInfo = getDI().getString("Qualification");
|
wstring wInfo = getDCI().getString("Qualification");
|
||||||
if (!wInfo.empty()) {
|
if (!wInfo.empty()) {
|
||||||
if (qualificatonFinal && !qualificatonFinal->matchSerialization(wInfo))
|
if (qualificatonFinal && !qualificatonFinal->matchSerialization(wInfo))
|
||||||
clearQualificationFinal();
|
clearQualificationFinal();
|
||||||
@ -2897,7 +2901,7 @@ void oClass::reinitialize() {
|
|||||||
tIgnoreStartPunch = -1;
|
tIgnoreStartPunch = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void oClass::clearQualificationFinal() {
|
void oClass::clearQualificationFinal() const {
|
||||||
if (!qualificatonFinal)
|
if (!qualificatonFinal)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2911,15 +2915,12 @@ void oClass::clearQualificationFinal() {
|
|||||||
qualificatonFinal.reset();
|
qualificatonFinal.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void oEvent::reinitializeClasses() const {
|
||||||
void oEvent::reinitializeClasses()
|
for (auto &c : Classes)
|
||||||
{
|
c.reinitialize(true);
|
||||||
for (oClassList::iterator it = Classes.begin(); it != Classes.end(); ++it)
|
|
||||||
it->reinitialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int oClass::getSortIndex(int candidate)
|
int oClass::getSortIndex(int candidate) const {
|
||||||
{
|
|
||||||
int major = numeric_limits<int>::max();
|
int major = numeric_limits<int>::max();
|
||||||
int minor = 0;
|
int minor = 0;
|
||||||
|
|
||||||
@ -3340,6 +3341,7 @@ bool oClass::canRemove() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
int oClass::getMaximumRunnerTime() const {
|
int oClass::getMaximumRunnerTime() const {
|
||||||
|
reinitialize(false);
|
||||||
return tMaxTime;
|
return tMaxTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3821,10 +3823,10 @@ pair<int, int> oClass::autoForking(const vector< vector<int> > &inputCourses) {
|
|||||||
lastSet = j;
|
lastSet = j;
|
||||||
for (size_t k = 0; k < courseMatrix[j].size(); k++) {
|
for (size_t k = 0; k < courseMatrix[j].size(); k++) {
|
||||||
if (k < fperm.size()) {
|
if (k < fperm.size()) {
|
||||||
addStageCourse(j, courseMatrix[j][fperm[k]]);
|
addStageCourse(j, courseMatrix[j][fperm[k]], -1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addStageCourse(j, courseMatrix[j][k]);
|
addStageCourse(j, courseMatrix[j][k], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4402,6 +4404,7 @@ void oClass::configureInstance(int instance, bool allowCreation) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int oClass::getNumQualificationFinalClasses() const {
|
int oClass::getNumQualificationFinalClasses() const {
|
||||||
|
reinitialize(false);
|
||||||
if (qualificatonFinal)
|
if (qualificatonFinal)
|
||||||
return qualificatonFinal->getNumClasses()+1;
|
return qualificatonFinal->getNumClasses()+1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -200,8 +200,10 @@ protected:
|
|||||||
mutable int tIgnoreStartPunch;
|
mutable int tIgnoreStartPunch;
|
||||||
|
|
||||||
// Sort classes for this index
|
// Sort classes for this index
|
||||||
int tSortIndex;
|
mutable int tSortIndex;
|
||||||
int tMaxTime;
|
mutable int tMaxTime;
|
||||||
|
|
||||||
|
mutable bool isInitialized = false;
|
||||||
|
|
||||||
// True when courses was changed on this client. Used to update course pool bindings
|
// True when courses was changed on this client. Used to update course pool bindings
|
||||||
bool tCoursesChanged;
|
bool tCoursesChanged;
|
||||||
@ -244,7 +246,7 @@ protected:
|
|||||||
void exportIOFStart(xmlparser &xml);
|
void exportIOFStart(xmlparser &xml);
|
||||||
|
|
||||||
/** Setup transient data */
|
/** Setup transient data */
|
||||||
void reinitialize();
|
void reinitialize(bool force) const;
|
||||||
|
|
||||||
/** Recalculate derived data */
|
/** Recalculate derived data */
|
||||||
void apply();
|
void apply();
|
||||||
@ -264,7 +266,7 @@ protected:
|
|||||||
mutable vector<ClassResultInfo> tResultInfo;
|
mutable vector<ClassResultInfo> tResultInfo;
|
||||||
|
|
||||||
/** Get/calculate sort index from candidate */
|
/** Get/calculate sort index from candidate */
|
||||||
int getSortIndex(int candidate);
|
int getSortIndex(int candidate) const;
|
||||||
|
|
||||||
/** Get internal data buffers for DI */
|
/** Get internal data buffers for DI */
|
||||||
oDataContainer &getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const;
|
oDataContainer &getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const;
|
||||||
@ -276,7 +278,7 @@ protected:
|
|||||||
mutable vector<pClass> virtualClasses;
|
mutable vector<pClass> virtualClasses;
|
||||||
pClass parentClass;
|
pClass parentClass;
|
||||||
|
|
||||||
shared_ptr<QualificationFinal> qualificatonFinal;
|
mutable shared_ptr<QualificationFinal> qualificatonFinal;
|
||||||
|
|
||||||
int tMapsRemaining;
|
int tMapsRemaining;
|
||||||
mutable int tMapsUsed;
|
mutable int tMapsUsed;
|
||||||
@ -288,9 +290,12 @@ public:
|
|||||||
/** The master class in a qualification/final scheme. */
|
/** The master class in a qualification/final scheme. */
|
||||||
const pClass getParentClass() const { return parentClass; }
|
const pClass getParentClass() const { return parentClass; }
|
||||||
|
|
||||||
const QualificationFinal *getQualificationFinal() const { return qualificatonFinal.get(); }
|
const QualificationFinal *getQualificationFinal() const {
|
||||||
|
reinitialize(false);
|
||||||
|
return qualificatonFinal.get();
|
||||||
|
}
|
||||||
|
|
||||||
void clearQualificationFinal();
|
void clearQualificationFinal() const;
|
||||||
|
|
||||||
bool isQualificationFinalClass() const {
|
bool isQualificationFinalClass() const {
|
||||||
return parentClass && parentClass->isQualificationFinalBaseClass();
|
return parentClass && parentClass->isQualificationFinalBaseClass();
|
||||||
@ -565,9 +570,10 @@ public:
|
|||||||
int getCourseId() const {if (Course) return Course->getId(); else return 0;}
|
int getCourseId() const {if (Course) return Course->getId(); else return 0;}
|
||||||
void setCourse(pCourse c);
|
void setCourse(pCourse c);
|
||||||
|
|
||||||
bool addStageCourse(int stage, int courseId);
|
bool addStageCourse(int stage, int courseId, int index);
|
||||||
bool addStageCourse(int stage, pCourse pc);
|
bool addStageCourse(int stage, pCourse pc, int index);
|
||||||
void clearStageCourses(int stage);
|
void clearStageCourses(int stage);
|
||||||
|
bool moveStageCourse(int stage, int index, int offset);
|
||||||
|
|
||||||
bool removeStageCourse(int stage, int courseId, int position);
|
bool removeStageCourse(int stage, int courseId, int position);
|
||||||
|
|
||||||
|
|||||||
@ -317,12 +317,13 @@ Table *oEvent::getClubsTB()//Table mode
|
|||||||
|
|
||||||
void oEvent::generateClubTableData(Table &table, oClub *addClub)
|
void oEvent::generateClubTableData(Table &table, oClub *addClub)
|
||||||
{
|
{
|
||||||
oe->setupClubInfoData();
|
|
||||||
if (addClub) {
|
if (addClub) {
|
||||||
addClub->addTableRow(table);
|
addClub->addTableRow(table);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronizeList(oListId::oLClubId);
|
synchronizeList(oListId::oLClubId);
|
||||||
|
oe->setupClubInfoData();
|
||||||
|
|
||||||
oClubList::iterator it;
|
oClubList::iterator it;
|
||||||
|
|
||||||
for (it=Clubs.begin(); it != Clubs.end(); ++it){
|
for (it=Clubs.begin(); it != Clubs.end(); ++it){
|
||||||
@ -919,7 +920,9 @@ void oEvent::printInvoices(gdioutput &gdi, InvoicePrintType type,
|
|||||||
if (!it->isRemoved() && clubId.count(it->getId()) > 0) {
|
if (!it->isRemoved() && clubId.count(it->getId()) > 0) {
|
||||||
|
|
||||||
gdi.addStringUT(yp, 50, fontMedium, itos(it->getDCI().getInt("InvoiceNo")));
|
gdi.addStringUT(yp, 50, fontMedium, itos(it->getDCI().getInt("InvoiceNo")));
|
||||||
gdi.addStringUT(yp, 240, textRight|fontMedium, itos(it->getId()));
|
if (it->getExtIdentifier() != 0)
|
||||||
|
gdi.addStringUT(yp, 240, textRight|fontMedium, it->getExtIdentifierString());
|
||||||
|
|
||||||
gdi.addStringUT(yp, 250, fontMedium, it->getName());
|
gdi.addStringUT(yp, 250, fontMedium, it->getName());
|
||||||
gdi.addStringUT(yp, 550, fontMedium|textRight, oe->formatCurrency(fees[k]));
|
gdi.addStringUT(yp, 550, fontMedium|textRight, oe->formatCurrency(fees[k]));
|
||||||
gdi.addStringUT(yp, 620, fontMedium|textRight, oe->formatCurrency(vpaid[k]));
|
gdi.addStringUT(yp, 620, fontMedium|textRight, oe->formatCurrency(vpaid[k]));
|
||||||
|
|||||||
@ -904,6 +904,7 @@ void oCourse::clearCache() const {
|
|||||||
cachedHasRogaining = 0;
|
cachedHasRogaining = 0;
|
||||||
cachedControlOrdinal.clear();
|
cachedControlOrdinal.clear();
|
||||||
cacheDataRevision = oe->dataRevision;
|
cacheDataRevision = oe->dataRevision;
|
||||||
|
oe->tCalcNumMapsDataRevision = -1;
|
||||||
tMapsUsed = -1;
|
tMapsUsed = -1;
|
||||||
tMapsUsedNoVacant = -1;
|
tMapsUsedNoVacant = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,8 +68,8 @@ protected:
|
|||||||
vector<int> legLengths;
|
vector<int> legLengths;
|
||||||
|
|
||||||
int tMapsRemaining;
|
int tMapsRemaining;
|
||||||
mutable int tMapsUsed;
|
mutable int tMapsUsed = -1;
|
||||||
mutable int tMapsUsedNoVacant;
|
mutable int tMapsUsedNoVacant = -1;
|
||||||
|
|
||||||
// Get an identity sum based on controls
|
// Get an identity sum based on controls
|
||||||
int getIdSum(int nControls);
|
int getIdSum(int nControls);
|
||||||
|
|||||||
258
code/oEvent.cpp
258
code/oEvent.cpp
@ -650,16 +650,24 @@ pControl oEvent::getControl(int Id) const {
|
|||||||
return const_cast<oEvent *>(this)->getControl(Id, false);
|
return const_cast<oEvent *>(this)->getControl(Id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pControl oEvent::getControlByType(int type) const {
|
||||||
|
for (auto &c : Controls) {
|
||||||
|
if (!c.isRemoved() && c.getFirstNumber() == type)
|
||||||
|
return pControl(&c);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
pControl oEvent::getControl(int Id, bool create) {
|
pControl oEvent::getControl(int Id, bool create) {
|
||||||
oControlList::const_iterator it;
|
oControlList::const_iterator it;
|
||||||
|
|
||||||
for (it=Controls.begin(); it != Controls.end(); ++it) {
|
for (it=Controls.begin(); it != Controls.end(); ++it) {
|
||||||
if (it->Id==Id)
|
if (it->Id==Id && !it->isRemoved())
|
||||||
return pControl(&*it);
|
return pControl(&*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!create || Id<=0)
|
if (!create || Id<=0)
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
//Not found. Auto add...
|
//Not found. Auto add...
|
||||||
return addControl(Id, Id, L"");
|
return addControl(Id, Id, L"");
|
||||||
@ -1420,14 +1428,7 @@ pRunner oEvent::dbLookUpById(__int64 extId) const
|
|||||||
sRunner.setTemporary();
|
sRunner.setTemporary();
|
||||||
RunnerWDBEntry *dbr = runnerDB->getRunnerById(int(extId));
|
RunnerWDBEntry *dbr = runnerDB->getRunnerById(int(extId));
|
||||||
if (dbr != 0) {
|
if (dbr != 0) {
|
||||||
sRunner.init(*dbr);
|
sRunner.init(*dbr, false);
|
||||||
/*dbr->getName(sRunner.Name);
|
|
||||||
sRunner.CardNo = dbr->cardNo;
|
|
||||||
sRunner.Club = runnerDB->getClub(dbr->clubNo);
|
|
||||||
sRunner.getDI().setString("Nationality", dbr->getNationality());
|
|
||||||
sRunner.getDI().setInt("BirthYear", dbr->getBirthYear());
|
|
||||||
sRunner.getDI().setString("Sex", dbr->getSex());
|
|
||||||
sRunner.setExtIdentifier(dbr->getExtId());*/
|
|
||||||
return &sRunner;
|
return &sRunner;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1446,7 +1447,7 @@ pRunner oEvent::dbLookUpByCard(int cardNo) const
|
|||||||
if (dbr != 0) {
|
if (dbr != 0) {
|
||||||
dbr->getName(sRunner.sName);
|
dbr->getName(sRunner.sName);
|
||||||
oRunner::getRealName(sRunner.sName, sRunner.tRealName);
|
oRunner::getRealName(sRunner.sName, sRunner.tRealName);
|
||||||
sRunner.init(*dbr);
|
sRunner.init(*dbr, false);
|
||||||
sRunner.cardNumber = cardNo;
|
sRunner.cardNumber = cardNo;
|
||||||
return &sRunner;
|
return &sRunner;
|
||||||
}
|
}
|
||||||
@ -1482,14 +1483,7 @@ pRunner oEvent::dbLookUpByName(const wstring &name, int clubId, int classId, int
|
|||||||
RunnerWDBEntry *dbr = runnerDB->getRunnerByName(name, clubId, birthYear);
|
RunnerWDBEntry *dbr = runnerDB->getRunnerByName(name, clubId, birthYear);
|
||||||
|
|
||||||
if (dbr) {
|
if (dbr) {
|
||||||
sRunner.init(*dbr);
|
sRunner.init(*dbr, false);
|
||||||
/*
|
|
||||||
dbr->getName(sRunner.Name);
|
|
||||||
sRunner.CardNo = dbr->cardNo;
|
|
||||||
sRunner.Club = runnerDB->getClub(dbr->clubNo);
|
|
||||||
sRunner.getDI().setString("Nationality", dbr->getNationality());
|
|
||||||
sRunner.getDI().setInt("BirthYear", dbr->getBirthYear());
|
|
||||||
sRunner.getDI().setString("Sex", dbr->getSex());*/
|
|
||||||
sRunner.setExtIdentifier(int(dbr->getExtId()));
|
sRunner.setExtIdentifier(int(dbr->getExtId()));
|
||||||
return &sRunner;
|
return &sRunner;
|
||||||
}
|
}
|
||||||
@ -2050,6 +2044,15 @@ bool oEvent::sortRunners(SortOrder so) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool oEvent::sortRunners(SortOrder so, vector<const oRunner *> &runners) const {
|
||||||
|
reinitializeClasses();
|
||||||
|
auto oldSortOrder = CurrentSortOrder;
|
||||||
|
CurrentSortOrder = so;
|
||||||
|
sort(runners.begin(), runners.end(), [](const oRunner * &a, const oRunner * &b)->bool {return *a < *b; });
|
||||||
|
CurrentSortOrder = oldSortOrder;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool oEvent::sortTeams(SortOrder so, int leg, bool linearLeg) {
|
bool oEvent::sortTeams(SortOrder so, int leg, bool linearLeg) {
|
||||||
reinitializeClasses();
|
reinitializeClasses();
|
||||||
oTeamList::iterator it;
|
oTeamList::iterator it;
|
||||||
@ -2165,6 +2168,120 @@ bool oEvent::sortTeams(SortOrder so, int leg, bool linearLeg) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool oEvent::sortTeams(SortOrder so, int leg, bool linearLeg, vector<const oTeam *> &teams) const {
|
||||||
|
reinitializeClasses();
|
||||||
|
map<int, int> classId2Linear;
|
||||||
|
if (so == ClassResult || so == ClassTotalResult || so == ClassTeamLegResult) {
|
||||||
|
bool totalResult = so == ClassTotalResult;
|
||||||
|
bool legResult = so == ClassTeamLegResult;
|
||||||
|
bool hasRunner = (leg == -1);
|
||||||
|
for (auto it : teams) {
|
||||||
|
int lg = leg;
|
||||||
|
int clsId = it->Class->getId();
|
||||||
|
|
||||||
|
if (leg >= 0 && !linearLeg && it->Class) {
|
||||||
|
map<int, int>::iterator res = classId2Linear.find(it->Class->getId());
|
||||||
|
if (res == classId2Linear.end()) {
|
||||||
|
unsigned linLegBase = it->Class->getLegNumberLinear(leg, 0);
|
||||||
|
while (linLegBase + 1 < it->Class->getNumStages()) {
|
||||||
|
if (it->Class->isParallel(linLegBase + 1) || it->Class->isOptional(linLegBase + 1))
|
||||||
|
linLegBase++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lg = linLegBase;
|
||||||
|
//lg = linLegBase + it->Class->getNumParallel(linLegBase) - 1;
|
||||||
|
classId2Linear[clsId] = lg;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lg = res->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int lastIndex = it->Class ? it->Class->getLastStageIndex() : 0;
|
||||||
|
lg = min<unsigned>(lg, lastIndex);
|
||||||
|
|
||||||
|
|
||||||
|
if (lg >= leg)
|
||||||
|
hasRunner = true;
|
||||||
|
if (legResult) {
|
||||||
|
pRunner r = it->getRunner(lg);
|
||||||
|
if (r) {
|
||||||
|
it->_sortTime = r->getRunningTime();
|
||||||
|
it->_cachedStatus = r->getStatus();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it->_sortTime = 0;
|
||||||
|
it->_cachedStatus = StatusUnknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it->_sortTime = it->getLegRunningTime(lg, totalResult) + it->getNumShortening(lg) * 3600 * 24 * 10;
|
||||||
|
it->_cachedStatus = it->getLegStatus(lg, totalResult);
|
||||||
|
|
||||||
|
// Ensure number of restarts has effect on final result
|
||||||
|
if (lg == lastIndex)
|
||||||
|
it->_sortTime += it->tNumRestarts * 24 * 3600;
|
||||||
|
}
|
||||||
|
unsigned rawStatus = it->_cachedStatus;
|
||||||
|
it->_sortStatus = RunnerStatusOrderMap[rawStatus < 100u ? rawStatus : 0];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasRunner)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sort(teams.begin(), teams.end(), [](const oTeam * &a, const oTeam * &b)->bool {return oTeam::compareResult(*a, *b); });
|
||||||
|
}
|
||||||
|
else if (so == ClassStartTime || so == ClassStartTimeClub) {
|
||||||
|
if (leg == -1)
|
||||||
|
leg = 0;
|
||||||
|
for (auto it : teams) {
|
||||||
|
it->_cachedStatus = StatusUnknown;
|
||||||
|
it->_sortStatus = 0;
|
||||||
|
it->_sortTime = it->getLegStartTime(leg);
|
||||||
|
if (it->_sortTime <= 0)
|
||||||
|
it->_sortStatus = 1;
|
||||||
|
}
|
||||||
|
if (so == ClassStartTime)
|
||||||
|
sort(teams.begin(), teams.end(), [](const oTeam * &a, const oTeam * &b)->bool {return oTeam::compareResult(*a, *b); });
|
||||||
|
else
|
||||||
|
sort(teams.begin(), teams.end(), [](const oTeam * &a, const oTeam * &b)->bool {return oTeam::compareResultNoSno(*a, *b); });
|
||||||
|
}
|
||||||
|
else if (so == ClassKnockoutTotalResult) {
|
||||||
|
for (auto it : teams) {
|
||||||
|
it->_cachedStatus = StatusUnknown;
|
||||||
|
it->_sortStatus = 0;
|
||||||
|
it->_sortTime = 0;
|
||||||
|
|
||||||
|
// Count number of races with results
|
||||||
|
int numResult = 0;
|
||||||
|
int lastClassHeat = 0;
|
||||||
|
for (pRunner r : it->Runners) {
|
||||||
|
if (r && (r->prelStatusOK() ||
|
||||||
|
(r->tStatus != StatusUnknown && r->tStatus != StatusDNS && r->tStatus != StatusCANCEL))) {
|
||||||
|
|
||||||
|
if (r->Class && r->tLeg > 0 && r->Class->isQualificationFinalBaseClass() && r->getClassRef(true) == r->Class)
|
||||||
|
continue; // Skip if not qualified.
|
||||||
|
|
||||||
|
numResult++;
|
||||||
|
lastClassHeat = r->getDCI().getInt("Heat");
|
||||||
|
it->_cachedStatus = r->tStatus;
|
||||||
|
it->_sortTime = r->getRunningTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastClassHeat > 50 || lastClassHeat < 0)
|
||||||
|
lastClassHeat = 0;
|
||||||
|
|
||||||
|
unsigned rawStatus = it->_cachedStatus;
|
||||||
|
it->_sortStatus = RunnerStatusOrderMap[rawStatus < 100u ? rawStatus : 0] - (numResult * 100 + lastClassHeat) * 1000;
|
||||||
|
|
||||||
|
}
|
||||||
|
sort(teams.begin(), teams.end(), [](const oTeam * &a, const oTeam * &b)->bool {return oTeam::compareResult(*a, *b); });
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
wstring oEvent::getZeroTime() const
|
wstring oEvent::getZeroTime() const
|
||||||
{
|
{
|
||||||
return getAbsTime(0);
|
return getAbsTime(0);
|
||||||
@ -2896,6 +3013,8 @@ void oEvent::generateInForestList(gdioutput &gdi, GUICALLBACK cb, GUICALLBACK cb
|
|||||||
typedef multimap<int, pFreePunch>::const_iterator TPunchIter;
|
typedef multimap<int, pFreePunch>::const_iterator TPunchIter;
|
||||||
|
|
||||||
for (oFreePunchList::iterator it = punches.begin(); it != punches.end(); ++it) {
|
for (oFreePunchList::iterator it = punches.begin(); it != punches.end(); ++it) {
|
||||||
|
if (it->isRemoved() || it->isHiredCard())
|
||||||
|
continue;
|
||||||
punchHash.insert(make_pair(it->getCardNo(), &*it));
|
punchHash.insert(make_pair(it->getCardNo(), &*it));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3087,7 +3206,7 @@ void oEvent::generateMinuteStartlist(gdioutput &gdi) {
|
|||||||
for (size_t k=0;k<blocks.size();k++) {
|
for (size_t k=0;k<blocks.size();k++) {
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
if (k>0)
|
if (k>0)
|
||||||
gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, "");
|
gdi.addStringUT(gdi.getCY()-1, 0, pageNewChapter, "");
|
||||||
|
|
||||||
gdi.addStringUT(boldLarge|Capitalize, lang.tl(L"Minutstartlista", true) + makeDash(L" - ") + getName());
|
gdi.addStringUT(boldLarge|Capitalize, lang.tl(L"Minutstartlista", true) + makeDash(L" - ") + getName());
|
||||||
if (!starts[k].empty()) {
|
if (!starts[k].empty()) {
|
||||||
@ -3103,9 +3222,9 @@ void oEvent::generateMinuteStartlist(gdioutput &gdi) {
|
|||||||
sb.reserve(Runners.size());
|
sb.reserve(Runners.size());
|
||||||
int LastStartTime=-1;
|
int LastStartTime=-1;
|
||||||
for (oRunnerList::iterator it=Runners.begin(); it != Runners.end(); ++it) {
|
for (oRunnerList::iterator it=Runners.begin(); it != Runners.end(); ++it) {
|
||||||
if (it->Class && it->Class->getBlock()!=blocks[k])
|
if (it->Class && it->Class->getBlock() != blocks[k])
|
||||||
continue;
|
continue;
|
||||||
if (it->Class && it->Class->getStart() != starts[k] )
|
if (it->Class && it->Class->getStart() != starts[k])
|
||||||
continue;
|
continue;
|
||||||
if (!it->Class && blocks[k]!=0)
|
if (!it->Class && blocks[k]!=0)
|
||||||
continue;
|
continue;
|
||||||
@ -3626,6 +3745,7 @@ void oEvent::clear()
|
|||||||
punchIndex.clear();
|
punchIndex.clear();
|
||||||
punches.clear();
|
punches.clear();
|
||||||
cachedFirstStart.clear();
|
cachedFirstStart.clear();
|
||||||
|
hiredCardHash.clear();
|
||||||
|
|
||||||
updateFreeId();
|
updateFreeId();
|
||||||
|
|
||||||
@ -3778,7 +3898,7 @@ void oEvent::reEvaluateAll(const set<int> &cls, bool doSync)
|
|||||||
if (cls.empty() || cls.count(it->Id)) {
|
if (cls.empty() || cls.count(it->Id)) {
|
||||||
it->clearSplitAnalysis();
|
it->clearSplitAnalysis();
|
||||||
it->resetLeaderTime();
|
it->resetLeaderTime();
|
||||||
it->reinitialize();
|
it->reinitialize(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3877,7 +3997,7 @@ void oEvent::reEvaluateChanged()
|
|||||||
if (it->wasSQLChanged(-1, oPunch::PunchFinish)) {
|
if (it->wasSQLChanged(-1, oPunch::PunchFinish)) {
|
||||||
it->clearSplitAnalysis();
|
it->clearSplitAnalysis();
|
||||||
it->resetLeaderTime();
|
it->resetLeaderTime();
|
||||||
it->reinitialize();
|
it->reinitialize(true);
|
||||||
resetClasses[it->getId()] = it->hasClassGlobalDependence();
|
resetClasses[it->getId()] = it->hasClassGlobalDependence();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4281,11 +4401,13 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
|
|||||||
if (cls == 0)
|
if (cls == 0)
|
||||||
throw meosException("Class not found");
|
throw meosException("Class not found");
|
||||||
|
|
||||||
if (cls->getParentClass())
|
if (cls->getParentClass()) {
|
||||||
cls->getParentClass()->setBibMode(BibFree);
|
cls->getParentClass()->setBibMode(BibFree);
|
||||||
|
cls->getParentClass()->synchronize(true);
|
||||||
|
}
|
||||||
if (!firstNumber.empty()) {
|
if (!firstNumber.empty()) {
|
||||||
cls->setBibMode(BibFree);
|
cls->setBibMode(BibFree);
|
||||||
|
cls->synchronize(true);
|
||||||
wchar_t pattern[32];
|
wchar_t pattern[32];
|
||||||
int num = oClass::extractBibPattern(firstNumber, pattern);
|
int num = oClass::extractBibPattern(firstNumber, pattern);
|
||||||
|
|
||||||
@ -4536,6 +4658,8 @@ void oEvent::addAutoBib() {
|
|||||||
// Switch to free mode if bib set for subclass
|
// Switch to free mode if bib set for subclass
|
||||||
cls->getParentClass()->setBibMode(BibFree);
|
cls->getParentClass()->setBibMode(BibFree);
|
||||||
cls->setBibMode(BibFree);
|
cls->setBibMode(BibFree);
|
||||||
|
cls->getParentClass()->synchronize(true);
|
||||||
|
cls->synchronize(true);
|
||||||
}
|
}
|
||||||
for (size_t k = 0; k < rl.size(); k++) {
|
for (size_t k = 0; k < rl.size(); k++) {
|
||||||
if (pattern[0]) {
|
if (pattern[0]) {
|
||||||
@ -4553,27 +4677,40 @@ void oEvent::addAutoBib() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::checkOrderIdMultipleCourses(int ClassId)
|
void oEvent::checkOrderIdMultipleCourses(int ClassId) {
|
||||||
{
|
|
||||||
sortRunners(ClassStartTime);
|
sortRunners(ClassStartTime);
|
||||||
int order=1;
|
int order=1;
|
||||||
oRunnerList::iterator it;
|
oRunnerList::iterator it;
|
||||||
|
|
||||||
//Find first free order
|
//Find first free order
|
||||||
for(it=Runners.begin(); it != Runners.end(); ++it){
|
for (it = Runners.begin(); it != Runners.end(); ++it) {
|
||||||
if (ClassId==0 || it->getClassId(false)==ClassId){
|
if (it->isRemoved())
|
||||||
|
continue;
|
||||||
|
if (ClassId == 0 || it->getClassId(false) == ClassId) {
|
||||||
it->synchronize();//Ensure we are up-to-date
|
it->synchronize();//Ensure we are up-to-date
|
||||||
order=max(order, it->StartNo);
|
order = max(order, it->StartNo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Assign orders
|
//Assign orders
|
||||||
for(it=Runners.begin(); it != Runners.end(); ++it){
|
for (it = Runners.begin(); it != Runners.end(); ++it) {
|
||||||
if (ClassId==0 || it->getClassId(false)==ClassId)
|
if (it->isRemoved())
|
||||||
if (it->StartNo==0){
|
continue;
|
||||||
it->StartNo=++order;
|
if (it->getClassRef(true) && it->getClassRef(true)->lockedForking())
|
||||||
it->updateChanged(); //Mark as changed.
|
continue;
|
||||||
it->synchronize(); //Sync!
|
if (ClassId == 0 || it->getClassId(false) == ClassId)
|
||||||
|
if (it->StartNo == 0) {
|
||||||
|
if (it->getTeam()) {
|
||||||
|
if (it->getTeam()->getStartNo() == 0) {
|
||||||
|
it->updateStartNo(++order);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it->setStartNo(it->getTeam()->getStartNo(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it->updateStartNo(++order);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4817,7 +4954,7 @@ void oEvent::calcUseStartSeconds()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const wstring &oEvent::formatStatus(RunnerStatus status)
|
const wstring &oEvent::formatStatus(RunnerStatus status, bool forPrint)
|
||||||
{
|
{
|
||||||
const static wstring stats[9]={L"?", L"Godkänd", L"Ej start", L"Felst.", L"Utg.", L"Disk.",
|
const static wstring stats[9]={L"?", L"Godkänd", L"Ej start", L"Felst.", L"Utg.", L"Disk.",
|
||||||
L"Maxtid", L"Deltar ej", L"Återbud[status]"};
|
L"Maxtid", L"Deltar ej", L"Återbud[status]"};
|
||||||
@ -4838,6 +4975,12 @@ const wstring &oEvent::formatStatus(RunnerStatus status)
|
|||||||
return lang.tl(stats[6]);
|
return lang.tl(stats[6]);
|
||||||
case StatusNotCompetiting:
|
case StatusNotCompetiting:
|
||||||
return lang.tl(stats[7]);
|
return lang.tl(stats[7]);
|
||||||
|
case StatusUnknown: {
|
||||||
|
if (forPrint)
|
||||||
|
return formatTime(-1);
|
||||||
|
else
|
||||||
|
return stats[0];
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return stats[0];
|
return stats[0];
|
||||||
}
|
}
|
||||||
@ -5081,8 +5224,8 @@ pClass oEvent::generateTestClass(int nlegs, int nrunners,
|
|||||||
setupRelay(*cls, PPatrol, 2, start);
|
setupRelay(*cls, PPatrol, 2, start);
|
||||||
int nCtrl=rand()%15+10;
|
int nCtrl=rand()%15+10;
|
||||||
pCourse pc=generateTestCourse(nCtrl);
|
pCourse pc=generateTestCourse(nCtrl);
|
||||||
cls->addStageCourse(0, pc->getId());
|
cls->addStageCourse(0, pc->getId(), -1);
|
||||||
cls->addStageCourse(1, pc->getId());
|
cls->addStageCourse(1, pc->getId(), -1);
|
||||||
}
|
}
|
||||||
else if (nlegs>1 && nrunners==2) {
|
else if (nlegs>1 && nrunners==2) {
|
||||||
setupRelay(*cls, PTwinRelay, nlegs, start);
|
setupRelay(*cls, PTwinRelay, nlegs, start);
|
||||||
@ -5093,7 +5236,7 @@ pClass oEvent::generateTestClass(int nlegs, int nrunners,
|
|||||||
|
|
||||||
for (int k=0;k<nlegs;k++)
|
for (int k=0;k<nlegs;k++)
|
||||||
for (int j=0;j<nlegs;j++)
|
for (int j=0;j<nlegs;j++)
|
||||||
cls->addStageCourse(k, cid[(k+j)%nlegs]);
|
cls->addStageCourse(k, cid[(k+j)%nlegs], -1);
|
||||||
}
|
}
|
||||||
else if (nlegs>1 && nrunners==nlegs) {
|
else if (nlegs>1 && nrunners==nlegs) {
|
||||||
setupRelay(*cls, PRelay, nlegs, start);
|
setupRelay(*cls, PRelay, nlegs, start);
|
||||||
@ -5104,12 +5247,12 @@ pClass oEvent::generateTestClass(int nlegs, int nrunners,
|
|||||||
|
|
||||||
for (int k=0;k<nlegs;k++)
|
for (int k=0;k<nlegs;k++)
|
||||||
for (int j=0;j<nlegs;j++)
|
for (int j=0;j<nlegs;j++)
|
||||||
cls->addStageCourse(k, cid[(k+j)%nlegs]);
|
cls->addStageCourse(k, cid[(k+j)%nlegs], -1);
|
||||||
}
|
}
|
||||||
else if (nlegs>1 && nrunners==1) {
|
else if (nlegs>1 && nrunners==1) {
|
||||||
setupRelay(*cls, PHunting, 2, start);
|
setupRelay(*cls, PHunting, 2, start);
|
||||||
cls->addStageCourse(0, generateTestCourse(rand()%8+10)->getId());
|
cls->addStageCourse(0, generateTestCourse(rand()%8+10)->getId(), -1);
|
||||||
cls->addStageCourse(1, generateTestCourse(rand()%8+10)->getId());
|
cls->addStageCourse(1, generateTestCourse(rand()%8+10)->getId(), -1);
|
||||||
}
|
}
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
@ -5256,7 +5399,7 @@ void oEvent::getFreeImporter(oFreeImport &fi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void oEvent::fillFees(gdioutput &gdi, const string &name, bool withAuto) const {
|
void oEvent::fillFees(gdioutput &gdi, const string &name, bool onlyDirect, bool withAuto) const {
|
||||||
gdi.clearList(name);
|
gdi.clearList(name);
|
||||||
|
|
||||||
set<int> fees;
|
set<int> fees;
|
||||||
@ -5265,6 +5408,8 @@ void oEvent::fillFees(gdioutput &gdi, const string &name, bool withAuto) const {
|
|||||||
for (oClassList::const_iterator it = Classes.begin(); it != Classes.end(); ++it) {
|
for (oClassList::const_iterator it = Classes.begin(); it != Classes.end(); ++it) {
|
||||||
if (it->isRemoved())
|
if (it->isRemoved())
|
||||||
continue;
|
continue;
|
||||||
|
if (onlyDirect && !it->getAllowQuickEntry())
|
||||||
|
continue;
|
||||||
|
|
||||||
f = it->getDCI().getInt("ClassFee");
|
f = it->getDCI().getInt("ClassFee");
|
||||||
if (f > 0)
|
if (f > 0)
|
||||||
@ -5285,18 +5430,21 @@ void oEvent::fillFees(gdioutput &gdi, const string &name, bool withAuto) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f = getDCI().getInt("EliteFee");
|
if (fees.empty()) {
|
||||||
if (f > 0)
|
if (!onlyDirect) {
|
||||||
fees.insert(f);
|
f = getDCI().getInt("EliteFee");
|
||||||
|
if (f > 0)
|
||||||
|
fees.insert(f);
|
||||||
|
}
|
||||||
|
|
||||||
f = getDCI().getInt("EntryFee");
|
f = getDCI().getInt("EntryFee");
|
||||||
if (f > 0)
|
if (f > 0)
|
||||||
fees.insert(f);
|
fees.insert(f);
|
||||||
|
|
||||||
f = getDCI().getInt("YouthFee");
|
|
||||||
if (f > 0)
|
|
||||||
fees.insert(f);
|
|
||||||
|
|
||||||
|
f = getDCI().getInt("YouthFee");
|
||||||
|
if (f > 0)
|
||||||
|
fees.insert(f);
|
||||||
|
}
|
||||||
vector< pair<wstring, size_t> > ff;
|
vector< pair<wstring, size_t> > ff;
|
||||||
if (withAuto)
|
if (withAuto)
|
||||||
ff.push_back(make_pair(lang.tl(L"Från klassen"), -1));
|
ff.push_back(make_pair(lang.tl(L"Från klassen"), -1));
|
||||||
|
|||||||
@ -351,7 +351,7 @@ protected:
|
|||||||
void updateFreeId();
|
void updateFreeId();
|
||||||
void updateFreeId(oBase *ob);
|
void updateFreeId(oBase *ob);
|
||||||
|
|
||||||
SortOrder CurrentSortOrder;
|
mutable SortOrder CurrentSortOrder;
|
||||||
|
|
||||||
list<CompetitionInfo> cinfo;
|
list<CompetitionInfo> cinfo;
|
||||||
list<BackupInfo> backupInfo;
|
list<BackupInfo> backupInfo;
|
||||||
@ -433,7 +433,7 @@ protected:
|
|||||||
void exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldStylePatrol);
|
void exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldStylePatrol);
|
||||||
|
|
||||||
/** Set up transient data in classes */
|
/** Set up transient data in classes */
|
||||||
void reinitializeClasses();
|
void reinitializeClasses() const;
|
||||||
|
|
||||||
/** Analyze the result status of each class*/
|
/** Analyze the result status of each class*/
|
||||||
void analyzeClassResultStatus() const;
|
void analyzeClassResultStatus() const;
|
||||||
@ -656,7 +656,7 @@ public:
|
|||||||
pTeam findTeam(const wstring &s, int lastId, unordered_set<int> &filter) const;
|
pTeam findTeam(const wstring &s, int lastId, unordered_set<int> &filter) const;
|
||||||
pRunner findRunner(const wstring &s, int lastId, const unordered_set<int> &inputFilter, unordered_set<int> &filter) const;
|
pRunner findRunner(const wstring &s, int lastId, const unordered_set<int> &inputFilter, unordered_set<int> &filter) const;
|
||||||
|
|
||||||
static const wstring &formatStatus(RunnerStatus status);
|
static const wstring &formatStatus(RunnerStatus status, bool forPrint);
|
||||||
|
|
||||||
inline bool useStartSeconds() const {return tUseStartSeconds;}
|
inline bool useStartSeconds() const {return tUseStartSeconds;}
|
||||||
void calcUseStartSeconds();
|
void calcUseStartSeconds();
|
||||||
@ -808,7 +808,14 @@ public:
|
|||||||
void getResultEvents(const set<int> &classFilter, const set<int> &controlFilter, vector<ResultEvent> &results) const;
|
void getResultEvents(const set<int> &classFilter, const set<int> &controlFilter, vector<ResultEvent> &results) const;
|
||||||
|
|
||||||
/** Compute results for split times while runners are on course.*/
|
/** Compute results for split times while runners are on course.*/
|
||||||
void computePreliminarySplitResults(const set<int> &classes);
|
void computePreliminarySplitResults(const set<int> &classes) const;
|
||||||
|
|
||||||
|
/** Synchronizes to server and checks if there are hired card data*/
|
||||||
|
bool hasHiredCardData();
|
||||||
|
bool isHiredCard(int cardNo) const;
|
||||||
|
void setHiredCard(int cardNo, bool flag);
|
||||||
|
vector<int> getHiredCards() const;
|
||||||
|
void clearHiredCards();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Returns hash key for punch based on control id, and leg. Class is marked as changed if oldHashKey != newHashKey.
|
// Returns hash key for punch based on control id, and leg. Class is marked as changed if oldHashKey != newHashKey.
|
||||||
@ -821,6 +828,9 @@ protected:
|
|||||||
mutable shared_ptr<unordered_multimap<int, pRunner>> cardToRunnerHash;
|
mutable shared_ptr<unordered_multimap<int, pRunner>> cardToRunnerHash;
|
||||||
unordered_multimap<int, pRunner> &getCardToRunner() const;
|
unordered_multimap<int, pRunner> &getCardToRunner() const;
|
||||||
|
|
||||||
|
mutable set<int> hiredCardHash;
|
||||||
|
mutable int tHiredCardHashDataRevision = -1;
|
||||||
|
|
||||||
int tClubDataRevision;
|
int tClubDataRevision;
|
||||||
int tCalcNumMapsDataRevision = -1;
|
int tCalcNumMapsDataRevision = -1;
|
||||||
|
|
||||||
@ -872,7 +882,7 @@ public:
|
|||||||
void removeFreePunch(int id);
|
void removeFreePunch(int id);
|
||||||
pFreePunch getPunch(int id) const;
|
pFreePunch getPunch(int id) const;
|
||||||
pFreePunch getPunch(int runnerId, int courseControlId, int card) const;
|
pFreePunch getPunch(int runnerId, int courseControlId, int card) const;
|
||||||
void getPunchesForRunner(int runnerId, vector<pFreePunch> &punches) const;
|
void getPunchesForRunner(int runnerId, bool sort, vector<pFreePunch> &punches) const;
|
||||||
|
|
||||||
//Returns true if data is changed.
|
//Returns true if data is changed.
|
||||||
bool autoSynchronizeLists(bool syncPunches);
|
bool autoSynchronizeLists(bool syncPunches);
|
||||||
@ -1011,8 +1021,8 @@ public:
|
|||||||
|
|
||||||
enum class ResultType {ClassResult, TotalResult, CourseResult,
|
enum class ResultType {ClassResult, TotalResult, CourseResult,
|
||||||
ClassCourseResult, PreliminarySplitResults};
|
ClassCourseResult, PreliminarySplitResults};
|
||||||
void calculateResults(const set<int> &classes, ResultType result, bool includePreliminary = false);
|
void calculateResults(const set<int> &classes, ResultType result, bool includePreliminary = false) const;
|
||||||
void calculateRogainingResults(const set<int> &classSelection);
|
void calculateRogainingResults(const set<int> &classSelection) const;
|
||||||
|
|
||||||
void calculateResults(list<oSpeakerObject> &rl);
|
void calculateResults(list<oSpeakerObject> &rl);
|
||||||
void calculateTeamResults(bool totalMultiday);
|
void calculateTeamResults(bool totalMultiday);
|
||||||
@ -1021,9 +1031,15 @@ public:
|
|||||||
void calculateTeamResultAtControl(const set<int> &classId, int leg, int controlId, bool totalResults);
|
void calculateTeamResultAtControl(const set<int> &classId, int leg, int controlId, bool totalResults);
|
||||||
|
|
||||||
bool sortRunners(SortOrder so);
|
bool sortRunners(SortOrder so);
|
||||||
|
|
||||||
|
bool sortRunners(SortOrder so, vector<const oRunner *> &runners) const;
|
||||||
|
|
||||||
/** If linear leg is true, leg is interpreted as actual leg numer, otherwise w.r.t to parallel legs. */
|
/** If linear leg is true, leg is interpreted as actual leg numer, otherwise w.r.t to parallel legs. */
|
||||||
bool sortTeams(SortOrder so, int leg, bool linearLeg);
|
bool sortTeams(SortOrder so, int leg, bool linearLeg);
|
||||||
|
|
||||||
|
bool sortTeams(SortOrder so, int leg, bool linearLeg, vector<const oTeam *> &teams) const;
|
||||||
|
|
||||||
|
|
||||||
pCard allocateCard(pRunner owner);
|
pCard allocateCard(pRunner owner);
|
||||||
|
|
||||||
/** Optimize the start order based on drawInfo. Result in cInfo */
|
/** Optimize the start order based on drawInfo. Result in cInfo */
|
||||||
@ -1153,7 +1169,7 @@ public:
|
|||||||
void updateClubsFromDB();
|
void updateClubsFromDB();
|
||||||
void updateRunnersFromDB();
|
void updateRunnersFromDB();
|
||||||
|
|
||||||
void fillFees(gdioutput &gdi, const string &name, bool withAuto) const;
|
void fillFees(gdioutput &gdi, const string &name, bool onlyDirect, bool withAuto) const;
|
||||||
wstring getAutoClassName() const;
|
wstring getAutoClassName() const;
|
||||||
pClass addClass(const wstring &pname, int CourseId = 0, int classId = 0);
|
pClass addClass(const wstring &pname, int CourseId = 0, int classId = 0);
|
||||||
pClass addClass(oClass &c);
|
pClass addClass(oClass &c);
|
||||||
@ -1214,6 +1230,7 @@ public:
|
|||||||
void calculateNumRemainingMaps(bool forceRecalculate);
|
void calculateNumRemainingMaps(bool forceRecalculate);
|
||||||
|
|
||||||
pControl getControl(int Id) const;
|
pControl getControl(int Id) const;
|
||||||
|
pControl getControlByType(int type) const;
|
||||||
pControl getControl(int Id, bool create);
|
pControl getControl(int Id, bool create);
|
||||||
enum ControlType {CTAll, CTRealControl, CTCourseControl};
|
enum ControlType {CTAll, CTRealControl, CTCourseControl};
|
||||||
|
|
||||||
|
|||||||
@ -938,12 +938,13 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
|||||||
throw std::exception("Det går endast att sätta in vakanser på sträcka 1.");
|
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()) {
|
if (size_t(spec[k].leg) < pc->legInfo.size()) {
|
||||||
pc->legInfo[spec[k].leg].startMethod = STDrawn; //Automatically change start method
|
pc->setStartType(spec[k].leg, STDrawn, true); //Automatically change start method
|
||||||
}
|
}
|
||||||
else if (spec[k].leg == -1) {
|
else if (spec[k].leg == -1) {
|
||||||
for (size_t j = 0; j < pc->legInfo.size(); j++)
|
for (size_t j = 0; j < pc->legInfo.size(); j++)
|
||||||
pc->legInfo[j].startMethod = STDrawn; //Automatically change start method
|
pc->setStartType(j, STDrawn, true); //Automatically change start method
|
||||||
}
|
}
|
||||||
|
pc->synchronize(true);
|
||||||
clsId2Ix[spec[k].classID] = k;
|
clsId2Ix[spec[k].classID] = k;
|
||||||
if (!multiDay && spec[k].leg == 0 && pc->getParentClass() == 0)
|
if (!multiDay && spec[k].leg == 0 && pc->getParentClass() == 0)
|
||||||
clsIdClearVac.insert(spec[k].classID);
|
clsIdClearVac.insert(spec[k].classID);
|
||||||
@ -1080,20 +1081,26 @@ void oEvent::drawList(const vector<ClassDrawSpecification> &spec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int minStartNo = Runners.size();
|
int minStartNo = Runners.size();
|
||||||
|
vector<pair<int, int>> newStartNo;
|
||||||
for(unsigned k=0;k<stimes.size(); k++) {
|
for(unsigned k=0;k<stimes.size(); k++) {
|
||||||
runners[k]->setStartTime(stimes[k], true, false, false);
|
runners[k]->setStartTime(stimes[k], true, false, false);
|
||||||
|
runners[k]->synchronize();
|
||||||
minStartNo = min(minStartNo, runners[k]->getStartNo());
|
minStartNo = min(minStartNo, runners[k]->getStartNo());
|
||||||
|
newStartNo.emplace_back(stimes[k], k);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentSortOrder = SortByStartTime;
|
sort(newStartNo.begin(), newStartNo.end());
|
||||||
sort(runners.begin(), runners.end());
|
//CurrentSortOrder = SortByStartTime;
|
||||||
|
//sort(runners.begin(), runners.end());
|
||||||
|
|
||||||
if (minStartNo == 0)
|
if (minStartNo == 0)
|
||||||
minStartNo = nextFreeStartNo + 1;
|
minStartNo = nextFreeStartNo + 1;
|
||||||
|
|
||||||
for(size_t k=0; k<runners.size(); k++) {
|
for(size_t k=0; k<runners.size(); k++) {
|
||||||
runners[k]->setStartNo(k+minStartNo, false);
|
pClass pCls = runners[k]->getClassRef(true);
|
||||||
runners[k]->synchronize();
|
if (pCls && pCls->lockedForking() || runners[k]->getLegNumber() > 0)
|
||||||
|
continue;
|
||||||
|
runners[k]->updateStartNo(newStartNo[k].second + minStartNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
nextFreeStartNo = max<int>(nextFreeStartNo, minStartNo + stimes.size());
|
nextFreeStartNo = max<int>(nextFreeStartNo, minStartNo + stimes.size());
|
||||||
|
|||||||
@ -41,8 +41,7 @@
|
|||||||
#include "listeditor.h"
|
#include "listeditor.h"
|
||||||
|
|
||||||
|
|
||||||
void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo)
|
void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo) {
|
||||||
{
|
|
||||||
oRunnerList::iterator it;
|
oRunnerList::iterator it;
|
||||||
|
|
||||||
for (it=Runners.begin(); it!=Runners.end(); ++it) {
|
for (it=Runners.begin(); it!=Runners.end(); ++it) {
|
||||||
@ -98,14 +97,14 @@ void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo)
|
|||||||
|
|
||||||
cTime=it->tempRT;
|
cTime=it->tempRT;
|
||||||
|
|
||||||
it->tPlace=vPlace;
|
it->tPlace.update(*this, vPlace); // XXX User other result container
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
it->tPlace=99000+it->tStatus;
|
it->tPlace.update(*this, 99000+it->tStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bool includePreliminary) {
|
void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bool includePreliminary) const {
|
||||||
if (resultType == ResultType::PreliminarySplitResults) {
|
if (resultType == ResultType::PreliminarySplitResults) {
|
||||||
computePreliminarySplitResults(classes);
|
computePreliminarySplitResults(classes);
|
||||||
return;
|
return;
|
||||||
@ -114,14 +113,26 @@ void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bo
|
|||||||
const bool courseResults = resultType == ResultType::CourseResult;
|
const bool courseResults = resultType == ResultType::CourseResult;
|
||||||
const bool classCourseResults = resultType == ResultType::ClassCourseResult;
|
const bool classCourseResults = resultType == ResultType::ClassCourseResult;
|
||||||
|
|
||||||
|
bool all = classes.empty();
|
||||||
|
vector<const oRunner *> runners;
|
||||||
|
runners.reserve(Runners.size());
|
||||||
|
for (auto &r : Runners) {
|
||||||
|
if (r.isRemoved())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!all && !classes.count(r.getClassId(true)))
|
||||||
|
continue;
|
||||||
|
runners.push_back(&r);
|
||||||
|
}
|
||||||
|
|
||||||
if (classCourseResults)
|
if (classCourseResults)
|
||||||
sortRunners(ClassCourseResult);
|
sortRunners(ClassCourseResult, runners);
|
||||||
else if (courseResults)
|
else if (courseResults)
|
||||||
sortRunners(CourseResult);
|
sortRunners(CourseResult, runners);
|
||||||
else if (!totalResults)
|
else if (!totalResults)
|
||||||
sortRunners(ClassResult);
|
sortRunners(ClassResult, runners);
|
||||||
else
|
else
|
||||||
sortRunners(ClassTotalResult);
|
sortRunners(ClassTotalResult, runners);
|
||||||
|
|
||||||
oRunnerList::iterator it;
|
oRunnerList::iterator it;
|
||||||
|
|
||||||
@ -133,9 +144,8 @@ void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bo
|
|||||||
int cLegEquClass = 0;
|
int cLegEquClass = 0;
|
||||||
bool invalidClass = false;
|
bool invalidClass = false;
|
||||||
bool useResults = false;
|
bool useResults = false;
|
||||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
for (auto it : runners) {
|
||||||
if (it->isRemoved())
|
|
||||||
continue;
|
|
||||||
// Start new "class"
|
// Start new "class"
|
||||||
if (classCourseResults) {
|
if (classCourseResults) {
|
||||||
const pCourse crs = it->getCourse(false);
|
const pCourse crs = it->getCourse(false);
|
||||||
@ -175,7 +185,7 @@ void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bo
|
|||||||
// Calculate results
|
// Calculate results
|
||||||
if (invalidClass) {
|
if (invalidClass) {
|
||||||
it->tTotalPlace = 0;
|
it->tTotalPlace = 0;
|
||||||
it->tPlace = 0;
|
it->tPlace.update(*this, 0);
|
||||||
}
|
}
|
||||||
else if (!totalResults) {
|
else if (!totalResults) {
|
||||||
int tPlace = 0;
|
int tPlace = 0;
|
||||||
@ -197,7 +207,7 @@ void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bo
|
|||||||
tPlace = 99000 + it->tStatus;
|
tPlace = 99000 + it->tStatus;
|
||||||
|
|
||||||
if (!classCourseResults)
|
if (!classCourseResults)
|
||||||
it->tPlace = tPlace;
|
it->tPlace.update(*this, tPlace);
|
||||||
else
|
else
|
||||||
it->tCoursePlace = tPlace;
|
it->tCoursePlace = tPlace;
|
||||||
}
|
}
|
||||||
@ -224,10 +234,22 @@ void oEvent::calculateResults(const set<int> &classes, ResultType resultType, bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::calculateRogainingResults(const set<int> &classSelection) {
|
void oEvent::calculateRogainingResults(const set<int> &classSelection) const {
|
||||||
const bool all = classSelection.empty();
|
const bool all = classSelection.empty();
|
||||||
sortRunners(ClassPoints);
|
vector<const oRunner *> runners;
|
||||||
oRunnerList::iterator it;
|
runners.reserve(Runners.size());
|
||||||
|
for (auto &r : Runners) {
|
||||||
|
if (r.isRemoved())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!all && !classSelection.count(r.getClassId(true)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (r.Class && r.Class->isRogaining()) {
|
||||||
|
runners.push_back(&r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sortRunners(ClassPoints, runners);
|
||||||
|
|
||||||
int cClassId=-1;
|
int cClassId=-1;
|
||||||
int cPlace = 0;
|
int cPlace = 0;
|
||||||
@ -238,13 +260,7 @@ void oEvent::calculateRogainingResults(const set<int> &classSelection) {
|
|||||||
bool isRogaining = false;
|
bool isRogaining = false;
|
||||||
bool invalidClass = false;
|
bool invalidClass = false;
|
||||||
|
|
||||||
for (it=Runners.begin(); it != Runners.end(); ++it) {
|
for (auto it : runners) {
|
||||||
if (it->isRemoved())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!all && !classSelection.count(it->getClassId(false)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (it->getClassId(true)!=cClassId || it->tDuplicateLeg!=cDuplicateLeg) {
|
if (it->getClassId(true)!=cClassId || it->tDuplicateLeg!=cDuplicateLeg) {
|
||||||
cClassId = it->getClassId(true);
|
cClassId = it->getClassId(true);
|
||||||
useResults = it->Class ? !it->Class->getNoTiming() : false;
|
useResults = it->Class ? !it->Class->getNoTiming() : false;
|
||||||
@ -252,16 +268,12 @@ void oEvent::calculateRogainingResults(const set<int> &classSelection) {
|
|||||||
vPlace = 0;
|
vPlace = 0;
|
||||||
cTime = numeric_limits<int>::min();
|
cTime = numeric_limits<int>::min();
|
||||||
cDuplicateLeg = it->tDuplicateLeg;
|
cDuplicateLeg = it->tDuplicateLeg;
|
||||||
isRogaining = it->Class ? it->Class->isRogaining() : false;
|
|
||||||
invalidClass = it->Class ? it->Class->getClassStatus() != oClass::Normal : false;
|
invalidClass = it->Class ? it->Class->getClassStatus() != oClass::Normal : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isRogaining)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (invalidClass) {
|
if (invalidClass) {
|
||||||
it->tTotalPlace = 0;
|
it->tTotalPlace = 0;
|
||||||
it->tPlace = 0;
|
it->tPlace.update(*this, 0);
|
||||||
}
|
}
|
||||||
else if (it->tStatus==StatusOK) {
|
else if (it->tStatus==StatusOK) {
|
||||||
cPlace++;
|
cPlace++;
|
||||||
@ -274,12 +286,12 @@ void oEvent::calculateRogainingResults(const set<int> &classSelection) {
|
|||||||
cTime = cmpRes;
|
cTime = cmpRes;
|
||||||
|
|
||||||
if (useResults)
|
if (useResults)
|
||||||
it->tPlace = vPlace;
|
it->tPlace.update(*this, vPlace);
|
||||||
else
|
else
|
||||||
it->tPlace = 0;
|
it->tPlace.update(*this, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
it->tPlace = 99000 + it->tStatus;
|
it->tPlace.update(*this, 99000 + it->tStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,9 +615,9 @@ void oEvent::calculateTeamResultAtControl(const set<int> &classId, int leg, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
void oEvent::computePreliminarySplitResults(const set<int> &classes) const {
|
||||||
bool allClasses = classes.empty();
|
bool allClasses = classes.empty();
|
||||||
map<pair<int, int>, vector<pRunner>> runnerByClassLeg;
|
map<pair<int, int>, vector<const oRunner *>> runnerByClassLeg;
|
||||||
for (auto &r : Runners) {
|
for (auto &r : Runners) {
|
||||||
r.tOnCourseResults.clear();
|
r.tOnCourseResults.clear();
|
||||||
r.currentControlTime.first = 1;
|
r.currentControlTime.first = 1;
|
||||||
@ -637,11 +649,14 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
|||||||
|
|
||||||
map<pair<int, int>, set<int>> classLeg2ExistingCCId;
|
map<pair<int, int>, set<int>> classLeg2ExistingCCId;
|
||||||
for (auto &p : punches) {
|
for (auto &p : punches) {
|
||||||
if (p.isRemoved())
|
if (p.isRemoved() || p.isHiredCard())
|
||||||
continue;
|
continue;
|
||||||
pRunner r = p.getTiedRunner();
|
pRunner r = p.getTiedRunner();
|
||||||
if (!r)
|
if (!r)
|
||||||
continue;
|
continue;
|
||||||
|
if (!p.isCheck() && r->getCourse(false) == nullptr)
|
||||||
|
r->tOnCourseResults.hasAnyRes = true; // Register all punches for runners without course
|
||||||
|
|
||||||
pClass cls = r->getClassRef(false);
|
pClass cls = r->getClassRef(false);
|
||||||
if (r->getCourse(false) && cls) {
|
if (r->getCourse(false) && cls) {
|
||||||
int ccId = p.getCourseControlId();
|
int ccId = p.getCourseControlId();
|
||||||
@ -669,7 +684,7 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
|||||||
|
|
||||||
const set<int> &expectedCCid = classLeg2ExistingCCId[make_pair(clsId, leg)];
|
const set<int> &expectedCCid = classLeg2ExistingCCId[make_pair(clsId, leg)];
|
||||||
size_t nRT = 0;
|
size_t nRT = 0;
|
||||||
for (auto &radioTimes : r.tOnCourseResults) {
|
for (auto &radioTimes : r.tOnCourseResults.res) {
|
||||||
if (expectedCCid.count(radioTimes.courseControlId))
|
if (expectedCCid.count(radioTimes.courseControlId))
|
||||||
nRT++;
|
nRT++;
|
||||||
}
|
}
|
||||||
@ -681,7 +696,7 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
|||||||
int ccId = crs->getCourseControlId(p.tIndex);
|
int ccId = crs->getCourseControlId(p.tIndex);
|
||||||
if (expectedCCid.count(ccId)) {
|
if (expectedCCid.count(ccId)) {
|
||||||
bool added = false;
|
bool added = false;
|
||||||
for (auto &stored : r.tOnCourseResults) {
|
for (auto &stored : r.tOnCourseResults.res) {
|
||||||
if (stored.courseControlId == ccId) {
|
if (stored.courseControlId == ccId) {
|
||||||
added = true;
|
added = true;
|
||||||
break;
|
break;
|
||||||
@ -714,7 +729,7 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
|||||||
if (ccId == oPunch::PunchFinish) {
|
if (ccId == oPunch::PunchFinish) {
|
||||||
negLeg = -1000; //Finish, smallest number
|
negLeg = -1000; //Finish, smallest number
|
||||||
for (int j = 0; j < nRun; j++) {
|
for (int j = 0; j < nRun; j++) {
|
||||||
pRunner r = rr[j];
|
auto r = rr[j];
|
||||||
if (r->prelStatusOK()) {
|
if (r->prelStatusOK()) {
|
||||||
int time;
|
int time;
|
||||||
if (!r->tInTeam || !totRes)
|
if (!r->tInTeam || !totRes)
|
||||||
@ -723,15 +738,15 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
|||||||
time = r->tInTeam->getLegRunningTime(r->tLeg, false);
|
time = r->tInTeam->getLegRunningTime(r->tLeg, false);
|
||||||
}
|
}
|
||||||
int ix = -1;
|
int ix = -1;
|
||||||
int nr = r->tOnCourseResults.size();
|
int nr = r->tOnCourseResults.res.size();
|
||||||
for (int i = 0; i < nr; i++) {
|
for (int i = 0; i < nr; i++) {
|
||||||
if (r->tOnCourseResults[i].courseControlId == ccId) {
|
if (r->tOnCourseResults.res[i].courseControlId == ccId) {
|
||||||
ix = i;
|
ix = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ix == -1) {
|
if (ix == -1) {
|
||||||
ix = r->tOnCourseResults.size();
|
ix = r->tOnCourseResults.res.size();
|
||||||
int nc = 0;
|
int nc = 0;
|
||||||
pCourse crs = r->getCourse(false);
|
pCourse crs = r->getCourse(false);
|
||||||
if (crs)
|
if (crs)
|
||||||
@ -744,12 +759,12 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int j = 0; j < nRun; j++) {
|
for (int j = 0; j < nRun; j++) {
|
||||||
pRunner r = rr[j];
|
auto r = rr[j];
|
||||||
int nr = r->tOnCourseResults.size();
|
int nr = r->tOnCourseResults.res.size();
|
||||||
for (int i = 0; i < nr; i++) {
|
for (int i = 0; i < nr; i++) {
|
||||||
if (r->tOnCourseResults[i].courseControlId == ccId) {
|
if (r->tOnCourseResults.res[i].courseControlId == ccId) {
|
||||||
timeRunnerIx.emplace_back(r->tOnCourseResults[i].time, j, i);
|
timeRunnerIx.emplace_back(r->tOnCourseResults.res[i].time, j, i);
|
||||||
negLeg = min(negLeg, -r->tOnCourseResults[i].controlIx);
|
negLeg = min(negLeg, -r->tOnCourseResults.res[i].controlIx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,10 +784,10 @@ void oEvent::computePreliminarySplitResults(const set<int> &classes) {
|
|||||||
if (leadTime == 0)
|
if (leadTime == 0)
|
||||||
leadTime = time;
|
leadTime = time;
|
||||||
}
|
}
|
||||||
pRunner r = rr[get<1>(timeRunnerIx[i])];
|
auto r = rr[get<1>(timeRunnerIx[i])];
|
||||||
int locIx = get<2>(timeRunnerIx[i]);
|
int locIx = get<2>(timeRunnerIx[i]);
|
||||||
r->tOnCourseResults[locIx].place = place;
|
r->tOnCourseResults.res[locIx].place = place;
|
||||||
r->tOnCourseResults[locIx].after = time - leadTime;
|
r->tOnCourseResults.res[locIx].after = time - leadTime;
|
||||||
|
|
||||||
int &legWithTimeIndexNeg = r->currentControlTime.first;
|
int &legWithTimeIndexNeg = r->currentControlTime.first;
|
||||||
if (negLeg < legWithTimeIndexNeg) {
|
if (negLeg < legWithTimeIndexNeg) {
|
||||||
|
|||||||
@ -344,7 +344,7 @@ void renderRowSpeakerList(const oSpeakerObject &r, const oSpeakerObject *next_r,
|
|||||||
if (r.finishStatus<=1 || r.finishStatus==r.status)
|
if (r.finishStatus<=1 || r.finishStatus==r.status)
|
||||||
row.push_back(SpeakerString(normalText, names));
|
row.push_back(SpeakerString(normalText, names));
|
||||||
else
|
else
|
||||||
row.push_back(SpeakerString(normalText, names + L" ("+ oEvent::formatStatus(r.finishStatus) +L")"));
|
row.push_back(SpeakerString(normalText, names + L" ("+ oEvent::formatStatus(r.finishStatus, true) +L")"));
|
||||||
|
|
||||||
row.push_back(SpeakerString(normalText, r.club));
|
row.push_back(SpeakerString(normalText, r.club));
|
||||||
|
|
||||||
@ -410,7 +410,7 @@ void renderRowSpeakerList(const oSpeakerObject &r, const oSpeakerObject *next_r,
|
|||||||
else{
|
else{
|
||||||
//gdi.addStringUT(y, x+dx[4], textRight, oEvent::formatStatus(r.status)).setColor(colorDarkRed);
|
//gdi.addStringUT(y, x+dx[4], textRight, oEvent::formatStatus(r.status)).setColor(colorDarkRed);
|
||||||
row.push_back(SpeakerString());
|
row.push_back(SpeakerString());
|
||||||
row.push_back(SpeakerString(textRight, oEvent::formatStatus(r.status)));
|
row.push_back(SpeakerString(textRight, oEvent::formatStatus(r.status, true)));
|
||||||
row.back().color = colorDarkRed;
|
row.back().color = colorDarkRed;
|
||||||
row.push_back(SpeakerString());
|
row.push_back(SpeakerString());
|
||||||
}
|
}
|
||||||
@ -1742,7 +1742,7 @@ void oEvent::getResultEvents(const set<int> &classFilter, const set<int> &punchF
|
|||||||
|
|
||||||
for (oFreePunchList::const_iterator it = punches.begin(); it != punches.end(); ++it) {
|
for (oFreePunchList::const_iterator it = punches.begin(); it != punches.end(); ++it) {
|
||||||
const oFreePunch &fp = *it;
|
const oFreePunch &fp = *it;
|
||||||
if (fp.isRemoved() || fp.tRunnerId == 0 || fp.Type == oPunch::PunchCheck || fp.Type == oPunch::PunchStart)
|
if (fp.isRemoved() || fp.tRunnerId == 0 || fp.Type == oPunch::PunchCheck || fp.Type == oPunch::PunchStart || fp.Type == oPunch::HiredCard)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pRunner r = getRunner(fp.tRunnerId, 0);
|
pRunner r = getRunner(fp.tRunnerId, 0);
|
||||||
|
|||||||
@ -178,7 +178,7 @@ void oEvent::generatePunchTableData(Table &table, oFreePunch *addPunch)
|
|||||||
oFreePunchList::iterator it;
|
oFreePunchList::iterator it;
|
||||||
table.reserve(punches.size());
|
table.reserve(punches.size());
|
||||||
for (it = punches.begin(); it != punches.end(); ++it){
|
for (it = punches.begin(); it != punches.end(); ++it){
|
||||||
if (!it->isRemoved()){
|
if (!it->isRemoved() && !it->isHiredCard()){
|
||||||
it->addTableRow(table);
|
it->addTableRow(table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,7 +292,7 @@ void oFreePunch::rehashPunches(oEvent &oe, int cardNo, pFreePunch newPunch) {
|
|||||||
// Rehash all punches. Ignore cardNo and newPunch (will be included automatically)
|
// Rehash all punches. Ignore cardNo and newPunch (will be included automatically)
|
||||||
fp.reserve(oe.punches.size());
|
fp.reserve(oe.punches.size());
|
||||||
for (oFreePunchList::iterator pit = oe.punches.begin(); pit != oe.punches.end(); ++pit) {
|
for (oFreePunchList::iterator pit = oe.punches.begin(); pit != oe.punches.end(); ++pit) {
|
||||||
if (pit->isRemoved())
|
if (pit->isRemoved() || pit->isHiredCard())
|
||||||
continue;
|
continue;
|
||||||
fp.push_back(&(*pit));
|
fp.push_back(&(*pit));
|
||||||
}
|
}
|
||||||
@ -335,7 +335,7 @@ void oFreePunch::rehashPunches(oEvent &oe, int cardNo, pFreePunch newPunch) {
|
|||||||
it->second.erase(res.first, res.second);
|
it->second.erase(res.first, res.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPunch)
|
if (newPunch && !newPunch->isHiredCard())
|
||||||
fp.push_back(newPunch);
|
fp.push_back(newPunch);
|
||||||
|
|
||||||
sort(fp.begin(), fp.end(), FreePunchComp());
|
sort(fp.begin(), fp.end(), FreePunchComp());
|
||||||
@ -614,12 +614,12 @@ pFreePunch oEvent::getPunch(int runnerId, int courseControlId, int card) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::getPunchesForRunner(int runnerId, vector<pFreePunch> &runnerPunches) const {
|
void oEvent::getPunchesForRunner(int runnerId, bool doSort, vector<pFreePunch> &runnerPunches) const {
|
||||||
runnerPunches.clear();
|
runnerPunches.clear();
|
||||||
pRunner r = getRunner(runnerId, 0);
|
pRunner r = getRunner(runnerId, 0);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return;
|
return;
|
||||||
|
/*
|
||||||
// Get times for when other runners used this card
|
// Get times for when other runners used this card
|
||||||
vector< pair<int, int> > times;
|
vector< pair<int, int> > times;
|
||||||
int refCno = r->getCardNo();
|
int refCno = r->getCardNo();
|
||||||
@ -641,6 +641,9 @@ void oEvent::getPunchesForRunner(int runnerId, vector<pFreePunch> &runnerPunches
|
|||||||
|
|
||||||
for (oFreePunchList::const_iterator it = punches.begin(); it != punches.end(); ++it) {
|
for (oFreePunchList::const_iterator it = punches.begin(); it != punches.end(); ++it) {
|
||||||
if (it->CardNo == refCno) {
|
if (it->CardNo == refCno) {
|
||||||
|
if (it->isRemoved() || it->isHiredCard())
|
||||||
|
continue;
|
||||||
|
|
||||||
bool other = false;
|
bool other = false;
|
||||||
int t = it->Time;
|
int t = it->Time;
|
||||||
for (size_t k = 0; k<times.size(); k++) {
|
for (size_t k = 0; k<times.size(); k++) {
|
||||||
@ -652,8 +655,33 @@ void oEvent::getPunchesForRunner(int runnerId, vector<pFreePunch> &runnerPunches
|
|||||||
runnerPunches.push_back(pFreePunch(&*it));
|
runnerPunches.push_back(pFreePunch(&*it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// XXX Advance punches...
|
//Lazy setup
|
||||||
|
oFreePunch::rehashPunches(*oe, 0, 0);
|
||||||
|
|
||||||
|
int card = r->getCardNo();
|
||||||
|
if (card == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto &it1 :punchIndex) {
|
||||||
|
const oEvent::PunchIndexType &cIndex = it1.second;
|
||||||
|
pair<oEvent::PunchConstIterator, oEvent::PunchConstIterator> res = cIndex.equal_range(card);
|
||||||
|
oEvent::PunchConstIterator pIter = res.first;
|
||||||
|
while (pIter != res.second) {
|
||||||
|
pFreePunch punch = pIter->second;
|
||||||
|
if (!punch->isRemoved()) {
|
||||||
|
assert(punch && punch->CardNo == card);
|
||||||
|
if (punch->tRunnerId == runnerId || runnerId == 0)
|
||||||
|
runnerPunches.push_back(punch);
|
||||||
|
++pIter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doSort) {
|
||||||
|
sort(runnerPunches.begin(), runnerPunches.end(), [](const oPunch *p1, const oPunch *p2)->bool {return p1->Time < p2->Time; });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -732,3 +760,75 @@ void oFreePunch::changedObject() {
|
|||||||
if (r && tMatchControlId>0)
|
if (r && tMatchControlId>0)
|
||||||
r->markClassChanged(tMatchControlId);
|
r->markClassChanged(tMatchControlId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool oEvent::hasHiredCardData() {
|
||||||
|
synchronizeList(oListId::oLPunchId);
|
||||||
|
isHiredCard(0);
|
||||||
|
return !hiredCardHash.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool oEvent::isHiredCard(int cardNo) const {
|
||||||
|
if (tHiredCardHashDataRevision != dataRevision) {
|
||||||
|
hiredCardHash.clear();
|
||||||
|
for (auto &p : punches) {
|
||||||
|
if (!p.isRemoved() && p.isHiredCard())
|
||||||
|
hiredCardHash.insert(p.getCardNo());
|
||||||
|
}
|
||||||
|
tHiredCardHashDataRevision = dataRevision;
|
||||||
|
}
|
||||||
|
return hiredCardHash.count(cardNo) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void oEvent::setHiredCard(int cardNo, bool flag) {
|
||||||
|
if (cardNo <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isHiredCard(cardNo) != flag) {
|
||||||
|
if (flag) {
|
||||||
|
addFreePunch(0, oPunch::HiredCard, cardNo, false);
|
||||||
|
hiredCardHash.insert(cardNo);
|
||||||
|
tHiredCardHashDataRevision = dataRevision;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hiredCardHash.erase(cardNo);
|
||||||
|
for (auto it = punches.begin(); it != punches.end();) {
|
||||||
|
if (!it->isRemoved() && it->isHiredCard() && it->CardNo == cardNo) {
|
||||||
|
if (HasDBConnection)
|
||||||
|
msRemove(&*it);
|
||||||
|
|
||||||
|
auto toErase = it;
|
||||||
|
++it;
|
||||||
|
punches.erase(toErase);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tHiredCardHashDataRevision = dataRevision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<int> oEvent::getHiredCards() const {
|
||||||
|
isHiredCard(0); // Update hash
|
||||||
|
vector<int> r(hiredCardHash.begin(), hiredCardHash.end());
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void oEvent::clearHiredCards() {
|
||||||
|
vector<int> toRemove;
|
||||||
|
for (auto it = punches.begin(); it != punches.end();) {
|
||||||
|
if (!it->isRemoved() && it->isHiredCard()) {
|
||||||
|
if (HasDBConnection)
|
||||||
|
msRemove(&*it);
|
||||||
|
|
||||||
|
auto toErase = it;
|
||||||
|
++it;
|
||||||
|
punches.erase(toErase);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hiredCardHash.clear();
|
||||||
|
}
|
||||||
|
|||||||
@ -118,7 +118,7 @@ bool oEvent::exportOECSV(const wchar_t *file, int languageTypeIndex, bool includ
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
calculateResults({}, ResultType::ClassResult);
|
calculateResults({}, ResultType::ClassResult);
|
||||||
|
sortRunners(SortOrder::ClassResult);
|
||||||
oRunnerList::iterator it;
|
oRunnerList::iterator it;
|
||||||
string maleString;
|
string maleString;
|
||||||
string femaleString;
|
string femaleString;
|
||||||
@ -269,7 +269,7 @@ bool oEvent::exportOECSV(const wchar_t *file, int languageTypeIndex, bool includ
|
|||||||
// Extra punches
|
// Extra punches
|
||||||
vector<pFreePunch> punches;
|
vector<pFreePunch> punches;
|
||||||
|
|
||||||
oe->getPunchesForRunner(it->getId(), punches);
|
oe->getPunchesForRunner(it->getId(), true, punches);
|
||||||
for (vector<pFreePunch>::iterator punchIt = punches.begin(); punchIt != punches.end(); ++punchIt) {
|
for (vector<pFreePunch>::iterator punchIt = punches.begin(); punchIt != punches.end(); ++punchIt) {
|
||||||
pPunch punch = *punchIt;
|
pPunch punch = *punchIt;
|
||||||
if (!punch->isUsed && !(punch->isFinish() && !pc->useLastAsFinish()) && !(punch->isStart() && !pc->useFirstAsStart()) && !punch->isCheck())
|
if (!punch->isUsed && !(punch->isFinish() && !pc->useLastAsFinish()) && !(punch->isStart() && !pc->useFirstAsStart()) && !punch->isCheck())
|
||||||
@ -321,6 +321,10 @@ void oEvent::importXML_EntryData(gdioutput &gdi, const wstring &file,
|
|||||||
IOF30Interface reader(this, false);
|
IOF30Interface reader(this, false);
|
||||||
reader.setPreferredIdType(preferredIdType);
|
reader.setPreferredIdType(preferredIdType);
|
||||||
reader.readEntryList(gdi, xo, removeNonexisting, filter, ent, fail, removed);
|
reader.readEntryList(gdi, xo, removeNonexisting, filter, ent, fail, removed);
|
||||||
|
|
||||||
|
for (auto &c : Clubs) {
|
||||||
|
c.updateFromDB();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
xmlList xl;
|
xmlList xl;
|
||||||
@ -604,6 +608,24 @@ void oEvent::importXML_EntryData(gdioutput &gdi, const wstring &file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xo = xml.getObject("ServiceRequestList");
|
||||||
|
|
||||||
|
if (xo) {
|
||||||
|
gdi.addString("", 0, "Importerar tävlingsdata (IOF, xml)");
|
||||||
|
gdi.refreshFast();
|
||||||
|
|
||||||
|
if (xo.getAttrib("iofVersion")) {
|
||||||
|
IOF30Interface reader(this, false);
|
||||||
|
int imp = 0, fail = 0;
|
||||||
|
|
||||||
|
reader.readServiceRequestList(gdi, xo, imp, fail);
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.refreshFast();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
vector<int> toRemove;
|
vector<int> toRemove;
|
||||||
for (size_t k = 0; k < runnersInTeam.size(); k++) {
|
for (size_t k = 0; k < runnersInTeam.size(); k++) {
|
||||||
int id = runnersInTeam[k].first;
|
int id = runnersInTeam[k].first;
|
||||||
@ -1194,7 +1216,7 @@ void oEvent::importXML_IOF_Data(const wstring &clubfile,
|
|||||||
xmlparser xml_club;
|
xmlparser xml_club;
|
||||||
xml_club.setProgress(gdibase.getHWNDTarget());
|
xml_club.setProgress(gdibase.getHWNDTarget());
|
||||||
|
|
||||||
if (clear)
|
if (clear && !competitorfile.empty())
|
||||||
runnerDB->clearClubs();
|
runnerDB->clearClubs();
|
||||||
|
|
||||||
gdibase.addString("",0,"Läser klubbar...");
|
gdibase.addString("",0,"Läser klubbar...");
|
||||||
@ -1567,17 +1589,17 @@ bool oEvent::addXMLCourse(const xmlobject &xcrs, bool addClasses, set<wstring> &
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (size_t i = 0; i<pCls->getNumStages(); i++)
|
for (size_t i = 0; i<pCls->getNumStages(); i++)
|
||||||
pCls->addStageCourse(i, courses[0]->getId());
|
pCls->addStageCourse(i, courses[0]->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (courses.size() == pCls->getNumStages()) {
|
if (courses.size() == pCls->getNumStages()) {
|
||||||
for (size_t i = 0; i<courses.size(); i++)
|
for (size_t i = 0; i<courses.size(); i++)
|
||||||
pCls->addStageCourse(i, courses[i]->getId());
|
pCls->addStageCourse(i, courses[i]->getId(), -1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (size_t i = 0; i<courses.size(); i++)
|
for (size_t i = 0; i<courses.size(); i++)
|
||||||
pCls->addStageCourse(0, courses[i]->getId());
|
pCls->addStageCourse(0, courses[i]->getId(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2605,6 +2627,9 @@ void oEvent::exportIOFSplits(IOFVersion version, const wchar_t *file,
|
|||||||
calculateResults(set<int>(), ResultType::ClassResult);
|
calculateResults(set<int>(), ResultType::ClassResult);
|
||||||
calculateTeamResults(true);
|
calculateTeamResults(true);
|
||||||
calculateTeamResults(false);
|
calculateTeamResults(false);
|
||||||
|
sortRunners(SortOrder::ClassResult);
|
||||||
|
sortTeams(SortOrder::ClassResult, -1, false);
|
||||||
|
|
||||||
set<int> rgClasses;
|
set<int> rgClasses;
|
||||||
for (int clz : classes) {
|
for (int clz : classes) {
|
||||||
pClass pc = getClass(clz);
|
pClass pc = getClass(clz);
|
||||||
|
|||||||
@ -645,7 +645,7 @@ const wstring &oEvent::formatPunchStringAux(const oPrintPost &pp, const oListPar
|
|||||||
else {
|
else {
|
||||||
pControl ctrl = getControl(punch->getControlId());
|
pControl ctrl = getControl(punch->getControlId());
|
||||||
if (!ctrl)
|
if (!ctrl)
|
||||||
ctrl = getControl(punch->Type);
|
ctrl = getControlByType(punch->Type);
|
||||||
|
|
||||||
if (ctrl && ctrl->hasName()) {
|
if (ctrl && ctrl->hasName()) {
|
||||||
swprintf_s(bfw, L"%s", ctrl->getName().c_str());
|
swprintf_s(bfw, L"%s", ctrl->getName().c_str());
|
||||||
@ -654,7 +654,7 @@ const wstring &oEvent::formatPunchStringAux(const oPrintPost &pp, const oListPar
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case lPunchTimeSinceLast:
|
case lPunchTimeSinceLast:
|
||||||
if (punch && punch->previousPunchTime && r && r->Card && !invalidClass) {
|
if (punch && punch->previousPunchTime && r && !invalidClass) {
|
||||||
int time = punch->Time;
|
int time = punch->Time;
|
||||||
int pTime = punch->previousPunchTime;
|
int pTime = punch->previousPunchTime;
|
||||||
if (pTime > 0 && time > pTime) {
|
if (pTime > 0 && time > pTime) {
|
||||||
@ -673,7 +673,7 @@ const wstring &oEvent::formatPunchStringAux(const oPrintPost &pp, const oListPar
|
|||||||
case lPunchSplitTime:
|
case lPunchSplitTime:
|
||||||
case lPunchTotalTime:
|
case lPunchTotalTime:
|
||||||
case lPunchAbsTime:
|
case lPunchAbsTime:
|
||||||
if (punch && r && r->Card && !invalidClass) {
|
if (punch && r && !invalidClass) {
|
||||||
if (punch->tIndex >= 0) {
|
if (punch->tIndex >= 0) {
|
||||||
// Punch in course
|
// Punch in course
|
||||||
counter.level3 = punch->tIndex;
|
counter.level3 = punch->tIndex;
|
||||||
@ -1074,6 +1074,23 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter);
|
return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case lClassAvailableMaps:
|
||||||
|
if (pc) {
|
||||||
|
int n = pc->getNumRemainingMaps(false);
|
||||||
|
if (n != numeric_limits<int>::min())
|
||||||
|
wsptr = &itow(n);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case lClassTotalMaps:
|
||||||
|
if (pc) {
|
||||||
|
int n = pc->getNumberMaps();
|
||||||
|
if (n > 0)
|
||||||
|
wsptr = &itow(n);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case lCourseClimb:
|
case lCourseClimb:
|
||||||
if (r) {
|
if (r) {
|
||||||
pCourse crs = r->getCourse(false);
|
pCourse crs = r->getCourse(false);
|
||||||
@ -1119,7 +1136,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r->getStatus() == StatusCANCEL) {
|
if (r->getStatus() == StatusCANCEL) {
|
||||||
wsptr = &oEvent::formatStatus(StatusCANCEL);
|
wsptr = &oEvent::formatStatus(StatusCANCEL, true);
|
||||||
}
|
}
|
||||||
else if (r->startTimeAvailable()) {
|
else if (r->startTimeAvailable()) {
|
||||||
if (pp.type != lRunnerStartZero)
|
if (pp.type != lRunnerStartZero)
|
||||||
@ -1233,7 +1250,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ok)
|
if (ok)
|
||||||
wsptr = &formatStatus(StatusOK);
|
wsptr = &formatStatus(StatusOK, true);
|
||||||
else
|
else
|
||||||
wsptr = &r->getStatusS(true);
|
wsptr = &r->getStatusS(true);
|
||||||
}
|
}
|
||||||
@ -1269,7 +1286,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
swap(vts, timeStatus);
|
swap(vts, timeStatus);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wstring vts = formatStatus(ts) + L" (" + timeStatus + L")";
|
wstring vts = formatStatus(ts, true) + L" (" + timeStatus + L")";
|
||||||
swap(vts, timeStatus);
|
swap(vts, timeStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1400,7 +1417,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
if (r->tempStatus==StatusOK && pc && !pc->getNoTiming())
|
if (r->tempStatus==StatusOK && pc && !pc->getNoTiming())
|
||||||
wcscpy_s(wbf, formatTime(r->tempRT).c_str());
|
wcscpy_s(wbf, formatTime(r->tempRT).c_str());
|
||||||
else
|
else
|
||||||
wcscpy_s(wbf, formatStatus(r->tempStatus).c_str() );
|
wcscpy_s(wbf, formatStatus(r->tempStatus, true).c_str() );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case lRunnerPlace:
|
case lRunnerPlace:
|
||||||
@ -1683,6 +1700,12 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
|||||||
wcscpy_s(wbf, s.c_str());
|
wcscpy_s(wbf, s.c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case lRunnerExpectedFee:
|
||||||
|
if (r) {
|
||||||
|
wstring s = formatCurrency(r->getDefaultFee());
|
||||||
|
wcscpy_s(wbf, s.c_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case lRunnerPaid:
|
case lRunnerPaid:
|
||||||
if (r) {
|
if (r) {
|
||||||
wstring s = formatCurrency(r->getDCI().getInt("Paid"));
|
wstring s = formatCurrency(r->getDCI().getInt("Paid"));
|
||||||
@ -2465,7 +2488,7 @@ void oEvent::listGeneratePunches(const oListInfo &listInfo, gdioutput &gdi,
|
|||||||
ppi.counter.level3++;
|
ppi.counter.level3++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(type == oListInfo::EBaseType::EBaseTypeAllPunches && r->Card) {
|
else if(type == oListInfo::EBaseType::EBaseTypeAllPunches) {
|
||||||
int startType = -1;
|
int startType = -1;
|
||||||
int finishType = -1;
|
int finishType = -1;
|
||||||
const pCourse pcrs = r->getCourse(false);
|
const pCourse pcrs = r->getCourse(false);
|
||||||
@ -2475,7 +2498,20 @@ void oEvent::listGeneratePunches(const oListInfo &listInfo, gdioutput &gdi,
|
|||||||
finishType = pcrs->getFinishPunchType();
|
finishType = pcrs->getFinishPunchType();
|
||||||
}
|
}
|
||||||
int prevPunchTime = r->getStartTime();
|
int prevPunchTime = r->getStartTime();
|
||||||
for (auto &punch : r->Card->punches) {
|
vector<pPunch> punches;
|
||||||
|
if (r->Card) {
|
||||||
|
for (auto &punch : r->Card->punches)
|
||||||
|
punches.push_back(&punch);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vector<pFreePunch> fPunches;
|
||||||
|
oe->getPunchesForRunner(r->getId(), true, fPunches);
|
||||||
|
for (auto punch : fPunches)
|
||||||
|
punches.push_back(punch);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &pPunch : punches) {
|
||||||
|
const oPunch &punch = *pPunch;
|
||||||
punch.previousPunchTime = prevPunchTime;
|
punch.previousPunchTime = prevPunchTime;
|
||||||
|
|
||||||
if (punch.isCheck() || punch.isStart(startType))
|
if (punch.isCheck() || punch.isStart(startType))
|
||||||
@ -2605,7 +2641,7 @@ bool oListInfo::filterRunner(const oRunner &r) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (filter(EFilterAnyResult)) {
|
if (filter(EFilterAnyResult)) {
|
||||||
if (r.tOnCourseResults.empty())
|
if (!r.hasOnCourseResult())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2614,6 +2650,11 @@ bool oListInfo::filterRunner(const oRunner &r) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter(EFilterWrongFee)) {
|
||||||
|
if (r.getEntryFee() == r.getDefaultFee())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (filter(EFilterRentCard) && r.getDCI().getInt("CardFee") == 0)
|
if (filter(EFilterRentCard) && r.getDCI().getInt("CardFee") == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -2734,27 +2775,24 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
|||||||
}
|
}
|
||||||
|
|
||||||
calculateTeamResults(true);
|
calculateTeamResults(true);
|
||||||
|
sortRunners(li.sortOrder);
|
||||||
calculateResults(li.lp.selection, ResultType::TotalResult);
|
calculateResults(li.lp.selection, ResultType::TotalResult);
|
||||||
|
|
||||||
if (li.sortOrder != ClassTotalResult)
|
|
||||||
sortRunners(li.sortOrder);
|
|
||||||
}
|
}
|
||||||
else if (li.calcResults) {
|
else if (li.calcResults) {
|
||||||
if (li.rogainingResults) {
|
if (li.rogainingResults) {
|
||||||
|
sortRunners(li.sortOrder);
|
||||||
calculateRogainingResults(li.lp.selection);
|
calculateRogainingResults(li.lp.selection);
|
||||||
if (li.sortOrder != ClassPoints)
|
|
||||||
sortRunners(li.sortOrder);
|
|
||||||
}
|
}
|
||||||
else if (li.lp.useControlIdResultTo > 0 || li.lp.useControlIdResultFrom > 0)
|
else if (li.lp.useControlIdResultTo > 0 || li.lp.useControlIdResultFrom > 0)
|
||||||
calculateSplitResults(li.lp.useControlIdResultFrom, li.lp.useControlIdResultTo);
|
calculateSplitResults(li.lp.useControlIdResultFrom, li.lp.useControlIdResultTo);
|
||||||
else if (li.sortOrder == CourseResult) {
|
else if (li.sortOrder == CourseResult) {
|
||||||
|
sortRunners(li.sortOrder);
|
||||||
calculateResults(li.lp.selection, ResultType::CourseResult);
|
calculateResults(li.lp.selection, ResultType::CourseResult);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
calculateTeamResults(false);
|
calculateTeamResults(false);
|
||||||
|
sortRunners(li.sortOrder);
|
||||||
calculateResults(li.lp.selection, ResultType::ClassResult);
|
calculateResults(li.lp.selection, ResultType::ClassResult);
|
||||||
if (li.sortOrder != ClassResult)
|
|
||||||
sortRunners(li.sortOrder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3051,8 +3089,10 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
|||||||
if (li.calcResults) {
|
if (li.calcResults) {
|
||||||
if (li.lp.useControlIdResultTo > 0 || li.lp.useControlIdResultFrom > 0)
|
if (li.lp.useControlIdResultTo > 0 || li.lp.useControlIdResultFrom > 0)
|
||||||
calculateSplitResults(li.lp.useControlIdResultFrom, li.lp.useControlIdResultTo);
|
calculateSplitResults(li.lp.useControlIdResultFrom, li.lp.useControlIdResultTo);
|
||||||
else
|
else {
|
||||||
|
sortRunners(li.sortOrder);
|
||||||
calculateResults(li.lp.selection, ResultType::ClassResult);
|
calculateResults(li.lp.selection, ResultType::ClassResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else sortRunners(li.sortOrder);
|
else sortRunners(li.sortOrder);
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,8 @@ enum EPostType
|
|||||||
lClassStartTimeRange,
|
lClassStartTimeRange,
|
||||||
lClassLength,
|
lClassLength,
|
||||||
lClassResultFraction,
|
lClassResultFraction,
|
||||||
|
lClassAvailableMaps,
|
||||||
|
lClassTotalMaps,
|
||||||
lCourseLength,
|
lCourseLength,
|
||||||
lCourseName,
|
lCourseName,
|
||||||
lCourseClimb,
|
lCourseClimb,
|
||||||
@ -114,6 +116,7 @@ enum EPostType
|
|||||||
lRunnerNationality,
|
lRunnerNationality,
|
||||||
lRunnerPhone,
|
lRunnerPhone,
|
||||||
lRunnerFee,
|
lRunnerFee,
|
||||||
|
lRunnerExpectedFee,
|
||||||
lRunnerPaid,
|
lRunnerPaid,
|
||||||
lRunnerPayMethod,
|
lRunnerPayMethod,
|
||||||
lRunnerEntryDate,
|
lRunnerEntryDate,
|
||||||
@ -258,6 +261,7 @@ enum EFilterList
|
|||||||
EFilterOnlyVacant,
|
EFilterOnlyVacant,
|
||||||
EFilterAnyResult, // With any (radio) punch on a leg
|
EFilterAnyResult, // With any (radio) punch on a leg
|
||||||
EFilterAPIEntry, // Entry via API
|
EFilterAPIEntry, // Entry via API
|
||||||
|
EFilterWrongFee,
|
||||||
_EFilterMax
|
_EFilterMax
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -70,6 +70,7 @@ public:
|
|||||||
|
|
||||||
wstring getInfo() const;
|
wstring getInfo() const;
|
||||||
|
|
||||||
|
bool isHiredCard() const { return Type == HiredCard; }
|
||||||
bool isStart() const {return Type==PunchStart;}
|
bool isStart() const {return Type==PunchStart;}
|
||||||
bool isStart(int startType) const {return Type==PunchStart || Type == startType;}
|
bool isStart(int startType) const {return Type==PunchStart || Type == startType;}
|
||||||
bool isFinish() const {return Type==PunchFinish;}
|
bool isFinish() const {return Type==PunchFinish;}
|
||||||
@ -93,7 +94,7 @@ public:
|
|||||||
|
|
||||||
wstring getRunningTime(int startTime) const;
|
wstring getRunningTime(int startTime) const;
|
||||||
|
|
||||||
enum SpecialPunch {PunchStart=1, PunchFinish=2, PunchCheck=3};
|
enum SpecialPunch {PunchStart=1, PunchFinish=2, PunchCheck=3, HiredCard=11111};
|
||||||
void decodeString(const string &s);
|
void decodeString(const string &s);
|
||||||
string codeString() const;
|
string codeString() const;
|
||||||
oPunch(oEvent *poe);
|
oPunch(oEvent *poe);
|
||||||
|
|||||||
132
code/oRunner.cpp
132
code/oRunner.cpp
@ -49,6 +49,16 @@
|
|||||||
|
|
||||||
oRunner::RaceIdFormatter oRunner::raceIdFormatter;
|
oRunner::RaceIdFormatter oRunner::raceIdFormatter;
|
||||||
|
|
||||||
|
bool oAbstractRunner::DynamicValue::isOld(const oEvent &oe) const {
|
||||||
|
return oe.dataRevision != dataRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
void oAbstractRunner::DynamicValue::update(const oEvent &oe, int v) {
|
||||||
|
value = v;
|
||||||
|
dataRevision = oe.dataRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const wstring &oRunner::RaceIdFormatter::formatData(const oBase *ob) const {
|
const wstring &oRunner::RaceIdFormatter::formatData(const oBase *ob) const {
|
||||||
return itow(dynamic_cast<const oRunner &>(*ob).getRaceIdentifier());
|
return itow(dynamic_cast<const oRunner &>(*ob).getRaceIdentifier());
|
||||||
}
|
}
|
||||||
@ -317,6 +327,20 @@ int oRunner::getBirthAge() const {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int oAbstractRunner::getDefaultFee() const {
|
||||||
|
int age = getBirthAge();
|
||||||
|
wstring date = getEntryDate();
|
||||||
|
if (Class) {
|
||||||
|
int fee = Class->getEntryFee(date, age);
|
||||||
|
return fee;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oAbstractRunner::getEntryFee() const {
|
||||||
|
return getDCI().getInt("Fee");
|
||||||
|
}
|
||||||
|
|
||||||
void oAbstractRunner::addClassDefaultFee(bool resetFees) {
|
void oAbstractRunner::addClassDefaultFee(bool resetFees) {
|
||||||
if (Class) {
|
if (Class) {
|
||||||
oDataInterface di = getDI();
|
oDataInterface di = getDI();
|
||||||
@ -343,8 +367,7 @@ void oAbstractRunner::addClassDefaultFee(bool resetFees) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((currentFee == 0 && !hasFlag(FlagFeeSpecified)) || resetFees) {
|
if ((currentFee == 0 && !hasFlag(FlagFeeSpecified)) || resetFees) {
|
||||||
int age = getBirthAge();
|
int fee = getDefaultFee();
|
||||||
int fee = Class->getEntryFee(date, age);
|
|
||||||
di.setInt("Fee", fee);
|
di.setInt("Fee", fee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -657,17 +680,13 @@ int oRunner::getTotalRunningTime() const {
|
|||||||
|
|
||||||
const wstring &oAbstractRunner::getStatusS(bool formatForPrint) const
|
const wstring &oAbstractRunner::getStatusS(bool formatForPrint) const
|
||||||
{
|
{
|
||||||
if (formatForPrint && tStatus == StatusUnknown)
|
return oEvent::formatStatus(tStatus, formatForPrint);
|
||||||
return formatTime(-1);
|
|
||||||
return oEvent::formatStatus(tStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const wstring &oAbstractRunner::getTotalStatusS(bool formatForPrint) const
|
const wstring &oAbstractRunner::getTotalStatusS(bool formatForPrint) const
|
||||||
{
|
{
|
||||||
auto ts = getTotalStatus();
|
auto ts = getTotalStatus();
|
||||||
if (formatForPrint && ts == StatusUnknown)
|
return oEvent::formatStatus(ts, formatForPrint);
|
||||||
return formatTime(-1);
|
|
||||||
return oEvent::formatStatus(ts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2138,6 +2157,14 @@ void oAbstractRunner::setStartNo(int no, bool tmpOnly) {
|
|||||||
|
|
||||||
void oRunner::setStartNo(int no, bool tmpOnly)
|
void oRunner::setStartNo(int no, bool tmpOnly)
|
||||||
{
|
{
|
||||||
|
if (tInTeam) {
|
||||||
|
if (tInTeam->getStartNo() == 0)
|
||||||
|
tInTeam->setStartNo(no, tmpOnly);
|
||||||
|
else {
|
||||||
|
// Do not allow different from team
|
||||||
|
no = tInTeam->getStartNo();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (tParentRunner)
|
if (tParentRunner)
|
||||||
tParentRunner->setStartNo(no, tmpOnly);
|
tParentRunner->setStartNo(no, tmpOnly);
|
||||||
else {
|
else {
|
||||||
@ -2149,17 +2176,51 @@ void oRunner::setStartNo(int no, bool tmpOnly)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int oRunner::getPlace() const
|
void oRunner::updateStartNo(int no) {
|
||||||
{
|
if (tInTeam) {
|
||||||
return tPlace;
|
tInTeam->synchronize(false);
|
||||||
|
for (pRunner r : tInTeam->Runners) {
|
||||||
|
if (r) {
|
||||||
|
r->synchronize(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tInTeam->setStartNo(no, false);
|
||||||
|
for (pRunner r : tInTeam->Runners) {
|
||||||
|
if (r) {
|
||||||
|
r->setStartNo(no, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tInTeam->synchronize(true);
|
||||||
|
for (pRunner r : tInTeam->Runners) {
|
||||||
|
r->synchronize(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setStartNo(no, false);
|
||||||
|
synchronize(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int oRunner::getCoursePlace() const
|
|
||||||
{
|
int oRunner::getPlace() const {
|
||||||
|
if (tPlace.isOld(*oe)) {
|
||||||
|
if (Class) {
|
||||||
|
oEvent::ResultType rt = oEvent::ResultType::ClassResult;
|
||||||
|
if (Class->isRogaining())
|
||||||
|
oe->calculateRogainingResults({ getClassId(true) });
|
||||||
|
else
|
||||||
|
oe->calculateResults({ getClassId(true) }, rt, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tPlace.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oRunner::getCoursePlace() const {
|
||||||
return tCoursePlace;
|
return tCoursePlace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int oRunner::getTotalPlace() const
|
int oRunner::getTotalPlace() const
|
||||||
{
|
{
|
||||||
if (tInTeam)
|
if (tInTeam)
|
||||||
@ -3873,7 +3934,8 @@ void oEvent::analyseDNS(vector<pRunner> &unknown_dns, vector<pRunner> &known_dns
|
|||||||
|
|
||||||
typedef multimap<int, pFreePunch>::const_iterator TPunchIter;
|
typedef multimap<int, pFreePunch>::const_iterator TPunchIter;
|
||||||
for (oFreePunchList::iterator it = punches.begin(); it != punches.end(); ++it) {
|
for (oFreePunchList::iterator it = punches.begin(); it != punches.end(); ++it) {
|
||||||
punchHash.insert(make_pair(it->getCardNo(), &*it));
|
if (!it->isRemoved() && !it->isHiredCard())
|
||||||
|
punchHash.insert(make_pair(it->getCardNo(), &*it));
|
||||||
}
|
}
|
||||||
|
|
||||||
set<int> knownCards;
|
set<int> knownCards;
|
||||||
@ -5015,7 +5077,7 @@ int oRunner::getLegTimeAfter(int ctrlNo) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int oRunner::getLegPlaceAcc(int ctrlNo) const {
|
int oRunner::getLegPlaceAcc(int ctrlNo) const {
|
||||||
for (auto &res : tOnCourseResults) {
|
for (auto &res : tOnCourseResults.res) {
|
||||||
if (res.controlIx == ctrlNo)
|
if (res.controlIx == ctrlNo)
|
||||||
return res.place;
|
return res.place;
|
||||||
}
|
}
|
||||||
@ -5030,7 +5092,7 @@ int oRunner::getLegPlaceAcc(int ctrlNo) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int oRunner::getLegTimeAfterAcc(int ctrlNo) const {
|
int oRunner::getLegTimeAfterAcc(int ctrlNo) const {
|
||||||
for (auto &res : tOnCourseResults) {
|
for (auto &res : tOnCourseResults.res) {
|
||||||
if (res.controlIx == ctrlNo)
|
if (res.controlIx == ctrlNo)
|
||||||
return res.after;
|
return res.after;
|
||||||
}
|
}
|
||||||
@ -5265,7 +5327,7 @@ void oAbstractRunner::setInputStatus(RunnerStatus s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wstring oAbstractRunner::getInputStatusS() const {
|
wstring oAbstractRunner::getInputStatusS() const {
|
||||||
return oe->formatStatus(inputStatus);
|
return oe->formatStatus(inputStatus, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void oAbstractRunner::setInputPoints(int p)
|
void oAbstractRunner::setInputPoints(int p)
|
||||||
@ -5341,16 +5403,26 @@ void oEvent::getDBRunnersInEvent(intkeymap<pClass, __int64> &runners) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oRunner::init(const RunnerWDBEntry &dbr) {
|
void oRunner::init(const RunnerWDBEntry &dbr, bool updateOnlyExt) {
|
||||||
setTemporary();
|
if (updateOnlyExt) {
|
||||||
dbr.getName(sName);
|
dbr.getName(sName);
|
||||||
getRealName(sName, tRealName);
|
getRealName(sName, tRealName);
|
||||||
cardNumber = dbr.dbe().cardNo;
|
getDI().setString("Nationality", dbr.getNationality());
|
||||||
Club = oe->getRunnerDatabase().getClub(dbr.dbe().clubNo);
|
getDI().setInt("BirthYear", dbr.getBirthYear());
|
||||||
getDI().setString("Nationality", dbr.getNationality());
|
getDI().setString("Sex", dbr.getSex());
|
||||||
getDI().setInt("BirthYear", dbr.getBirthYear());
|
setExtIdentifier(dbr.getExtId());
|
||||||
getDI().setString("Sex", dbr.getSex());
|
}
|
||||||
setExtIdentifier(dbr.getExtId());
|
else {
|
||||||
|
setTemporary();
|
||||||
|
dbr.getName(sName);
|
||||||
|
getRealName(sName, tRealName);
|
||||||
|
cardNumber = dbr.dbe().cardNo;
|
||||||
|
Club = oe->getRunnerDatabase().getClub(dbr.dbe().clubNo);
|
||||||
|
getDI().setString("Nationality", dbr.getNationality());
|
||||||
|
getDI().setInt("BirthYear", dbr.getBirthYear());
|
||||||
|
getDI().setString("Sex", dbr.getSex());
|
||||||
|
setExtIdentifier(dbr.getExtId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void oEvent::selectRunners(const wstring &classType, int lowAge,
|
void oEvent::selectRunners(const wstring &classType, int lowAge,
|
||||||
@ -5605,11 +5677,11 @@ void oAbstractRunner::setTempResultZero(const TempResult &tr) {
|
|||||||
|
|
||||||
const wstring &oAbstractRunner::TempResult::getStatusS(RunnerStatus inputStatus) const {
|
const wstring &oAbstractRunner::TempResult::getStatusS(RunnerStatus inputStatus) const {
|
||||||
if (inputStatus == StatusOK)
|
if (inputStatus == StatusOK)
|
||||||
return oEvent::formatStatus(getStatus());
|
return oEvent::formatStatus(getStatus(), true);
|
||||||
else if (inputStatus == StatusUnknown)
|
else if (inputStatus == StatusUnknown)
|
||||||
return formatTime(-1);
|
return formatTime(-1);
|
||||||
else
|
else
|
||||||
return oEvent::formatStatus(max(inputStatus, getStatus()));
|
return oEvent::formatStatus(max(inputStatus, getStatus()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const wstring &oAbstractRunner::TempResult::getPrintPlaceS(bool withDot) const {
|
const wstring &oAbstractRunner::TempResult::getPrintPlaceS(bool withDot) const {
|
||||||
|
|||||||
@ -198,6 +198,12 @@ public:
|
|||||||
// a non-zero fee is changed only if resetFee is true
|
// a non-zero fee is changed only if resetFee is true
|
||||||
void addClassDefaultFee(bool resetFees);
|
void addClassDefaultFee(bool resetFees);
|
||||||
|
|
||||||
|
/** Returns fee from the class. */
|
||||||
|
int getDefaultFee() const;
|
||||||
|
|
||||||
|
/** Returns the currently assigned fee. */
|
||||||
|
int getEntryFee() const;
|
||||||
|
|
||||||
/** Returns true if the entry fee is a late fee. */
|
/** Returns true if the entry fee is a late fee. */
|
||||||
bool hasLateEntryFee() const;
|
bool hasLateEntryFee() const;
|
||||||
|
|
||||||
@ -362,6 +368,13 @@ public:
|
|||||||
oAbstractRunner(oEvent *poe, bool loading);
|
oAbstractRunner(oEvent *poe, bool loading);
|
||||||
virtual ~oAbstractRunner() {};
|
virtual ~oAbstractRunner() {};
|
||||||
|
|
||||||
|
struct DynamicValue {
|
||||||
|
int dataRevision;
|
||||||
|
int value;
|
||||||
|
bool isOld(const oEvent &oe) const;
|
||||||
|
void update(const oEvent &oe, int v);
|
||||||
|
};
|
||||||
|
|
||||||
friend class oListInfo;
|
friend class oListInfo;
|
||||||
friend class GeneralResult;
|
friend class GeneralResult;
|
||||||
};
|
};
|
||||||
@ -413,7 +426,7 @@ protected:
|
|||||||
wstring tRealName;
|
wstring tRealName;
|
||||||
|
|
||||||
//Can be changed by apply
|
//Can be changed by apply
|
||||||
mutable int tPlace;
|
mutable DynamicValue tPlace;
|
||||||
mutable int tCoursePlace;
|
mutable int tCoursePlace;
|
||||||
mutable int tTotalPlace;
|
mutable int tTotalPlace;
|
||||||
mutable int tLeg;
|
mutable int tLeg;
|
||||||
@ -499,8 +512,22 @@ protected:
|
|||||||
int place;
|
int place;
|
||||||
int after;
|
int after;
|
||||||
};
|
};
|
||||||
pair<int, int> currentControlTime;
|
mutable pair<int, int> currentControlTime;
|
||||||
mutable vector<OnCourseResult> tOnCourseResults;
|
|
||||||
|
struct OnCourseResultCollection {
|
||||||
|
bool hasAnyRes = false;
|
||||||
|
vector<OnCourseResult> res;
|
||||||
|
void clear() { hasAnyRes = false; res.clear(); }
|
||||||
|
void emplace_back(int courseControlId,
|
||||||
|
int controlIx,
|
||||||
|
int time) {
|
||||||
|
res.emplace_back(courseControlId, controlIx, time);
|
||||||
|
hasAnyRes = true;
|
||||||
|
}
|
||||||
|
bool empty() const { return hasAnyRes == false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable OnCourseResultCollection tOnCourseResults;
|
||||||
|
|
||||||
// Rogainig results. Control and punch time
|
// Rogainig results. Control and punch time
|
||||||
vector< pair<pControl, int> > tRogaining;
|
vector< pair<pControl, int> > tRogaining;
|
||||||
@ -538,7 +565,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Returns true if there are radio control results, provided result calculation oEvent::ResultType::PreliminarySplitResults was invoked.
|
// Returns true if there are radio control results, provided result calculation oEvent::ResultType::PreliminarySplitResults was invoked.
|
||||||
bool hasOnCourseResult() const { return tOnCourseResults.size() > 0 || getFinishTime() > 0; }
|
bool hasOnCourseResult() const { return !tOnCourseResults.empty() || getFinishTime() > 0 || getStatus() != RunnerStatus::StatusUnknown; }
|
||||||
|
|
||||||
/** Get a runner reference (drawing) */
|
/** Get a runner reference (drawing) */
|
||||||
pRunner getReference() const;
|
pRunner getReference() const;
|
||||||
@ -656,7 +683,7 @@ public:
|
|||||||
void setTemporary() {isTemporaryObject=true;}
|
void setTemporary() {isTemporaryObject=true;}
|
||||||
|
|
||||||
/** Init from dbrunner */
|
/** Init from dbrunner */
|
||||||
void init(const RunnerWDBEntry &entry);
|
void init(const RunnerWDBEntry &entry, bool updateOnlyExt);
|
||||||
|
|
||||||
/** Use db to pdate runner */
|
/** Use db to pdate runner */
|
||||||
bool updateFromDB(const wstring &name, int clubId, int classId,
|
bool updateFromDB(const wstring &name, int clubId, int classId,
|
||||||
@ -686,6 +713,8 @@ public:
|
|||||||
// which should be more stable.
|
// which should be more stable.
|
||||||
void setBib(const wstring &bib, int bibNumerical, bool updateStartNo, bool setTmpOnly);
|
void setBib(const wstring &bib, int bibNumerical, bool updateStartNo, bool setTmpOnly);
|
||||||
void setStartNo(int no, bool setTmpOnly);
|
void setStartNo(int no, bool setTmpOnly);
|
||||||
|
// Update and synch start number for runner and team.
|
||||||
|
void updateStartNo(int no);
|
||||||
|
|
||||||
pRunner nextNeedReadout() const;
|
pRunner nextNeedReadout() const;
|
||||||
|
|
||||||
|
|||||||
@ -653,7 +653,7 @@ RunnerStatus oTeam::getLegStatus(int leg, bool multidayTotal) const
|
|||||||
|
|
||||||
const wstring &oTeam::getLegStatusS(int leg, bool multidayTotal) const
|
const wstring &oTeam::getLegStatusS(int leg, bool multidayTotal) const
|
||||||
{
|
{
|
||||||
return oe->formatStatus(getLegStatus(leg, multidayTotal));
|
return oe->formatStatus(getLegStatus(leg, multidayTotal), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int oTeam::getLegPlace(int leg, bool multidayTotal) const {
|
int oTeam::getLegPlace(int leg, bool multidayTotal) const {
|
||||||
|
|||||||
@ -76,9 +76,9 @@ protected:
|
|||||||
|
|
||||||
TeamPlace _places[maxRunnersTeam];
|
TeamPlace _places[maxRunnersTeam];
|
||||||
|
|
||||||
int _sortTime;
|
mutable int _sortTime;
|
||||||
int _sortStatus;
|
mutable int _sortStatus;
|
||||||
RunnerStatus _cachedStatus;
|
mutable RunnerStatus _cachedStatus;
|
||||||
|
|
||||||
mutable vector< vector< vector<int> > > resultCalculationCache;
|
mutable vector< vector< vector<int> > > resultCalculationCache;
|
||||||
|
|
||||||
|
|||||||
@ -422,7 +422,7 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
|
|||||||
cls.setCoursePool(type == PPool);
|
cls.setCoursePool(type == PPool);
|
||||||
|
|
||||||
if (crs) {
|
if (crs) {
|
||||||
cls.addStageCourse(0, crsId);
|
cls.addStageCourse(0, crsId, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -437,7 +437,7 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
|
|||||||
cls.setCoursePool(true);
|
cls.setCoursePool(true);
|
||||||
|
|
||||||
if (crs) {
|
if (crs) {
|
||||||
cls.addStageCourse(0, crsId);
|
cls.addStageCourse(0, crsId, -1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -456,8 +456,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
|
|||||||
cls.setRopeTime(1, L"-");
|
cls.setRopeTime(1, L"-");
|
||||||
|
|
||||||
if (crs) {
|
if (crs) {
|
||||||
cls.addStageCourse(0, crsId);
|
cls.addStageCourse(0, crsId, -1);
|
||||||
cls.addStageCourse(1, crsId);
|
cls.addStageCourse(1, crsId, -1);
|
||||||
}
|
}
|
||||||
cls.setCoursePool(false);
|
cls.setCoursePool(false);
|
||||||
break;
|
break;
|
||||||
@ -477,8 +477,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
|
|||||||
cls.setRopeTime(1, L"-");
|
cls.setRopeTime(1, L"-");
|
||||||
|
|
||||||
if (crs) {
|
if (crs) {
|
||||||
cls.addStageCourse(0, crsId);
|
cls.addStageCourse(0, crsId, -1);
|
||||||
cls.addStageCourse(1, crsId);
|
cls.addStageCourse(1, crsId, -1);
|
||||||
}
|
}
|
||||||
cls.setCoursePool(false);
|
cls.setCoursePool(false);
|
||||||
break;
|
break;
|
||||||
@ -498,8 +498,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
|
|||||||
cls.setRopeTime(1, L"-");
|
cls.setRopeTime(1, L"-");
|
||||||
|
|
||||||
if (crs) {
|
if (crs) {
|
||||||
cls.addStageCourse(0, crsId);
|
cls.addStageCourse(0, crsId, -1);
|
||||||
cls.addStageCourse(1, crsId);
|
cls.addStageCourse(1, crsId, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cls.setCoursePool(false);
|
cls.setCoursePool(false);
|
||||||
|
|||||||
@ -471,6 +471,9 @@ void OnlineInput::processEntries(oEvent &oe, const xmlList &entries) {
|
|||||||
r->setCardNo(cardNo, false, false);
|
r->setCardNo(cardNo, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fee == 0)
|
||||||
|
fee = r->getDefaultFee();
|
||||||
|
|
||||||
r->getDI().setInt("Fee", fee);
|
r->getDI().setInt("Fee", fee);
|
||||||
int toPay = fee;
|
int toPay = fee;
|
||||||
int cf = 0;
|
int cf = 0;
|
||||||
@ -479,6 +482,7 @@ void OnlineInput::processEntries(oEvent &oe, const xmlList &entries) {
|
|||||||
if (cf > 0)
|
if (cf > 0)
|
||||||
toPay += cf;
|
toPay += cf;
|
||||||
}
|
}
|
||||||
|
r->setFlag(oRunner::FlagAddedViaAPI, true);
|
||||||
r->getDI().setInt("CardFee", cf);
|
r->getDI().setInt("CardFee", cf);
|
||||||
r->getDI().setInt("Paid", paid ? toPay : 0);
|
r->getDI().setInt("Paid", paid ? toPay : 0);
|
||||||
|
|
||||||
|
|||||||
@ -342,8 +342,10 @@ void OnlineResults::status(gdioutput &gdi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sendToFile || sendToURL) {
|
if (sendToFile || sendToURL) {
|
||||||
gdi.addString("", 0, "Exporterar om: ");
|
if (interval > 0) {
|
||||||
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign, (GetTickCount()-timeout)/1000);
|
gdi.addString("", 0, "Exporterar om: ");
|
||||||
|
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign, (GetTickCount() - timeout) / 1000);
|
||||||
|
}
|
||||||
gdi.addString("", 0, "Antal skickade uppdateringar X (Y kb)#" +
|
gdi.addString("", 0, "Antal skickade uppdateringar X (Y kb)#" +
|
||||||
itos(exportCounter-1) + "#" + itos(bytesExported/1024));
|
itos(exportCounter-1) + "#" + itos(bytesExported/1024));
|
||||||
}
|
}
|
||||||
@ -515,7 +517,7 @@ void OnlineResults::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
|
|||||||
if (ast == SyncNone)
|
if (ast == SyncNone)
|
||||||
throw;
|
throw;
|
||||||
else
|
else
|
||||||
gdi.addInfoBox("", L"Online Results Error X#" + ex.wwhat(), 5000);
|
gdi.addInfoBox("", L"Online Results Error X#" + lang.tl(ex.wwhat()), 5000);
|
||||||
}
|
}
|
||||||
catch(std::exception &ex) {
|
catch(std::exception &ex) {
|
||||||
if (ast == SyncNone)
|
if (ast == SyncNone)
|
||||||
|
|||||||
@ -354,7 +354,7 @@ int QualificationFinal::getLevel(int instance) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool QualificationFinal::isFinalClass(int instance) const {
|
bool QualificationFinal::isFinalClass(int instance) const {
|
||||||
return sourcePlaceToFinalOrder.count(make_pair(instance, 1)) == 0;
|
return instance > 0 && sourcePlaceToFinalOrder.count(make_pair(instance, 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QualificationFinal::getNumLevels() const {
|
int QualificationFinal::getNumLevels() const {
|
||||||
|
|||||||
@ -88,12 +88,18 @@ static void method_handler(const shared_ptr< restbed::Session > session) {
|
|||||||
|
|
||||||
void RestServer::handleRequest(const shared_ptr<restbed::Session> &session) {
|
void RestServer::handleRequest(const shared_ptr<restbed::Session> &session) {
|
||||||
const auto request = session->get_request();
|
const auto request = session->get_request();
|
||||||
size_t content_length = request->get_header("Content-Length", 0);
|
string path = request->get_path();
|
||||||
|
|
||||||
|
size_t content_length = request->get_header("Content-Length", 0);
|
||||||
chrono::time_point<chrono::system_clock> start, end;
|
chrono::time_point<chrono::system_clock> start, end;
|
||||||
start = chrono::system_clock::now();
|
start = chrono::system_clock::now();
|
||||||
|
|
||||||
auto param = request->get_query_parameters();
|
auto param = request->get_query_parameters();
|
||||||
|
|
||||||
|
if (path == "/" && !root.empty()) {
|
||||||
|
param = rootMap;
|
||||||
|
}
|
||||||
|
|
||||||
auto answer = RestServer::addRequest(param);
|
auto answer = RestServer::addRequest(param);
|
||||||
{
|
{
|
||||||
unique_lock<mutex> mlock(lock);
|
unique_lock<mutex> mlock(lock);
|
||||||
@ -131,9 +137,30 @@ void RestServer::startThread(int port) {
|
|||||||
resource->set_method_handler("GET", method_handler);
|
resource->set_method_handler("GET", method_handler);
|
||||||
restService->publish(resource);
|
restService->publish(resource);
|
||||||
|
|
||||||
|
|
||||||
|
auto resourceRoot = make_shared<MeOSResource>(this);
|
||||||
|
resourceRoot->set_path("/");
|
||||||
|
resourceRoot->set_method_handler("GET", method_handler);
|
||||||
|
restService->publish(resourceRoot);
|
||||||
|
|
||||||
restService->start(settings);
|
restService->start(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RestServer::setRootMap(const string &rmap) {
|
||||||
|
root = rmap;
|
||||||
|
vector<string> sp;
|
||||||
|
rootMap.clear();
|
||||||
|
split(rmap, "&", sp);
|
||||||
|
for (string arg : sp) {
|
||||||
|
vector<string> sp2;
|
||||||
|
split(arg, "=", sp2);
|
||||||
|
if (sp2.size() == 1)
|
||||||
|
rootMap.emplace(sp2[0], "");
|
||||||
|
else if (sp2.size() == 2)
|
||||||
|
rootMap.emplace(sp2[0], sp2[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RestServer::startService(int port) {
|
void RestServer::startService(int port) {
|
||||||
if (service)
|
if (service)
|
||||||
throw meosException("Server started");
|
throw meosException("Server started");
|
||||||
@ -243,6 +270,40 @@ void RestServer::computeInternal(oEvent &ref, shared_ptr<RestServer::EventReques
|
|||||||
|
|
||||||
rq->answer += entryLinks;
|
rq->answer += entryLinks;
|
||||||
|
|
||||||
|
vector<pRunner> runners;
|
||||||
|
ref.getRunners(-1, -1, runners, false);
|
||||||
|
string sRunnerId, sRunnerBib, sRunnerCard, sRunnerName, sRunnerClub, sRunnerClubId;
|
||||||
|
for (pRunner r : runners) {
|
||||||
|
if (sRunnerId.empty())
|
||||||
|
sRunnerId = itos(r->getId());
|
||||||
|
|
||||||
|
if (sRunnerClub.empty()) {
|
||||||
|
sRunnerName = gdioutput::toUTF8(r->getName());
|
||||||
|
sRunnerClub = gdioutput::toUTF8(r->getClub());
|
||||||
|
if (r->getClubId())
|
||||||
|
sRunnerClubId = gdioutput::toUTF8(r->getClubRef()->getExtIdentifierString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sRunnerCard.empty() && r->getCardNo() > 0)
|
||||||
|
sRunnerCard = itos(r->getCardNo());
|
||||||
|
|
||||||
|
if (sRunnerBib.empty() && !r->getBib().empty())
|
||||||
|
sRunnerBib = gdioutput::recodeToNarrow(r->getBib());
|
||||||
|
}
|
||||||
|
if (sRunnerId.empty())
|
||||||
|
sRunnerId = "1";
|
||||||
|
if (sRunnerCard.empty())
|
||||||
|
sRunnerCard = "12345";
|
||||||
|
if (sRunnerBib.empty())
|
||||||
|
sRunnerBib = "100";
|
||||||
|
if (sRunnerClub.empty())
|
||||||
|
sRunnerClub = "Lost and Found";
|
||||||
|
if (sRunnerName.empty())
|
||||||
|
sRunnerName = "Charles Kinsley";
|
||||||
|
|
||||||
|
|
||||||
|
string sRunnerDbName, sRunnerDbId, sRunnerDbClub;
|
||||||
|
//oe.getRunnerDatabase().
|
||||||
|
|
||||||
HINSTANCE hInst = GetModuleHandle(0);
|
HINSTANCE hInst = GetModuleHandle(0);
|
||||||
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(132), RT_HTML);
|
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(132), RT_HTML);
|
||||||
@ -257,8 +318,44 @@ void RestServer::computeInternal(oEvent &ref, shared_ptr<RestServer::EventReques
|
|||||||
htmlS += "<";
|
htmlS += "<";
|
||||||
else if (*html == '#')
|
else if (*html == '#')
|
||||||
htmlS += "&";
|
htmlS += "&";
|
||||||
|
else if (*html == '%') {
|
||||||
|
string key;
|
||||||
|
char *pKey = html + 1;
|
||||||
|
resSize--;
|
||||||
|
while (*pKey != '%' && resSize > 0) {
|
||||||
|
key += *pKey;
|
||||||
|
++pKey;
|
||||||
|
resSize--;
|
||||||
|
}
|
||||||
|
if (key == "runnerid") {
|
||||||
|
htmlS += sRunnerId;
|
||||||
|
}
|
||||||
|
else if (key == "card") {
|
||||||
|
htmlS += sRunnerCard;
|
||||||
|
}
|
||||||
|
else if (key == "bib") {
|
||||||
|
htmlS += sRunnerBib;
|
||||||
|
}
|
||||||
|
else if (key == "name") {
|
||||||
|
htmlS += sRunnerName;
|
||||||
|
}
|
||||||
|
else if (key == "club") {
|
||||||
|
htmlS += sRunnerClub;
|
||||||
|
}
|
||||||
|
else if (key == "dbname") {
|
||||||
|
htmlS += sRunnerName.substr(0, sRunnerName.size() / 2);
|
||||||
|
}
|
||||||
|
else if (key == "dbclub") {
|
||||||
|
htmlS += sRunnerClub;
|
||||||
|
}
|
||||||
|
else if (key == "clubid") {
|
||||||
|
htmlS += sRunnerClubId;
|
||||||
|
}
|
||||||
|
html = pKey;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
htmlS += *html;
|
htmlS += *html;
|
||||||
|
|
||||||
++html;
|
++html;
|
||||||
resSize--;
|
resSize--;
|
||||||
}
|
}
|
||||||
@ -959,17 +1056,13 @@ void RestServer::lookup(oEvent &oe, const string &what, const multimap<string, s
|
|||||||
if (param.count("card") > 0) {
|
if (param.count("card") > 0) {
|
||||||
int card = atoi(param.find("card")->second.c_str());
|
int card = atoi(param.find("card")->second.c_str());
|
||||||
int time = 0;
|
int time = 0;
|
||||||
if (param.count("running") && param.find("card")->second == "true") {
|
if (param.count("running") && param.find("running")->second == "true") {
|
||||||
time = oe.getRelativeTime(getLocalTime());
|
time = oe.getRelativeTime(getLocalTime());
|
||||||
if (time < 0)
|
if (time < 0)
|
||||||
time = 0;
|
time = 0;
|
||||||
}
|
}
|
||||||
pRunner r = oe.getRunnerByCardNo(card, time, oEvent::CardLookupProperty::CardInUse);
|
|
||||||
if (!r)
|
|
||||||
r = oe.getRunnerByCardNo(card, time, oEvent::CardLookupProperty::Any);
|
|
||||||
|
|
||||||
if (r)
|
oe.getRunnersByCardNo(card, false, oEvent::CardLookupProperty::Any, runners);
|
||||||
runners.push_back(r);
|
|
||||||
}
|
}
|
||||||
if (param.count("name") > 0) {
|
if (param.count("name") > 0) {
|
||||||
wstring club;
|
wstring club;
|
||||||
@ -986,7 +1079,7 @@ void RestServer::lookup(oEvent &oe, const string &what, const multimap<string, s
|
|||||||
runners.push_back(r);
|
runners.push_back(r);
|
||||||
}
|
}
|
||||||
if (param.count("bib") > 0) {
|
if (param.count("bib") > 0) {
|
||||||
pRunner r = oe.getRunnerByBibOrStartNo(wideParam(param.find("bib")->second), false);
|
pRunner r = oe.getRunnerByBibOrStartNo(wideParam(param.find("bib")->second), true);
|
||||||
if (r)
|
if (r)
|
||||||
runners.push_back(r);
|
runners.push_back(r);
|
||||||
}
|
}
|
||||||
@ -1012,7 +1105,9 @@ void RestServer::lookup(oEvent &oe, const string &what, const multimap<string, s
|
|||||||
}
|
}
|
||||||
if (r->getTeam()) {
|
if (r->getTeam()) {
|
||||||
xml.write("Team", { make_pair("id", itow(r->getTeam()->getId())) }, r->getTeam()->getName());
|
xml.write("Team", { make_pair("id", itow(r->getTeam()->getId())) }, r->getTeam()->getName());
|
||||||
xml.write("Leg", r->getLegNumber());
|
pClass cls = r->getClassRef(false);
|
||||||
|
if (cls)
|
||||||
|
xml.write("Leg", cls->getLegNumber(r->getLegNumber()));
|
||||||
}
|
}
|
||||||
if ((r->getFinishTime() > 0 || r->getCard() != nullptr) && r->getCourse(false)) {
|
if ((r->getFinishTime() > 0 || r->getCard() != nullptr) && r->getCourse(false)) {
|
||||||
auto &sd = r->getSplitTimes(false);
|
auto &sd = r->getSplitTimes(false);
|
||||||
@ -1200,7 +1295,16 @@ void RestServer::newEntry(oEvent &oe, const multimap<string, string> ¶m, str
|
|||||||
|
|
||||||
if (epType != EntryPermissionType::Any) {
|
if (epType != EntryPermissionType::Any) {
|
||||||
if (extId == 0) {
|
if (extId == 0) {
|
||||||
dbr = oe.getRunnerDatabase().getRunnerByName(name, clubId, 0);
|
int clubExtId = 0;
|
||||||
|
if (existingClub)
|
||||||
|
clubExtId = (int)existingClub->getExtIdentifier();
|
||||||
|
else if (!club.empty()) {
|
||||||
|
pClub dbClub = oe.getRunnerDatabase().getClub(club);
|
||||||
|
if (dbClub) {
|
||||||
|
clubExtId = dbClub->getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbr = oe.getRunnerDatabase().getRunnerByName(name, clubExtId, 0);
|
||||||
if (dbr)
|
if (dbr)
|
||||||
extId = dbr->getExtId();
|
extId = dbr->getExtId();
|
||||||
}
|
}
|
||||||
@ -1220,6 +1324,12 @@ void RestServer::newEntry(oEvent &oe, const multimap<string, string> ¶m, str
|
|||||||
else if (epClass != EntryPermissionClass::Any && !cls->getAllowQuickEntry()) {
|
else if (epClass != EntryPermissionClass::Any && !cls->getAllowQuickEntry()) {
|
||||||
permissionDenied = true;
|
permissionDenied = true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
int nm = cls->getNumRemainingMaps(false);
|
||||||
|
if (nm != numeric_limits<int>::min() && nm<=0) {
|
||||||
|
error = L"Klassen är full";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (epType != EntryPermissionType::Any && extId == 0) {
|
if (epType != EntryPermissionType::Any && extId == 0) {
|
||||||
error = L"Anmälan måste hanteras manuellt";
|
error = L"Anmälan måste hanteras manuellt";
|
||||||
@ -1249,7 +1359,7 @@ void RestServer::newEntry(oEvent &oe, const multimap<string, string> ¶m, str
|
|||||||
if (!permissionDenied && error.empty()) {
|
if (!permissionDenied && error.empty()) {
|
||||||
pRunner r = oe.addRunner(name, club, classId, cardNo, 0, true);
|
pRunner r = oe.addRunner(name, club, classId, cardNo, 0, true);
|
||||||
if (r && dbr) {
|
if (r && dbr) {
|
||||||
r->init(*dbr);
|
r->init(*dbr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|||||||
@ -108,6 +108,9 @@ private:
|
|||||||
void computeInternal(oEvent &ref, shared_ptr<RestServer::EventRequest> &rq);
|
void computeInternal(oEvent &ref, shared_ptr<RestServer::EventRequest> &rq);
|
||||||
|
|
||||||
map<int, pair<oListParam, shared_ptr<oListInfo> > > listCache;
|
map<int, pair<oListParam, shared_ptr<oListInfo> > > listCache;
|
||||||
|
|
||||||
|
string root;
|
||||||
|
multimap<string, string> rootMap;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~RestServer();
|
~RestServer();
|
||||||
@ -121,6 +124,9 @@ public:
|
|||||||
|
|
||||||
void setEntryPermission(EntryPermissionClass epClass, EntryPermissionType epType);
|
void setEntryPermission(EntryPermissionClass epClass, EntryPermissionType epType);
|
||||||
|
|
||||||
|
void setRootMap(const string &rootMap);
|
||||||
|
const string &getRootMap() const { return root; }
|
||||||
|
|
||||||
tuple<EntryPermissionClass, EntryPermissionType> getEntryPermission() const {
|
tuple<EntryPermissionClass, EntryPermissionType> getEntryPermission() const {
|
||||||
return make_tuple(epClass, epType);
|
return make_tuple(epClass, epType);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,6 +126,8 @@ void DirectSocket::listenDirectSocket() {
|
|||||||
closesocket(clientSocket);
|
closesocket(clientSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern HWND hWndMain;
|
||||||
|
|
||||||
void startListeningDirectSocket(void *p) {
|
void startListeningDirectSocket(void *p) {
|
||||||
wstring error;
|
wstring error;
|
||||||
try {
|
try {
|
||||||
@ -142,8 +144,9 @@ void startListeningDirectSocket(void *p) {
|
|||||||
error = L"Unknown error";
|
error = L"Unknown error";
|
||||||
}
|
}
|
||||||
if (!error.empty()) {
|
if (!error.empty()) {
|
||||||
error = L"Setting up advance information service for punches failed. Punches will be recieved with some seconds delay. Is the network port blocked by an other MeOS session?\n\n" + error;
|
PostMessage(hWndMain, WM_USER + 5, 0, 0);
|
||||||
MessageBox(NULL, error.c_str(), L"MeOS", MB_OK|MB_ICONSTOP);
|
//error = L"Setting up advance information service for punches failed. Punches will be recieved with some seconds delay. Is the network port blocked by an other MeOS session?\n\n" + error;
|
||||||
|
//MessageBox(NULL, error.c_str(), L"MeOS", MB_OK|MB_ICONSTOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1310,7 +1310,7 @@ help:30750 = Här kan du skapa olika sorters listor och rapporter. Du kan visa d
|
|||||||
help:31661 = En omstart definieras av en repdragningstid och en omstartstid. Vid repdragningstiden stängs växlingen, och inga startande släpps ut i skogen. Vid omstartstiden går omstarten. Det går att ställa in olika omstartstid på olika sträckor, men med hjälp av den här funktionen sätter du snabbt omstartstid för hela klasser.
|
help:31661 = En omstart definieras av en repdragningstid och en omstartstid. Vid repdragningstiden stängs växlingen, och inga startande släpps ut i skogen. Vid omstartstiden går omstarten. Det går att ställa in olika omstartstid på olika sträckor, men med hjälp av den här funktionen sätter du snabbt omstartstid för hela klasser.
|
||||||
help:33940 = Importera anmälningsdata i fritextformat. Ange Namn, Klubb, Klass, och SI (och eventuell starttid) gärna separerade med komma, en person (ett lag) per rad. Det går också att anmäla flera personer i samma klubb/klass genom att (delvis) utelämna fälten klubb/klass. Det är också möjligt att importera anmälningar formaterade på andra sätt.\n\nKlasser skapas automatiskt, men om du importerar lag för stafett eller patrull bör du lägga upp klasserna själv innan du importerar anmälningarna. Annars finns risk att sträcktilldelningen blir fel.
|
help:33940 = Importera anmälningsdata i fritextformat. Ange Namn, Klubb, Klass, och SI (och eventuell starttid) gärna separerade med komma, en person (ett lag) per rad. Det går också att anmäla flera personer i samma klubb/klass genom att (delvis) utelämna fälten klubb/klass. Det är också möjligt att importera anmälningar formaterade på andra sätt.\n\nKlasser skapas automatiskt, men om du importerar lag för stafett eller patrull bör du lägga upp klasserna själv innan du importerar anmälningarna. Annars finns risk att sträcktilldelningen blir fel.
|
||||||
help:41072 = Markera en stämpling i stämplingslistan för att ta bort den eller ändra tiden. Från banmallen kan saknade stämplingar läggas till. Saknas måltid får löparen status utgått. Saknas stämpling får löparen status felstämplat. Det går inte att sätta en status på löparen som inte överensstämmer med stämplingsdata. Finns målstämpling måste tiden för denna ändras för att ändra måltiden; samma princip gäller för startstämpling.
|
help:41072 = Markera en stämpling i stämplingslistan för att ta bort den eller ändra tiden. Från banmallen kan saknade stämplingar läggas till. Saknas måltid får löparen status utgått. Saknas stämpling får löparen status felstämplat. Det går inte att sätta en status på löparen som inte överensstämmer med stämplingsdata. Finns målstämpling måste tiden för denna ändras för att ändra måltiden; samma princip gäller för startstämpling.
|
||||||
help:41641 = Fyll i första starttid och startintervall. Lottning innebär slumpmässig lottning, SOFT-lottning en lottning enligt SOFT:s klubbfördelningsregler. Klungstart innebär att hela klassen startar i småklungor under det intervall du anger ("utdragen" masstart). \n\nAnge intervall 0 för gemensam start.\n\nNummerlappar: Ange första nummer eller lämna blankt för inga nummerlappar. I fältet sträcka (Str.) anger du vilken sträcka som ska lottas (om klassen har flera sträckor).
|
help:41641 = Välj metod för lottning. <Lottning> är helt slumpmässig. <Lottning (MeOS)> och <SOFT-lottning> ser till löpare från samma klubb inte startar på närliggande tider.\n\n<Klungstart> innebär att hela klassen startar i småklungor under det intervall du anger ("utdragen" masstart). \n\nNummerlappar: Ange första nummer som ska användas i klassen. I fältet sträcka (Str.) anger du vilken sträcka som ska lottas (om klassen har flera sträckor).
|
||||||
help:425188 = Du kan automatiskt hantera <Ej Start> genom att läsa in SI-stationer (töm/check/start/kontroller) i SI-Config, spara inläsningen som en semikolonseparerad textfil och importera denna i MeOS. De löpare som förekommer i denna import får en registrering. Därefter kan du sätta <Ej Start> på löpare utan registrering. Läser du senare in fler löpare kan du återställa de löpare som tidigare fått Ej Start men nu fått en registrering.
|
help:425188 = Du kan automatiskt hantera <Ej Start> genom att läsa in SI-stationer (töm/check/start/kontroller) i SI-Config, spara inläsningen som en semikolonseparerad textfil och importera denna i MeOS. De löpare som förekommer i denna import får en registrering. Därefter kan du sätta <Ej Start> på löpare utan registrering. Läser du senare in fler löpare kan du återställa de löpare som tidigare fått Ej Start men nu fått en registrering.
|
||||||
help:471101 = Aktivera SI-enheten genom att välja rätt COM-port, eller genom att söka efter installerade SI-enheter. Info ger dig information om den valda enheten/porten. För att läsa in brickor ska enheten vara programmerad utan autosänd (men för radiokontroller används autosänd). Utökat protokoll rekommenderas, då det ger en stabilare uppkoppling. Enheten programmeras med SportIdents programvara SI-Config.\n\nInteraktiv inläsning används om du direkt vill ta hand om eventuella problem som felaktigt bricknummer; avmarkera om arrangemanget använder 'röd utgång'.\n\nLöpardatabasen används om du automatiskt vill lägga till inkommande löpare med hjälp av löpardatabasen. Löparens stämplingar används för att välja rätt klass.
|
help:471101 = Aktivera SI-enheten genom att välja rätt COM-port, eller genom att söka efter installerade SI-enheter. Info ger dig information om den valda enheten/porten. För att läsa in brickor ska enheten vara programmerad utan autosänd (men för radiokontroller används autosänd). Utökat protokoll rekommenderas, då det ger en stabilare uppkoppling. Enheten programmeras med SportIdents programvara SI-Config.\n\nInteraktiv inläsning används om du direkt vill ta hand om eventuella problem som felaktigt bricknummer; avmarkera om arrangemanget använder 'röd utgång'.\n\nLöpardatabasen används om du automatiskt vill lägga till inkommande löpare med hjälp av löpardatabasen. Löparens stämplingar används för att välja rätt klass.
|
||||||
help:50431 = Du är nu ansluten mot en server. För att öppna en tävling från servern, markera den i listan och välj öppna. För att lägga upp en tävling på servern, öppna först tävlingen lokalt, och använd därefter knappen ladda upp tävling. När du öppnat en tävling på servern ser du vilka andra MeOS-klienter som är anslutna mot den.\n\nOm det står (på server) efter tävlingen är den öppnad på en server och kan delas av andra MeOS-klienter. Står det (lokalt) kan man bara komma åt tävlingen från den aktuella datorn.
|
help:50431 = Du är nu ansluten mot en server. För att öppna en tävling från servern, markera den i listan och välj öppna. För att lägga upp en tävling på servern, öppna först tävlingen lokalt, och använd därefter knappen ladda upp tävling. När du öppnat en tävling på servern ser du vilka andra MeOS-klienter som är anslutna mot den.\n\nOm det står (på server) efter tävlingen är den öppnad på en server och kan delas av andra MeOS-klienter. Står det (lokalt) kan man bara komma åt tävlingen från den aktuella datorn.
|
||||||
@ -2409,3 +2409,30 @@ info:pageswithcolumns = Visa listan en sida i taget med angivet antal kolumner.
|
|||||||
Pages with columns = Sidor med kolumner
|
Pages with columns = Sidor med kolumner
|
||||||
Pages with columns, no header = Sidor med kolumner utan rubrik
|
Pages with columns, no header = Sidor med kolumner utan rubrik
|
||||||
Externa adresser = Externa adresser
|
Externa adresser = Externa adresser
|
||||||
|
info:advanceinfo = Det gick inte att starta tjänsten för förhandsinformation om resultat; resultat kommer med några sekunders fördröjning. Detta är väntat om fler än en MeOS-process körs på samma dator.
|
||||||
|
Klassen är full = Klassen är full
|
||||||
|
Flytta upp = Flytta upp
|
||||||
|
Flytta ner = Flytta ner
|
||||||
|
EFilterWrongFee = Oväntat avgift
|
||||||
|
RunnerExpectedFee = Deltagares förväntade avgift
|
||||||
|
Unexpected Fee = Oväntade anmälningsavgifter
|
||||||
|
Anmälningsdatum = Anmälningsdatum
|
||||||
|
Förväntad = Förväntad
|
||||||
|
Registrera hyrbrickor = Registrera hyrbrickor
|
||||||
|
Vill du sätta hyrbricka på befintliga löpare med dessa brickor? = Vill du sätta hyrbricka på befintliga löpare med dessa brickor?
|
||||||
|
Vill du ta bort brickan från hyrbrickslistan? = Vill du ta bort brickan från hyrbrickslistan?
|
||||||
|
Vill du tömma listan med hyrbrickor? = Vill du tömma listan med hyrbrickor?
|
||||||
|
help:registerhiredcards = Förregistrera hyrbrickor för att få automatisk hyrbricka när den används.
|
||||||
|
prefsLastExportTarget = Senaste exportmål
|
||||||
|
prefsServiceRootMap = Standardfunktion för webbserverns root
|
||||||
|
prefsshowheader = Visa sidrubriker i listor
|
||||||
|
Lagändringblankett = Lagändringblankett
|
||||||
|
Mappa rootadresssen (http:///localhost:port/) till funktion = Mappa rootadresssen (http:///localhost:port/) till funktion
|
||||||
|
ClassAvailableMaps = Klassens lediga kartor
|
||||||
|
ClassTotalMaps = Klassens antal kartor
|
||||||
|
Patrol overtime = Patrulls tid övertid
|
||||||
|
Patrol score reduction = Patrulls poängreduktion
|
||||||
|
Patrol score, rogaining = Patrullpoäng, rogaining
|
||||||
|
Rogaining points before automatic reduction = Rogainingpoäng före automatisk reduktion
|
||||||
|
Runner's course id = Deltagares banans id
|
||||||
|
Status code for cancelled entry = Statuskod för återbud
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user