MeOS version 3.7.1146 Beta 1

This commit is contained in:
Erik Melin 2020-01-26 21:18:49 +01:00
parent 7a99f0a4cd
commit 3dcdfa3b65
172 changed files with 6449 additions and 3922 deletions

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1194,19 +1194,13 @@ void RunnerDB::refreshTables() {
}
void RunnerDB::releaseTables() {
if (runnerTable)
runnerTable->releaseOwnership();
runnerTable = 0;
if (clubTable)
clubTable->releaseOwnership();
clubTable = 0;
runnerTable.reset();
clubTable.reset();
}
Table *RunnerDB::getRunnerTB()//Table mode
{
if (runnerTable == 0) {
Table *table=new Table(oe, 20, L"Löpardatabasen", "runnerdb");
const shared_ptr<Table> &RunnerDB::getRunnerTB() {
if (!runnerTable) {
auto table = make_shared<Table>(oe, 20, L"Löpardatabasen", "runnerdb");
table->addColumn("Index", 70, true, true);
table->addColumn("Id", 70, true, true);
@ -1220,7 +1214,6 @@ Table *RunnerDB::getRunnerTB()//Table mode
table->setTableProp(Table::CAN_INSERT|Table::CAN_DELETE|Table::CAN_PASTE);
table->setClearOnHide(false);
table->addOwnership();
runnerTable = table;
}
int nr = 0;
@ -1284,18 +1277,17 @@ void RunnerDB::refreshRunnerTableData(Table &table) {
}
}
Table *RunnerDB::getClubTB()//Table mode
{
const shared_ptr<Table> &RunnerDB::getClubTB() {
bool canEdit = !oe->isClient();
if (clubTable == 0) {
Table *table = new Table(oe, 20, L"Klubbdatabasen", "clubdb");
if (!clubTable) {
auto table = make_shared<Table>(oe, 20, L"Klubbdatabasen", "clubdb");
table->addColumn("Id", 70, true, true);
table->addColumn("Ändrad", 70, false);
table->addColumn("Namn", 200, false);
oClub::buildTableCol(oe, table);
oClub::buildTableCol(oe, table.get());
if (canEdit)
table->setTableProp(Table::CAN_DELETE|Table::CAN_INSERT|Table::CAN_PASTE);
@ -1303,7 +1295,6 @@ Table *RunnerDB::getClubTB()//Table mode
table->setTableProp(0);
table->setClearOnHide(false);
table->addOwnership();
clubTable = table;
}
@ -1318,7 +1309,6 @@ Table *RunnerDB::getClubTB()//Table mode
return clubTable;
}
void oDBRunnerEntry::addTableRow(Table &table) const {
bool canEdit = !oe->isClient();
@ -1377,7 +1367,7 @@ const RunnerDBEntry &oDBRunnerEntry::getRunner() const {
return db->rdb[index];
}
bool oDBRunnerEntry::inputData(int id, const wstring &input,
pair<int, bool> oDBRunnerEntry::inputData(int id, const wstring &input,
int inputId, wstring &output, bool noUpdate)
{
if (!db)
@ -1392,7 +1382,7 @@ bool oDBRunnerEntry::inputData(int id, const wstring &input,
db->nhash.clear();
db->runnerHash.clear();
db->runnerHashByClub.clear();
return true;
break;
case TID_CARD:
db->rhash.remove(rd.cardNo);
rd.cardNo = _wtoi(input.c_str());
@ -1401,7 +1391,7 @@ bool oDBRunnerEntry::inputData(int id, const wstring &input,
output = itow(rd.cardNo);
else
output = L"";
return true;
break;
case TID_NATIONAL:
if (input.empty()) {
rd.national[0] = 0;
@ -1429,7 +1419,7 @@ bool oDBRunnerEntry::inputData(int id, const wstring &input,
output = input;
break;
}
return false;
return make_pair(0, false);
}
void oDBRunnerEntry::fillInput(int id, vector< pair<wstring, size_t> > &out, size_t &selected)

View File

@ -11,7 +11,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -161,8 +161,8 @@ class RunnerDB {
private:
oEvent *oe;
Table *runnerTable;
Table *clubTable;
shared_ptr<Table> runnerTable;
shared_ptr<Table> clubTable;
static int cellEntryIndex;
@ -286,8 +286,8 @@ public:
void refreshClubTableData(Table &table);
void refreshTables();
Table *getRunnerTB();
Table *getClubTB();
const shared_ptr<Table> &getRunnerTB();
const shared_ptr<Table> &getClubTB();
void hasEnteredCompetition(__int64 extId);
@ -368,9 +368,9 @@ public:
const RunnerDBEntry &getRunner() const;
void addTableRow(Table &table) const;
bool inputData(int id, const wstring &input,
int inputId, wstring &output, bool noUpdate);
void fillInput(int id, vector< pair<wstring, size_t> > &out, size_t &selected);
pair<int, bool> inputData(int id, const wstring &input,
int inputId, wstring &output, bool noUpdate) override;
void fillInput(int id, vector< pair<wstring, size_t> > &out, size_t &selected) override;
oDBRunnerEntry(oEvent *oe);
virtual ~oDBRunnerEntry();

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -13,7 +13,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -291,7 +291,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.setInputStatus("ExportScript", stat);
gdi.setInputStatus("BrowseFile", stat);
gdi.setInputStatus("BrowseScript", stat);
if (gdi.hasField("HTMLRefresh")) {
if (gdi.hasWidget("HTMLRefresh")) {
gdi.setInputStatus("HTMLRefresh", stat);
gdi.setInputStatus("StructuredExport", stat);
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,6 +30,7 @@
#include <algorithm>
#include "oEvent.h"
#include "metalist.h"
#include "xmlparser.h"
#include "gdioutput.h"
#include "csvparser.h"
@ -37,12 +38,15 @@
#include "meos_util.h"
#include "oListInfo.h"
#include "TabClass.h"
#include "TabList.h"
#include "methodeditor.h"
#include "ClassConfigInfo.h"
#include "meosException.h"
#include "gdifonts.h"
#include "oEventDraw.h"
#include "MeOSFeatures.h"
#include "qualification_final.h"
#include "generalresult.h"
extern pEvent gEvent;
const char *visualDrawWindow = "visualdraw";
@ -70,6 +74,7 @@ TabClass::TabClass(oEvent *poe):TabBase(poe)
}
void TabClass::clearCompetitionData() {
currentResultModuleTags.clear();
pSettings.clear();
pSavedDepth = 3600;
pFirstRestart = 3600;
@ -460,15 +465,15 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
save(gdi, false); //Clears and reloads
if (gdi.hasField("Courses")) {
if (gdi.hasWidget("Courses")) {
gdi.selectItemByData("Courses", -2);
gdi.disableInput("Courses");
}
oe->setupRelay(*pc, newType, nstages, st);
if (gdi.hasField("MAdd")) {
if (gdi.hasWidget("MAdd")) {
for (const char *s : {"MCourses", "StageCourses", "MAdd", "MRemove", "MUp", "MDown"}) {
if (gdi.hasField(s)) {
if (gdi.hasWidget(s)) {
gdi.enableInput(s);
}
}
@ -481,7 +486,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
pc->synchronize();
gdi.restore();
gdi.enableInput("MultiCourse", true);
if (gdi.hasField("Courses"))
if (gdi.hasWidget("Courses"))
gdi.enableInput("Courses");
oe->adjustTeamMultiRunners(pc);
}
@ -705,6 +710,18 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
tableMode=!tableMode;
loadPage(gdi);
}
else if (bi.id == "EditModule") {
save(gdi, true);
size_t ix = gdi.getSelectedItem("Module").first;
if (ix < currentResultModuleTags.size()) {
TabList &tc = dynamic_cast<TabList &>(*gdi.getTabs().get(TListTab));
tc.getMethodEditor().show(this, gdi);
const string &mtag = currentResultModuleTags[ix];
tc.getMethodEditor().load(gdi, mtag, false);
gdi.refresh();
}
}
else if (bi.id=="Restart") {
save(gdi, true);
clearPage(gdi, true);
@ -842,56 +859,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
}
DrawSettingsCSV::write(gdi, *oe, fn, res);
/*csvparser writer;
writer.openOutput(fn.c_str());
vector<string> header;
writer.outputRow(header);
header.emplace_back("ClassId");
header.emplace_back("Class");
header.emplace_back("Competitors");
header.emplace_back("Course");
header.emplace_back("First Control");
header.emplace_back("First Start");
header.emplace_back("Interval");
header.emplace_back("Vacant");
writer.outputRow(header);
vector<string> line;
for (size_t k = 0; k<cInfo.size(); k++) {
const ClassInfo &ci = cInfo[k];
if (ci.pc) {
line.clear();
line.push_back(itos(ci.pc->getId()));
line.push_back(gdi.toUTF8(ci.pc->getName()));
line.push_back(itos(ci.pc->getNumRunners(1, false, false)));
pCourse crs = ci.pc->getCourse();
pControl ctrl = nullptr;
if (crs) {
line.push_back(gdi.toUTF8(crs->getName()));
ctrl = crs->getControl(0);
}
else line.emplace_back("");
if (ctrl) {
line.push_back(itos(ctrl->getId()));
}
else line.emplace_back("");
// Save settings with class
line.push_back(gdi.narrow(oe->getAbsTime(drawInfo.firstStart + drawInfo.baseInterval * ci.firstStart)));
line.push_back(gdi.narrow(formatTime(ci.interval * drawInfo.baseInterval)));
line.push_back(itos(ci.nVacant));
writer.outputRow(line);
}
}*/
}
else if (bi.id == "ImportDrawSettings") {
wstring fn = gdi.browseForOpen({ make_pair(lang.tl("Kalkylblad/csv"), L"*.csv") }, L"csv");
if (fn.empty())
@ -1030,7 +999,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
prepareForDrawing(gdi);
}
else if (bi.id == "DrawMode") {
if (gdi.hasField("Name"))
if (gdi.hasWidget("Name"))
save(gdi, false);
ClassId = 0;
@ -1120,7 +1089,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oListParam par;
for (int k = 0; k < oe->getNumClasses(); k++) {
if (!gdi.hasField("PLUse" + itos(k)))
if (!gdi.hasWidget("PLUse" + itos(k)))
continue;
BaseInfo *biu = gdi.setText("PLUse" + itos(k), L"", false);
if (biu) {
@ -1188,7 +1157,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oe->setProperty("DrawInterlace", allowNeighbourSameCourse ? 1 : 0);
int pairSize = 1;
if (gdi.hasField("PairSize")) {
if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
@ -1269,7 +1238,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
wstring firstStart = oe->getAbsTime(3600);
wstring minInterval = L"2:00";
wstring vacances = getDefaultVacant();
if (gdi.hasField("Vacances")) {
if (gdi.hasWidget("Vacances")) {
vacances = gdi.getText("Vacances");
setDefaultVacant(vacances);
}
@ -1277,7 +1246,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
int maxNumControl = 1;
int pairSize = 1;
if (gdi.hasField("AllowNeighbours")) {
if (gdi.hasWidget("AllowNeighbours")) {
bool allowNeighbourSameCourse = gdi.isChecked("AllowNeighbours");
oe->setProperty("DrawInterlace", allowNeighbourSameCourse ? 1 : 0);
}
@ -1296,7 +1265,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
minInterval = gdi.getText("MinInterval");
vacances = gdi.getText("Vacances");
//pairwise = gdi.isChecked("Pairwise");
if (gdi.hasField("PairSize")) {
if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
}
@ -1480,15 +1449,15 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oEvent::DrawMethod method = oEvent::DrawMethod(gdi.getSelectedItem("Method").first);
int interval = 0;
if (gdi.hasField("Interval"))
if (gdi.hasWidget("Interval"))
interval = convertAbsoluteTimeMS(gdi.getText("Interval"));
int vacanses = 0;
if (gdi.hasField("Vacanses"))
if (gdi.hasWidget("Vacanses"))
vacanses = gdi.getTextNo("Vacanses");
int leg = 0;
if (gdi.hasField("Leg")) {
if (gdi.hasWidget("Leg")) {
leg = gdi.getSelectedItem("Leg").first;
}
else if (pc && pc->getParentClass() != 0)
@ -1497,7 +1466,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
wstring bib;
bool doBibs = false;
if (gdi.hasField("Bib")) {
if (gdi.hasWidget("Bib")) {
bib = gdi.getText("Bib");
doBibs = gdi.isChecked("HandleBibs");
}
@ -1520,23 +1489,23 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
}
//bool pairwise = false;
// if (gdi.hasField("Pairwise"))
// if (gdi.hasWidget("Pairwise"))
// pairwise = gdi.isChecked("Pairwise");
int pairSize = 1;
if (gdi.hasField("PairSize")) {
if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
int maxTime = 0, restartTime = 0;
double scaleFactor = 1.0;
if (gdi.hasField("TimeRestart"))
if (gdi.hasWidget("TimeRestart"))
restartTime = oe->getRelativeTime(gdi.getText("TimeRestart"));
if (gdi.hasField("MaxAfter"))
if (gdi.hasWidget("MaxAfter"))
maxTime = convertAbsoluteTimeMS(gdi.getText("MaxAfter"));
if (gdi.hasField("ScaleFactor"))
if (gdi.hasWidget("ScaleFactor"))
scaleFactor = _wtof(gdi.getText("ScaleFactor").c_str());
if (method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::MeOS) {
@ -1623,7 +1592,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
return 0;
int leg = 0;
if (gdi.hasField("Leg")) {
if (gdi.hasWidget("Leg")) {
leg = gdi.getSelectedItem("Leg").first;
}
vector<ClassDrawSpecification> spec;
@ -1836,8 +1805,23 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oListParam par;
par.selection.insert(cid);
oListInfo info;
ClassConfigInfo cc;
if (pc->getNumDistinctRunnersMinimal() == 1) {
par.listCode = EStdStartList;
par.setLegNumberCoded(leg);
}
else {
if (pc->getClassType() == ClassType::oClassPatrol) {
par.listCode = oe->getListContainer().getType("patrolstart");
}
else if (leg >= 0) {
par.listCode = EStdTeamStartListLeg;
par.setLegNumberCoded(leg);
}
else {
par.listCode = EStdStartList;
}
}
oe->generateListInfo(par, gdi.getLineHeight(), info);
oe->generateList(gdi, false, info, true);
@ -2146,6 +2130,13 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
int num = bi.data;
updateSplitDistribution(gdi, num, bi.getExtraInt());
}
else if (bi.id == "Module") {
size_t ix = gdi.getSelectedItem("Module").first;
if (ix < currentResultModuleTags.size()) {
const string &mtag = currentResultModuleTags[ix];
gdi.hideWidget("EditModule", mtag.empty());
}
}
else if (bi.id=="Courses")
EditChanged=true;
else if (bi.id == "BibSettings") {
@ -2496,7 +2487,7 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
if (cid==0) {
gdi.restore("", true);
gdi.disableInput("MultiCourse", true);
if (gdi.hasField("Courses"))
if (gdi.hasWidget("Courses"))
gdi.enableInput("Courses");
gdi.enableEditControls(false);
gdi.setText("Name", L"");
@ -2504,19 +2495,19 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
gdi.check("AllowQuickEntry", true);
gdi.setText("NumberMaps", L"");
if (gdi.hasField("FreeStart"))
if (gdi.hasWidget("FreeStart"))
gdi.check("FreeStart", false);
if (gdi.hasField("IgnoreStart"))
if (gdi.hasWidget("IgnoreStart"))
gdi.check("IgnoreStart", false);
if (gdi.hasField("DirectResult"))
if (gdi.hasWidget("DirectResult"))
gdi.check("DirectResult", false);
if (gdi.hasField("LockStartList")) {
if (gdi.hasWidget("LockStartList")) {
gdi.check("LockStartList", false);
gdi.setInputStatus("LockStartList", false);
}
if (gdi.hasField("NoTiming"))
if (gdi.hasWidget("NoTiming"))
gdi.check("NoTiming", false);
ClassId=cid;
@ -2549,28 +2540,30 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
else
gdi.selectItemByData("StartBlock", -1);
if (gdi.hasField("Status")) {
if (gdi.hasWidget("Status")) {
vector< pair<wstring, size_t> > out;
size_t selected = 0;
pc->getDCI().fillInput("Status", out, selected);
gdi.addItem("Status", out);
gdi.selectItemByData("Status", selected);
fillResultModules(gdi, pc);
}
gdi.check("AllowQuickEntry", pc->getAllowQuickEntry());
if (gdi.hasField("NoTiming"))
if (gdi.hasWidget("NoTiming"))
gdi.check("NoTiming", pc->getNoTiming());
if (gdi.hasField("FreeStart"))
if (gdi.hasWidget("FreeStart"))
gdi.check("FreeStart", pc->hasFreeStart());
if (gdi.hasField("IgnoreStart"))
if (gdi.hasWidget("IgnoreStart"))
gdi.check("IgnoreStart", pc->ignoreStartPunch());
if (gdi.hasField("DirectResult"))
if (gdi.hasWidget("DirectResult"))
gdi.check("DirectResult", pc->hasDirectResult());
if (gdi.hasField("LockStartList")) {
if (gdi.hasWidget("LockStartList")) {
bool active = pc->getParentClass() != 0;
gdi.setInputStatus("LockStartList", active);
gdi.check("LockStartList", active && pc->lockedClassAssignment());
@ -2581,7 +2574,7 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
gdi.restore("", false);
gdi.enableInput("MultiCourse", false);
if (gdi.hasField("Courses")) {
if (gdi.hasWidget("Courses")) {
gdi.enableInput("Courses");
pCourse pcourse = pc->getCourse();
gdi.selectItemByData("Courses", pcourse ? pcourse->getId() : -2);
@ -2611,22 +2604,22 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
multiCourse(gdi, pc->getNumStages());
gdi.refresh();
if (gdi.hasField("Courses")) {
if (gdi.hasWidget("Courses")) {
gdi.addItem("Courses", lang.tl("Flera banor"), -3);
gdi.selectItemByData("Courses", -3);
gdi.disableInput("Courses");
gdi.check("CoursePool", pc->hasCoursePool());
}
if (gdi.hasField("Unordered"))
if (gdi.hasWidget("Unordered"))
gdi.check("Unordered", pc->hasUnorderedLegs());
if (gdi.hasField("LockForking")) {
if (gdi.hasWidget("LockForking")) {
gdi.check("LockForking", pc->lockedForking());
setLockForkingState(gdi, pc->hasCoursePool(), pc->lockedForking());
}
if (gdi.hasField("MCourses")) {
if (gdi.hasWidget("MCourses")) {
oe->fillCourses(gdi, "MCourses", true);
string strId = "StageCourses_label";
gdi.setTextTranslate(strId, getCourseLabel(pc->hasCoursePool()), true);
@ -2659,11 +2652,11 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
gdi.setInputStatus(string("Restart")+legno, !pc->restartIgnored(k), true);
gdi.setInputStatus(string("RestartRope")+legno, !pc->restartIgnored(k), true);
if (gdi.hasField(string("Restart")+legno))
if (gdi.hasWidget(string("Restart")+legno))
gdi.setText(string("Restart")+legno, pc->getRestartTimeS(k));
if (gdi.hasField(string("RestartRope")+legno))
if (gdi.hasWidget(string("RestartRope")+legno))
gdi.setText(string("RestartRope")+legno, pc->getRopeTimeS(k));
if (gdi.hasField(string("MultiR")+legno))
if (gdi.hasWidget(string("MultiR")+legno))
gdi.selectItemByData((string("MultiR")+legno).c_str(), pc->getLegRunner(k));
}
}
@ -2671,13 +2664,13 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
else {
gdi.restore("", true);
gdi.enableInput("MultiCourse", true);
if (gdi.hasField("Courses")) {
if (gdi.hasWidget("Courses")) {
gdi.enableInput("Courses");
pCourse pcourse = pc->getCourse();
gdi.selectItemByData("Courses", pcourse ? pcourse->getId() : -2);
}
}
if (gdi.hasField("QualificationFinal"))
if (gdi.hasWidget("QualificationFinal"))
gdi.setInputStatus("QualificationFinal", pc->getParentClass() == 0);
gdi.selectItemByData("Classes", cid);
@ -2966,44 +2959,44 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
ClassId=pc->getId();
pc->setName(name);
if (gdi.hasField("NumberMaps")) {
pc->setName(name, true);
if (gdi.hasWidget("NumberMaps")) {
pc->setNumberMaps(gdi.getTextNo("NumberMaps"));
}
if (gdi.hasField("StartName"))
if (gdi.hasWidget("StartName"))
pc->setStart(gdi.getText("StartName"));
if (gdi.hasField("ClassType"))
if (gdi.hasWidget("ClassType"))
pc->setType(gdi.getText("ClassType"));
if (gdi.hasField("StartBlock"))
if (gdi.hasWidget("StartBlock"))
pc->setBlock(gdi.getTextNo("StartBlock"));
if (gdi.hasField("Status")) {
if (gdi.hasWidget("Status")) {
pc->getDI().setEnum("Status", gdi.getSelectedItem("Status").first);
}
if (gdi.hasField("CoursePool"))
if (gdi.hasWidget("CoursePool"))
pc->setCoursePool(gdi.isChecked("CoursePool"));
if (gdi.hasField("Unordered"))
if (gdi.hasWidget("Unordered"))
pc->setUnorderedLegs(gdi.isChecked("Unordered"));
if (gdi.hasField("LockForking"))
if (gdi.hasWidget("LockForking"))
pc->lockedForking(gdi.isChecked("LockForking"));
pc->setAllowQuickEntry(gdi.isChecked("AllowQuickEntry"));
if (gdi.hasField("NoTiming"))
if (gdi.hasWidget("NoTiming"))
pc->setNoTiming(gdi.isChecked("NoTiming"));
if (gdi.hasField("FreeStart"))
if (gdi.hasWidget("FreeStart"))
pc->setFreeStart(gdi.isChecked("FreeStart"));
if (gdi.hasField("IgnoreStart"))
if (gdi.hasWidget("IgnoreStart"))
pc->setIgnoreStartPunch(gdi.isChecked("IgnoreStart"));
if (gdi.hasField("DirectResult")) {
if (gdi.hasWidget("DirectResult")) {
bool withDirect = gdi.isChecked("DirectResult");
if (withDirect && !pc->hasDirectResult() && !hasWarnedDirect &&
@ -3017,13 +3010,13 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
pc->setDirectResult(withDirect);
}
if (gdi.hasField("LockStartList")) {
if (gdi.hasWidget("LockStartList")) {
bool locked = gdi.isChecked("LockStartList");
if (pc->getParentClass())
pc->lockedClassAssignment(locked);
}
if (gdi.hasField("Courses")) {
if (gdi.hasWidget("Courses")) {
int crs = gdi.getSelectedItem("Courses").first;
if (crs == 0) {
@ -3039,8 +3032,15 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
pc->setCourse(oe->getCourse(crs));
}
if (pc->hasMultiCourse()) {
if (gdi.hasWidget("Module")) {
size_t ix = gdi.getSelectedItem("Module").first;
if (ix < currentResultModuleTags.size()) {
const string &mtag = currentResultModuleTags[ix];
pc->setResultModule(mtag);
}
}
if (pc->hasMultiCourse()) {
if (gdi.hasData("SimpleMulti")) {
bool sim = gdi.isChecked("CommonStart");
if (sim) {
@ -3059,7 +3059,7 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
char legno[10];
sprintf_s(legno, "%d", k);
if (!gdi.hasField(string("LegType")+legno))
if (!gdi.hasWidget(string("LegType")+legno))
continue;
pc->setLegType(k, LegTypes(gdi.getSelectedItem(string("LegType")+legno).first));
@ -3079,16 +3079,16 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
string key;
key = string("Restart")+legno;
if (gdi.hasField(key))
if (gdi.hasWidget(key))
pc->setRestartTime(k, gdi.getText(key));
key = string("RestartRope")+legno;
if (gdi.hasField(key))
if (gdi.hasWidget(key))
pc->setRopeTime(k, gdi.getText(key));
key = string("MultiR")+legno;
if (gdi.hasField(key)) {
if (gdi.hasWidget(key)) {
int mr = gdi.getSelectedItem(key).first;
if (pc->getLegRunner(k) != mr)
@ -3143,6 +3143,14 @@ bool TabClass::loadPage(gdioutput &gdi)
oe->checkDB();
oe->checkNecessaryFeatures();
gdi.selectTab(tabId);
TabList &tc = dynamic_cast<TabList &>(*gdi.getTabs().get(TListTab));
if (tc.getMethodEditor().isShown(this)) {
tc.getMethodEditor().show(this, gdi);
gdi.refresh();
return true;
}
clearPage(gdi, false);
int xp = gdi.getCX();
@ -3153,8 +3161,7 @@ bool TabClass::loadPage(gdioutput &gdi)
ClassesCB, "Välj vy", false, false).fixedCorner();
if (tableMode) {
Table *tbl = oe->getClassTB();
gdi.addTable(tbl, xp, 30);
gdi.addTable(oClass::getTable(oe), xp, gdi.scaleLength(30));
return true;
}
@ -3235,7 +3242,23 @@ bool TabClass::loadPage(gdioutput &gdi)
gdi.popX();
gdi.dropLine(3);
gdi.addSelection("Status", 200, 300, 0, L"Status:");
gdi.addSelection("Status", 100, 300, 0, L"Status:");
vector<pair<wstring, wstring>> statusClass;
oClass::fillClassStatus(statusClass);
vector< pair<wstring, size_t> > st;
for (auto &sc : statusClass)
st.emplace_back(lang.tl(sc.second), st.size());
gdi.addItem("Status", st);
gdi.autoGrow("Status");
gdi.popX();
gdi.dropLine(3);
gdi.addSelection("Module", 100, 400, ClassesCB, L"Resultatuträkning:");
fillResultModules(gdi, nullptr);
gdi.dropLine(0.9);
gdi.addButton("EditModule", "Redigera", ClassesCB);
gdi.hideWidget("EditModule");
gdi.dropLine(-0.9);
}
gdi.popX();
@ -3454,7 +3477,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi) {
saveClassSettingsTable(gdi, modifiedFee, modifiedBib);
oe->synchronize(true);
if (gdi.hasField("BibGap")) {
if (gdi.hasWidget("BibGap")) {
int gap = gdi.getTextNo("BibGap");
if (oe->getBibClassGap() != gap) {
oe->setBibClassGap(gap);
@ -3544,17 +3567,17 @@ void TabClass::drawDialog(gdioutput &gdi, oEvent::DrawMethod method, const oClas
int pairSize = lastPairSize;
if (gdi.hasField("FirstStart"))
if (gdi.hasWidget("FirstStart"))
firstStart = oe->getRelativeTime(gdi.getText("FirstStart"));
else if (!lastFirstStart.empty())
firstStart = oe->getRelativeTime(lastFirstStart);
if (gdi.hasField("Interval"))
if (gdi.hasWidget("Interval"))
interval = convertAbsoluteTimeMS(gdi.getText("Interval"));
else if (!lastInterval.empty())
interval = convertAbsoluteTimeMS(lastInterval);
if (gdi.hasField("PairSize")) {
if (gdi.hasWidget("PairSize")) {
pairSize = gdi.getSelectedItem("PairSize").first;
}
gdi.restore("MultiDayDraw", false);
@ -3698,10 +3721,10 @@ void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMetho
gdi.selectItemByData("Method", int(defaultMethod));
if (gdi.hasField("Vacanses")) {
if (gdi.hasWidget("Vacanses")) {
gdi.setInputStatus("Vacanses", !hasMulti);
}
if (gdi.hasField("HandleBibs")) {
if (gdi.hasWidget("HandleBibs")) {
gdi.setInputStatus("HandleBibs", !hasMulti);
if (hasMulti) {
@ -3710,7 +3733,7 @@ void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMetho
}
}
if (gdi.hasField("DoDrawBefore")) {
if (gdi.hasWidget("DoDrawBefore")) {
gdi.setInputStatus("DoDrawBefore", !hasMulti);
gdi.setInputStatus("DoDrawAfter", !hasMulti);
}
@ -3869,7 +3892,7 @@ void TabClass::showClassSelection(gdioutput &gdi, int &bx, int &by, GUICALLBACK
}
void TabClass::enableLoadSettings(gdioutput &gdi) {
if (!gdi.hasField("LoadSettings"))
if (!gdi.hasWidget("LoadSettings"))
return;
set<int> sel;
gdi.getSelection("Classes", sel);
@ -3982,21 +4005,18 @@ void TabClass::selectCourses(gdioutput &gdi, int legNo) {
}
void TabClass::updateFairForking(gdioutput &gdi, pClass pc) const {
if (!gdi.hasField("FairForking"))
if (!gdi.hasWidget("FairForking"))
return;
vector< vector<int> > forks;
vector< vector<int> > forksC;
set< pair<int, int> > unfairLegs;
if (pc->checkForking(forksC, forks, unfairLegs)) {
BaseInfo *bi = gdi.setText("FairForking", gdi.getText("FairForking"), false);
TextInfo &text = dynamic_cast<TextInfo &>(*bi);
if (pc->checkForking(forksC, forks, unfairLegs)) {
text.setColor(colorGreen);
gdi.setText("FairForking", lang.tl("The forking is fair."), true);
}
else {
BaseInfo *bi = gdi.setText("FairForking", gdi.getText("FairForking"), false);
TextInfo &text = dynamic_cast<TextInfo &>(*bi);
text.setColor(colorRed);
gdi.setText("FairForking", lang.tl("The forking is not fair."), true);
}
@ -4215,7 +4235,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set<int> &classModifiedFee
int block = gdi.getTextNo("Blck"+id);
int sort = gdi.getTextNo("Sort"+id);
if (gdi.hasField("Fee" + id)) {
if (gdi.hasWidget("Fee" + id)) {
int fee = oe->interpretCurrency(gdi.getText("Fee"+id));
int latefee = oe->interpretCurrency(gdi.getText("LateFee"+id));
int feered = oe->interpretCurrency(gdi.getText("RedFee"+id));
@ -4236,7 +4256,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set<int> &classModifiedFee
it->getDI().setInt("HighClassFeeRed", latefeered);
}
if (gdi.hasField("Bib" + id)) {
if (gdi.hasWidget("Bib" + id)) {
ListBoxInfo lbi;
bool mod = false;
if (gdi.getSelectedItem("Bib" + id, lbi)) {
@ -4248,7 +4268,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set<int> &classModifiedFee
}
modifiedBib |= mod;
if (gdi.hasField("BibTeam" + id)) {
if (gdi.hasWidget("BibTeam" + id)) {
ListBoxInfo lbi_bib;
if (gdi.getSelectedItem("BibTeam" + id, lbi_bib)) {
if (it->getBibMode() != lbi_bib.data)
@ -4270,6 +4290,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi, set<int> &classModifiedFee
it->setCourse(oe->getCourse(courseId));
it->getDI().setInt("SortIndex", sort);
it->setAllowQuickEntry(direct);
it->synchronize(true);
}
}
@ -4293,7 +4314,7 @@ void TabClass::updateStartData(gdioutput &gdi, pClass pc, int leg, bool updateDe
if (st == STChange) {
if (typeid(sdataBase) != typeid(ListBoxInfo)) {
InputInfo sdII = dynamic_cast<InputInfo &>(sdataBase);
gdi.removeControl(sdKey);
gdi.removeWidget(sdKey);
gdi.addSelection(sdII.getX(), sdII.getY(), sdKey, sdII.getWidth(), 200, MultiCB);
setParallelOptions(sdKey, gdi, pc, leg);
}
@ -4304,7 +4325,7 @@ void TabClass::updateStartData(gdioutput &gdi, pClass pc, int leg, bool updateDe
else {
if (typeid(sdataBase) != typeid(InputInfo)) {
ListBoxInfo sdLBI = dynamic_cast<ListBoxInfo &>(sdataBase);
gdi.removeControl(sdKey);
gdi.removeWidget(sdKey);
string val = "-";
gdi.addInput(sdLBI.getX(), sdLBI.getY(), sdKey, pc->getStartDataS(leg), 8, MultiCB);
}
@ -4452,19 +4473,19 @@ void TabClass::setLockForkingState(gdioutput &gdi, const oClass &c) {
}
void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockState) {
if (gdi.hasField("DefineForking"))
if (gdi.hasWidget("DefineForking"))
gdi.setInputStatus("DefineForking", !lockState && !poolState);
if (gdi.hasField("LockForking"))
if (gdi.hasWidget("LockForking"))
gdi.setInputStatus("LockForking", !poolState);
int legno = 0;
while (gdi.hasField("@Course" + itos(legno))) {
while (gdi.hasWidget("@Course" + itos(legno))) {
gdi.setInputStatus("@Course" + itos(legno++), !lockState || poolState);
}
for (string s : {"MCourses", "StageCourses", "MAdd", "MRemove"}) {
if (gdi.hasField(s)) {
if (gdi.hasWidget(s)) {
gdi.setInputStatus(s, !lockState || poolState);
}
}
@ -4472,7 +4493,7 @@ void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockStat
bool moveUp = false;
bool moveDown = false;
if (gdi.hasField("MCourses")) {
if (gdi.hasWidget("MCourses")) {
ListBoxInfo lbi;
if (gdi.getSelectedItem("StageCourses", lbi)) {
if (lbi.index > 0)
@ -4483,10 +4504,10 @@ void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockStat
}
}
if (gdi.hasField("MUp")) {
if (gdi.hasWidget("MUp")) {
gdi.setInputStatus("MUp", (!lockState || poolState) && moveUp);
}
if (gdi.hasField("MDown")) {
if (gdi.hasWidget("MDown")) {
gdi.setInputStatus("MDown", (!lockState || poolState) && moveDown);
}
}
@ -4780,3 +4801,28 @@ void TabClass::setDefaultVacant(const wstring &v) {
if (val >= 0 && val <= 100)
oe->setProperty("VacantPercent", val);
}
void TabClass::fillResultModules(gdioutput &gdi, pClass pc) {
string tag;
if (pc)
tag = pc->getResultModuleTag();
vector< pair<wstring, size_t> > st;
vector< pair<int, pair<string, wstring> > > mol;
oe->loadGeneralResults(false, true);
oe->getGeneralResults(false, mol, true);
currentResultModuleTags.clear();
st.emplace_back(lang.tl("Standard"), 0);
currentResultModuleTags.emplace_back("");
int current = 0;
for (size_t k = 0; k < mol.size(); k++) {
st.emplace_back(mol[k].second.second, k+1);
if (tag == mol[k].second.first)
current = k+1;
currentResultModuleTags.push_back(mol[k].second.first);
}
gdi.addItem("Module", st);
gdi.autoGrow("Module");
gdi.selectItemByData("Module", current);
gdi.hideWidget("EditModule", current == 0);
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -159,6 +159,9 @@ class TabClass :
wstring getDefaultVacant();
void setDefaultVacant(const wstring &val);
vector<string> currentResultModuleTags;
void fillResultModules(gdioutput &gdi, pClass pc);
public:
void clearCompetitionData();

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -132,10 +132,11 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
pClub pc=oe->getClub(lbi.data);
if (pc) {
gdi.clearPage(true);
oe->calculateTeamResults(false);
oe->sortTeams(ClassStartTime, 0, true);
oe->calculateResults({}, oEvent::ResultType::ClassResult);
oe->sortRunners(ClassStartTime);
oe->calculateTeamResults(set<int>({}), oEvent::ResultType::ClassResult);
oe->sortTeams(ClassStartTime, 0, true);
int pay, paid;
{
map<int, int> ppm;
@ -581,7 +582,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
else if (type == GUI_LINK) {
TextInfo *ti = static_cast<TextInfo*>(data);
if (ti->id == "CmpSettings") {
if (gdi.hasField("SaveSettings"))
if (gdi.hasWidget("SaveSettings"))
gdi.sendCtrlMessage("SaveSettings");
TabCompetition &tc = dynamic_cast<TabCompetition &>(*gdi.getTabs().get(TCmpTab));
tc.loadPage(gdi);
@ -592,7 +593,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
}
else if (type == GUI_CLEAR) {
if (gdi.isInputChanged("")) {
if (gdi.hasField("SaveSettings")) {
if (gdi.hasWidget("SaveSettings")) {
gdi.sendCtrlMessage("SaveSettings");
}
}
@ -664,8 +665,7 @@ bool TabClub::loadPage(gdioutput &gdi)
gdi.dropLine(2);
gdi.addString("", 10, "help:29758");
gdi.dropLine(1);
Table *tbl=oe->getClubsTB();
gdi.addTable(tbl, gdi.getCX(), gdi.getCY());
gdi.addTable(oClub::getTable(oe), gdi.getCX(), gdi.getCY());
gdi.refresh();
return true;
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -60,6 +60,7 @@
#include <cassert>
#include <cmath>
#include <io.h>
#include "generalresult.h"
void Setup(bool overwrite, bool overWriteall);
void exportSetup();
@ -132,11 +133,11 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
oe->updateStartTimes(delta);
}
oe->setDate(date);
oe->setDate(date, true);
oe->useLongTimes(longTimes);
oe->setName(gdi.getText("Name"));
oe->setName(gdi.getText("Name"), true);
oe->setAnnotation(gdi.getText("Annotation"));
oe->setZeroTime(zt);
oe->setZeroTime(zt, true);
oe->synchronize();
@ -872,7 +873,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.disableInput("ExpandTResults", true);
gdi.disableInput("SelectAll", true);
gdi.disableInput("SelectNone", true);
if (gdi.hasField("ClassNewEntries")) {
if (gdi.hasWidget("ClassNewEntries")) {
gdi.getSelection("ClassNewEntries", allTransfer);
transferNoCompet = gdi.isChecked("TransferEconomy");
}
@ -977,7 +978,6 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.addButton("MultiEvent", "Återgå", CompetitionCB);
gdi.scrollToBottom();
gdi.refresh();
}
else
throw std::exception("Kunde inte lokalisera nästa etapp");
@ -1406,7 +1406,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
ci = &events[eventIndex];
bool removeRemoved = true;
if (gdi.hasField("RemoveRemoved"))
if (gdi.hasWidget("RemoveRemoved"))
removeRemoved = gdi.isChecked("RemoveRemoved");
wstring course = gdi.getText("FileName", true);
@ -1431,7 +1431,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
lastEntry = gdi.getText("LastEntryDate");
}
if (gdi.hasField("EventorImport")) {
if (gdi.hasWidget("EventorImport")) {
gdi.disableInput("EventorImport");
gdi.disableInput("FileName");
gdi.disableInput("FirstStart");
@ -1504,7 +1504,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.addString("", 1, "Skapar ny tävling");
oe->newCompetition(L"New");
oe->importXML_EntryData(gdi, tEvent, false, false, noFilter, noType);
oe->setZeroTime(formatTimeHMS(zeroTime));
oe->setZeroTime(formatTimeHMS(zeroTime), false);
oe->getDI().setDate("OrdinaryEntry", lastEntry);
if (ci) {
if (!ci->account.empty())
@ -1598,7 +1598,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
}
gdi.scrollToBottom();
gdi.dropLine();
if (gdi.hasField("Cancel"))
if (gdi.hasWidget("Cancel"))
gdi.disableInput("Cancel"); // Disable "cancel" above
gdi.fillRight();
if (id > 0)
@ -1740,10 +1740,10 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (save.empty())
throw meosException("Filnamn kan inte vara tomt");
bool individual = !gdi.hasField("ExportTeam") || gdi.isChecked("ExportTeam");
bool individual = !gdi.hasWidget("ExportTeam") || gdi.isChecked("ExportTeam");
bool includeStage = true;
if (gdi.hasField("IncludeRaceNumber"))
if (gdi.hasWidget("IncludeRaceNumber"))
includeStage = gdi.isChecked("IncludeRaceNumber");
gdi.getSelection("ClassNewEntries", allTransfer);
@ -1784,7 +1784,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (save.empty())
throw meosException("Filnamn kan inte vara tomt");
//bool individual = !gdi.hasField("ExportTeam") || gdi.isChecked("ExportTeam");
//bool individual = !gdi.hasWidget("ExportTeam") || gdi.isChecked("ExportTeam");
gdi.getSelection("ClassNewEntries", allTransfer);
checkReadyForResultExport(gdi, allTransfer);
@ -1795,7 +1795,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
bool unroll = gdi.isChecked("UnrollLoops"); // If not applicable, field does not exist.
bool includeStage = true;
if (gdi.hasField("IncludeRaceNumber"))
if (gdi.hasWidget("IncludeRaceNumber"))
includeStage = gdi.isChecked("IncludeRaceNumber");
gdi.setWaitCursor(true);
@ -2259,7 +2259,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
}
else if (type==GUI_CLEAR) {
if (gdi.isInputChanged("")) {
if (gdi.hasField("SaveSettings")) {
if (gdi.hasWidget("SaveSettings")) {
gdi.sendCtrlMessage("SaveSettings");
}
else {
@ -2310,7 +2310,7 @@ int TabCompetition::restoreCB(gdioutput &gdi, int type, void *data) {
else {
const wstring &name = oe->getName();
if (name.find_last_of(L"}") != name.length()-1)
oe->setName(name + L" {" + lang.tl(L"återställd") + L"}");
oe->setName(name + L" {" + lang.tl(L"återställd") + L"}", false);
oe->restoreBackup();
@ -2357,7 +2357,7 @@ void TabCompetition::copyrightLine(gdioutput &gdi) const
gdi.dropLine(0.4);
gdi.fillDown();
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2019 Melin Software HB"));
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2020 Melin Software HB"));
gdi.dropLine(1);
gdi.popX();
@ -2387,7 +2387,7 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
gdi.dropLine(1.5);
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2019 Melin Software HB"));
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2020 Melin Software HB"));
gdi.dropLine();
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
"(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB,"
@ -3210,14 +3210,14 @@ void TabCompetition::loadRunnerDB(gdioutput &gdi, int tableToShow, bool updateTa
if (tableToShow == 1) {
oe->updateRunnerDatabase();
Table *tb = oe->getRunnerDatabase().getRunnerTB();
gdi.addTable(tb, 40, gdi.getCY());
auto tb = oe->getRunnerDatabase().getRunnerTB();
gdi.addTable(tb, gdi.scaleLength(40), gdi.getCY());
gdi.registerEvent("CellAction", CompetitionCB);
}
else if (tableToShow == 2) {
oe->updateRunnerDatabase();
Table *tb = oe->getRunnerDatabase().getClubTB();
gdi.addTable(tb, 40, gdi.getCY());
auto tb = oe->getRunnerDatabase().getClubTB();
gdi.addTable(tb, gdi.scaleLength(40), gdi.getCY());
}
gdi.refresh();
@ -3646,17 +3646,17 @@ TabCompetition::FlowOperation TabCompetition::checkStageFilter(gdioutput & gdi,
gdi.scrollToBottom();
gdi.refresh();
gdi.runSubCommand();
while (gdi.hasField("OK_Stage") && gdi.getExtraInt("OK_Stage") == 0 && gdi.getExtraInt("Cancel_Stage") == 0) {
while (gdi.hasWidget("OK_Stage") && gdi.getExtraInt("OK_Stage") == 0 && gdi.getExtraInt("Cancel_Stage") == 0) {
mainMessageLoop(0, 10);
}
bool ok = false, cancel = false;
if (gdi.hasField("OK_Stage")) {
if (gdi.hasWidget("OK_Stage")) {
ok = gdi.getExtraInt("OK_Stage") != 0;
cancel = gdi.getExtraInt("Cancel_Stage") != 0;
gdi.removeControl("OK_Stage");
gdi.removeControl("Cancel_Stage");
gdi.removeWidget("OK_Stage");
gdi.removeWidget("Cancel_Stage");
if (stageFilter)
gdi.disableInput("Stage");
if (idtype)
@ -3827,20 +3827,20 @@ void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
}
void TabCompetition::setExportOptionsStatus(gdioutput &gdi, int format) const {
if (gdi.hasField("LegType")) {
if (gdi.hasWidget("LegType")) {
gdi.setInputStatus("LegType", format == ImportFormats::IOF30 || format == ImportFormats::IOF203); // Enable on IOF-XML
}
if (gdi.hasField("ExportTeam")) {
if (gdi.hasWidget("ExportTeam")) {
gdi.setInputStatus("ExportTeam", format == ImportFormats::IOF30); // Enable on IOF-XML
}
if (gdi.hasField("ExportSplitTimes")) {
if (gdi.hasWidget("ExportSplitTimes")) {
gdi.setInputStatus("ExportSplitTimes", format == ImportFormats::OE);
if (format == ImportFormats::IOF203 || format == ImportFormats::IOF30)
gdi.check("ExportSplitTimes", true);
}
if (gdi.hasField("IncludeRaceNumber")) {
if (gdi.hasWidget("IncludeRaceNumber")) {
gdi.setInputStatus("IncludeRaceNumber", format == ImportFormats::IOF30); // Enable on IOF-XML
}
@ -4047,7 +4047,7 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
oe->getPayModes(modes);
for (size_t k = 0; k < modes.size(); k++) {
string field = "M"+itos(k);
if (gdi.hasField(field)) {
if (gdi.hasWidget(field)) {
wstring mode = gdi.getText("M"+itos(k));
int id = gdi.getBaseInfo(field.c_str()).getExtraInt();
oe->setPayMode(id, mode);

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -96,7 +96,7 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
gdi.setText("Name", pc->getName());
gdi.setText("TimeAdjust", pc->getTimeAdjustS());
gdi.setText("MinTime", pc->getMinTimeS());
if (gdi.hasField("Point"))
if (gdi.hasWidget("Point"))
gdi.setText("Point", pc->getRogainingPointsS());
controlId = pc->getId();
@ -114,7 +114,7 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
if (st == oControl::StatusNoTiming)
gdi.disableInput("TimeAdjust");
if (gdi.hasField("Point") && st != oControl::StatusRogaining)
if (gdi.hasWidget("Point") && st != oControl::StatusRogaining)
gdi.disableInput("Point");
}
}
@ -127,7 +127,7 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
gdi.setText("ControlID", makeDash(L"-"), true);
gdi.setText("TimeAdjust", L"00:00");
if (gdi.hasField("Point"))
if (gdi.hasWidget("Point"))
gdi.setText("Point", L"");
gdi.disableInput("Remove");
@ -169,7 +169,7 @@ void TabControl::save(gdioutput &gdi)
pc->setRogainingPoints(0);
}
else {
if (gdi.hasField("Point")) {
if (gdi.hasWidget("Point")) {
pc->setMinTime(0);
pc->setRogainingPoints(gdi.getTextNo("Point"));
}
@ -355,7 +355,7 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="Visitors") {
save(gdi);
Table *table=new Table(oe, 20, L"Kontroll X#" + itow(controlId), "controlvisitor");
shared_ptr<Table> table=make_shared<Table>(oe, 20, L"Kontroll X#" + itow(controlId), "controlvisitor");
table->addColumn("Id", 70, true, true);
table->addColumn("Ändrad", 70, false);
@ -379,7 +379,7 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
gdi.refresh();
}
else if (bi.id=="Courses") {
Table *table=new Table(oe, 20, L"Kontroll X#" + itow(controlId), "controlcourse");
auto table=make_shared<Table>(oe, 20, L"Kontroll X#" + itow(controlId), "controlcourse");
table->addColumn("Id", 70, true, true);
table->addColumn("Ändrad", 70, false);
@ -445,8 +445,7 @@ bool TabControl::loadPage(gdioutput &gdi)
ControlsCB, "Välj vy", false, false).fixedCorner();
if (tableMode) {
Table *tbl=oe->getControlTB();
gdi.addTable(tbl, xp, 30);
gdi.addTable(oControl::getTable(oe), xp, gdi.scaleLength(30));
return true;
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -59,7 +59,7 @@ void LoadClassPage(gdioutput &gdi);
void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
{
if (gdi.hasField("Rogaining")) {
if (gdi.hasWidget("Rogaining")) {
gdi.setText("TimeLimit", L"");
gdi.disableInput("TimeLimit");
gdi.setText("PointLimit", L"");
@ -77,7 +77,8 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
wstring uis = pc->getControlsUI();
gdi.setText("Controls", uis);
gdi.setText("CourseExpanded", encodeCourse(uis, pc->useFirstAsStart(), pc->useLastAsFinish()), true);
gdi.setText("CourseExpanded", encodeCourse(uis, pc->getMaximumRogainingTime() > 0,
pc->useFirstAsStart(), pc->useLastAsFinish()), true);
gdi.setText("Name", pc->getName());
@ -88,7 +89,7 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
gdi.check("FirstAsStart", pc->useFirstAsStart());
gdi.check("LastAsFinish", pc->useLastAsFinish());
if (gdi.hasField("Rogaining")) {
if (gdi.hasWidget("Rogaining")) {
int rt = pc->getMaximumRogainingTime();
int rp = pc->getMinimumRogainingPoints();
@ -215,20 +216,20 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
gdi.setInputStatus("DrawCourse", pc != 0);
}
int CourseCB(gdioutput *gdi, int type, void *data)
{
int CourseCB(gdioutput *gdi, int type, void *data) {
TabCourse &tc = dynamic_cast<TabCourse &>(*gdi->getTabs().get(TCourseTab));
return tc.courseCB(*gdi, type, data);
}
void TabCourse::save(gdioutput &gdi, int canSwitchViewMode)
{
void TabCourse::save(gdioutput &gdi, int canSwitchViewMode) {
DWORD cid = courseId;
pCourse pc;
wstring name=gdi.getText("Name");
if (cid == 0 && name.empty())
return;
if (name.empty()) {
gdi.alert("Banan måste ha ett namn.");
return;
@ -292,7 +293,7 @@ void TabCourse::save(gdioutput &gdi, int canSwitchViewMode)
else
pc->setShorterVersion(false, 0);
if (gdi.hasField("Rogaining")) {
if (gdi.hasWidget("Rogaining")) {
string t;
pc->setMaximumRogainingTime(convertAbsoluteTimeMS(gdi.getText("TimeLimit")));
pc->setMinimumRogainingPoints(_wtoi(gdi.getText("PointLimit").c_str()));
@ -338,6 +339,12 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
if (bi.id=="Save") {
save(gdi, 1);
}
else if (bi.id == "SwitchMode") {
if (!tableMode)
save(gdi, true);
tableMode = !tableMode;
loadPage(gdi);
}
else if (bi.id == "LegLengths") {
save(gdi, 2);
@ -723,9 +730,22 @@ bool TabCourse::loadPage(gdioutput &gdi) {
gdi.getData("RunnerID", RunnerID);
gdi.clearPage(false);
int xp = gdi.getCX();
gdi.setData("ClassID", ClassID);
gdi.setData("RunnerID", RunnerID);
string switchMode;
const int button_w = gdi.scaleLength(90);
switchMode = tableMode ? "Formulärläge" : "Tabelläge";
gdi.addButton(2, 2, button_w, "SwitchMode", switchMode,
CourseCB, "Välj vy", false, false).fixedCorner();
if (tableMode) {
gdi.addTable(oCourse::getTable(oe), xp, gdi.scaleLength(30));
return true;
}
gdi.addString("", boldLarge, "Banor");
gdi.pushY();
@ -1125,17 +1145,21 @@ oEvent::DrawMethod TabCourse::getDefaultMethod() const {
void TabCourse::clearCompetitionData() {
courseId = 0;
addedCourse = false;
tableMode = false;
}
void TabCourse::refreshCourse(const wstring &text, gdioutput &gdi) {
bool firstAsStart = gdi.isChecked("FirstAsStart");
bool lastAsFinish = gdi.isChecked("LastAsFinish");
wstring controls = encodeCourse(text, firstAsStart, lastAsFinish);
bool rogaining = gdi.hasWidget("Rogaining") && gdi.getSelectedItem("Rogaining").first == 1;
wstring controls = encodeCourse(text, rogaining, firstAsStart, lastAsFinish);
if (controls != gdi.getText("CourseExpanded"))
gdi.setText("CourseExpanded", controls, true);
}
wstring TabCourse::encodeCourse(const wstring &in, bool firstStart, bool lastFinish) {
wstring TabCourse::encodeCourse(const wstring &in, bool rogaining, bool firstStart, bool lastFinish) {
vector<int> newC;
string ins;
wide2String(in, ins);
@ -1144,6 +1168,8 @@ wstring TabCourse::encodeCourse(const wstring &in, bool firstStart, bool lastFin
wstring out;
out.reserve(in.length() * 2);
wstring bf;
if (!rogaining) {
for (size_t i = 0; i < newC.size(); ++i) {
if (i == 0 && (newC.size() > 1 || firstStart)) {
out += lang.tl("Start");
@ -1174,6 +1200,22 @@ wstring TabCourse::encodeCourse(const wstring &in, bool firstStart, bool lastFin
out += formatControl(newC[i], bf);
}
}
}
else {
int pcnt = 0;
for (size_t i = 0; i < newC.size(); ++i) {
if (i > 0)
out += L"; ";
auto pc = oe->getControl(newC[i]);
if (pc)
pcnt += pc->getRogainingPoints();
out += formatControl(newC[i], bf);
}
if (pcnt > 0)
out += L" = " + itow(pcnt) + L"p";
}
return out;
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -38,6 +38,8 @@ class TabCourse :
wstring point_limit;
wstring point_reduction;
bool tableMode = false;
void fillCourseControls(gdioutput &gdi, const wstring &ctrl);
void fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops);
@ -47,7 +49,7 @@ class TabCourse :
oEvent::DrawMethod getDefaultMethod() const;
wstring encodeCourse(const wstring &in, bool firstStart, bool lastFinish);
wstring encodeCourse(const wstring &in, bool rogaining, bool firstStart, bool lastFinish);
void refreshCourse(const wstring &text, gdioutput &gdi);
const wstring &formatControl(int id, wstring &bf) const;

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -52,12 +52,14 @@
#include "animationdata.h"
#include <algorithm>
#include "HTMLWriter.h"
#include "generalresult.h"
const static int CUSTOM_OFFSET = 10;
const static int NUMTEXTSAMPLE = 13;
const static int ForcePageBreak = 1024;
const static int IgnoreLimitPer = 512;
const static int AddTeamRogaining = 5;
const static int AddTeamClasses = 4;
const static int AddPatrolClasses = 3;
const static int AddRogainingClasses = 2;
@ -65,20 +67,12 @@ const static int AddAllClasses = 1;
TabList::TabList(oEvent *poe):TabBase(poe)
{
listEditor = 0;
methodEditor = 0;
lastHtmlTarget = poe->getPropertyString("LastExportTarget", L"");
clearCompetitionData();
}
TabList::~TabList(void)
{
delete listEditor;
delete methodEditor;
listEditor = 0;
methodEditor = 0;
for (size_t k = 0; k < liveResults.size(); k++) {
delete liveResults[k];
liveResults[k] = 0;
@ -140,7 +134,7 @@ int NoStartRunnerCB(gdioutput *gdi, int type, void *data)
pRunner p = tc.getEvent()->getRunner(id, 0);
if (p) {
p->setStatus(StatusDNS, true, false);
p->setStatus(StatusDNS, true, oBase::ChangeType::Update);
p->synchronize();
ti->callBack=0;
ti->highlight=false;
@ -368,7 +362,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (bi.id == "ClassSelection") {
gdioutput *gdi_settings = getExtraWindow("list_class", true);
if (!gdi_settings) {
gdi_settings = createExtraWindow("list_class", lang.tl("Klassval"), gdi.scaleLength(350), gdi.scaleLength(600), true);
gdi_settings = createExtraWindow("list_class", lang.tl("Klassval"), gdi.scaleLength(350), gdi.scaleLength(650), true);
}
if (gdi_settings) {
loadClassSettings(*gdi_settings, gdi.getTag());
@ -560,7 +554,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
lst.insert(-1);
gdi.setSelection("ListSelection", lst);
if (gdi.hasField("ResultType")) {
if (gdi.hasWidget("ResultType")) {
ListBoxInfo entry;
gdi.getSelectedItem("ResultType", entry);
gdi.setInputStatus("Generate", int(entry.data) >= 0);
@ -569,7 +563,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="SelectNone") {
set<int> lst;
gdi.setSelection("ListSelection", lst);
if (gdi.hasField("ResultType")) {
if (gdi.hasWidget("ResultType")) {
gdi.setInputStatus("Generate", false);
}
}
@ -580,18 +574,18 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
const char *ctype = (char *)gdi.getData("Type");
saveExtraLines(*oe, ctype, gdi);
if (gdi.hasField("SplitAnalysis")) {
if (gdi.hasWidget("SplitAnalysis")) {
int aflag = (gdi.isChecked("SplitAnalysis") ? 0 : 1) + (gdi.isChecked("Speed") ? 0 : 2)
+ (gdi.isChecked("Results") ? 0 : 4);
oe->getDI().setInt("Analysis", aflag);
}
if (gdi.hasField("WideFormat")) {
if (gdi.hasWidget("WideFormat")) {
bool wide = gdi.isChecked("WideFormat");
oe->setProperty("WideSplitFormat", wide);
if (wide && gdi.hasField("NumPerPage")) {
if (wide && gdi.hasWidget("NumPerPage")) {
pair<int, bool> res = gdi.getSelectedItem("NumPerPage");
if (res.second)
oe->setProperty("NumSplitsOnePage", res.first);
@ -665,19 +659,12 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
loadGeneralList(gdi);
}
else if (bi.id == "EditList") {
if (!listEditor)
listEditor = new ListEditor(oe);
gdi.clearPage(false);
listEditor->show(gdi);
getListEditor().show(this, gdi);
gdi.refresh();
}
else if (bi.id == "EditMethod") {
if (!methodEditor)
methodEditor = new MethodEditor(oe);
gdi.clearPage(false);
methodEditor->show(gdi);
getMethodEditor().show(this, gdi);
gdi.refresh();
}
else if (bi.id=="ResultIndividual") {
@ -686,7 +673,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
getResultIndividual(par, cnf);
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, false);
readSettings(gdi, par, true);
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
@ -698,7 +685,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oListParam par;
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, false);
par.listCode = EStdResultList;
readSettings(gdi, par, true);
@ -901,7 +888,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
par.back().listCode = EIndCourseList;
par.back().showInterTitle = false;
par.back().setLegNumberCoded(-1);
cnf.getIndividual(par.back().selection);
cnf.getIndividual(par.back().selection, true);
}
oe->generateListInfo(par, gdi.getLineHeight(), currentList);
@ -923,7 +910,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
oListParam par;
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, false);
par.listCode = EIndPriceList;
par.showHeader = gdi.isChecked("ShowHeader");
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
@ -956,6 +943,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
bool isStartList = bi.id.substr(0, 7) == "StartL:";
bool allClasses = baseType == AddAllClasses;
bool rogaining = baseType == AddRogainingClasses;
bool rogainingTeam = baseType == AddTeamRogaining;
bool patrol = baseType == AddPatrolClasses;
bool team = baseType == AddTeamClasses;
oe->sanityCheck(gdi, bi.id.substr(0, 7) == "Result:");
@ -979,6 +967,11 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oe->getClassConfigurationInfo(cnf);
cnf.getRogaining(par.selection);
}
else if (rogainingTeam) {
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
cnf.getRogaining(par.selection);
}
else if (team) {
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
@ -987,7 +980,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (!isReport && !allClasses) {
ClassConfigInfo cnf;
oe->getClassConfigurationInfo(cnf);
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, isStartList);
cnf.getPatrol(par.selection);
}
@ -1044,7 +1037,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oListInfo::EBaseType type = oe->getListContainer().getList(index).getListType();
if (oListInfo::addRunners(type))
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, true);
if (oListInfo::addPatrols(type))
cnf.getPatrol(par.selection);
if (oListInfo::addTeams(type))
@ -1186,7 +1179,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
}
else if (lbi.id == "ListSelection") {
gdi.getSelection(lbi.id, lastClassSelection);
if (gdi.hasField("ResultType")) {
if (gdi.hasWidget("ResultType")) {
ListBoxInfo entry;
gdi.getSelectedItem("ResultType", entry);
gdi.setInputStatus("Generate", !lastClassSelection.empty() && int(entry.data) >= 0);
@ -1225,7 +1218,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
oe->synchronize(false);
oe->getListContainer().load(MetaListContainer::ExternalList, xlist, false);
oe->synchronize(true);
oe->loadGeneralResults(true);
oe->loadGeneralResults(true, false);
}
ButtonInfo bi;
bi.id = "ImportCustom";
@ -1261,10 +1254,10 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (ti.id == "EditInstalled") {
int ix = ti.getExtraInt();
if (!listEditor)
listEditor = new ListEditor(oe);
listEditor = make_shared<ListEditor>(oe);
gdi.clearPage(false);
listEditor->load(oe->getListContainer(), ix);
listEditor->show(gdi);
listEditor->show(this, gdi);
gdi.refresh();
}
}
@ -1646,7 +1639,7 @@ void TabList::handleRememberSettings(gdioutput &gdi, BaseInfo &info, GuiEventTyp
}
oe->synchronize(true);
dest_gdi.removeControl("Remember");
dest_gdi.removeWidget("Remember");
gdi.closeWindow();
}
else if (bi.id == "DoMerge") {
@ -1876,13 +1869,13 @@ void TabList::handleListSettings(gdioutput &gdi, BaseInfo &info, GuiEventType ty
addAnimationSettings(gdi, tmpSettingsParam);
}
else {
if (gdi.hasField("Time"))
if (gdi.hasWidget("Time"))
saveAnimationSettings(gdi, tmpSettingsParam);
gdi.removeControl("Time");
gdi.removeControl("NPage");
gdi.removeControl("Margin");
gdi.removeControl("Animate");
gdi.removeWidget("Time");
gdi.removeWidget("NPage");
gdi.removeWidget("Margin");
gdi.removeWidget("Animate");
}
gdi.refresh();
}
@ -2000,7 +1993,7 @@ void TabList::handleHTMLSettings(gdioutput &gdi, BaseInfo &info, GuiEventType ty
int time_ms = 0;
double scale = 0;
if (gdi.hasField("Margin")) {
if (gdi.hasWidget("Margin")) {
margin = gdi.getTextNo("Margin");
if (gdi.isChecked("UseRows"))
rows = gdi.getTextNo("Rows");
@ -2129,6 +2122,14 @@ void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
gdi.dropLine(2.5);
gdi.fillDown();
gdi.addSelection("AgeFilter", 200, 150, nullptr, L"Åldersfiltrering:");
vector<pair<wstring, size_t>> ages;
ages.emplace_back(L"Alla", size_t(oListParam::AgeFilter::All));
ages.emplace_back(L"Ungdom", size_t(oListParam::AgeFilter::OnlyYouth));
ages.emplace_back(L"Vuxna", size_t(oListParam::AgeFilter::ExludeYouth));
gdi.addItem("AgeFilter", ages);
gdi.selectItemByData("AgeFilter", int(currentList.getParam().ageFilter));
gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, currentList.getParam().pageBreak).setHandler(&settingsClassSelection);
gdi.addCheckbox("ShowHeader", "Visa rubrik", 0, currentList.getParam().showHeader).setHandler(&settingsClassSelection);
@ -2141,12 +2142,6 @@ void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
gdi.addButton("Cancel", "Avbryt").setCancel().setHandler(&settingsClassSelection);
gdi.dropLine(2.5);
gdi.popX();
//
// int ey = gdi.getCY() + gdi.scaleLength(4);
// int ex = gdi.getWidth();
// RECT rc = { sx, sy, ex, ey };
// gdi.addRectangle(rc, colorLightBlue);
gdi.refresh();
}
@ -2159,6 +2154,9 @@ void TabList::handleClassSettings(gdioutput &gdi, BaseInfo &info, GuiEventType t
oListParam &param = currentList.getParam();
param.lockUpdate = true;
gdi.getSelection("ListSelection", param.selection);
auto filter = gdi.getSelectedItem("AgeFilter");
param.ageFilter = oListParam::AgeFilter(filter.first);
bool pb = gdi.isChecked("PageBreak");
param.pageBreak = pb;
@ -2347,6 +2345,19 @@ bool TabList::loadPage(gdioutput &gdi)
oe->checkDB();
oe->synchronize();
gdi.selectTab(tabId);
if (getMethodEditor().isShown(this)) {
getMethodEditor().show(this, gdi);
gdi.refresh();
return true;
}
if (getListEditor().isShown(this)) {
getListEditor().show(this, gdi);
gdi.refresh();
return true;
}
noReEvaluate = false;
gdi.clearPage(false);
if (SelectedList!="") {
@ -2402,6 +2413,11 @@ bool TabList::loadPage(gdioutput &gdi)
}
}
if (cnf.hasRogainingTeam()) {
checkWidth(gdi);
gdi.addButton("StartL:teamstartlist", "Rogaining", ListsCB).setExtra(AddRogainingClasses);
}
checkWidth(gdi);
gdi.addButton("MinuteStartList", "Minutstartlista", ListsCB);
@ -2496,6 +2512,11 @@ bool TabList::loadPage(gdioutput &gdi)
gdi.addButton("Result:rogainingind", "Rogaining", ListsCB).setExtra(AddRogainingClasses);
}
if (cnf.hasRogainingTeam()) {
checkWidth(gdi);
gdi.addButton("Result:teamrogainingresult", "Rogaining", ListsCB).setExtra(AddTeamRogaining);
}
checkWidth(gdi);
gdi.addButton("ResultList", "Avancerat...", ListsCB);
@ -2680,7 +2701,7 @@ bool TabList::loadPage(gdioutput &gdi)
}
void TabList::enableWideFormat(gdioutput &gdi, bool wide) {
if (gdi.hasField("NumPerPage")) {
if (gdi.hasWidget("NumPerPage")) {
gdi.setInputStatus("NumPerPage", wide);
bool needTime = gdi.getSelectedItem("NumPerPage").first != 1;
@ -2982,10 +3003,8 @@ void TabList::clearCompetitionData() {
lastLeg = 0;
lastFilledResultClassType = -1;
delete listEditor;
delete methodEditor;
listEditor = 0;
methodEditor = 0;
listEditor.reset();
methodEditor.reset();
}
void TabList::setAnimationMode(gdioutput &gdi) {
@ -2997,7 +3016,7 @@ void TabList::setAnimationMode(gdioutput &gdi) {
void TabList::getStartIndividual(oListParam &par, ClassConfigInfo &cnf){
par.listCode = EStdStartList;
par.setLegNumberCoded(-1);
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, true);
}
void TabList::getStartClub(oListParam &par) {
@ -3006,7 +3025,7 @@ void TabList::getStartClub(oListParam &par) {
}
void TabList::getResultIndividual(oListParam &par, ClassConfigInfo &cnf) {
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, false);
par.listCode = EStdResultList;
par.showInterTimes = true;
par.setLegNumberCoded(-1);
@ -3015,7 +3034,7 @@ void TabList::getResultIndividual(oListParam &par, ClassConfigInfo &cnf) {
void TabList::getResultClub(oListParam &par, ClassConfigInfo &cnf) {
par.listCode = EStdClubResultList;
par.setLegNumberCoded(-1);
cnf.getIndividual(par.selection);
cnf.getIndividual(par.selection, true);
cnf.getPatrol(par.selection);
}
@ -3124,3 +3143,20 @@ void TabList::readSettings(gdioutput &gdi, oListParam &par, bool forResult) {
par.filterMaxPer = gdi.getSelectedItem("ClassLimit").first;
}
}
MethodEditor &TabList::getMethodEditor() {
if (!methodEditor)
methodEditor = make_shared<MethodEditor>(oe);
return *methodEditor;
}
ListEditor &TabList::getListEditor() {
if (!listEditor)
listEditor = make_shared<ListEditor>(oe);
return *listEditor;
}
ListEditor *TabList::getListEditorPtr() const {
return listEditor.get();
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -67,8 +67,8 @@ protected:
bool hideButtons;
bool ownWindow;
ListEditor *listEditor;
MethodEditor *methodEditor;
shared_ptr<ListEditor> listEditor;
shared_ptr<MethodEditor> methodEditor;
bool noReEvaluate;
@ -112,6 +112,8 @@ public:
/** Returns a collection of public lists. */
void static getPublicLists(oEvent &oe, vector<oListParam> &lists);
MethodEditor &getMethodEditor();
bool loadPage(gdioutput &gdi);
bool loadPage(gdioutput &gdi, const string &command);
@ -149,7 +151,8 @@ public:
static void saveExtraLines(oEvent &oe, const char *dataField, gdioutput &gdi);
static void enableWideFormat(gdioutput &gdi, bool wide);
ListEditor *getListeditor() const {return listEditor;}
ListEditor &getListEditor();
ListEditor *getListEditorPtr() const;
const char * getTypeStr() const {return "TListTab";}
TabType getType() const {return TListTab;}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -131,7 +131,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.selectItemByData("Runners", -1);
gdi.setInputFocus("Name", true);
if (gdi.hasField("MultiR")) {
if (gdi.hasWidget("MultiR")) {
gdi.clearList("MultiR");
gdi.disableInput("MultiR");
}
@ -139,18 +139,18 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
enableControlButtons(gdi, false, false);
disablePunchCourse(gdi);
if (gdi.hasField("EditTeam"))
if (gdi.hasWidget("EditTeam"))
gdi.disableInput("EditTeam");
gdi.setText("RunnerInfo", L"", true);
gdi.setText("TimeAdjust", makeDash(L"-"));
gdi.setText("PointAdjust", L"");
if (gdi.hasField("StatusIn")) {
if (gdi.hasWidget("StatusIn")) {
gdi.selectFirstItem("StatusIn");
gdi.setText("PlaceIn", L"");
gdi.setText("TimeIn", makeDash(L"-"));
if (gdi.hasField("PointIn"))
if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", L"");
}
@ -163,9 +163,8 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
pRunner parent = r->getMultiRunner(0);
r->synchronizeAll();
//r->apply(false);
vector<int> mp;
r->evaluateCard(true, mp, 0, false);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
gdi.selectItemByData("Runners", parent->getId());
@ -174,7 +173,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.setText("Name", r->getNameRaw());
wstring bib = r->getBib();
if (gdi.hasField("Bib")) {
if (gdi.hasWidget("Bib")) {
gdi.setText("Bib", bib);
bool controlBib = r->getTeam() == 0 || (r->getClassRef(true) && r->getClassRef(true)->getBibMode() == BibFree);
gdi.setInputStatus("Bib", controlBib);
@ -188,7 +187,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.addItem("RClass", lang.tl("Ingen klass"), 0);
gdi.selectItemByData("RClass", r->getClassId(true));
if (gdi.hasField("EditTeam")) {
if (gdi.hasWidget("EditTeam")) {
gdi.setInputStatus("EditTeam", r->getTeam() != 0);
if (r->getTeam()) {
@ -239,7 +238,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.refresh();
#endif
if (gdi.hasField("MultiR")) {
if (gdi.hasWidget("MultiR")) {
int numMulti = parent->getNumMulti();
if (numMulti == 0) {
gdi.clearList("MultiR");
@ -268,7 +267,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
warnDuplicateCard(gdi, cno, r);
gdi.check("RentCard", r->isHiredCard());
bool hasFee = gdi.hasField("Fee");
bool hasFee = gdi.hasWidget("Fee");
if (hasFee)
gdi.setText("Fee", oe->formatCurrency(parent->getDI().getInt("Fee")));
@ -282,24 +281,25 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
if (hasFee)
gdi.setInputStatus("Fee", parent == r);
if(gdi.hasField("Club"))
if(gdi.hasWidget("Club"))
gdi.setInputStatus("Club", parent == r);
enableControlButtons(gdi, true, r->isVacant());
gdi.setText("Start", r->getStartTimeS());
//gdi.setText("Start", r->getStartTimeS());
gdi.setInputStatus("Start", canSetStart(r));
gdi.setText("Finish", r->getFinishTimeS());
//gdi.setText("Finish", r->getFinishTimeS());
gdi.setInputStatus("Finish", canSetFinish(r));
gdi.setText("Time", r->getRunningTimeS());
gdi.setText("Points", itow(r->getRogainingPoints(false)));
//gdi.setText("Time", r->getRunningTimeS(true));
//gdi.setText("Points", itow(r->getRogainingPoints(false)));
gdi.selectItemByData("Status", r->getStatus());
gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
//gdi.selectItemByData("Status", r->getStatus());
//gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
updateStatus(gdi, r);
if (gdi.hasField("StatusIn")) {
if (gdi.hasWidget("StatusIn")) {
gdi.selectItemByData("StatusIn", r->getInputStatus());
int ip = r->getInputPlace();
if (ip > 0)
@ -308,7 +308,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.setText("PlaceIn", makeDash(L"-"));
gdi.setText("TimeIn", r->getInputTimeS());
if (gdi.hasField("PointIn"))
if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", r->getInputPoints());
}
@ -554,7 +554,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->getCard()->getCardNo() != cardNo && r->getCardNo() != cardNo) {
if (gdi.ask(L"Vill du koppla isär X från inläst bricka Y?#" + r->getName() +
L"#" + r->getCard()->getCardNoString())) {
r->setStatus(StatusUnknown, true, false, false);
r->setStatus(StatusUnknown, true, oBase::ChangeType::Update, false);
r->setCard(0);
r->setFinishTime(0);
r->synchronize(true);
@ -581,7 +581,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->getDI().setInt("CardFee", 0);
}
if (gdi.hasField("Fee"))
if (gdi.hasWidget("Fee"))
r->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee")));
gdioutput *gdi_settings = getExtraWindow("ecosettings", false);
@ -593,16 +593,16 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->setStartTimeS(gdi.getText("Start"));
r->setFinishTimeS(gdi.getText("Finish"));
if (gdi.hasField("NumShort")) {
if (gdi.hasWidget("NumShort")) {
r->setNumShortening(gdi.getSelectedItem("NumShort").first);
}
if (gdi.hasField("TimeAdjust")) {
if (gdi.hasWidget("TimeAdjust")) {
int t = convertAbsoluteTimeMS(gdi.getText("TimeAdjust"));
if (t != NOTIME)
r->setTimeAdjustment(t);
}
if (gdi.hasField("PointAdjust")) {
if (gdi.hasWidget("PointAdjust")) {
r->setPointAdjustment(-gdi.getTextNo("PointAdjust"));
}
@ -635,25 +635,56 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->setClassId(classId, true);
if (gdi.hasField("Bib")) {
if (gdi.hasWidget("Bib")) {
const wstring &bib = gdi.getText("Bib");
wchar_t pat[32];
int num = oClass::extractBibPattern(bib, pat);
bool lockedForking = r->getClassRef(true) && r->getClassRef(true)->lockedForking();
r->setBib(bib, num, num>0 && !lockedForking, false);
r->setBib(bib, num, num>0 && !lockedForking);
}
r->setCourseId(gdi.getSelectedItem("RCourse").first);
int crsId = gdi.getSelectedItem("RCourse").first;
if (crsId > 0 && r->getCourseId() != -1) {
pClass cls = r->getClassRef(true);
pCourse crs = oe->getCourse(crsId);
vector<pCourse> courses;
if (cls && crs) {
cls->getCourses(r->getLegNumber(), courses);
set<int> crsIds;
for (auto c : courses)
crsIds.insert(c->getId());
if (crsIds.count(crsId) == 0) {
vector<pRunner> clsRunner;
oe->getRunners(cls->getId(), -1, clsRunner, false);
bool ok = clsRunner.size() < 2;
for (auto cr : clsRunner) {
if (cr->getCourseId() > 0 && !crsIds.count(cr->getCourseId())) {
ok = true;
break;
}
}
if (!ok) {
if (!gdi.ask(L"ask:usecourseinclass"))
crsId = 0;
}
}
}
}
r->setCourseId(crsId);
RunnerStatus sIn = (RunnerStatus)gdi.getSelectedItem("Status").first;
bool checkStatus = sIn != originalStatus;
if (r->getStatus() != sIn && !noSetStatus) {
r->setStatus(sIn, true, false);
r->setStatus(sIn, true, oBase::ChangeType::Update);
}
r->addClassDefaultFee(false);
vector<int> mp;
r->evaluateCard(true, mp, 0, true);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
if (r->getClassId(true) != classId && r->getClassId(false) != classId) {
gdi.alert("Deltagarens klass styrs av laget.");
@ -662,11 +693,11 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
if (checkStatus && sIn != r->getStatus())
gdi.alert("Status matchar inte data i löparbrickan.");
if (gdi.hasField("StatusIn") && readStatusIn) {
if (gdi.hasWidget("StatusIn") && readStatusIn) {
r->setInputStatus(RunnerStatus(gdi.getSelectedItem("StatusIn").first));
r->setInputPlace(gdi.getTextNo("PlaceIn"));
r->setInputTime(gdi.getText("TimeIn"));
if (gdi.hasField("PointIn"))
if (gdi.hasWidget("PointIn"))
r->setInputPoints(gdi.getTextNo("PointIn"));
}
@ -827,7 +858,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="SetDNS") {
for (size_t k=0; k<unknown.size(); k++) {
if (unknown[k]->getStatus()==StatusUnknown) {
unknown[k]->setStatus(StatusDNS, true, false);
unknown[k]->setStatus(StatusDNS, true, oBase::ChangeType::Update);
unknown[k]->setFlag(oAbstractRunner::FlagAutoDNS, true);
unknown[k]->synchronize(true);
}
@ -842,7 +873,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
oe->getRunners(0, 0, runners, true);
for (pRunner r : runners) {
if (r->getStatus() == StatusDNS && r->hasFlag(oAbstractRunner::FlagAutoDNS)) {
r->setStatus(StatusUnknown, true, false);
r->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
r->setFlag(oAbstractRunner::FlagAutoDNS, false);
r->synchronize(true);
}
@ -855,7 +886,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
else if (bi.id=="SetUnknown") {
for (size_t k=0; k<known_dns.size(); k++) {
if (known_dns[k]->getStatus()==StatusDNS) {
known_dns[k]->setStatus(StatusUnknown, true, false);
known_dns[k]->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
known_dns[k]->synchronize(true);
}
}
@ -984,7 +1015,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
if (r->getStartTime()>0) {
pRunner newRunner = oe->addRunnerVacant(r->getClassId(true));
newRunner->cloneStartTime(r);
newRunner->setStartNo(r->getStartNo(), false);
newRunner->setStartNo(r->getStartNo(), oBase::ChangeType::Update);
if (r->getCourseId())
newRunner->setCourseId(r->getCourseId());
newRunner->synchronizeAll();
@ -993,9 +1024,9 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
for (int k=0;k<r->getNumMulti()+1; k++) {
pRunner rr = r->getMultiRunner(k);
if (rr) {
rr->setStartTime(0, true, false);
rr->setStartTime(0, true, oBase::ChangeType::Update);
//rr->setStartNo(0, false);
rr->setStatus(StatusCANCEL, true, false);
rr->setStatus(StatusCANCEL, true, oBase::ChangeType::Update);
rr->setCardNo(0, false);
}
}
@ -1047,11 +1078,11 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
card->synchronize();
//Update runner
vector<int> mp;
r->evaluateCard(true, mp, 0, true);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
r->synchronize();
card->fillPunches(gdi, "Punches", r->getCourse(true));
gdi.setText("Time", r->getRunningTimeS());
gdi.setText("Time", r->getRunningTimeS(true));
gdi.selectItemByData("Status", r->getStatus());
}
else if (bi.id=="Check") {
@ -1314,19 +1345,19 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
oRunner temp(oe, 0);
temp.setTemporary();
temp.setBib(r->getBib(), 0, false, false);
temp.setStartNo(r->getStartNo(), false);
temp.setBib(r->getBib(), 0, false);
temp.setStartNo(r->getStartNo(), oBase::ChangeType::Update);
temp.setClassId(r->getClassId(true), true);
temp.apply(false, 0, false);
temp.apply(oBase::ChangeType::Update, nullptr);
temp.cloneStartTime(r);
r->setClassId(vacancy->getClassId(true), true);
// Remove or create multi runners
r->createMultiRunner(true, true);
r->apply(false, 0, false);
r->apply(oBase::ChangeType::Quiet, nullptr);
r->cloneStartTime(vacancy);
r->setBib(vacancy->getBib(), 0, false, false);
r->setStartNo(vacancy->getStartNo(), false);
r->setBib(vacancy->getBib(), 0, false);
r->setStartNo(vacancy->getStartNo(), oBase::ChangeType::Update);
if (oe->hasPrevStage()) {
if (gdi.ask(L"Vill du sätta resultatet från tidigare etapper till <Deltar ej>?"))
@ -1336,10 +1367,10 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
vacancy->setClassId(temp.getClassId(true), true);
// Remove or create multi runners
vacancy->createMultiRunner(true, true);
vacancy->apply(false, 0, false);
vacancy->apply(oBase::ChangeType::Update, nullptr);
vacancy->cloneStartTime(&temp);
vacancy->setBib(temp.getBib(), 0, false, false);
vacancy->setStartNo(temp.getStartNo(), false);
vacancy->setBib(temp.getBib(), 0, false);
vacancy->setStartNo(temp.getStartNo(), oBase::ChangeType::Update);
r->synchronizeAll();
vacancy->synchronizeAll();
@ -1361,8 +1392,7 @@ void TabRunner::showCardsList(gdioutput &gdi)
addToolbar(gdi);
gdi.dropLine();
cardModeStartY=gdi.getCY();
Table *t=oe->getCardsTB();
gdi.addTable(t,gdi.getCX(),gdi.getCY()+15);
gdi.addTable(oCard::getTable(oe), gdi.getCX(), gdi.getCY() + gdi.scaleLength(15));
gdi.registerEvent("CellAction", RunnerCB);
gdi.refresh();
}
@ -1410,7 +1440,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
wstring club;
int birthYear = 0;
if (gdi.hasField("Club")) {
if (gdi.hasWidget("Club")) {
club = gdi.getText("Club");
pClub pc = oe->getClubCreate(0, club);
if (pc)
@ -1422,7 +1452,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
r->setClub(club);
int fee = 0;
if (gdi.hasField("Fee")) {
if (gdi.hasWidget("Fee")) {
ListBoxInfo lbi;
if (gdi.getSelectedItem("Fee", lbi) && lbi.data == -1) {
lastFee = L"@";
@ -1454,7 +1484,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
TabSI::writePayMode(gdi, fee + cardFee, *r);
if (gdi.hasField("AllStages")) {
if (gdi.hasWidget("AllStages")) {
r->setFlag(oRunner::FlagTransferSpecified, true);
r->setFlag(oRunner::FlagTransferNew, gdi.isChecked("AllStages"));
}
@ -1506,7 +1536,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
tsi.storedInfo.allStages = gdi.isChecked("AllStages");
tsi.storedInfo.rentState = gdi.isChecked("RentCard");
tsi.storedInfo.hasPaid = gdi.isChecked("Paid");
tsi.storedInfo.payMode = gdi.hasField("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
tsi.storedInfo.payMode = gdi.hasWidget("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
return 1;
}
return 0;
@ -1595,7 +1625,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi) {
runnerReport(oe, gdi, runnersToReport[k].first, runnersToReport[k].second);
}
else {
oe.calculateTeamResults(false);
oe.calculateTeamResults(clsSet, oEvent::ResultType::ClassResult);
set<int> selectedRunners;
bool selHasRes = false;
@ -1607,13 +1637,13 @@ void TabRunner::showRunnerReport(gdioutput &gdi) {
}
wstring tInfo = t->getName();
if (t->statusOK()) {
tInfo += L", " + t->getRunningTimeS() + lang.tl(".S Placering: ") + t->getPlaceS();
if (t->statusOK(true)) {
tInfo += L", " + t->getRunningTimeS(true) + lang.tl(", Placering: ") + t->getPlaceS();
if (t->getTimeAfter(-1) > 0)
tInfo += L", +" + formatTime(t->getTimeAfter(-1));
}
else if (t->getStatus() != StatusUnknown) {
tInfo += L" " + t->getStatusS(true);
else if (t->getStatusComputed() != StatusUnknown) {
tInfo += L" " + t->getStatusS(true, true);
}
gdi.addStringUT(fontMediumPlus, t->getClass(true));
@ -1676,7 +1706,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
gdi.dropLine(0.3);
if (r->statusOK()) {
if (r->statusOK(true)) {
int total, finished, dns;
r->getClassRef(true)->getNumResults(r->getLegNumber(), total, finished, dns);
@ -1693,7 +1723,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
}
}
}
else if (r->getStatus() != StatusUnknown) {
else if (r->getStatusComputed() != StatusUnknown) {
gdi.addStringUT(fontMediumPlus, str).setColor(colorRed);
}
@ -2125,7 +2155,7 @@ void TabRunner::listRunners(gdioutput &gdi, const vector<pRunner> &r, bool filte
gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, "(" + itos(c) + ")", 190);
}
else {
TextInfo &ti = gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, L"(" + itow(c) + lang.tl(", reused card") + L")", gdi.scaleLength(100));
TextInfo &ti = gdi.addStringUT(yp, xp+gdi.scaleLength(550), 0, L"(" + itow(c) + lang.tl(", reused card") + L")", gdi.scaleLength(150));
wstring tt;
for (size_t j = 0; j < out.size(); j++) {
if (out[j] == r[k]->getMultiRunner(0))
@ -2219,15 +2249,27 @@ void disablePunchCourse(gdioutput &gdi)
disablePunchCourseChange(gdi);
}
void UpdateStatus(gdioutput &gdi, pRunner r)
{
void TabRunner::updateStatus(gdioutput &gdi, pRunner r) {
if (!r) return;
gdi.setText("Start", r->getStartTimeS());
gdi.setText("Finish", r->getFinishTimeS());
gdi.setText("Time", r->getRunningTimeS());
gdi.setText("Time", r->getRunningTimeS(false));
gdi.setText("Points", itow(r->getRogainingPoints(false, false)));
gdi.selectItemByData("Status", r->getStatus());
gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
auto ri = r->getRaceInfo();
BaseInfo *bi = gdi.setText("RunnerInfo", ri.first, true);
TextInfo *ti = dynamic_cast<TextInfo*>(bi);
assert(ti);
if (ti) {
if (ri.second > 0)
ti->setColor(GDICOLOR::colorGreen);
else if (ri.second < 0)
ti->setColor(GDICOLOR::colorRed);
else
ti->setColor(GDICOLOR::colorDefault);
}
}
int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
@ -2313,7 +2355,8 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
if (bi.id == "AddC") {
vector<int> mp;
r->evaluateCard(true, mp);
r->synchronize();
r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
pCourse pc = r->getCourse(true);
@ -2330,30 +2373,30 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
vector<int> nmp;
if (oc->getStatus() == oControl::StatusRogaining) {
r->evaluateCard(true, nmp, oc->getFirstNumber()); //Add this punch
r->evaluateCard(true, nmp, oc->getFirstNumber(), oBase::ChangeType::Update); //Add this punch
}
else {
for (size_t k = 0; k < mp.size(); k++) {
if (oc->hasNumber(mp[k]))
r->evaluateCard(true, nmp, mp[k]); //Add this punch
r->evaluateCard(true, nmp, mp[k], oBase::ChangeType::Update); //Add this punch
}
}
//synchronize SQL
card->synchronize();
r->synchronize(true);
r->evaluateCard(true, mp);
r->synchronizeAll(true);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->hasManuallyUpdatedTimeStatus();
card->fillPunches(gdi, "Punches", pc);
UpdateStatus(gdi, r);
updateStatus(gdi, r);
}
else if (bi.id == "AddAllC") {
vector<int> mp;
r->evaluateCard(true, mp);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
vector<int>::iterator it = mp.begin();
while (it != mp.end()) {
vector<int> nmp;
r->evaluateCard(true, nmp, *it); //Add this punch
r->evaluateCard(true, nmp, *it, oBase::ChangeType::Update); //Add this punch
++it;
if (nmp.empty())
break;
@ -2361,11 +2404,11 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
//synchronize SQL
card->synchronize();
r->synchronize(true);
r->evaluateCard(true, mp);
r->synchronizeAll(true);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
card->fillPunches(gdi, "Punches", r->getCourse(true));
r->hasManuallyUpdatedTimeStatus();
UpdateStatus(gdi, r);
updateStatus(gdi, r);
}
else if (bi.id == "SaveC") {
if (!savePunchTime(r, gdi))
@ -2392,10 +2435,10 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
card->synchronize();*/
vector<int> mp;
r->synchronize();
r->evaluateCard(true, mp);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->hasManuallyUpdatedTimeStatus();
card->fillPunches(gdi, "Punches", r->getCourse(true));
UpdateStatus(gdi, r);
updateStatus(gdi, r);
gdi.selectItemByData("Punches", lbi.data);
}
}
@ -2419,10 +2462,11 @@ bool TabRunner::savePunchTime(pRunner r, gdioutput &gdi) {
card->setPunchTime(pp, gdi.getText("PTime"));
vector<int> mp;
r->evaluateCard(true, mp);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
//synchronize SQL
card->synchronize();
r->synchronizeAll();
return true;
}
@ -2440,10 +2484,9 @@ bool TabRunner::loadPage(gdioutput &gdi)
int basex = gdi.getCX();
if (currentMode == 1) {
Table *tbl = oe->getRunnersTB();
addToolbar(gdi);
gdi.dropLine(1);
gdi.addTable(tbl, basex, gdi.getCY());
gdi.addTable(oRunner::getTable(oe), basex, gdi.getCY());
return true;
}
else if (currentMode == 2) {
@ -2625,8 +2668,8 @@ bool TabRunner::loadPage(gdioutput &gdi)
gdi.popX();
gdi.selectItemByData("Status", 0);
gdi.addString("RunnerInfo", 1, "").setColor(colorRed);
gdi.addString("RunnerInfo", 0, "").setColor(colorRed);
gdi.dropLine(0.4);
const bool multiDay = oe->hasPrevStage();
if (multiDay) {
@ -2714,13 +2757,13 @@ bool TabRunner::loadPage(gdioutput &gdi)
gdi.dropLine(0.2);
gdi.fillRight();
gdi.addButton(gdi.getCX(), gdi.getCY(), gdi.scaleLength(120), "SplitPrint",
"Skriv ut sträcktider", RunnerCB, "", false, false).isEdit(true).setExtra(0);
"Sträcktider", RunnerCB, "", false, false).isEdit(true).setExtra(0);
gdi.addButton("PrintSettings", "...", RunnerCB, "Inställningar").isEdit(true).setExtra(0);
gdi.dropLine(2.5);
gdi.setCX(contX);
gdi.addButton(gdi.getCX(), gdi.getCY(), gdi.scaleLength(120), "SplitPrint",
"Skriv ut startbevis", RunnerCB, "", false, false).isEdit(true).setExtra(1);
"Startbevis", RunnerCB, "", false, false).isEdit(true).setExtra(1);
gdi.addButton("PrintSettings", "...", RunnerCB, "Inställningar").isEdit(true).setExtra(1);
gdi.pushY();
@ -2908,7 +2951,7 @@ int TabRunner::numShorteningLevels() const {
}
void TabRunner::updateNumShort(gdioutput &gdi, pCourse crs, pRunner r) {
if (gdi.hasField("NumShort")) {
if (gdi.hasWidget("NumShort")) {
if (crs && crs->getShorterVersion().first) {
gdi.enableInput("NumShort");
if (r)
@ -3086,12 +3129,12 @@ void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
auto &db = oe->getRunnerDatabase();
auto runner = db.getRunnerByIndex(ix);
if (runner && gdi.hasField("Club") && gdi.getText("Club").empty()) {
if (runner && gdi.hasWidget("Club") && gdi.getText("Club").empty()) {
pClub club = db.getClub(runner->dbe().clubNo);
if (club)
gdi.setText("Club", club->getName());
}
if (runner && runner->dbe().cardNo > 0 && gdi.hasField("CardNo") && gdi.getText("CardNo").empty()) {
if (runner && runner->dbe().cardNo > 0 && gdi.hasWidget("CardNo") && gdi.getText("CardNo").empty()) {
gdi.setText("CardNo", runner->dbe().cardNo);
}
}
@ -3102,7 +3145,7 @@ void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
pClub TabRunner::extractClub(oEvent *oe, gdioutput &gdi) {
oClub *dbClub = nullptr;
if (gdi.hasField("Club")) {
if (gdi.hasWidget("Club")) {
auto &db = oe->getRunnerDatabase();
int clubId = gdi.getExtraInt("Club");
if (clubId >= 0) {

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -90,7 +90,7 @@ private:
int numShorteningLevels() const;
void updateNumShort(gdioutput &gdi, pCourse crs, pRunner r);
static void updateStatus(gdioutput &gdi, pRunner r);
static void autoGrowCourse(gdioutput &gdi);
void loadEconomy(gdioutput &gdi, oRunner &r);

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -67,7 +67,6 @@ TabSI::TabSI(oEvent *poe):TabBase(poe), activeSIC(ConvertedTimeStatus::Unknown)
lastClubId=0;
lastClassId=0;
logger = 0;
minRunnerId = 0;
inputId = 0;
@ -77,9 +76,6 @@ TabSI::TabSI(oEvent *poe):TabBase(poe), activeSIC(ConvertedTimeStatus::Unknown)
TabSI::~TabSI(void)
{
if (logger!=0)
delete logger;
logger = 0;
}
@ -93,8 +89,8 @@ static void entryTips(gdioutput &gdi) {
void TabSI::logCard(gdioutput &gdi, const SICard &card)
{
if (logger == 0) {
logger = new csvparser;
if (!logger) {
logger = make_shared<csvparser>();
wstring readlog = L"sireadlog_" + getLocalTimeFileName() + L".csv";
wchar_t file[260];
wstring subfolder = makeValidFileName(oe->getName(), true);
@ -124,6 +120,20 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (type == GUI_BUTTON) {
ButtonInfo bi = *(ButtonInfo *)data;
if (bi.id == "LockFunction") {
lockedFunction = true;
loadPage(gdi);
}
else if (bi.id == "UnlockFunction") {
lockedFunction = false;
loadPage(gdi);
}
else if (bi.id == "AllowStart")
allowStart = gdi.isChecked(bi.id);
else if (bi.id == "AllowControl")
allowControl = gdi.isChecked(bi.id);
else if (bi.id == "AllowFinish")
allowFinish = gdi.isChecked(bi.id);
if (bi.id == "ClearMemory") {
if (gdi.ask(L"Do you want to clear the card memory?")) {
savedCards.clear();
@ -675,7 +685,9 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
int year = 0;
pRunner r = gEvent->addRunner(gdi.getText("Runners"), club,
classes[0]->getId(), activeSIC.CardNumber, year, true);
if (oe->isHiredCard(activeSIC.CardNumber)) {
r->getDI().setInt("CardFee", oe->getBaseCardFee());
}
gdi.setData("RunnerId", r->getId());
gdi.restore();
@ -743,6 +755,10 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pRunner r = gEvent->addRunner(gdi.getText("Runners"), club,
lbi.data, activeSIC.CardNumber, year, true);
if (activeSIC.CardNumber > 0 && oe->isHiredCard(activeSIC.CardNumber)) {
r->getDI().setInt("CardFee", oe->getBaseCardFee());
}
r->setStartTimeS(gdi.getText("StartTime"));
r->setCardNo(activeSIC.CardNumber, false);
@ -777,7 +793,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
oe->getClass(1)->getNumRunners(false, false, false) == 0) {
pclass = oe->getClass(1);
pclass->setType(L"");
pclass->setName(gdi.getText("ClassName"));
pclass->setName(gdi.getText("ClassName"), true);
pc = pclass->getCourse();
if (pc)
pc->setName(gdi.getText("ClassName"));
@ -798,6 +814,9 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pRunner r = gEvent->addRunner(gdi.getText("Runners"), gdi.getText("Club", true),
pclass->getId(), activeSIC.CardNumber, year, true);
if (activeSIC.CardNumber > 0 && oe->isHiredCard(activeSIC.CardNumber)) {
r->getDI().setInt("CardFee", oe->getBaseCardFee());
}
r->setStartTimeS(gdi.getText("StartTime"));
r->setCardNo(activeSIC.CardNumber, false);
gdi.restore();
@ -925,7 +944,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
di.setString("Phone", gdi.getText("Phone"));
r->setFlag(oRunner::FlagTransferSpecified, gdi.hasField("AllStages"));
r->setFlag(oRunner::FlagTransferSpecified, gdi.hasWidget("AllStages"));
r->setFlag(oRunner::FlagTransferNew, gdi.isChecked("AllStages"));
r->setStartTimeS(gdi.getText("StartTime"));
@ -943,7 +962,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
}
}
else {
r->setBib(bibIn, 0, false, false);
r->setBib(bibIn, 0, false);
bib = L", " + lang.tl(L"Nummerlapp: ") + r->getBib();
}
r->synchronize();
@ -1178,7 +1197,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pRunner r = gEvent->getRunner(bi.data, 0);
if (r) {
gdi.setData("RunnerId", bi.data);
if (gdi.hasField("Club"))
if (gdi.hasWidget("Club"))
gdi.setText("Club", r->getClub());
gdi.setText("FindMatch", lang.tl("Press Enter to continue"), true);
}
@ -1231,6 +1250,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
showManualInput(gdi);
}
else if (mode == ModeCardData) {
numSavedCardsOnCmpOpen = savedCards.size();
showModeCardData(gdi);
}
else if (mode == ModeCheckCards) {
@ -1239,6 +1259,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
else if (mode == ModeRegisterCards) {
showRegisterHiredCards(gdi);
}
updateReadoutFunction(gdi);
gdi.refresh();
}
else if (bi.id=="Fee") {
@ -1282,7 +1303,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (!db_r && lastClubId)
db_r = oe->dbLookUpByName(bi.text, lastClubId, 0, 0);
if (db_r && gdi.hasField("Club")) {
if (db_r && gdi.hasWidget("Club")) {
gdi.setText("Club", db_r->getClub());
}
}
@ -1325,7 +1346,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.setInputFocus("OK1");
gdi.setText("Runners", r->getName());
gdi.setData("RunnerId", runnerMatchedId);
if (gdi.hasField("Club"))
if (gdi.hasWidget("Club"))
gdi.setText("Club", r->getClub());
inputId = -1;
gdi.setText("FindMatch", lang.tl("Press Enter to continue"), true);
@ -1530,7 +1551,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
storedInfo.clear();
storedInfo.storedName = gdi.getText("Name");
storedInfo.storedCardNo = gdi.getText("CardNo");
storedInfo.storedClub = gdi.hasField("Club") ? gdi.getText("Club") : L"";
storedInfo.storedClub = gdi.hasWidget("Club") ? gdi.getText("Club") : L"";
storedInfo.storedFee = gdi.getText("Fee", true);
ListBoxInfo lbi;
@ -1542,7 +1563,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
storedInfo.allStages = gdi.isChecked("AllStages");
storedInfo.rentState = gdi.isChecked("RentCard");
storedInfo.hasPaid = gdi.isChecked("Paid");
storedInfo.payMode = gdi.hasField("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
storedInfo.payMode = gdi.hasWidget("PayMode") ? gdi.getSelectedItem("PayMode").first : 0;
}
return 1;
}
@ -1748,6 +1769,8 @@ bool TabSI::loadPage(gdioutput &gdi) {
if (!oe->empty()) {
gdi.setCX(xb + gdi.scaleLength(10));
gdi.setCY(yb + gdi.scaleLength(10));
if (!lockedFunction) {
gdi.addString("", fontMediumPlus, "Funktion:");
gdi.addSelection("ReadType", 200, 200, SportIdentCB);
gdi.addItem("ReadType", lang.tl("Avläsning/radiotider"), ModeReadOut);
@ -1756,11 +1779,29 @@ bool TabSI::loadPage(gdioutput &gdi) {
gdi.addItem("ReadType", lang.tl("Registrera hyrbrickor"), ModeRegisterCards);
gdi.addItem("ReadType", lang.tl("Anmälningsläge"), ModeEntry);
gdi.addItem("ReadType", lang.tl("Print card data"), ModeCardData);
gdi.selectItemByData("ReadType", mode);
gdi.dropLine(-0.1);
gdi.addButton("LockFunction", "Lås funktion...", SportIdentCB);
readoutFunctionX = gdi.getCX();
readoutFunctionY = gdi.getCY();
gdi.dropLine(0.3);
gdi.addString("Allow", 0, "Tillåt:");
gdi.addCheckbox("AllowStart", "Start", SportIdentCB, allowStart);
gdi.addCheckbox("AllowControl", "Radio", SportIdentCB, allowControl);
gdi.addCheckbox("AllowFinish", "Mål", SportIdentCB, allowFinish);
updateReadoutFunction(gdi);
gdi.dropLine(2.5);
gdi.setCX(xb + gdi.scaleLength(10));
}
else {
gdi.addButton("UnlockFunction", "Lås upp", SportIdentCB);
gdi.dropLine(0.2);
}
}
else {
mode = ModeCardData;
}
@ -1831,6 +1872,14 @@ bool TabSI::loadPage(gdioutput &gdi) {
return true;
}
void TabSI::updateReadoutFunction(gdioutput &gdi) {
bool hide = mode != SIMode::ModeReadOut;
gdi.hideWidget("Allow", hide);
gdi.hideWidget("AllowStart", hide);
gdi.hideWidget("AllowControl", hide);
gdi.hideWidget("AllowFinish", hide);
}
void InsertSICard(gdioutput &gdi, SICard &sic)
{
TabSI &tsi = dynamic_cast<TabSI &>(*gdi.getTabs().get(TSITab));
@ -1856,6 +1905,10 @@ pRunner TabSI::autoMatch(const SICard &sic, pRunner db_r)
if (classes.size()==1 && dist>=-1 && dist<=1) { //Almost perfect match found. Assume it is it!
r = gEvent->addRunnerFromDB(db_r, classes[0]->getId(), true);
r->setCardNo(sic.CardNumber, false);
if (oe->isHiredCard(sic.CardNumber)) {
r->getDI().setInt("CardFee", oe->getBaseCardFee());
}
}
else r=0; //Do not assume too much...
}
@ -1968,6 +2021,11 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
else
sic.analyseHour12Time(zt2);
}
// Write read card to log
logCard(gdi, sic);
bool first = savedCards.size() == numSavedCardsOnCmpOpen;
savedCards.push_back(make_pair(savedCardUniqueId++, sic));
if (printSplits) {
@ -1980,11 +2038,15 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
if (pageLoaded) {
gdi.enableInput("CreateCompetition", true);
printCard(gdi, savedCards.back().first, false);
printCard(gdi, savedCards.back().first, nullptr, false);
gdi.dropLine();
gdi.refreshFast();
gdi.scrollToBottom();
}
if (first && !oe->empty())
gdi.alert(L"warn:printmodeonly");
return;
}
gEvent->synchronizeList({ oListId::oLCardId, oListId::oLRunnerId });
@ -2209,7 +2271,7 @@ void TabSI::startInteractive(gdioutput &gdi, const SICard &sic, pRunner r, pRunn
if (db_r)
gdi.setText("Club", db_r->getClub()); //Data from DB
}
if (gdi.getText("Runners").empty() || !gdi.hasField("Club"))
if (gdi.getText("Runners").empty() || !gdi.hasWidget("Club"))
gdi.setInputFocus("Runners");
else
gdi.setInputFocus("Club");
@ -2444,7 +2506,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
if (pcourse)
pcourse->synchronize();
else if (pclass && pclass->hasDirectResult())
runner->setStatus(StatusOK, true, false, false);
runner->setStatus(StatusOK, true, oBase::ChangeType::Update, false);
//silent=true;
SICard sic(csic);
wstring info, warnings, cardno;
@ -2502,20 +2564,21 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
runner->setCard(0);
if (csic.statusOK) {
runner->setStatus(StatusOK, true, false);
runner->setStatus(StatusOK, true, oBase::ChangeType::Update);
runner->setFinishTime(csic.relativeFinishTime);
}
else if (csic.statusDNF) {
runner->setStatus(StatusDNF, true, false);
runner->setStatus(StatusDNF, true, oBase::ChangeType::Update);
runner->setFinishTime(0);
}
else {
runner->setStatus(StatusMP, true, false);
runner->setStatus(StatusMP, true, oBase::ChangeType::Update);
runner->setFinishTime(csic.relativeFinishTime);
}
cardno = makeDash(L"-");
runner->evaluateCard(true, MP, false, false);
runner->evaluateCard(true, MP, 0, oBase::ChangeType::Update);
runner->synchronizeAll(true);
runner->hasManuallyUpdatedTimeStatus();
}
@ -2531,13 +2594,14 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
if (!warnings.empty())
rc.bottom+=gdi.getLineHeight();
if (runner->getStatus()==StatusOK) {
set<int> clsSet;
if (runner->getClassId(false))
clsSet.insert(runner->getClassId(true));
gEvent->calculateResults(clsSet, oEvent::ResultType::ClassResult);
if (runner->getTeam())
gEvent->calculateTeamResults(runner->getLegNumber(), false);
gEvent->calculateTeamResults(clsSet, oEvent::ResultType::ClassResult);
if (runner->getStatusComputed()==StatusOK || isPossibleResultStatus(runner->getStatusComputed())) {
bool qfClass = runner->getClassId(false) != runner->getClassId(true);
wstring placeS = (runner->getTeam() && !qfClass) ?
runner->getTeam()->getLegPlaceS(runner->getLegNumber(), false) :
@ -2553,27 +2617,27 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
gdi.addStringUT(rc.top+6+2*lh, rc.left+20, 0, warnings);
wstring statusline = lang.tl(L"Status OK, ") +
lang.tl(L"Tid: ") + runner->getRunningTimeS() +
lang.tl(L", Prel. placering: ") + placeS;
lang.tl(L"Tid: ") + runner->getRunningTimeS(true);
if (!placeS.empty())
statusline += lang.tl(L", Prel. placering: ") + placeS;
statusline += lang.tl(L", Prel. bomtid: ") + runner->getMissedTimeS();
gdi.addStringUT(rc.top+6+lh, rc.left+20, 0, statusline);
if (runner->isHiredCard())
if (runner->isHiredCard() || oe->isHiredCard(sic.CardNumber))
rentCardInfo(gdi, rc.right-rc.left);
gdi.scrollToBottom();
}
else {
wstring msg = L"#" + runner->getName() + L" (" + cardno + L")\n"+
runner->getClub() + L". " + runner->getClass(true) +
L"\n" + lang.tl("Tid: ") + runner->getRunningTimeS() + lang.tl(L", Plats ") + placeS;
L"\n" + lang.tl("Tid: ") + runner->getRunningTimeS(true) + lang.tl(L", Plats ") + placeS;
gdi.addInfoBox("SIINFO", msg, 10000);
}
}
else {
wstring msg=lang.tl(L"Status: ") + runner->getStatusS(true);
wstring msg=lang.tl(L"Status: ") + runner->getStatusS(true, true);
if (!MP.empty()) {
msg=msg + L", (";
@ -2629,16 +2693,28 @@ void TabSI::processPunchOnly(gdioutput &gdi, const SICard &csic)
DWORD loaded;
gEvent->convertTimes(nullptr, sic);
oFreePunch *ofp = 0;
if (sic.nPunch==1)
wstring accessError;
if (sic.nPunch == 1) {
if (allowControl)
ofp = gEvent->addFreePunch(sic.Punch[0].Time, sic.Punch[0].Code, sic.CardNumber, true);
else if (sic.FinishPunch.Time > 0)
else
accessError = L"Radio tillåts inte (X)#" + itow(sic.CardNumber);
}
else if (sic.FinishPunch.Time > 0) {
if (allowFinish)
ofp = gEvent->addFreePunch(sic.FinishPunch.Time, oPunch::PunchFinish, sic.CardNumber, true);
else if (sic.StartPunch.Time > 0)
else
accessError = L"Målstämpling tillåts inte (X)#" + itow(sic.CardNumber);
}
else if (sic.StartPunch.Time > 0) {
if (allowStart)
ofp = gEvent->addFreePunch(sic.StartPunch.Time, oPunch::PunchStart, sic.CardNumber, true);
else
accessError = L"Startstämpling tillåts inte (X)#" + itow(sic.CardNumber);
}
else {
ofp = gEvent->addFreePunch(sic.CheckPunch.Time, oPunch::PunchCheck, sic.CardNumber, true);
}
if (ofp) {
pRunner r = ofp->getTiedRunner();
if (gdi.getData("SIPageLoaded", loaded)){
@ -2650,7 +2726,7 @@ void TabSI::processPunchOnly(gdioutput &gdi, const SICard &csic)
gdi.dropLine();
}
else {
wstring str=L"SI " + itow(sic.CardNumber) + lang.tl(" (okänd) stämplade vid ") + ofp->getSimpleString();
wstring str= itow(sic.CardNumber) + lang.tl(" (okänd) stämplade vid ") + ofp->getSimpleString();
gdi.addStringUT(0, str);
gdi.dropLine(0.3);
}
@ -2659,14 +2735,21 @@ void TabSI::processPunchOnly(gdioutput &gdi, const SICard &csic)
tabForceSync(gdi, gEvent);
gdi.makeEvent("DataUpdate", "sireadout", r ? r->getId() : 0, 0, true);
}
else if (!accessError.empty()) {
if (gdi.getData("SIPageLoaded", loaded)) {
gdi.addString("", 0, accessError).setColor(colorDarkRed);
gdi.dropLine(0.3);
gdi.scrollToBottom();
}
else
gdi.addInfoBox("Access", accessError);
}
checkMoreCardsInQueue(gdi);
return;
}
void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
{
gdi.setText("CardNo", sic.CardNumber);
@ -2692,10 +2775,10 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
name=wstring(sic.lastName) + L", " + wstring(sic.firstName);
gdi.setText("Name", name);
if (gdi.hasField("Club") && !club.empty())
if (gdi.hasWidget("Club") && !club.empty())
gdi.setText("Club", club);
if (club.empty() && gdi.hasField("Club"))
if (club.empty() && gdi.hasWidget("Club"))
gdi.setInputFocus("Club");
else if (name.empty())
gdi.setInputFocus("Name");
@ -2863,27 +2946,27 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r) {
gdi.setText("CardNo", r->getCardNo());
gdi.setText("Name", r->getNameRaw());
if (gdi.hasField("Club")) {
if (gdi.hasWidget("Club")) {
gdi.selectItemByData("Club", r->getClubId());
}
gdi.selectItemByData("Class", r->getClassId(true));
oDataConstInterface dci = r->getDCI();
if (gdi.hasField("Fee"))
if (gdi.hasWidget("Fee"))
gdi.setText("Fee", oe->formatCurrency(dci.getInt("Fee")));
gdi.setText("Phone", dci.getString("Phone"));
gdi.setText("Bib", r->getBib());
gdi.check("RentCard", dci.getInt("CardFee") != 0);
if (gdi.hasField("Paid"))
if (gdi.hasWidget("Paid"))
gdi.check("Paid", dci.getInt("Paid")>0);
else if (gdi.hasField("PayMode")) {
else if (gdi.hasWidget("PayMode")) {
int paidId = dci.getInt("Paid") > 0 ? r->getPaymentMode() : 1000;
gdi.selectItemByData("PayMode", paidId);
}
if (gdi.hasField("AllStages")) {
if (gdi.hasWidget("AllStages")) {
gdi.check("AllStages", r->hasFlag(oRunner::FlagTransferNew));
}
}
@ -2926,7 +3009,7 @@ void TabSI::updateEntryInfo(gdioutput &gdi)
wstring method;
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy)) {
bool invoice = true;
if (gdi.hasField("PayMode")) {
if (gdi.hasWidget("PayMode")) {
invoice = gdi.getSelectedItem("PayMode").first == 1000;
}
else
@ -2956,7 +3039,7 @@ void TabSI::generateSplits(const pRunner r, gdioutput &gdi)
else {
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
vector<int> mp;
r->evaluateCard(true, mp);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->printSplits(gdiprint);
printProtected(gdi, gdiprint);
//gdiprint.print(splitPrinter, oe, false, true);
@ -3217,7 +3300,7 @@ void TabSI::showModeCardData(gdioutput &gdi) {
gdi.dropLine(3);
gdi.popX();
bool first = true;
for (list<pair<int, SICard> >::iterator it = savedCards.begin(); it != savedCards.end(); ++it) {
for (auto it = savedCards.begin(); it != savedCards.end(); ++it) {
gdi.dropLine(0.5);
if (!first) {
RECT rc = {30, gdi.getCY(), gdi.scaleLength(250), gdi.getCY() + 3};
@ -3225,7 +3308,7 @@ void TabSI::showModeCardData(gdioutput &gdi) {
}
first = false;
printCard(gdi, it->first, false);
printCard(gdi, it->first, &it->second, false);
}
}
@ -3235,10 +3318,10 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
int cardId = ti.getExtraInt();
SICard &card = tabSI->getCard(cardId);
ti.id = "card" + itos(cardId);
gdi.removeControl("CardName");
gdi.removeControl("ClubName");
gdi.removeControl("OKCard");
gdi.removeControl("CancelCard");
gdi.removeWidget("CardName");
gdi.removeWidget("ClubName");
gdi.removeWidget("OKCard");
gdi.removeWidget("CancelCard");
wstring name, club;
if (card.firstName[0])
@ -3283,10 +3366,10 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
gdi.setText("card" + itos(cardId), s, true);
}
gdi.removeControl("CardName");
gdi.removeControl("ClubName");
gdi.removeControl("OKCard");
gdi.removeControl("CancelCard");
gdi.removeWidget("CardName");
gdi.removeWidget("ClubName");
gdi.removeWidget("OKCard");
gdi.removeWidget("CancelCard");
}
else if (type == GUI_FOCUS) {
InputInfo &ii = dynamic_cast<InputInfo &>(info);
@ -3297,8 +3380,11 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
}
}
void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
SICard &c = getCard(cardId);
void TabSI::printCard(gdioutput &gdi, int cardId, SICard *crdRef, bool forPrinter) const {
if (crdRef == nullptr)
crdRef = &getCard(cardId);
SICard &c = *crdRef;
if (c.readOutTime[0] == 0)
strcpy_s(c.readOutTime, getLocalTimeN().c_str());
@ -3421,7 +3507,7 @@ int TabSI::analyzePunch(SIPunch &p, int &start, int &accTime, int &days) {
void TabSI::generateSplits(int cardId, gdioutput &gdi) {
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
printCard(gdiprint, cardId, true);
printCard(gdiprint, cardId, nullptr, true);
printProtected(gdi, gdiprint);
}
@ -3511,7 +3597,7 @@ void TabSI::createCompetitionFromCards(gdioutput &gdi) {
if (zeroTime < 0)
zeroTime += 3600 * 24;
zeroTime -= zeroTime % 1800;
oe->setZeroTime(formatTime(zeroTime));
oe->setZeroTime(formatTime(zeroTime), false);
// Add competitors
for (size_t k = 0; k < cards.size(); k++) {
@ -3578,6 +3664,17 @@ void TabSI::clearCompetitionData() {
checkedCardFlags.clear();
currentAssignIndex = 0;
warnedClassOutOfMaps.clear();
lockedFunction = false;
allowControl = true;
allowFinish = true;
allowStart = false;
if (mode == ModeCardData)
mode = SIMode::ModeReadOut;
logger.reset();
numSavedCardsOnCmpOpen = savedCards.size();
}
SICard &TabSI::getCard(int id) const {
@ -3761,7 +3858,7 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
wstring cp = r[k]->getCompleteIdentification();
if (r[k]->getStatus() != StatusUnknown)
cp += L" " + r[k]->getStatusS(true);
cp += L" " + r[k]->getStatusS(true, true);
else
cp += makeDash(L" -");
@ -3889,7 +3986,7 @@ bool TabSI::writePayMode(gdioutput &gdi, int amount, oRunner &r) {
int paid = 0;
bool hasPaid = false;
if (gdi.hasField("PayMode"))
if (gdi.hasWidget("PayMode"))
hasPaid = gdi.getSelectedItem("PayMode").first != 1000;
bool fixPay = gdi.isChecked("Paid");
@ -3928,7 +4025,7 @@ bool TabSI::checkpPrintQueue(gdioutput &gdi) {
printPunchRunnerIdQueue.pop_front();
pRunner r = oe->getRunner(rid, 0);
if (r) {
r->evaluateCard(true, mp);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Quiet);
r->printSplits(gdiprint);
}
gdiprint.dropLine(4);
@ -3950,7 +4047,7 @@ void TabSI::printSIInfo(gdioutput &gdi, const wstring &port) const {
oClub *TabSI::extractClub(gdioutput &gdi) const {
auto &db = oe->getRunnerDatabase();
oClub *dbClub = nullptr;
if (gdi.hasField("Club")) {
if (gdi.hasWidget("Club")) {
int clubId = gdi.getExtraInt("Club");
if (clubId > 0) {
dbClub = db.getClub(clubId-1);
@ -4128,14 +4225,14 @@ void TabSI::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
}
}
if (r) {
if (gdi.hasField("Club") && r->dbe().clubNo) {
if (gdi.hasWidget("Club") && r->dbe().clubNo) {
if (gdi.getText("Club").empty()) {
auto pclub = oe->getRunnerDatabase().getClub(r->dbe().clubNo);
if (pclub)
gdi.setText("Club", pclub->getName());
}
}
if (gdi.hasField("CardNo") && r->dbe().cardNo) {
if (gdi.hasWidget("CardNo") && r->dbe().cardNo) {
if (gdi.getText("CardNo").empty())
gdi.setText("CardNo", r->dbe().cardNo);
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -81,8 +81,13 @@ private:
bool printErrorShown;
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
//Interactive card assign
//Operation mode
SIMode mode;
bool lockedFunction = false;
bool allowControl = true;
bool allowFinish = true;
bool allowStart = false;
int currentAssignIndex;
void printSIInfo(gdioutput &gdi, const wstring &port) const;
@ -96,7 +101,7 @@ private:
int lastClubId;
wstring lastFee;
int inputId;
int numSavedCardsOnCmpOpen = 0;
void showCheckCardStatus(gdioutput &gdi, const string &cmd);
void showRegisterHiredCards(gdioutput &gdi);
@ -142,7 +147,7 @@ private:
void generateSplits(const pRunner r, gdioutput &gdi);
int logcounter;
csvparser *logger;
shared_ptr<csvparser> logger;
string insertCardNumberField;
@ -159,7 +164,7 @@ private:
void showModeCardData(gdioutput &gdi);
void printCard(gdioutput &gdi, int cardId, bool forPrinter) const;
void printCard(gdioutput &gdi, int cardId, SICard *crdRef, bool forPrinter) const;
void generateSplits(int cardId, gdioutput &gdi);
static int analyzePunch(SIPunch &p, int &start, int &accTime, int &days);
@ -197,6 +202,10 @@ private:
oClub *extractClub(gdioutput &gdi) const;
RunnerWDBEntry *extractRunner(gdioutput &gdi) const;
void updateReadoutFunction(gdioutput &gdi);
int readoutFunctionX = 0;
int readoutFunctionY = 0;
protected:
void clearCompetitionData();

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -214,7 +214,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.clearPage(false);
gdi.addButton("Cancel", "Stäng", tabSpeakerCB);
gdi.dropLine();
gdi.addTable(oe->getPunchesTB(), gdi.getCX(), gdi.getCY());
gdi.addTable(oFreePunch::getTable(oe), gdi.getCX(), gdi.getCY());
gdi.refresh();
}
else if (bu.id == "Report") {
@ -745,7 +745,7 @@ void TabSpeaker::generateControlList(gdioutput &gdi, int classId)
return;
bool keepLegs = false;
if (gdi.hasField("Leg")) {
if (gdi.hasWidget("Leg")) {
DWORD clsSel = 0;
if (gdi.getData("ClassSelection", clsSel) && clsSel == pc->getId()) {
gdi.restore("LegSelection", true);
@ -1125,17 +1125,17 @@ bool TabSpeaker::loadPage(gdioutput &gdi) {
if (classId == -1) {
string btn = "Events";
if (gdi.hasField(btn))
if (gdi.hasWidget(btn))
gdi.sendCtrlMessage(btn);
}
else if (classId == -2) {
string btn = "Report";
if (gdi.hasField(btn))
if (gdi.hasWidget(btn))
gdi.sendCtrlMessage(btn);
}
else if (classId > 0) {
string btn = "cid" + itos(classId);
if (gdi.hasField(btn))
if (gdi.hasWidget(btn))
gdi.sendCtrlMessage(btn);
}
@ -1265,7 +1265,7 @@ void TabSpeaker::savePriorityClass(gdioutput &gdi) {
pRunner r = oe->getRunner(runnersToSet[k], 0);
if (r) {
int id = runnersToSet[k];
if (!gdi.hasField("A" + itos(id))) {
if (!gdi.hasWidget("A" + itos(id))) {
runnersToSet.clear(); //Page not loaded. Abort.
return;
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -179,7 +179,7 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
{
if (t){
t->synchronize();
t->evaluate(false);
t->evaluate(oBase::ChangeType::Quiet);
teamId=t->getId();
@ -192,7 +192,7 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.selectItemByData("RClass", t->getClassId(false));
gdi.selectItemByData("Teams", t->getId());
if (gdi.hasField("StatusIn")) {
if (gdi.hasWidget("StatusIn")) {
gdi.selectItemByData("StatusIn", t->getInputStatus());
int ip = t->getInputPlace();
if (ip > 0)
@ -201,11 +201,11 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.setText("PlaceIn", makeDash(L"-"));
gdi.setText("TimeIn", t->getInputTimeS());
if (gdi.hasField("PointIn"))
if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", t->getInputPoints());
}
if (gdi.hasField("NoRestart")) {
if (gdi.hasWidget("NoRestart")) {
gdi.check("NoRestart", t->preventRestart());
}
@ -224,11 +224,11 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.selectItemByData("Teams", -1);
if (gdi.hasField("StatusIn")) {
if (gdi.hasWidget("StatusIn")) {
gdi.selectFirstItem("StatusIn");
gdi.setText("PlaceIn", L"");
gdi.setText("TimeIn", makeDash(L"-"));
if (gdi.hasField("PointIn"))
if (gdi.hasWidget("PointIn"))
gdi.setText("PointIn", L"");
}
@ -243,11 +243,11 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
{
if (!t) {
gdi.setText("Name", L"");
if (gdi.hasField("StartNo"))
if (gdi.hasWidget("StartNo"))
gdi.setText("StartNo", L"");
if (gdi.hasField("Club"))
if (gdi.hasWidget("Club"))
gdi.setText("Club", L"");
bool hasFee = gdi.hasField("Fee");
bool hasFee = gdi.hasWidget("Fee");
if (hasFee) {
gdi.setText("Fee", L"");
}
@ -262,19 +262,19 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
}
gdi.setText("Name", t->getName());
if (gdi.hasField("StartNo"))
if (gdi.hasWidget("StartNo"))
gdi.setText("StartNo", t->getBib());
if (gdi.hasField("Club"))
if (gdi.hasWidget("Club"))
gdi.setText("Club", t->getClub());
bool hasFee = gdi.hasField("Fee");
bool hasFee = gdi.hasWidget("Fee");
if (hasFee) {
gdi.setText("Fee", oe->formatCurrency(t->getDI().getInt("Fee")));
}
gdi.setText("Start", t->getStartTimeS());
gdi.setText("Finish",t->getFinishTimeS());
gdi.setText("Time", t->getRunningTimeS());
gdi.setText("Time", t->getRunningTimeS(true));
gdi.setText("TimeAdjust", getTimeMS(t->getTimeAdjustment()));
gdi.setText("PointAdjust", -t->getPointAdjustment());
gdi.selectItemByData("Status", t->getStatus());
@ -305,13 +305,13 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
bool bibModified = false;
if (t) {
t->setName(name, true);
if (gdi.hasField("StartNo")) {
if (gdi.hasWidget("StartNo")) {
const wstring &bib = gdi.getText("StartNo");
if (bib != t->getBib()) {
bibModified = true;
wchar_t pat[32];
int no = oClass::extractBibPattern(bib, pat);
t->setBib(bib, no, no > 0, false);
t->setBib(bib, no, no > 0);
}
}
wstring start = gdi.getText("Start");
@ -321,16 +321,16 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
t->setFinishTimeS(gdi.getText("Finish"));
if (gdi.hasField("Fee"))
if (gdi.hasWidget("Fee"))
t->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee")));
if (gdi.hasField("NoRestart"))
if (gdi.hasWidget("NoRestart"))
t->preventRestart(gdi.isChecked("NoRestart"));
t->apply(false, 0, false);
t->apply(oBase::ChangeType::Quiet, nullptr);
if (gdi.hasField("Club")) {
if (gdi.hasWidget("Club")) {
ListBoxInfo lbi;
gdi.getSelectedItem("Club", lbi);
@ -351,13 +351,13 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
RunnerStatus sIn = (RunnerStatus)lbi.data;
// Must be done AFTER all runners are set. But setting runner can modify status, so decide here.
bool setDNS = (sIn == StatusDNS || sIn == StatusCANCEL) && (t->getStatus() != sIn);
bool setTeamStatus = (!oAbstractRunner::isResultStatus(sIn) || sIn == StatusOK) && (t->getStatus() != sIn);
bool checkStatus = (sIn != t->getStatus());
if (sIn == StatusUnknown && (t->getStatus() == StatusDNS || t->getStatus() == StatusCANCEL))
t->setTeamNoStart(false, StatusDNS);
if (sIn == StatusUnknown && !oAbstractRunner::isResultStatus(t->getStatus()))
t->setTeamMemberStatus(StatusUnknown);
else if ((RunnerStatus)lbi.data != t->getStatus())
t->setStatus((RunnerStatus)lbi.data, true, false);
t->setStatus((RunnerStatus)lbi.data, true, oBase::ChangeType::Update);
gdi.getSelectedItem("RClass", lbi);
@ -384,27 +384,27 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
if (pc) {
pair<int, wstring> snoBib = pc->getNextBib();
if (snoBib.first > 0) {
t->setBib(snoBib.second, snoBib.first, true, false);
t->setBib(snoBib.second, snoBib.first, true);
}
}
}
t->setClassId(classId, true);
if (gdi.hasField("TimeAdjust")) {
if (gdi.hasWidget("TimeAdjust")) {
int time = convertAbsoluteTimeMS(gdi.getText("TimeAdjust"));
if (time != NOTIME)
t->setTimeAdjustment(time);
}
if (gdi.hasField("PointAdjust")) {
if (gdi.hasWidget("PointAdjust")) {
t->setPointAdjustment(-gdi.getTextNo("PointAdjust"));
}
if (gdi.hasField("StatusIn") && readStatusIn) {
if (gdi.hasWidget("StatusIn") && readStatusIn) {
t->setInputStatus(RunnerStatus(gdi.getSelectedItem("StatusIn").first));
t->setInputPlace(gdi.getTextNo("PlaceIn"));
t->setInputTime(gdi.getText("TimeIn"));
if (gdi.hasField("PointIn"))
if (gdi.hasWidget("PointIn"))
t->setInputPoints(gdi.getTextNo("PointIn"));
}
@ -416,7 +416,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
for (unsigned i=0;i<pc->getNumStages(); i++) {
char bf[16];
sprintf_s(bf, "R%d", i);
if (!gdi.hasField("SI" + itos(i))) // Skip if field not loaded in page
if (!gdi.hasWidget("SI" + itos(i))) // Skip if field not loaded in page
continue;
if (pc->getLegRunner(i)==i) {
@ -474,10 +474,10 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
}
}
}
}
if (setDNS)
t->setTeamNoStart(true, sIn);
if (setTeamStatus)
t->setTeamMemberStatus(sIn);
if (t->checkValdParSetup()) {
gdi.alert("Laguppställningen hade fel, som har rättats");
@ -486,7 +486,8 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
if (t->getRunner(0))
t->getRunner(0)->setStartTimeS(start);
t->evaluate(true);
t->applyBibs();
t->evaluate(oBase::ChangeType::Update);
if (globalDep)
oe->reEvaluateAll(classes, false);
@ -660,7 +661,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
else {
oldR->setClassId(0, true);
vector<int> mp;
oldR->evaluateCard(true, mp, 0, true);
oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
oldR->synchronize(true);
t->setRunner(leg, r, true);
t->checkValdParSetup();
@ -731,17 +732,9 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
int currentKey = max(newSno-1, 0) % nf;
if (currentKey == lbi.data) {
t->setStartNo(newSno, false);
t->apply(false, 0, false);
t->setStartNo(newSno, oBase::ChangeType::Update);
t->synchronize(true);
for (int i = 0; i < t->getNumRunners(); i++) {
pRunner r = t->getRunner(i);
if (r) {
vector<int> mp;
r->evaluateCard(true, mp);
r->synchronize(true);
}
}
t->evaluate(oBase::ChangeType::Update);
selectTeam(gdi, t);
return 0;
}
@ -921,11 +914,12 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
if (pc) {
pair<int, wstring> snoBib = pc->getNextBib();
if (snoBib.first > 0) {
t->setBib(snoBib.second, snoBib.first, true, false);
t->setBib(snoBib.second, snoBib.first, true);
}
}
t->setClassId(clsId, true);
t->synchronize();
fillTeamList(gdi);
//oe->fillTeams(gdi, "Teams");
@ -993,7 +987,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
if (gdi.isInputChanged("")) {
pTeam t = oe->getTeam(teamId);
bool newName = t && t->getName() != gdi.getText("Name");
bool newBib = gdi.hasField("StartNo") && t && t->getBib() != gdi.getText("StartNo");
bool newBib = gdi.hasWidget("StartNo") && t && t->getBib() != gdi.getText("StartNo");
save(gdi, true);
if (newName || newBib) {
@ -1272,13 +1266,13 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
gdi.check("RENT" + itos(i), r->getDCI().getInt("CardFee") != 0);
}
string sid = "STATUS"+itos(i);
if (r->statusOK()) {
TextInfo * ti = (TextInfo *)gdi.setText(sid, L"OK, " + r->getRunningTimeS(), false);
if (r->statusOK(true)) {
TextInfo * ti = (TextInfo *)gdi.setText(sid, L"OK, " + r->getRunningTimeS(true), false);
if (ti)
ti->setColor(colorGreen);
}
else if (r->getStatus() != StatusUnknown) {
TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS(false) + L", " + r->getRunningTimeS(), false);
else if (r->getStatusComputed() != StatusUnknown) {
TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS(false, true) + L", " + r->getRunningTimeS(true), false);
if (ti)
ti->setColor(colorRed);
}
@ -1344,10 +1338,9 @@ bool TabTeam::loadPage(gdioutput &gdi)
gdi.clearPage(false);
if (currentMode == 1) {
Table *tbl=oe->getTeamsTB();
addToolbar(gdi);
gdi.dropLine(1);
gdi.addTable(tbl, gdi.getCX(), gdi.getCY());
gdi.addTable(oTeam::getTable(oe), gdi.getCX(), gdi.getCY());
return true;
}
@ -1790,7 +1783,7 @@ void TabTeam::doAddTeamMembers(gdioutput &gdi) {
}
}
if (ch) {
mt->apply(false, 0, false);
mt->apply(oBase::ChangeType::Update, nullptr);
mt->synchronize();
for (int j = 0; j < mt->getNumRunners(); j++) {
if (mt->getRunner(j) != 0) {
@ -1905,9 +1898,9 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
int otherLeg = r->getLegNumber();
otherTeam->setRunner(otherLeg, oldR, true);
if (oldR)
oldR->evaluateCard(true, mp, 0, true);
oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
otherTeam->checkValdParSetup();
otherTeam->apply(true, 0, false);
otherTeam->apply(oBase::ChangeType::Update, nullptr);
otherTeam->synchronize(true);
}
else if (oldR) {
@ -1918,14 +1911,14 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
else
oldR->setClassId(r->getClassId(false), true);
removeAnnonumousTeamMember = oldR->isAnnonumousTeamMember();
oldR->evaluateCard(true, mp, 0, true);
oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
oldR->synchronize(true);
}
t->setRunner(leg, r, true);
r->evaluateCard(true, mp, 0, true);
r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
t->checkValdParSetup();
t->apply(true, 0, false);
t->apply(oBase::ChangeType::Update, nullptr);
t->synchronize(true);
if (removeAnnonumousTeamMember)
@ -1981,12 +1974,12 @@ void TabTeam::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
auto &db = oe->getRunnerDatabase();
auto runner = db.getRunnerByIndex(ix);
if (runner && gdi.hasField("Club") && gdi.getText("Club").empty()) {
if (runner && gdi.hasWidget("Club") && gdi.getText("Club").empty()) {
pClub club = db.getClub(runner->dbe().clubNo);
if (club)
gdi.setText("Club", club->getName());
}
if (runner && runner->dbe().cardNo > 0 && gdi.hasField("DirCard") && gdi.getText("DirCard").empty()) {
if (runner && runner->dbe().cardNo > 0 && gdi.hasWidget("DirCard") && gdi.getText("DirCard").empty()) {
gdi.setText("DirCard", runner->dbe().cardNo);
}
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -72,7 +72,6 @@ Table::Table(oEvent *oe_, int rowH,
partialCell = false;
startSelect = false;
ownerCounter = 0;
clearCellSelection(0);
tableProp = -1;
dataPointer = -1;
@ -86,18 +85,10 @@ Table::Table(oEvent *oe_, int rowH,
Table::~Table(void)
{
assert(ownerCounter == 0);
if (hEdit)
DestroyWindow(hEdit);
}
void Table::releaseOwnership() {
ownerCounter--;
if (ownerCounter == 0)
delete this;
}
void Table::clearCellSelection(gdioutput *gdi) {
upperRow = -1;
lowerRow = -1;
@ -111,8 +102,12 @@ void Table::clearCellSelection(gdioutput *gdi) {
}
int Table::addColumn(const string &Title, int width, bool isnum, bool formatRight) {
return addColumn(lang.tl(Title).c_str(), width, isnum, formatRight);
}
int Table::addColumn(const wstring &translatedTitle, int width, bool isnum, bool formatRight) {
ColInfo ri;
wcscpy_s(ri.name, lang.tl(Title).c_str());
wcscpy_s(ri.name, translatedTitle.c_str());
ri.baseWidth = width;
ri.width = 0;
ri.padWidthZeroSort = 0;
@ -440,26 +435,21 @@ void Table::sort(int col)
}
}
int TablesCB(gdioutput *gdi, int type, void *data)
{
int TablesCB(gdioutput *gdi, int type, void *data) {
if (type!=GUI_LINK || gdi->Tables.empty())
return 0;
TableInfo &tai=gdi->Tables.front();
Table *t=tai.table;
auto &t = tai.table;
TextInfo *ti=(TextInfo *)data;
if (ti->id.substr(0,4)=="sort"){
int col=atoi(ti->id.substr(4).c_str());
t->sort(col);
}
gdi->refresh();
//gdi->Restore();
//t->Render(*gdi);
//*/
return 0;
}
@ -725,12 +715,21 @@ void Table::selection(gdioutput &gdi, const wstring &text, int data) {
TableCell &cell = Data[selectionRow].cells[selectionCol];
int id = Data[selectionRow].id;
pair<int, bool> res;
if (cell.hasOwner())
cell.getOwner()->inputData(cell.id, text, data, cell.contents, false);
res = cell.getOwner()->inputData(cell.id, text, data, cell.contents, false);
if (res.second) {
update();
gdi.refresh();
}
else {
reloadRow(id);
RECT rc;
getRowRect(selectionRow, rc);
InvalidateRect(gdi.getHWNDTarget(), &rc, false);
if (res.first)
reloadRow(res.first);
//RECT rc;
//getRowRect(selectionRow, rc);
InvalidateRect(gdi.getHWNDTarget(), nullptr, false);
}
}
#ifndef MEOSDB
@ -838,7 +837,7 @@ bool Table::destroyEditControl(gdioutput &gdi) {
hEdit=0;
}
}
gdi.removeControl(tId);
gdi.removeWidget(tId);
if (drawFilterLabel) {
drawFilterLabel=false;
@ -1643,7 +1642,7 @@ bool Table::enter(gdioutput &gdi)
}
}
}
else if (gdi.hasField(tId)) {
else if (gdi.hasWidget(tId)) {
ListBoxInfo lbi;
gdi.getSelectedItem(tId, lbi);
@ -1662,7 +1661,7 @@ void Table::escape(gdioutput &gdi)
DestroyWindow(hEdit);
hEdit = 0;
}
gdi.removeControl(tId);
gdi.removeWidget(tId);
drawFilterLabel=false;
gdi.refresh();
}
@ -2279,7 +2278,7 @@ void Table::autoSelectColumns() {
for (size_t r = 2; r<Data.size(); r++) {
const wstring &c = Data[r].cells[k].contents;
if (!c.empty() && c != first) {
if (c != first) {
nonEmpty++;
empty[k] = false;
break;

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -249,7 +249,6 @@ protected:
void getRowRange(int &rowLo, int &rowHi) const;
void getColRange(int &colLo, int &colHi) const;
int ownerCounter;
DWORD tableProp;
int selectionRow;
@ -302,8 +301,6 @@ public:
void setTableProp(DWORD w) {tableProp = w;}
void hide(gdioutput &gdi); //Ensure no edit contol is visible
void addOwnership() {ownerCounter++;}
void releaseOwnership();
void autoAdjust(gdioutput &gdi); // Adjust column widths
void autoSelectColumns();
@ -347,6 +344,8 @@ public:
void filter(int col, const wstring &filt, bool forceFilter=false);
int addColumn(const string &Title, int width, bool isnum, bool formatRight = false);
int addColumn(const wstring &translatedTitle, int width, bool isnum, bool formatRight = false);
int addColumnPaddedSort(const string &title, int width, int padding, bool formatRight = false);
void reserve(size_t siz);
@ -385,7 +384,7 @@ struct TableSortIndex {
enum {TID_CLASSNAME, TID_COURSE, TID_NUM, TID_ID, TID_MODIFIED,
TID_RUNNER, TID_CLUB, TID_START, TID_TIME,
TID_FINISH, TID_STATUS, TID_RUNNINGTIME, TID_PLACE,
TID_FINISH, TID_STATUS, TID_RUNNINGTIME, TID_PLACE, TID_POINTS,
TID_CARD, TID_TEAM, TID_LEG, TID_CONTROL, TID_CODES, TID_FEE, TID_PAID,
TID_INPUTTIME, TID_INPUTSTATUS, TID_INPUTPOINTS, TID_INPUTPLACE,
TID_NAME, TID_NATIONAL, TID_SEX, TID_YEAR, TID_INDEX, TID_ENTER, TID_STARTNO};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -10,7 +10,7 @@
#endif // _MSC_VER > 1000
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -48,11 +48,15 @@ void ClassConfigInfo::clear() {
}
bool ClassConfigInfo::empty() const {
return individual.empty() && relay.empty() && patrol.empty() && raceNStart.empty();
return individual.empty() && rogainingClasses.empty()
&& relay.empty() && patrol.empty()
&& raceNStart.empty() && rogainingTeam.empty();
}
void ClassConfigInfo::getIndividual(set<int> &sel) const {
void ClassConfigInfo::getIndividual(set<int> &sel, bool forStartList) const {
sel.insert(individual.begin(), individual.end());
if (forStartList)
sel.insert(rogainingClasses.begin(), rogainingClasses.end());
}
void ClassConfigInfo::getRelay(set<int> &sel) const {
@ -79,6 +83,9 @@ void ClassConfigInfo::getRogaining(set<int> &sel) const {
sel.insert(rogainingClasses.begin(), rogainingClasses.end());
}
void ClassConfigInfo::getRogainingTeam(set<int> &sel) const {
sel.insert(rogainingTeam.begin(), rogainingTeam.end());
}
void ClassConfigInfo::getRaceNStart(int race, set<int> &sel) const {
if (size_t(race) < raceNStart.size() && !raceNStart[race].empty())
@ -124,8 +131,6 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
cnf.maximumLegNumber = max<int>(cnf.maximumLegNumber, it->getNumStages());
ClassType ct = it->getClassType();
if (it->isRogaining())
cnf.rogainingClasses.push_back(it->getId());
if (it->getCourse() == 0)
cnf.classWithoutCourse.push_back(it->getName()); //MultiCourse not analysed...
@ -187,12 +192,20 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
cnf.hasMultiCourse = true;
}
}
if (ct == oClassIndividual) {
if (it->isRogaining())
cnf.rogainingClasses.push_back(it->getId());
else
cnf.individual.push_back(it->getId());
if (cnf.timeStart.empty())
cnf.timeStart.resize(1);
cnf.timeStart[0].push_back(it->getId());
}
else if ((ct == oClassPatrol || ct == oClassRelay) && it->isRogaining()) {
cnf.rogainingTeam.push_back(it->getId());
}
else if (ct == oClassPatrol)
cnf.patrol.push_back(it->getId());
else if (ct == oClassRelay) {

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -35,6 +35,7 @@ public:
vector<int> individual;
vector<int> relay;
vector<int> patrol;
vector<int> rogainingTeam;
vector< vector<int> > legNStart;
vector< vector<int> > raceNStart;
@ -65,15 +66,18 @@ public:
bool hasRelay() const {return relay.size()>0;}
bool hasPatrol() const {return patrol.size()>0;}
bool hasRogaining() const {return rogainingClasses.size()>0;}
bool hasRogainingTeam() const { return rogainingTeam.size()>0; }
bool empty() const;
// Return true of this is an event in a sequence of events.
bool isMultiStageEvent() const {return hasMultiEvent;}
void getIndividual(set<int> &sel) const;
void getIndividual(set<int> &sel, bool forStartList) const;
void getRelay(set<int> &sel) const;
void getPatrol(set<int> &sel) const;
void getTeamClass(set<int> &sel) const;
void getRogaining(set<int> &sel) const;
void getRogainingTeam(set<int> &sel) const;
bool hasTeamClass() const;

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -165,18 +165,18 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
pTeam team=event.addTeam(sp[OSclub] + L" " + sp[OSdesc], ClubId, ClassId);
team->setEntrySource(externalSourceId);
team->setStartNo(wtoi(sp[OSstno]), false);
team->setStartNo(wtoi(sp[OSstno]), oBase::ChangeType::Update);
if (sp[12].length()>0)
team->setStatus( ConvertOEStatus( wtoi(sp[OSstatus]) ), true, false);
team->setStatus( ConvertOEStatus( wtoi(sp[OSstatus]) ), true, oBase::ChangeType::Update);
team->setStartTime(event.convertAbsoluteTime(sp[OSstart]), true, false);
team->setStartTime(event.convertAbsoluteTime(sp[OSstart]), true, oBase::ChangeType::Update);
if (sp[OStime].length()>0)
team->setFinishTime( event.convertAbsoluteTime(sp[OSstart])+event.convertAbsoluteTime(sp[OStime])-event.getZeroTimeNum() );
if (team->getStatus()==StatusOK && team->getFinishTime()==0)
team->setStatus(StatusUnknown, true, false);
team->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
unsigned rindex=Offset;
@ -204,14 +204,14 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
DI.setInt("CardFee", event.getDCI().getInt("CardFee"));
//r->setCardNo(atoi(sp[rindex+OSRcard]), false);
r->setStartTime(event.convertAbsoluteTime(sp[rindex+OSRstart]), true, false);
r->setStartTime(event.convertAbsoluteTime(sp[rindex+OSRstart]), true, oBase::ChangeType::Update);
r->setFinishTime( event.convertAbsoluteTime(sp[rindex+OSRfinish]) );
if (sp[rindex+OSRstatus].length()>0)
r->setStatus( ConvertOEStatus( wtoi(sp[rindex+OSRstatus]) ), true, false, false);
r->setStatus( ConvertOEStatus( wtoi(sp[rindex+OSRstatus]) ), true, oBase::ChangeType::Update, false);
if (r->getStatus()==StatusOK && r->getRunningTime()==0)
r->setStatus(StatusUnknown, true, false, false);
if (r->getStatus()==StatusOK && r->getRunningTime(false)==0)
r->setStatus(StatusUnknown, true, oBase::ChangeType::Update, false);
r->addClassDefaultFee(false);
@ -225,7 +225,7 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
if (pc && runner>(int)pc->getNumStages())
pc->setNumStages(runner);
team->apply(true, 0, false);
team->evaluate(oBase::ChangeType::Update);
}
}
fin.close();
@ -324,14 +324,14 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
pr->setClubId(pclub ? pclub->getId():0);
pr->setCardNo( wtoi(sp[OEcard]), false );
pr->setStartTime(event.convertAbsoluteTime(sp[OEstart]), true, false);
pr->setStartTime(event.convertAbsoluteTime(sp[OEstart]), true, oBase::ChangeType::Update);
pr->setFinishTime(event.convertAbsoluteTime(sp[OEfinish]));
if (sp[OEstatus].length()>0)
pr->setStatus( ConvertOEStatus( wtoi(sp[OEstatus]) ), true, false);
pr->setStatus( ConvertOEStatus( wtoi(sp[OEstatus]) ), true, oBase::ChangeType::Update);
if (pr->getStatus()==StatusOK && pr->getRunningTime()==0)
pr->setStatus(StatusUnknown, true, false);
if (pr->getStatus()==StatusOK && pr->getRunningTime(false)==0)
pr->setStatus(StatusUnknown, true, oBase::ChangeType::Update);
//Autocreate class if it does not exist...
int classId=wtoi(sp[OEclassno]);
@ -350,9 +350,9 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
if (needSno || newEntry) {
if (stno>0)
pr->setStartNo(stno, false);
pr->setStartNo(stno, oBase::ChangeType::Update);
else
pr->setStartNo(nimport, false);
pr->setStartNo(nimport, oBase::ChangeType::Update);
}
oDataInterface DI=pr->getDI();
@ -361,7 +361,7 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
DI.setString("Nationality", sp[OEnat]);
if (sp.size()>OEbib && needBib)
pr->setBib(sp[OEbib], 0, false, false);
pr->setBib(sp[OEbib], 0, false);
if (sp.size()>=38) {//ECO
DI.setInt("Fee", wtoi(sp[OEfee]));
@ -682,7 +682,7 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
//Club is autocreated...
pTeam team=event.addTeam(sp[RAIDteam], ClubId, ClassId);
team->setStartNo(wtoi(sp[RAIDid]), false);
team->setStartNo(wtoi(sp[RAIDid]), oBase::ChangeType::Update);
if (sp.size()>8)
team->getDI().setInt("SortIndex", wtoi(sp[RAIDcanoe]));
oDataInterface teamDI=team->getDI();
@ -703,7 +703,7 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
pRunner r2=event.addRunner(sp[RAIDrunner2], ClubId, ClassId, 0, 0, false);
team->setRunner(1, r2, false);
team->apply(true, 0, false);
team->evaluate(oBase::ChangeType::Update);
}
}
fin.close();

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -7,7 +7,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1421,8 +1421,8 @@ xml-data = xml data
Ändrad = Modified
Ändrade avgift för X deltagare = Modified fee for X competitor(s)
Åldersfilter = Age filter
Åldersgräns ungdom = Age limit, low
Åldersgräns äldre = Age limit, high
Åldersgräns ungdom = Age limit, low (youth)
Åldersgräns äldre = Age limit, high (pensioner)
Åldersgränser, reducerad anmälningsavgift = Age Limits, Fee Reduction
Ångra = Undo
Återansluten mot databasen, tävlingen synkroniserad = Reconnected to database, competition synchronized
@ -1871,7 +1871,7 @@ Byt till rätt klass (behåll eventuell starttid) = Switch to the right class (k
Byt till vakansplats i rätt klass (om möjligt) = Switch to a vacant position in the right class (if possible)
Tillåt ny klass, behåll resultat från annan klass = Allow new class and keep results from other class
Tillåt ny klass, inget totalresultat = Allow new class but without total result
tooltip_explain_status = - = Unknown Status (No result yet)\nOK = Valid result\nDNS = Did Not Start\nCancelled = Cancelled entry (shown in start list)\nMP = Missing Punch\nDNF = Did Not Finish\nDISQ = Disqualified\nOMT = Over Maximum Time\nNTP = Not Taking Part
tooltip_explain_status = - = Unknown Status (No result yet)\nOK = Valid result\nDNS = Did Not Start\nCancelled = Cancelled entry (shown in start list)\nMP = Missing Punch\nDNF = Did Not Finish\nDISQ = Disqualified\nOMT = Over Maximum Time\nOOC = Out-of-competition\nNTP = Not Taking Part
Placering = Place
Resultat från tidigare etapper = Results from Earlier Stages
Input Results = Input Results
@ -2106,7 +2106,7 @@ prefsMaximumSpeakerDelay = Maximum delay in announcer's view update
prefsOrganizer = Organizer
prefsPort = MySQL network port
prefsRentCard = Rent card
prefsSeniorAge = Upper age limit
prefsSeniorAge = Upper (pensioner) age limit
prefsServer = Default network server
prefsSpeakerShortNames = Use initials in names
prefsStreet = Organizer street address
@ -2435,4 +2435,43 @@ Runner check time = Runner check time
ClassNumEntries = Number of entries in class
Flera lopp i valfri ordning = Several races in any order
Knockout sammanställning = Knock-out summary
Utom tävlan = OOC
Status code for running out-of-competition = Status code for running out-of-competition (OOC)
X anmälda = X entries
Lås funktion = Lock function
Lås upp = Unlock
Målstämpling tillåts inte (X) = Finish punch disallowed (X)
Radio = Radio
Radio tillåts inte (X) = Radio controls disallowed (X)
Startstämpling tillåts inte (X) = Start punch disallowed (X)
Tillåt = Allow
warn:printmodeonly = Note that you will only generate a printout of the card contents.\n\nTo save a result to the competition you need to select function readout/radio.
There is no result module with X as identifier = There is no result module with X as identifier
Senast sedd: X vid Y = Last seen: X at Y
Referens = Reference
Poäng E[stageno] = Points S
Status E[stageno] = Status S
Tid E[stageno] = Time S
Plac. E[stageno] = Pl. S
Från första = From first
Kartor = Maps
Poängreduktion = Reduction
Stigning = Climb
Till sista = To last
Heat = Heat
Kvalschema = Qualification scheme
Låst gaffling = Locked forking
Result module = Result module
ask:usecourseinclass = The course is not used by any other competitor in this class.\n\nWould you like to use it anyway?
Inkludera bana = Include course
Rogaining points before automatic reduction = Rogaining points before automatic reduction
Runner/team earlier stage places = Runner/team earlier stage places
Runner/team earlier stage points = Runner/team earlier stage points
Runner/team earlier stage running times = Runner/team earlier stage running times
Runner/team earlier stage statuses = Runner/team earlier stage statuses
Status code for cancelled entry = Status code for cancelled entry
Åldersfiltrering = Age filter
Age (on last day of current year) = Age (on last day of current year)
Age above or equal implies senior/pensioner = Age above or equal implies senior/pensioner
Age below or equal implies youth = Age below or equal implies youth
Status code for not no timing = Status code for not no timing

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -60,8 +60,10 @@ const int timerIgnoreSign = 1<<15;
const int Capitalize = 1<<16;
const int absolutePosition = 1 << 17;
const int skipBoundingBox = 1 << 18;
const int hiddenText = 1 << 19;
enum GDICOLOR {colorBlack = RGB(0,0,0),
enum GDICOLOR {
colorBlack = RGB(0, 0, 0),
colorRed = RGB(128, 0, 0),
colorGreen = RGB(0, 128, 0),
colorDarkGrey = RGB(40, 40, 40),
@ -70,15 +72,16 @@ enum GDICOLOR {colorBlack = RGB(0,0,0),
colorDarkBlue = RGB(0, 0, 92),
colorDarkGreen = RGB(0, 64, 0),
colorYellow = RGB(255, 230, 0),
colorLightBlue = RGB(240,240,255),
colorLightBlue = RGB(235, 238, 254),
colorLightRed = RGB(255, 230, 230),
colorLightGreen = RGB(180, 255, 180),
colorLightYellow = RGB(255, 255, 200),
colorLightCyan = RGB(200, 255, 255),
colorLightMagenta = RGB(255, 200, 255),
colorLightGreen = RGB(219, 247, 209),
colorLightYellow = RGB(248, 248, 216),
colorLightCyan = RGB(220, 249, 245),//RGB(200, 255, 255),
colorLightMagenta = RGB(240, 207, 244),//RGB(255, 200, 255),
colorMediumRed = RGB(255, 200, 200),
colorMediumDarkRed = RGB(240, 120, 120),
colorWindowBar = -2,
colorDefault = -1,
colorTransparent = -3};
colorTransparent = -3
};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -100,10 +100,11 @@ EventInfo::EventInfo() : callBack(0), keyEvent(KC_NONE) {}
/** Return true if rendering text should be skipped for
this format. */
bool gdioutput::skipTextRender(int format) {
format &= 0xFF;
format &= 0xFF | hiddenText;
return format == pageNewPage ||
format == pagePageInfo ||
format == pageNewChapter;
format == pageNewChapter ||
(format & hiddenText) == hiddenText;
}
#ifndef MEOSDB
@ -376,11 +377,8 @@ gdioutput::~gdioutput()
if (toolbar)
delete toolbar;
toolbar = 0;
//delete table;
while(!Tables.empty()){
Tables.front().table->releaseOwnership();
Tables.pop_front();
}
Tables.clear();
if (tabs) {
delete tabs;
@ -507,7 +505,7 @@ void gdioutput::drawBackground(HDC hDC, RECT &rc)
SelectObject(hDC, GetStockObject(ANSI_FIXED_FONT));
DeleteObject(hInfo);
}
/*
DWORD c=GetSysColor(COLOR_3DFACE);
double red = double(GetRValue(c)) *0.9;
double green = double(GetGValue(c)) * 0.85;
@ -523,7 +521,15 @@ void gdioutput::drawBackground(HDC hDC, RECT &rc)
double blue1=min(255., blue*1.3);
double green1=min(255., green*1.3);
double red1=min(255., red*1.3);
*/
double red = 242.0;
double green = 247.0;
double blue = 254.0;
double blue1 = 250.0;
double green1 = 232.0;
double red1 = 223.0;
TRIVERTEX vert[2];
if (hideBG) {
@ -661,8 +667,10 @@ void gdioutput::draw(HDC hDC, RECT &rc, RECT &drawArea)
}
void gdioutput::renderRectangle(HDC hDC, RECT *clipRegion, const RectangleInfo &ri) {
if (ri.drawBorder)
SelectObject(hDC, GetStockObject(BLACK_PEN));
if (ri.drawBorder) {
SelectObject(hDC, GetStockObject(DC_PEN));
SetDCPenColor(hDC, RGB(40,40,60));
}
else
SelectObject(hDC, GetStockObject(NULL_PEN));
@ -1213,7 +1221,8 @@ void gdioutput::enableCheckBoxLink(TextInfo &ti, bool enable) {
else {
needRefresh = ti.callBack != 0;
ti.callBack = 0;
ti.setColor(colorDarkGrey);
DWORD c = GetSysColor(COLOR_GRAYTEXT);
ti.setColor(GDICOLOR(c));
}
if (needRefresh)
InvalidateRect(hWndTarget, &ti.textRect, true);
@ -3049,14 +3058,10 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
LBI.clear();
}
//delete table;
//table=0;
while (!Tables.empty()) {
Table *t=Tables.front().table;
Tables.front().table=0;
auto t = Tables.front().table;
Tables.pop_front();
t->hide(*this);
t->releaseOwnership();
}
DataInfo.clear();
@ -3065,11 +3070,11 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
Rectangles.clear();
MaxX=40;
MaxY=100;
MaxX = scaleLength(60);
MaxY = scaleLength(100);
CurrentX=40;
CurrentY=START_YP;
CurrentX = scaleLength(40);
CurrentY = scaleLength(START_YP);
OffsetX = 0;
OffsetY = 0;
@ -3208,7 +3213,7 @@ const wstring &gdioutput::getText(const char *id, bool acceptMissing) const
return _EmptyWString;
}
bool gdioutput::hasField(const string &id) const
bool gdioutput::hasWidget(const string &id) const
{
for(list<InputInfo>::const_iterator it=II.begin();
it != II.end(); ++it){
@ -3602,8 +3607,8 @@ void gdioutput::setTabStops(const string &Name, int t1, int t2)
int n=1;
LONG bu=GetDialogBaseUnits();
int baseunitX=LOWORD(bu);
array[0]=(t1 * 4) / baseunitX ;
array[1]=(t2 * 4) / baseunitX ;
array[0]=int(t1 * 4.2) / baseunitX ;
array[1]=int(t2 * 4.2) / baseunitX ;
int lastTabStop = 0;
if (t2>0) {
n=2;
@ -3989,7 +3994,6 @@ void gdioutput::removeString(string id)
for (it=TL.begin(); it != TL.end(); ++it) {
if (it->id==id) {
HDC hDC=GetDC(hWndTarget);
//TextOut(
RECT rc;
rc.left=it->xp;
rc.top=it->yp;
@ -4213,12 +4217,12 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC)
ti.textRect.bottom+=ti.yp+dx;
if (ti.format == 10) {
DWORD c=GetSysColor(COLOR_INFOBK);
DWORD c = colorLightYellow;// GetSysColor(COLOR_INFOBK);
double red=GetRValue(c);
double green=GetGValue(c);
double blue=GetBValue(c);
double blue1=min(255., blue*0.8);
double blue1=min(255., blue*1.05);
double green1=min(255., green*1.05);
double red1=min(255., red*1.05);
@ -4273,7 +4277,7 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC)
rc.bottom+=ti.yp+dx-OffsetY;
rc.right=ti.xp+dx+width-OffsetX;
SetTextColor(hDC, GetSysColor(COLOR_INFOTEXT));
SetTextColor(hDC, 0);
DrawText(hDC, ti.text.c_str(), ti.text.length(), &rc, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
}
@ -4787,7 +4791,7 @@ void gdioutput::CheckInterfaceTimeouts(DWORD T)
}
}
bool gdioutput::removeControl(const string &id)
bool gdioutput::removeWidget(const string &id)
{
list<ButtonInfo>::iterator it=BI.begin();
@ -4834,13 +4838,15 @@ bool gdioutput::removeControl(const string &id)
return false;
}
bool gdioutput::hideControl(const string &id)
{
bool gdioutput::hideWidget(const string &id, bool hide) {
list<ButtonInfo>::iterator it=BI.begin();
while (it!=BI.end()) {
if (it->id == id) {
ShowWindow(it->hWnd, SW_HIDE);
ShowWindow(it->hWnd, hide ? SW_HIDE : SW_SHOW);
if (it->isCheckbox) {
hideWidget("T" + id, hide);
}
return true;
}
++it;
@ -4850,7 +4856,7 @@ bool gdioutput::hideControl(const string &id)
while (lit!=LBI.end()) {
if (lit->id==id) {
ShowWindow(lit->hWnd, SW_HIDE);
ShowWindow(lit->hWnd, hide ? SW_HIDE : SW_SHOW);
return true;
}
++lit;
@ -4860,15 +4866,25 @@ bool gdioutput::hideControl(const string &id)
while (iit!=II.end()) {
if (iit->id==id) {
ShowWindow(iit->hWnd, SW_HIDE);
ShowWindow(iit->hWnd, hide ? SW_HIDE : SW_SHOW);
return true;
}
++iit;
}
for (auto &ti : TL) {
if (ti.id == id) {
if (hide)
ti.format |= hiddenText;
else
ti.format &= ~hiddenText;
return true;
}
}
return false;
}
void gdioutput::setRestorePoint()
{
setRestorePoint("");
@ -4974,11 +4990,9 @@ void gdioutput::restoreInternal(const RestoreInfo &ri)
}
while(Tables.size() > unsigned(ri.nTables)){
Table *t=Tables.back().table;
Tables.back().table=0;
auto t=Tables.back().table;
Tables.pop_back();
t->hide(*this);
t->releaseOwnership();
}
int dataRemove=DataInfo.size()-ri.nData;
@ -5656,7 +5670,7 @@ Table &gdioutput::getTable() const {
if (Tables.empty())
throw std::exception("No table defined");
return *const_cast<Table *>(Tables.back().table);
return *const_cast<Table *>(Tables.back().table.get());
}
static int gdiTableCB(gdioutput *gdi, int type, void *data)
@ -5774,16 +5788,10 @@ void gdioutput::enableTables()
useTables=true;
#ifndef MEOSDB
if (!Tables.empty()) {
Table *t = Tables.front().table;
auto &t = Tables.front().table;
if (toolbar == 0)
toolbar = new Toolbar(*this);
/* RECT rc;
rc.top = 10;
rc.bottom = 100;
rc.left = 100;
rc.right = 200;
addToolTip("Hej hopp!", 0, &rc);
*/
toolbar->setData(t);
string tname = string("table") + itos(t->canDelete()) + itos(t->canInsert()) + itos(t->canPaste());
@ -5809,19 +5817,18 @@ void gdioutput::enableTables()
#endif
}
void gdioutput::processToolbarMessage(const string &id, void *data) {
void gdioutput::processToolbarMessage(const string &id, Table *tbl) {
if (hasCommandLock())
return;
wstring msg;
string cmd;
if (getRecorder().recording()) {
Table *tbl = (Table *)data;
cmd = "tableCmd(\"" + id + "\"); //" + narrow(tbl->getTableName());
}
try {
ButtonInfo bi;
bi.id = id;
tableCB(bi, (Table *)data);
tableCB(bi, tbl);
getRecorder().record(cmd);
}
catch (meosException &ex) {
@ -5879,7 +5886,7 @@ void gdioutput::disableTables()
if (bit->id.substr(0, 3)=="tbl" && bit->getExtra()!=0) {
string id = bit->id;
++bit;
removeControl(id);
removeWidget(id);
}
else
++bit;
@ -5887,7 +5894,7 @@ void gdioutput::disableTables()
}
void gdioutput::addTable(Table *t, int x, int y)
void gdioutput::addTable(const shared_ptr<Table> &t, int x, int y)
{
TableInfo ti;
ti.table = t;
@ -5899,7 +5906,6 @@ void gdioutput::addTable(Table *t, int x, int y)
t->autoSelectColumns();
t->autoAdjust(*this);
ti.table->addOwnership();
Tables.push_back(ti);
//updatePos(x, y, dx + TableXMargin, dy + TableYMargin);

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -371,7 +371,7 @@ public:
bool hasToolbar() const;
void activateToolbar(bool active);
void processToolbarMessage(const string &id, void *data);
void processToolbarMessage(const string &id, Table *data);
void synchronizeListScroll(const string &id1, const string &id2);
@ -424,7 +424,7 @@ public:
void selectTab(int Id);
void addTable(Table *table, int x, int y);
void addTable(const shared_ptr<Table> &table, int x, int y);
Table &getTable() const; //Get the (last) table. If needed, add support for named tables...
@ -468,8 +468,8 @@ public:
void setRestorePoint();
void setRestorePoint(const string &id);
bool removeControl(const string &id);
bool hideControl(const string &id);
bool removeWidget(const string &id);
bool hideWidget(const string &id, bool hide = true);
void CheckInterfaceTimeouts(DWORD T);
bool RemoveFirstInfoBox(const string &id);
@ -597,7 +597,7 @@ public:
bool clearList(const string &id);
bool hasField(const string &id) const;
bool hasWidget(const string &id) const;
const wstring &getText(const char *id, bool acceptMissing = false) const;

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -131,7 +131,7 @@ public:
TableInfo():xp(0), yp(0), table(0) {}
int xp;
int yp;
Table *table;
shared_ptr<Table> table;
HWND getControlWindow() const {throw std::exception("Unsupported");}
};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,22 +32,26 @@
extern gdioutput *gdi_main;
GeneralResultCtr::GeneralResultCtr(const char *tagIn, const wstring &nameIn, GeneralResult *ptrIn) {
GeneralResultCtr::GeneralResultCtr(const char *tagIn, const wstring &nameIn, const shared_ptr<GeneralResult> &ptrIn) {
name = nameIn;
tag = tagIn;
ptr = ptrIn;
}
GeneralResultCtr::GeneralResultCtr(wstring &file, DynamicResult *ptrIn) {
GeneralResultCtr::GeneralResultCtr(wstring &file, const shared_ptr<DynamicResult> &ptrIn) {
ptr = ptrIn;
name = ptrIn->getName(false);
tag = ptrIn->getTag();
fileSource = file;
}
bool GeneralResultCtr::operator<(const GeneralResultCtr &c) const {
return CompareString(LOCALE_USER_DEFAULT, 0,
name.c_str(), name.length(),
c.name.c_str(), c.name.length()) == CSTR_LESS_THAN;
}
GeneralResultCtr::~GeneralResultCtr() {
delete ptr;
ptr = 0;
}
GeneralResultCtr::GeneralResultCtr(const GeneralResultCtr &ctr) {
@ -55,16 +59,15 @@ GeneralResultCtr::GeneralResultCtr(const GeneralResultCtr &ctr) {
name = ctr.name;
tag = ctr.tag;
fileSource = ctr.fileSource;
ctr.ptr = 0;
}
void GeneralResultCtr::operator=(const GeneralResultCtr &ctr) {
if (this == &ctr)
return;
delete ptr;
name = ctr.name;
ptr = ctr.ptr;
ctr.ptr = 0;
tag = ctr.tag;
fileSource = ctr.fileSource;
}
bool GeneralResultCtr::isDynamic() const {
@ -87,6 +90,13 @@ void GRINSTANCE() {
gr.sort(b, SortByFinishTime);
}
const string &GeneralResult::getTimeStamp() const {
return gdioutput::narrow(getMeosDate());
}
bool GeneralResult::isRogaining() const {
return false;
}
void GeneralResult::setContext(const oListParam *contextIn) {
context = contextIn;
@ -112,7 +122,7 @@ int GeneralResult::getListParamTimeFromControl() const {
struct GRSortInfo {
int principalSort;
int score;
pair<int, int> score;
oAbstractRunner *tr;
bool operator<(const GRSortInfo &other) const {
@ -130,12 +140,33 @@ struct GRSortInfo {
}
};
void GeneralResult::calculateTeamResults(vector<oTeam *> &teams, oListInfo::ResultType resType, bool sortTeams, int inputNumber) const {
void GeneralResult::calculateTeamResults(vector<oTeam *> &teams,
bool classResult,
oListInfo::ResultType resType,
bool sortTeams,
int inputNumber) const {
if (teams.empty())
return;
prepareCalculations(*teams[0]->oe, true, inputNumber);
//bool classSort = resType == oListInfo::Global ? false : true;
if (lockPrepare)
throw meosException("Bad cyclic call");
lockPrepare = true;
try {
set<int> clsId;
vector<pRunner> runners;
for (pTeam t : teams) {
clsId.insert(t->getClassId(true));
for (int j = 0; j < t->getNumRunners(); j++) {
pRunner r = t->getRunner(j);
if (r) {
runners.push_back(r);
clsId.insert(r->getClassId(true));
}
}
}
prepareCalculations(*teams[0]->oe, classResult, clsId, runners, teams, inputNumber);
vector<GRSortInfo> teamScore(teams.size());
for (size_t k = 0; k < teams.size(); k++) {
if (resType == oListInfo::Classwise) {
@ -145,7 +176,7 @@ void GeneralResult::calculateTeamResults(vector<oTeam *> &teams, oListInfo::Resu
else
teamScore[k].principalSort = 0;
prepareCalculations(*teams[k]);
prepareCalculations(*teams[k], classResult);
teams[k]->tmpResult.runningTime = teams[k]->getStartTime(); //XXX
teams[k]->tmpResult.runningTime = deduceTime(*teams[k]);
teams[k]->tmpResult.status = deduceStatus(*teams[k]);
@ -197,6 +228,12 @@ void GeneralResult::calculateTeamResults(vector<oTeam *> &teams, oListInfo::Resu
teams[k] = (oTeam *)teamScore[k].tr;
}
}
lockPrepare = false;
}
catch (...) {
lockPrepare = false;
throw;
}
}
void GeneralResult::sortTeamMembers(vector<oRunner *> &runners) const {
@ -271,13 +308,26 @@ template<class T> void GeneralResult::sort(vector<T *> &rt, SortOrder so) const
}
void GeneralResult::calculateIndividualResults(vector<oRunner *> &runners,
bool classResult,
oListInfo::ResultType resType,
bool sortRunners,
int inputNumber) const {
if (runners.empty())
return;
prepareCalculations(*runners[0]->oe, false, inputNumber);
if (lockPrepare)
throw meosException("Bad cyclic call");
lockPrepare = true;
try {
set<int> clsId;
for (pRunner r : runners) {
clsId.insert(r->getClassId(true));
}
vector<pTeam> noTeams;
prepareCalculations(*runners[0]->oe, classResult, clsId, runners, noTeams, inputNumber);
//bool classSort = resType == oListInfo::Global ? false : true;
vector<GRSortInfo> runnerScore(runners.size());
for (size_t k = 0; k < runners.size(); k++) {
@ -321,7 +371,8 @@ void GeneralResult::calculateIndividualResults(vector<oRunner *> &runners,
else
runners[k]->tmpResult.startTime = runners[k]->getStartTime();
}
prepareCalculations(*runners[k]);
prepareCalculations(*runners[k], classResult);
runners[k]->tmpResult.runningTime = deduceTime(*runners[k], runners[k]->tmpResult.startTime);
runners[k]->tmpResult.status = deduceStatus(*runners[k]);
runners[k]->tmpResult.points = deducePoints(*runners[k]);
@ -373,16 +424,22 @@ void GeneralResult::calculateIndividualResults(vector<oRunner *> &runners,
}
}
}
void GeneralResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const {
catch (...) {
lockPrepare = false;
throw;
}
lockPrepare = false;
}
void GeneralResult::prepareCalculations(oTeam &team) const {
void GeneralResult::prepareCalculations(oEvent &oe, bool classResult, const set<int> &cls, vector<pRunner> &runners, vector<pTeam> &teams, int inputNumber) const {
}
void GeneralResult::prepareCalculations(oTeam &team, bool classResult) const {
int nr = team.getNumRunners();
for (int j = 0; j < nr; j++) {
pRunner r = team.getRunner(j);
if (r) {
prepareCalculations(*r);
prepareCalculations(*r, classResult);
r->tmpResult.runningTime = deduceTime(*r, r->getStartTime()); //XXX
r->tmpResult.status = deduceStatus(*r);
r->tmpResult.place = 0;//XXX?
@ -398,7 +455,7 @@ void GeneralResult::prepareCalculations(oTeam &team) const {
}
}
void GeneralResult::prepareCalculations(oRunner &runner) const {
void GeneralResult::prepareCalculations(oRunner &runner, bool classResult) const {
int from = getListParamTimeFromControl();
runner.tmpResult.startTime = runner.getStartTime();
@ -414,8 +471,8 @@ void GeneralResult::prepareCalculations(oRunner &runner) const {
void GeneralResult::storeOutput(vector<int> &times, vector<int> &numbers) const {
}
int GeneralResult::score(oTeam &team, RunnerStatus st, int rt, int points) const {
return (100 * RunnerStatusOrderMap[st] + team.getNumShortening()) * 900000 + rt;
pair<int, int> GeneralResult::score(oTeam &team, RunnerStatus st, int rt, int points) const {
return make_pair((100 * RunnerStatusOrderMap[st] + team.getNumShortening()) * 100000 - points, + rt);
}
RunnerStatus GeneralResult::deduceStatus(oTeam &team) const {
@ -423,19 +480,20 @@ RunnerStatus GeneralResult::deduceStatus(oTeam &team) const {
}
int GeneralResult::deduceTime(oTeam &team) const {
return team.getRunningTime();
return team.getRunningTime(false);
}
int GeneralResult::deducePoints(oTeam &team) const {
return team.getRogainingPoints(false);
return team.getRogainingPoints(false, false);
}
int GeneralResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
pair<int,int> GeneralResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (asTeamMember) {
return runner.getLegNumber();
return make_pair(runner.getLegNumber(), 0);
}
else {
return make_pair((100 * RunnerStatusOrderMap[st] + runner.getNumShortening()) * 100000 - points, time);
}
else
return (RunnerStatusOrderMap[st] * 100 + runner.getNumShortening()) * 900000 + time;
}
RunnerStatus GeneralResult::deduceStatus(oRunner &runner) const {
@ -443,14 +501,14 @@ RunnerStatus GeneralResult::deduceStatus(oRunner &runner) const {
}
int GeneralResult::deduceTime(oRunner &runner, int startTime) const {
return runner.getRunningTime();
return runner.getRunningTime(false);
}
int GeneralResult::deducePoints(oRunner &runner) const {
return runner.getRogainingPoints(false);
return runner.getRogainingPoints(false, false);
}
int ResultAtControl::score(oTeam &team, RunnerStatus st, int time, int points) const {
pair<int, int> ResultAtControl::score(oTeam &team, RunnerStatus st, int time, int points) const {
return GeneralResult::score(team, st, time, points);
}
@ -466,14 +524,11 @@ int ResultAtControl::deducePoints(oTeam &team) const {
return GeneralResult::deducePoints(team);
}
int ResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
pair<int, int> ResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (asTeamMember)
return runner.getLegNumber();
const int TK = 3600 * 100;
if (st == StatusOK)
return time;
else
return TK + st;
return make_pair(runner.getLegNumber(), 0);
return make_pair(RunnerStatusOrderMap[st], time);
}
RunnerStatus TotalResultAtControl::deduceStatus(oRunner &runner) const {
@ -492,7 +547,7 @@ RunnerStatus TotalResultAtControl::deduceStatus(oRunner &runner) const {
while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx)))
legIx--;
if (legIx > 0)
inputStatus = t->getLegStatus(legIx - 1, true);
inputStatus = t->getLegStatus(legIx - 1, false, true);
}
else {
inputStatus = t->getInputStatus();
@ -522,7 +577,7 @@ int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const {
while (legIx > 0 && (cls->isParallel(legIx) || cls->isOptional(legIx)))
legIx--;
if (legIx > 0)
inputTime = t->getLegRunningTime(legIx - 1, true);
inputTime = t->getLegRunningTime(legIx - 1, false, true);
}
else {
inputTime = t->getInputTime();
@ -535,16 +590,16 @@ int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const {
return singleTime + inputTime;
}
int TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
pair<int,int> TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (asTeamMember)
return runner.getLegNumber();
const int TK = 3600 * 100;
return make_pair(runner.getLegNumber(), 0);
const int TK = 3600 * 24 * 7;
RunnerStatus inputStatus = StatusOK;
if (runner.getTeam()) {
const pTeam t = runner.getTeam();
if (runner.getLegNumber() > 0) {
inputStatus = t->getLegStatus(runner.getLegNumber() - 1, true);
inputStatus = t->getLegStatus(runner.getLegNumber() - 1, false, true);
}
else {
inputStatus = t->getInputStatus();
@ -557,11 +612,7 @@ int TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int
if (st != StatusUnknown)
st = max(inputStatus, st);
if (st == StatusOK) {
return time;
}
else
return TK + st;
return make_pair(RunnerStatusOrderMap[st], time);
}
RunnerStatus ResultAtControl::deduceStatus(oRunner &runner) const {
@ -573,7 +624,7 @@ RunnerStatus ResultAtControl::deduceStatus(oRunner &runner) const {
return stat;
}
RunnerStatus st = runner.getStatus();
if (st == StatusUnknown && runner.getRunningTime() > 0)
if (st == StatusUnknown && runner.getRunningTime(false) > 0)
return StatusOK;
return st;
}
@ -644,6 +695,7 @@ DynamicResult::DynamicResult(const DynamicResult &resIn) {
}
void DynamicResult::operator=(const DynamicResult &resIn) {
clear();
isCompiled = false;
name = resIn.name;
tag = resIn.tag;
@ -718,17 +770,21 @@ RunnerStatus DynamicResult::toStatus(int status) const {
return StatusDQ;
case StatusMAX:
return StatusMAX;
case StatusOutOfCompetition:
return StatusOutOfCompetition;
case StatusNoTiming:
return StatusNoTiming;
default:
throw meosException("Unknown status code X#" + itos(status));
}
}
int DynamicResult::score(oTeam &team, RunnerStatus st, int time, int points) const {
pair<int,int> DynamicResult::score(oTeam &team, RunnerStatus st, int time, int points) const {
if (getMethod(MTScore)) {
parser.addSymbol("ComputedTime", time);
parser.addSymbol("ComputedStatus", st);
parser.addSymbol("ComputedPoints", points);
return getMethod(MTScore)->evaluate(parser);
return make_pair(0, getMethod(MTScore)->evaluate(parser));
}
else if (getMethodSource(MTScore).empty())
return GeneralResult::score(team, st, time, points);
@ -759,12 +815,12 @@ int DynamicResult::deducePoints(oTeam &team) const {
else throw meosException("Syntax error");
}
int DynamicResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
pair<int,int> DynamicResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
if (getMethod(MRScore)) {
parser.addSymbol("ComputedTime", time);
parser.addSymbol("ComputedStatus", st);
parser.addSymbol("ComputedPoints", points);
return getMethod(MRScore)->evaluate(parser);
return make_pair(0, getMethod(MRScore)->evaluate(parser));
}
else if (getMethodSource(MRScore).empty())
return GeneralResult::score(runner, st, time, points, asTeamMember);
@ -831,7 +887,7 @@ void DynamicResult::save(xmlparser &xml) const {
void DynamicResult::clear() {
parser.clear();
for (size_t k = 0; k < methods.size(); k++) {
methods[k].pn = 0;
methods[k].pn = nullptr;
methods[k].source.clear();
methods[k].description.clear();
}
@ -937,6 +993,11 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("InputPlace", "Runner/team input place", false);
parser.declareSymbol("InputPoints", "Runner/team input points", false);
parser.declareSymbol("StageStatus", "Runner/team earlier stage statuses", true);
parser.declareSymbol("StageTime", "Runner/team earlier stage running times", true);
parser.declareSymbol("StagePlace", "Runner/team earlier stage places", true);
parser.declareSymbol("StagePoints", "Runner/team earlier stage points", true);
parser.declareSymbol("Fee", "Runner/team fee", false);
parser.declareSymbol("ClubId", "Club id number", false);
@ -963,6 +1024,9 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("LegPlace", "Place on course leg", true);
parser.declareSymbol("Leg", "Leg number in team, zero indexed", false);
parser.declareSymbol("BirthYear", "Year of birth", false);
parser.declareSymbol("Age", "Age (on last day of current year)", false);
parser.declareSymbol("AgeLowLimit", "Age below or equal implies youth", false);
parser.declareSymbol("AgeHighLimit", "Age above or equal implies senior/pensioner", false);
parser.declareSymbol("CheckTime", "Runner check time", false);
}
else {
@ -997,7 +1061,9 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("StatusCANCEL", "Status code for cancelled entry", false);
parser.declareSymbol("StatusMAX", "Status code for a time over the maximum", false);
parser.declareSymbol("StatusDQ", "Status code for disqualification", false);
parser.declareSymbol("StatusOutOfCompetition", "Status code for running out-of-competition", false);
parser.declareSymbol("StatusNotCompetiting", "Status code for not competing", false);
parser.declareSymbol("StatusNoTiming", "Status code for not no timing", false);
parser.declareSymbol("ShortestClassTime", "Shortest time in class", false);
@ -1016,22 +1082,59 @@ void DynamicResult::getSymbolInfo(int ix, wstring &name, wstring &desc) const {
parser.getSymbolInfo(ix, name, desc);
}
void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const {
void DynamicResult::prepareCalculations(oEvent &oe,
bool classResult,
const set<int> &clsSelection,
vector<pRunner> &runners,
vector<pTeam> &teams,
int inputNumber) const {
compile(false);
oe.calculateResults(set<int>(), oEvent::ResultType::ClassResult);
oe.calculateResults(set<int>(), oEvent::ResultType::TotalResult);
oDataConstInterface odc = oe.getDCI();
lowAgeLimit = odc.getInt("YouthAge");
highAgeLimit = odc.getInt("SeniorAge");
oEvent::ResultType single, total;
if (classResult) {
single = oEvent::ResultType::ClassResultDefault;
total = oEvent::ResultType::TotalResultDefault;
}
else {
single = oEvent::ResultType::ClassResult;
total = oEvent::ResultType::TotalResult;
}
oe.calculateResults(clsSelection, single);
oe.calculateResults(clsSelection, total);
vector<pTeam> *tPtr = &teams;
vector<pTeam> prepTeam;
if (teams.empty()) {
vector<pTeam> allTeam;
oe.getTeams(0, allTeam, false);
if (clsSelection.empty())
prepTeam.swap(allTeam);
else {
for (pTeam t : allTeam)
if (clsSelection.count(t->getClassId(false))) {
prepTeam.push_back(t);
}
}
tPtr = &prepTeam;
}
oe.calculateTeamResults(*tPtr, single);
oe.calculateTeamResults(*tPtr, total);
declareSymbols(MRScore, true);
if (prepareForTeam) {
if (teams.size() > 0) {
declareSymbols(MTScore, false);
vector<pTeam> t;
oe.getTeams(0, t, false);
for (size_t k = 0; k < t.size(); k++)
t[k]->resetResultCalcCache();
for (pTeam t : teams)
t->resetResultCalcCache();
oe.calculateTeamResults(false);
oe.calculateTeamResults(true);
oe.calculateTeamResults(teams, single);
oe.calculateTeamResults(teams, total);
}
parser.addSymbol("StatusUnknown", StatusUnknown);
parser.addSymbol("StatusOK", StatusOK);
parser.addSymbol("StatusMP", StatusMP);
@ -1040,13 +1143,16 @@ void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inp
parser.addSymbol("StatusDNS", StatusDNS);
parser.addSymbol("StatusMAX", StatusMAX);
parser.addSymbol("StatusDQ", StatusDQ);
parser.addSymbol("StatusOutOfCompetition", StatusOutOfCompetition);
parser.addSymbol("StatusNoTiming", StatusNoTiming);
parser.addSymbol("StatusNotCompetiting", StatusNotCompetiting);
parser.addSymbol("MaxTime", oe.getMaximalTime());
parser.addSymbol("InputNumber", inputNumber);
}
void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
void DynamicResult::prepareCommon(oAbstractRunner &runner, bool classResult) const {
bool useComputed = classResult == false;
parser.clearVariables();
int st = runner.getStatus();
int ft = runner.getFinishTime();
@ -1055,12 +1161,12 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
parser.addSymbol("Status", st);
parser.addSymbol("Start", runner.getStartTime());
parser.addSymbol("Finish", ft);
parser.addSymbol("Time", runner.getRunningTime());
parser.addSymbol("Time", runner.getRunningTime(useComputed));
parser.addSymbol("Place", runner.getPlace());
parser.addSymbol("Points", runner.getRogainingPoints(false));
parser.addSymbol("PointReduction", runner.getRogainingReduction());
parser.addSymbol("PointOvertime", runner.getRogainingOvertime());
parser.addSymbol("PointGross", runner.getRogainingPointsGross());
parser.addSymbol("Points", runner.getRogainingPoints(useComputed, false));
parser.addSymbol("PointReduction", runner.getRogainingReduction(useComputed));
parser.addSymbol("PointOvertime", runner.getRogainingOvertime(useComputed));
parser.addSymbol("PointGross", runner.getRogainingPointsGross(useComputed));
parser.addSymbol("PointAdjustment", runner.getPointAdjustment());
parser.addSymbol("TimeAdjustment", runner.getTimeAdjustment());
@ -1075,6 +1181,25 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
parser.addSymbol("InputPoints", runner.getInputPoints());
parser.addSymbol("Shorten", runner.getNumShortening());
vector<RunnerStatus> inst;
vector<int> times;
vector<int> points;
vector<int> places;
vector<int> iinst;
runner.getInputResults(inst, times, points, places);
for (RunnerStatus s : inst)
iinst.push_back(s);
parser.addSymbol("StageStatus", iinst);
parser.addSymbol("StageTime", times);
parser.addSymbol("StagePlace", places);
parser.addSymbol("StagePoints", points);
parser.addSymbol("InputStatus", runner.getInputStatus());
parser.addSymbol("InputTime", runner.getInputTime());
parser.addSymbol("InputPlace", runner.getInputPlace());
parser.addSymbol("InputPoints", runner.getInputPoints());
parser.addSymbol("Fee", runner.getDCI().getInt("Fee"));
const pClub pc = runner.getClubRef();
@ -1089,9 +1214,9 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner) const {
parser.addSymbol("Bib", _wtoi(runner.getBib().c_str()));
}
void DynamicResult::prepareCalculations(oTeam &team) const {
GeneralResult::prepareCalculations(team);
prepareCommon(team);
void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
GeneralResult::prepareCalculations(team, classResult);
prepareCommon(team, classResult);
int nr = team.getNumRunners();
vector<int> status(nr), time(nr), start(nr), finish(nr), points(nr);
vector< vector<int> > runnerOutputTimes(nr);
@ -1126,6 +1251,7 @@ void DynamicResult::prepareCalculations(oTeam &team) const {
parser.removeSymbol("SplitTimesAccumulated");
parser.removeSymbol("LegTimeDeviation");
parser.removeSymbol("BirthYear");
parser.removeSymbol("Age");
parser.addSymbol("RunnerOutputNumbers", runnerOutputNumbers);
parser.addSymbol("RunnerOutputTimes", runnerOutputTimes);
@ -1150,13 +1276,13 @@ void DynamicResult::prepareCalculations(oTeam &team) const {
pClass cls = team.getClassRef(true);
if (cls) {
int nl = max<int>(1, cls->getNumStages() - 1);
parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(nl, false));
parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(nl, false, false));
}
}
void DynamicResult::prepareCalculations(oRunner &runner) const {
GeneralResult::prepareCalculations(runner);
prepareCommon(runner);
void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const {
GeneralResult::prepareCalculations(runner, classResult);
prepareCommon(runner, classResult);
pCard pc = runner.getCard();
if (pc) {
vector<pPunch> punches;
@ -1263,7 +1389,7 @@ void DynamicResult::prepareCalculations(oRunner &runner) const {
pClass cls = runner.getClassRef(true);
if (cls) {
int nl = runner.getLegNumber();
parser.addSymbol("ShortestClassTime", cls->getBestLegTime(nl));
parser.addSymbol("ShortestClassTime", cls->getBestLegTime(nl, false));
}
vector<int> delta;
vector<int> place;
@ -1277,6 +1403,11 @@ void DynamicResult::prepareCalculations(oRunner &runner) const {
parser.addSymbol("LegPlace", place);
parser.addSymbol("Leg", runner.getLegNumber());
parser.addSymbol("BirthYear", runner.getBirthYear());
int ba = runner.getBirthAge();
parser.addSymbol("Age", ba);
parser.addSymbol("AgeLowLimit", lowAgeLimit);
parser.addSymbol("AgeHighLimit", highAgeLimit);
parser.addSymbol("CheckTime", runner.getCheckTime());
}
@ -1298,12 +1429,17 @@ long long DynamicResult::getHashCode() const {
string DynamicResult::undecorateTag(const string &inputTag) {
int ix = inputTag.rfind("-v");
if (ix > 0 && ix != inputTag.npos)
int limit = inputTag.length() - 4;
if (ix > 0 && ix != inputTag.npos && ix >= limit)
return inputTag.substr(0, ix);
else
return inputTag;
}
bool DynamicResult::isRogaining() const {
return !methods[DynamicMethods::MDeduceRPoints].source.empty();
}
wstring DynamicResult::getName(bool withAnnotation) const {
if (annotation.empty() || !withAnnotation)
return name;
@ -1346,7 +1482,11 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
controlId.first == oPunch::PunchStart) {
if (!totalResults) {
oe.calculateResults(set<int>(), oEvent::ResultType::ClassResult, true);
set<int> clsId;
for (pRunner r : runners) {
clsId.insert(r->getClassId(true));
}
oe.calculateResults(clsId, oEvent::ResultType::ClassResult, true);
for (pRunner r : runners) {
ri.status = r->getStatus();
if (ri.status == StatusUnknown) {
@ -1368,8 +1508,8 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
else
ri.place = 0;
ri.score = r->getRogainingPoints(false);
ri.time = r->getRunningTime();
ri.score = r->getRogainingPoints(true, false);
ri.time = r->getRunningTime(true);
ri.src = r;
results.push_back(ri);
}
@ -1397,7 +1537,7 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
else
ri.place = 0;
ri.score = r->getRogainingPoints(true);
ri.score = r->getRogainingPoints(true, true);
ri.time = r->getTotalRunningTime();
ri.src = r;
results.push_back(ri);
@ -1432,14 +1572,14 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
}
else {
wstring srcDMY;
GeneralResult *gResult = 0;
GeneralResult *gResult = nullptr;
shared_ptr<GeneralResult> specialInstance;
oListParam param;
param.useControlIdResultTo = controlId.second;
param.useControlIdResultFrom = controlId.first;
if (!resTag.empty())
gResult = &oe.getGeneralResult(resTag, srcDMY);
gResult = oe.getGeneralResult(resTag, srcDMY).get();
else {
if (controlId.second == oPunch::PunchFinish &&
controlId.first == oPunch::PunchStart && !totalResults)
@ -1452,7 +1592,7 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
gResult = specialInstance.get();
}
gResult->setContext(&param);
gResult->calculateIndividualResults(runners, resType, true, inputNumber);
gResult->calculateIndividualResults(runners, false, resType, true, inputNumber);
gResult->clearContext();
map<int, bool> mapHasCourse;
GeneralResultInfo ri;
@ -1510,7 +1650,7 @@ GeneralResult::calculateTeamResults(vector<pTeam> &teams,
if (resTag.empty()) {
out->useModule = false;
if (controlId.second == oPunch::PunchFinish) {
oe.calculateTeamResults(false);
oe.calculateTeamResults(teams, oEvent::ResultType::ClassResult);
GeneralResultInfo ri;
for (pTeam r : teams) {
ri.status = r->getStatus();
@ -1524,9 +1664,9 @@ GeneralResult::calculateTeamResults(vector<pTeam> &teams,
else
ri.place = 0;
ri.score = r->getRogainingPoints(false);
ri.score = r->getRogainingPoints(true, false);
ri.status = r->getStatus();
ri.time = r->getRunningTime();
ri.time = r->getRunningTime(true);
ri.src = r;
results.push_back(ri);
}
@ -1555,7 +1695,7 @@ GeneralResult::calculateTeamResults(vector<pTeam> &teams,
out->useModule = true;
wstring srcDMY;
auto &gResult = oe.getGeneralResult(resTag, srcDMY);
gResult.calculateTeamResults(teams, resType, true, inputNumber);
gResult->calculateTeamResults(teams, false, resType, true, inputNumber);
GeneralResultInfo ri;
for (pTeam r : teams) {
const auto &tmp = r->getTempResult(0);
@ -1623,9 +1763,9 @@ bool GeneralResult::GeneralResultInfo::getSubResult(const BaseResultContext &con
}
else {
if (context.controlId.second == oPunch::PunchFinish) {
out.score = r->getRogainingPoints(false);
out.score = r->getRogainingPoints(true, false);
out.status = r->getStatus();
out.time = r->getRunningTime();
out.time = r->getRunningTime(true);
}
else {
out.score = 0; // Undefined

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -37,24 +37,25 @@ class GeneralResult
{
private:
const oListParam *context;
mutable bool lockPrepare = false;
protected:
enum PrincipalSort {None, ClassWise, CourseWise};
virtual int score(oTeam &team, RunnerStatus st, int time, int points) const;
virtual pair<int, int> score(oTeam &team, RunnerStatus st, int time, int points) const;
virtual RunnerStatus deduceStatus(oTeam &team) const;
virtual int deduceTime(oTeam &team) const;
virtual int deducePoints(oTeam &team) const;
virtual int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
virtual pair<int, int> score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
virtual RunnerStatus deduceStatus(oRunner &runner) const;
virtual int deduceTime(oRunner &runner, int startTime) const;
virtual int deducePoints(oRunner &runner) const;
virtual void prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const;
virtual void prepareCalculations(oTeam &team) const;
virtual void prepareCalculations(oRunner &runner) const;
virtual void prepareCalculations(oEvent &oe, bool classResult, const set<int> &clsSelection, vector<pRunner> &runners, vector<pTeam> &teams, int inputNumber) const;
virtual void prepareCalculations(oTeam &team, bool classResult) const;
virtual void prepareCalculations(oRunner &runner, bool classResult) const;
virtual void storeOutput(vector<int> &times, vector<int> &numbers) const;
int getListParamTimeToControl() const;
@ -62,6 +63,10 @@ protected:
public:
virtual const string &getTimeStamp() const;
virtual bool isRogaining() const;
struct BaseResultContext {
private:
int leg;
@ -142,10 +147,22 @@ public:
void setContext(const oListParam *context);
void clearContext();
void calculateTeamResults(vector<oTeam *> &teams, oListInfo::ResultType resType, bool sortTeams, int inputNumber) const;
void calculateIndividualResults(vector<oRunner *> &runners, oListInfo::ResultType resType, bool sortRunners, int inputNumber) const;
void calculateTeamResults(vector<oTeam *> &teams,
bool classResult,
oListInfo::ResultType resType,
bool sortTeams,
int inputNumber) const;
void calculateIndividualResults(vector<oRunner *> &runners,
bool classResult,
oListInfo::ResultType resType,
bool sortRunners,
int inputNumber) const;
void sortTeamMembers(vector<oRunner *> &runners) const;
virtual bool isDynamic() const {
return false;
}
template<class T> void sort(vector<T*> &rt, SortOrder so) const;
GeneralResult(void);
@ -154,22 +171,22 @@ public:
class ResultAtControl : public GeneralResult {
protected:
int score(oTeam &team, RunnerStatus st, int time, int points) const;
RunnerStatus deduceStatus(oTeam &team) const;
int deduceTime(oTeam &team) const;
int deducePoints(oTeam &team) const;
pair<int, int> score(oTeam &team, RunnerStatus st, int time, int points) const override;
RunnerStatus deduceStatus(oTeam &team) const override;
int deduceTime(oTeam &team) const override;
int deducePoints(oTeam &team) const override;
int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
RunnerStatus deduceStatus(oRunner &runner) const;
int deduceTime(oRunner &runner, int startTime) const;
int deducePoints(oRunner &runner) const;
pair<int, int> score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const override;
RunnerStatus deduceStatus(oRunner &runner) const override;
int deduceTime(oRunner &runner, int startTime) const override;
int deducePoints(oRunner &runner) const override;
};
class TotalResultAtControl : public ResultAtControl {
protected:
int deduceTime(oRunner &runner, int startTime) const;
RunnerStatus deduceStatus(oRunner &runner) const;
int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
int deduceTime(oRunner &runner, int startTime) const override;
RunnerStatus deduceStatus(oRunner &runner) const override;
pair<int, int> score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const override;
};
class DynamicResult : public GeneralResult {
@ -189,11 +206,14 @@ public:
};
private:
bool allowRetag = true;
static map<string, DynamicMethods> symb2Method;
static map<DynamicMethods, pair<string, string> > method2SymbName;
static int instanceCount;
mutable int lowAgeLimit = -1;
mutable int highAgeLimit = 1000;
class MethodInfo {
string source;
mutable ParseNode *pn;
@ -221,16 +241,24 @@ private:
void addSymbol(DynamicMethods method, const char *symb, const char *name);
RunnerStatus toStatus(int status) const;
void prepareCommon(oAbstractRunner &runner) const;
void prepareCommon(oAbstractRunner &runner, bool classResult) const;
static string getInternalPath(const string &tag);
public:
bool isDynamic() const override {
return true;
}
bool retaggable() const { return allowRetag; }
void retaggable(bool r) { allowRetag = r; }
void setReadOnly() const {readOnly = true;}
bool isReadOnly() const {return readOnly;}
const string &getTimeStamp() const {return timeStamp;}
const string &getTimeStamp() const override {return timeStamp;}
bool isRogaining() const override;
static string undecorateTag(const string &inputTag);
@ -241,20 +269,26 @@ public:
void declareSymbols(DynamicMethods m, bool clear) const;
void prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const;
void prepareCalculations(oTeam &team) const;
void prepareCalculations(oRunner &runner) const;
void prepareCalculations(oEvent &oe,
bool classResult,
const set<int> &clsSelection,
vector<pRunner> &runners,
vector<pTeam> &teams,
int inputNumber) const override;
void prepareCalculations(oTeam &team, bool classResult) const override;
void prepareCalculations(oRunner &runner, bool classResult) const override;
void storeOutput(vector<int> &times, vector<int> &numbers) const;
int score(oTeam &team, RunnerStatus st, int time, int points) const;
RunnerStatus deduceStatus(oTeam &team) const;
int deduceTime(oTeam &team) const;
int deducePoints(oTeam &team) const;
pair<int, int> score(oTeam &team, RunnerStatus st, int time, int points) const override;
RunnerStatus deduceStatus(oTeam &team) const override;
int deduceTime(oTeam &team) const override;
int deducePoints(oTeam &team) const override;
int score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const;
RunnerStatus deduceStatus(oRunner &runner) const;
int deduceTime(oRunner &runner, int startTime) const;
int deducePoints(oRunner &runner) const;
pair<int, int> score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const override;
RunnerStatus deduceStatus(oRunner &runner) const override;
int deduceTime(oRunner &runner, int startTime) const override;
int deducePoints(oRunner &runner) const override;
DynamicResult();
DynamicResult(const DynamicResult &resIn);
@ -294,3 +328,25 @@ public:
void clear();
};
struct GeneralResultCtr {
wstring name;
string tag;
wstring fileSource;
bool isDynamic() const;
bool operator<(const GeneralResultCtr &c) const;
shared_ptr<GeneralResult> ptr;
// True if implicitly loaded (form list or by class results)
bool isImplicit() const {
return fileSource == L"*";
}
GeneralResultCtr(const char *tag, const wstring &name, const shared_ptr<GeneralResult> &ptr);
GeneralResultCtr(wstring &file, const shared_ptr<DynamicResult> &ptr);
GeneralResultCtr() {}
~GeneralResultCtr();
GeneralResultCtr(const GeneralResultCtr &ctr);
void operator=(const GeneralResultCtr &ctr);
};

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -429,13 +429,16 @@ This query is suitable for auto complete functionality.</p>
<li><i>card</i> Card number.</li>
</ul>
<b>Returns:</b>
Status.
<p></p><b>Returns:</b>
Status.</p>
<b>Note: </b> <p></p>If the card number is registered as a rental card, it will be set as such and
<i>hiredCard</i> will be set in the Fee attribute. The returned fee includes any rental card fee.</p>
<pre>
*Answer>
*Status>OK*/Status>
*Fee>130*/Fee>
*Fee hiredCard="true">130*/Fee>
*Info>Open Long, Rudolf Minowski (OK Tisaren)*/Info>
*/Answer>
</pre>
@ -454,7 +457,6 @@ Status.
<b>Returns:</b>
Installed template file with the specified tag.
<h2>Image</h2>
<b>Syntax:</b>
<pre>/meos?image=*image></pre>

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -488,10 +488,14 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
ch = true;
}
int s = bc.getStatus();
int rt = bc.getRunningTime() * 10;
if (rt > 0 && s == RunnerStatus::StatusUnknown)
RunnerStatus s = bc.getStatus();
int rt = bc.getRunningTime(true) * 10;
if (rt > 0) {
if (s == RunnerStatus::StatusUnknown)
s = RunnerStatus::StatusOK;
}
else if (isPossibleResultStatus(s))
s = StatusUnknown;
if (status != s) {
status = s;
@ -547,8 +551,8 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
s = r.getTotalStatusInput();
}
else if (t && !isQF && r.getLegNumber() > 0) {
legInput = t->getLegRunningTime(r.getLegNumber() - 1, false) * 10;
s = t->getLegStatus(r.getLegNumber() - 1, false);
legInput = t->getLegRunningTime(r.getLegNumber() - 1, true, false) * 10;
s = t->getLegStatus(r.getLegNumber() - 1, true, false);
}
if (totalStatus != s) {
@ -569,9 +573,29 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
bool useTotalResults = cmp.includeTotalResults();
bool inludeCourse = cmp.includeCourse();
bool ch = synchronize(useTotalResults, inludeCourse, r);
int cno = r.getCardNo();
if (cno != cardNo) {
cardNo = cno;
changeCard = true;
ch = true;
}
bool nr;
if ((r.getStatus() == StatusUnknown || r.getStatus() == StatusOutOfCompetition || r.getStatus() == StatusNoTiming) && r.getFinishTime() <= 0) {
vector<pFreePunch> pv;
r.getEvent()->getPunchesForRunner(r.getId(), false, pv);
nr = pv.size() > 0;
}
else {
nr = false;
}
if (isRunning != nr) {
isRunning = nr;
ch = true;
}
vector<RadioTime> newRT;
if (r.getClassId(false) > 0) {
const vector<int> &radios = cmp.getControls(r.getClassId(true), r.getLegNumber());
@ -601,7 +625,16 @@ bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
void InfoCompetitor::serialize(xmlbuffer &xml, bool diffOnly) const {
vector< pair<string, wstring> > sprop;
sprop.push_back(make_pair("id", itow(getId())));
sprop.reserve(3);
sprop.emplace_back("id", itow(getId()));
if (changeCard || !diffOnly) {
sprop.emplace_back("card", itow(cardNo));
changeCard = false;
}
if (isRunning)
sprop.emplace_back("competing", L"true");
xmlbuffer &subTag = xml.startTag("cmp", sprop);
InfoBaseCompetitor::serialize(subTag, diffOnly, course);
@ -627,7 +660,6 @@ void InfoCompetitor::serialize(xmlbuffer &xml, bool diffOnly) const {
xml.endTag();
}
bool InfoTeam::synchronize(oTeam &t) {
bool ch = synchronizeBase(t);

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -182,9 +182,12 @@ class InfoCompetitor : public InfoBaseCompetitor {
int inputTime;
int totalStatus;
int course;
int cardNo = 0;
bool isRunning = false;
bool synchronize(const InfoCompetition &cmp, oRunner &c);
bool changeTotalSt;
bool changeRadio;
mutable bool changeCard = false;
public:
bool synchronize(bool useTotalResults, bool useCourse, oRunner &c);
void serialize(xmlbuffer &xml, bool diffOnly) const;

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1236,7 +1236,8 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
wstring name;
xo.getObjectString("Name", name);
oe.setName(name);
if (!oe.hasFlag(oEvent::TransferFlags::FlagManualName))
oe.setName(name, false);
int id = xo.getObjectInt("Id");
if (id>0) {
@ -1264,11 +1265,13 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
int zt = t - 3600;
if (zt < 0)
zt += 3600*24;
oe.setZeroTime(formatTimeHMS(zt));
}
}
oe.setDate(dateStr);
if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
oe.setZeroTime(formatTimeHMS(zt), false);
}
}
if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
oe.setDate(dateStr, false);
//oe.setZeroTime(...);
}
@ -1425,16 +1428,16 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
if (!matchStageFilter(stageFilter, races))
return 0;
bool newTeam;
pTeam t = getCreateTeam(gdi, xTeam, newTeam);
if (!t)
return 0;
// Class
map<int, vector<LegInfo> > localTeamClassConfig;
pClass pc = readClass(xTeam.getObject("Class"), localTeamClassConfig);
bool newTeam;
pTeam t = getCreateTeam(gdi, xTeam, pc ? pc->getId() : 0, newTeam);
if (!t)
return 0;
if (pc && (t->getClassId(false) == 0 || !t->hasFlag(oAbstractRunner::FlagUpdateClass)) ) {
t->setClassId(pc->getId(), false);
}
@ -1443,11 +1446,11 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
wchar_t pat[32];
int no = oClass::extractBibPattern(bib, pat);
if (no > 0 && t->getBib().empty())
t->setBib(bib, no, true, false);
t->setBib(bib, no, true);
else if (newTeam) {
pair<int, wstring> autoBib = pc->getNextBib(bibPatterns);
if (autoBib.first > 0) {
t->setBib(autoBib.second, autoBib.first, true, false);
t->setBib(autoBib.second, autoBib.first, true);
}
}
@ -1486,8 +1489,8 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
for (size_t k = 0; k<xEntries.size(); k++) {
readPersonEntry(gdi, xEntries[k], t, teamClassConfig, noFilter, personId2TeamLeg);
}
t->synchronize();
t->applyBibs();
t->evaluate(oBase::ChangeType::Update);
return t;
}
@ -1495,7 +1498,7 @@ pTeam IOF30Interface::readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
map<int, pair<wstring, int> > &bibPatterns,
const map<int, vector<LegInfo> > &teamClassConfig) {
bool newTeam;
pTeam t = getCreateTeam(gdi, xTeam, newTeam);
pTeam t = getCreateTeam(gdi, xTeam, pc ? pc->getId() : 0, newTeam);
if (!t)
return 0;
@ -1509,11 +1512,11 @@ pTeam IOF30Interface::readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
wchar_t pat[32];
int no = oClass::extractBibPattern(bib, pat);
if (no > 0 && t->getBib().empty())
t->setBib(bib, no, true, false);
t->setBib(bib, no, true);
else if (newTeam){
pair<int, wstring> autoBib = pc->getNextBib(bibPatterns);
if (autoBib.first > 0) {
t->setBib(autoBib.second, autoBib.first, true, false);
t->setBib(autoBib.second, autoBib.first, true);
}
}
xmlList xEntries;
@ -1522,12 +1525,12 @@ pTeam IOF30Interface::readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
for (size_t k = 0; k<xEntries.size(); k++) {
readPersonStart(gdi, pc, xEntries[k], t, teamClassConfig);
}
t->synchronize();
t->applyBibs();
t->evaluate(oBase::ChangeType::Update);
return t;
}
pTeam IOF30Interface::getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool &newTeam) {
pTeam IOF30Interface::getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, int expectedClassId, bool &newTeam) {
newTeam = false;
wstring name;
xTeam.getObjectString("Name", name);
@ -1542,7 +1545,8 @@ pTeam IOF30Interface::getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool
t = oe.getTeam(id);
else {
t = oe.getTeamByName(name);
// XXX Check class
if (t && expectedClassId > 0 && t->getClassId(false) != expectedClassId)
t = nullptr;
}
if (!t) {
if (id > 0) {
@ -1825,7 +1829,7 @@ pRunner IOF30Interface::readPersonStart(gdioutput &gdi, pClass pc, xmlobject &xo
starts[k].getObjectString("BibNumber", bib);
rRace->getDI().setString("Bib", bib);
rRace->setStartTime(parseISO8601Time(startTime), true, false);
rRace->setStartTime(parseISO8601Time(startTime), true, oBase::ChangeType::Update);
}
}
@ -2301,14 +2305,15 @@ pClass IOF30Interface::readClass(const xmlobject &xclass,
pc = oe.addClass(name);
oDataInterface DI = pc->getDI();
if (!pc->hasFlag(oClass::TransferFlags::FlagManualName)) {
if (!longName.empty()) {
pc->setName(name);
pc->setName(name, false);
DI.setString("LongName", longName);
}
else {
if (pc->getName() != name && DI.getString("LongName") != name)
pc->setName(name);
pc->setName(name, false);
}
}
xmlList legs;
xclass.getObjects("Leg", legs);
@ -2666,46 +2671,8 @@ void IOF30Interface::writeResultList(xmlparser &xml, const set<int> &classes,
oe.getClasses(c, false);
for (size_t k = 0; k < c.size(); k++) {
// bool indRel = c[k]->getClassType() == oClassIndividRelay;
if (classes.empty() || classes.count(c[k]->getId())) {
/* oe.getRunners(c[k]->getId(), r, false);
vector<pRunner> rToUse;
rToUse.reserve(r.size());
for (size_t j = 0; j < r.size(); j++) {
if (leg == -1 || leg == r[j]->getLegNumber()) {
if (leg == -1 && indRel && r[j]->getLegNumber() != 0)
continue; // Skip all but leg 0 for individual relay
if (leg == -1 && !indRel && r[j]->getTeam())
continue; // For teams, skip presonal results, unless individual relay
if (r[j]->getStatus() == StatusUnknown)
continue;
rToUse.push_back(r[j]);
}
}
vector<pTeam> tToUse;
if (leg == -1) {
oe.getTeams(c[k]->getId(), t, false);
tToUse.reserve(t.size());
for (size_t j = 0; j < t.size(); j++) {
for (int n = 0; n < t[j]->getNumRunners(); n++) {
pRunner tr = t[j]->getRunner(n);
if (tr && tr->getStatus() != StatusUnknown) {
tToUse.push_back(t[j]);
break;
}
}
}
}
*/
vector<pRunner> rToUse;
vector<pTeam> tToUse;
getRunnersToUse(c[k], rToUse, tToUse, leg, false);
@ -2716,7 +2683,6 @@ void IOF30Interface::writeResultList(xmlparser &xml, const set<int> &classes,
}
}
xml.endTag();
}
@ -2801,8 +2767,11 @@ void IOF30Interface::writeCourseInfo(xmlparser &xml, const oCourse &c) {
}
wstring formatStatus(RunnerStatus st) {
wstring formatStatus(RunnerStatus st, bool hasTime) {
switch (st) {
case StatusNoTiming:
if (!hasTime)
break;
case StatusOK:
return L"OK";
case StatusDNS:
@ -2817,11 +2786,13 @@ wstring formatStatus(RunnerStatus st) {
return L"Disqualified";
case StatusMAX:
return L"OverTime";
case StatusOutOfCompetition:
if (!hasTime)
break;
case StatusNotCompetiting:
return L"NotCompeting";
default:
return L"Inactive";
}
return L"Inactive";
}
void IOF30Interface::writePersonResult(xmlparser &xml, const oRunner &r,
@ -2890,6 +2861,8 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (teamMember)
writeLegOrder(xml, rPerson.getClassRef(false), rPerson.getLegNumber());
bool patrolResult = r.getTeam() && r.getClassRef(false)->getClassType() == oClassPatrol && !teamsAsIndividual;
wstring bib = rPerson.getBib();
if (!bib.empty())
xml.write("BibNumber", bib);
@ -2897,21 +2870,47 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (r.getStartTime() > 0)
xml.write("StartTime", oe.getAbsDateTimeISO(r.getStartTime(), true, useGMT));
int finishTime, runningTime, place, after;
RunnerStatus status;
if (!patrolResult) {
place = r.getPlace();
finishTime = r.getFinishTimeAdjusted();
runningTime = r.getRunningTime(true);
after = r.getTimeAfter();
status = r.getStatusComputed();
}
else {
int pl = r.getParResultLeg();
place = r.getTeam()->getLegPlace(pl, false);
runningTime = r.getTeam()->getLegRunningTime(pl, true, false);
if (runningTime > 0)
finishTime = r.getStartTime() + runningTime;
else
finishTime = 0;
after = r.getTeam()->getTimeAfter(pl);
status = r.getTeam()->getLegStatus(pl, true, false);
}
if ((r.getClassRef(false) && r.getClassRef(true)->getNoTiming()) ||
r.getStatusComputed() == StatusNoTiming) {
after = -1;
runningTime = 0;
}
if (r.getFinishTime() > 0)
xml.write("FinishTime", oe.getAbsDateTimeISO(r.getFinishTimeAdjusted(), true, useGMT));
xml.write("FinishTime", oe.getAbsDateTimeISO(finishTime, true, useGMT));
if (r.getRunningTime() > 0)
xml.write("Time", r.getRunningTime());
if (runningTime > 0)
xml.write("Time", runningTime);
int after = r.getTimeAfter();
if (after >= 0) {
if (teamMember) {
xml.write("TimeBehind", "type", L"Leg", itow(after));
after = r.getTimeAfterCourse();
if (after >= 0)
xml.write("TimeBehind", "type", L"Course", itow(after));
int afterCourse = r.getTimeAfterCourse();
if (afterCourse >= 0)
xml.write("TimeBehind", "type", L"Course", itow(afterCourse));
}
else
xml.write("TimeBehind", after);
@ -2919,27 +2918,26 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (r.getClassRef(false)) {
if (r.statusOK() && r.getClassRef(false)->getNoTiming() == false) {
if (!teamMember && r.getPlace() > 0 && r.getPlace() < 50000) {
xml.write("Position", r.getPlace());
if (r.statusOK(true) && r.getClassRef(false)->getNoTiming() == false) {
if (!teamMember && place > 0 && place < 50000) {
xml.write("Position", place);
}
else if (teamMember) {
int pos = r.getPlace();
if (pos > 0 && pos < 50000)
xml.write("Position", "type", L"Leg", itow(pos));
if (place > 0 && place < 50000)
xml.write("Position", "type", L"Leg", itow(place));
pos = r.getCoursePlace();
if (pos > 0)
xml.write("Position", "type", L"Course", itow(pos));
int placeCourse = r.getCoursePlace(true);
if (placeCourse > 0)
xml.write("Position", "type", L"Course", itow(placeCourse));
}
}
xml.write("Status", formatStatus(r.getStatus()));
xml.write("Status", formatStatus(status, r.getFinishTime()>0));
int rg = r.getRogainingPoints(false);
int rg = r.getRogainingPoints(true, false);
if (rg > 0) {
xml.write("Score", "type", L"Score", itow(rg));
xml.write("Score", "type", L"Penalty", itow(r.getRogainingReduction()));
xml.write("Score", "type", L"Penalty", itow(r.getRogainingReduction(true)));
}
if ( (r.getTeam() && r.getClassRef(false)->getClassType() != oClassPatrol && !teamsAsIndividual) || hasInputTime) {
xml.startTag("OverallResult");
@ -2953,7 +2951,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
int tleg = r.getLegNumber() >= 0 ? r.getLegNumber() : 0;
if (stat == StatusOK && hasTiming) {
int after = r.getTotalRunningTime() - r.getClassRef(true)->getTotalLegLeaderTime(tleg, true);
int after = r.getTotalRunningTime() - r.getClassRef(true)->getTotalLegLeaderTime(tleg, true, true);
if (after >= 0)
xml.write("TimeBehind", after);
}
@ -2961,7 +2959,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
if (stat == StatusOK && hasTiming)
xml.write("Position", r.getTotalPlace());
xml.write("Status", formatStatus(stat));
xml.write("Status", formatStatus(stat, r.getFinishTime() > 0));
xml.endTag();
}
@ -2972,9 +2970,10 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
writeCourse(xml, *crs);
const vector<SplitData> &sp = r.getSplitTimes(doUnroll);
if (r.getStatus()>0 && r.getStatus() != StatusDNS &&
r.getStatus() != StatusCANCEL &&
r.getStatus() != StatusNotCompetiting) {
RunnerStatus st = r.getStatusComputed();
if (r.getStatus()>0 && st != StatusDNS &&
st != StatusCANCEL &&
st != StatusNotCompetiting) {
int nc = crs->getNumControls();
bool hasRogaining = crs->hasRogaining();
int firstControl = crs->useFirstAsStart() ? 1 : 0;
@ -3264,7 +3263,7 @@ void IOF30Interface::getRunnersToUse(const pClass cls, vector<pRunner> &rToUse,
if (leg == -1 && !indRel && r[j]->getTeam())
continue; // For teams, skip presonal results, unless individual relay
if (!includeUnknown && r[j]->getStatus() == StatusUnknown)
if (!includeUnknown && !r[j]->hasResult())
continue;
}
rToUse.push_back(r[j]);
@ -3281,7 +3280,7 @@ void IOF30Interface::getRunnersToUse(const pClass cls, vector<pRunner> &rToUse,
else {
for (int n = 0; n < t[j]->getNumRunners(); n++) {
pRunner tr = t[j]->getRunner(n);
if (tr && tr->getStatus() != StatusUnknown) {
if (tr && tr->hasResult()) {
tToUse.push_back(t[j]);
break;
}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -163,7 +163,7 @@ class IOF30Interface {
map<int, pair<wstring, int> > &bibPatterns,
const map<int, vector<LegInfo> > &teamClassConfig);
pTeam getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool &newTeam);
pTeam getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, int expectedClassId, bool &newTeam);
static int getIndexFromLegPos(int leg, int legorder, const vector<LegInfo> &setup);

View File

@ -7,7 +7,7 @@ Third Party Code. Additional copyright notices and license terms applicable to p
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
------------------------------------
Copyright 2007-2019 Melin Software HB.
Copyright 2007-2020 Melin Software HB.
------------------------------------

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -34,6 +34,7 @@
#include "oEvent.h"
#include "tabbase.h"
#include "CommDlg.h"
#include "generalresult.h"
ListEditor::ListEditor(oEvent *oe_) {
oe = oe_;
@ -42,7 +43,7 @@ ListEditor::ListEditor(oEvent *oe_) {
dirtyExt = false;
dirtyInt = false;
lastSaved = NotSaved;
oe->loadGeneralResults(false);
oe->loadGeneralResults(false, true);
}
ListEditor::~ListEditor() {
@ -78,6 +79,13 @@ void ListEditor::load(const MetaListContainer &mlc, int index) {
savedFileName.clear();
}
void ListEditor::show(TabBase *dst, gdioutput &gdi) {
gdi.clearPage(false);
origin = dst;
show(gdi);
}
void ListEditor::show(gdioutput &gdi) {
gdi.setRestorePoint("BeginListEdit");
@ -452,7 +460,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
else
mlp.setLeg(-1);
if (gdi.hasField("UseResultModule") && gdi.isChecked("UseResultModule"))
if (gdi.hasWidget("UseResultModule") && gdi.isChecked("UseResultModule"))
mlp.setResultModule(currentList->getResultModule());
else
mlp.setResultModule("");
@ -604,7 +612,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
lastSaved = SavedFile;
savedFileName = fileName;
oe->loadGeneralResults(true);
oe->loadGeneralResults(true, true);
makeDirty(gdi, ClearDirty, ClearDirty);
show(gdi);
}
@ -700,7 +708,12 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
makeDirty(gdi, ClearDirty, ClearDirty);
currentIndex = -1;
savedFileName.clear();
gdi.getTabs().get(TListTab)->loadPage(gdi);
if (origin) {
auto oc = origin;
origin = nullptr;
oc->loadPage(gdi);
}
return 0;
}
/*else if (bi.id == "BrowseFont") {
@ -732,9 +745,12 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
if (type == lResultModuleNumber || type == lResultModuleTime ||
type == lResultModuleNumberTeam || type == lResultModuleTimeTeam) {
gdi.check("UseLeg", true);
gdi.disableInput("UseLeg");
if (gdi.hasWidget("UseResultModule")) {
gdi.check("UseResultModule", true);
gdi.disableInput("UseResultModule");
gdi.disableInput("UseLeg");
}
gdi.enableInput("Leg");
if (gdi.getText("Leg").empty())
gdi.setText("Leg", L"0");
@ -887,9 +903,11 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
if (storedType == lResultModuleNumber || storedType == lResultModuleTime || storedType == lResultModuleTimeTeam || storedType == lResultModuleNumberTeam) {
gdi.check("UseLeg", true);
gdi.disableInput("UseLeg");
if (gdi.hasWidget("UseResultModule")) {
gdi.check("UseResultModule", true);
gdi.disableInput("UseResultModule");
gdi.disableInput("UseLeg");
}
}
gdi.dropLine(2);
@ -1174,11 +1192,11 @@ void ListEditor::makeDirty(gdioutput &gdi, DirtyFlag inside, DirtyFlag outside)
else if (outside == ClearDirty)
dirtyExt = false;
if (gdi.hasField("SaveInside")) {
if (gdi.hasWidget("SaveInside")) {
gdi.setInputStatus("SaveInside", dirtyInt || lastSaved != SavedInside);
}
if (gdi.hasField("SaveFile")) {
if (gdi.hasWidget("SaveFile")) {
gdi.setInputStatus("SaveFile", dirtyExt || lastSaved != SavedFile);
}
}

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,6 +30,8 @@ class BaseInfo;
class ButtonInfo;
class oEvent;
enum EPostType;
class TabBase;
#include <vector>
class ListEditor {
@ -65,6 +67,10 @@ private:
void enableOpen(gdioutput &gdi);
void makeDirty(gdioutput &gdi, DirtyFlag inside, DirtyFlag outside);
TabBase *origin = nullptr;
void show(gdioutput &gdi);
public:
ListEditor(oEvent *oe);
virtual ~ListEditor();
@ -72,7 +78,9 @@ public:
//void load(MetaList *list);
void load(const MetaListContainer &mlc, int index);
void show(gdioutput &gdi);
void show(TabBase *dst, gdioutput &gdi);
bool isShown(TabBase *tab) const { return origin == tab; }
MetaList *getCurrentList() const {return currentList;};

View File

@ -1,6 +1,6 @@
/********************i****************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -284,7 +284,7 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
pRunner r = oe->getRunner(rToWatch[i], 0);
if (r) {
r->synchronize();
r->setStartTime(st, true, false, true);
r->setStartTime(st, true, oBase::ChangeType::Update, true);
r->synchronize(false);
}
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -67,6 +67,7 @@
#include "autocomplete.h"
#include "image.h"
#include "csvparser.h"
#include "generalresult.h"
int defaultCodePage = 1252;
@ -221,18 +222,27 @@ int APIENTRY WinMain(HINSTANCE hInstance,
RunnerStatusOrderMap[k] = 0;
}
RunnerStatusOrderMap[StatusOK] = 0;
RunnerStatusOrderMap[StatusMAX] = 1;
RunnerStatusOrderMap[StatusMP] = 2;
RunnerStatusOrderMap[StatusDNF] = 3;
RunnerStatusOrderMap[StatusDQ] = 4;
RunnerStatusOrderMap[StatusCANCEL] = 5;
RunnerStatusOrderMap[StatusDNS] = 6;
RunnerStatusOrderMap[StatusUnknown] = 7;
RunnerStatusOrderMap[StatusNotCompetiting] = 8;
RunnerStatusOrderMap[StatusNoTiming] = 1;
RunnerStatusOrderMap[StatusOutOfCompetition] = 2;
RunnerStatusOrderMap[StatusMAX] = 3;
RunnerStatusOrderMap[StatusMP] = 4;
RunnerStatusOrderMap[StatusDNF] = 5;
RunnerStatusOrderMap[StatusDQ] = 6;
RunnerStatusOrderMap[StatusCANCEL] = 7;
RunnerStatusOrderMap[StatusDNS] = 8;
RunnerStatusOrderMap[StatusUnknown] = 9;
RunnerStatusOrderMap[StatusNotCompetiting] = 10;
lang.init();
StringCache::getInstance().init();
for (RunnerStatus st : getAllRunnerStatus()) {
if (st != StatusOK)
assert(RunnerStatusOrderMap[st] > 0);
oAbstractRunner::encodeStatus(st);
}
GetCurrentDirectory(MAX_PATH, programPath);
bool utfRecode = false;
if (utfRecode) {
@ -469,14 +479,14 @@ int APIENTRY WinMain(HINSTANCE hInstance,
}
}
}
gdi_main = nullptr;
gdi_extra.clear();
if (gEvent)
gEvent->saveProperties(settings);
delete gEvent;
gEvent = 0;
gEvent = nullptr;
initMySQLCriticalSection(false);

View File

@ -169,7 +169,7 @@ BEGIN
VALUE "FileDescription", "meos"
VALUE "FileVersion", "3.3.0.1"
VALUE "InternalName", "meos"
VALUE "LegalCopyright", "Copyright © 2007-2019"
VALUE "LegalCopyright", "Copyright © 2007-2020"
VALUE "OriginalFilename", "meos.exe"
VALUE "ProductName", " meos"
VALUE "ProductVersion", "3.4.0.1"

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -2212,3 +2212,8 @@ void checkWriteAccess(const wstring &file) {
}
CloseHandle(h);
}
int compareStringIgnoreCase(const wstring &a, const wstring &b) {
return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a.c_str(), a.length(),
b.c_str(), b.length()) - CSTR_EQUAL;
}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -119,6 +119,9 @@ const vector<string> &split(const string &line, const string &separators, vector
const vector<wstring> &split(const wstring &line, const wstring &separators, vector<wstring> &split_vector);
const wstring &unsplit(const vector<wstring> &split_vector, const wstring &separators, wstring &line);
// Compare two strings, ignore case. 0 = equal, != zero compares as the integers.
int compareStringIgnoreCase(const wstring &a, const wstring &b);
const wstring &makeDash(const wstring &t);
const wstring &makeDash(const wchar_t *t);

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -40,6 +40,7 @@ class oFreePunch;
class oDataInterface;
class oTeam;
class oDataContainer;
struct SqlUpdated;
namespace mysqlpp {
class Query;
@ -118,17 +119,22 @@ protected:
bool checkOldVersion(oEvent *oe, mysqlpp::Row &row);
map<pair<int, int>, DWORD> readTimes;
void clearReadTimes();
void synchronized(const oBase &entity);
bool skipSynchronize(const oBase &entity) const;
mysqlpp::ResNSel updateCounter(const char *oTable, int id, mysqlpp::Query *updateqry);
string selectUpdated(const char *oTable, const string &updated, int counter);
string selectUpdated(const char *oTable, const SqlUpdated &updated);
void addedFromDatabase(oBase *object);
void updateCounters(OpFailStatus st,
int counter,
const string &modified,
SqlUpdated &update, int &maxCounter);
public:
void clearReadTimes();
bool dropDatabase(oEvent *oe);
bool checkConnection(oEvent *oe);
void processMissingObjects();

View File

@ -1,19 +0,0 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -69,6 +69,10 @@ int getListMask(oEvent &oe) {
return msql.getModifiedMask(oe);
}
void resetSynchTimes() {
msql.clearReadTimes();
}
bool MEOSDB_API msSynchronizeList(oEvent *oe, oListId lid)
{
nSynchList++;

View File

@ -1,29 +0,0 @@
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the MEOSDB_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// MEOSDB_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef MEOSDB_EXPORTS
#define MEOSDB_API __declspec(dllexport) __cdecl
#else
#define MEOSDB_API __declspec(dllimport) __cdecl
#endif
#include <vector>
#include <string>
/*
extern "C"{
// This class is exported from the meosdb.dll
class Cmeosdb {
public:
Cmeosdb(void);
// TODO: add your methods here.
};
//extern MEOSDB_API int nmeosdb;
MEOSDB_API int fnmeosdb(void);
}*/

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,6 +22,7 @@
************************************************************************/
enum OpFailStatus {
opStatusOKSkipped = 3,
opStatusOK = 2,
opStatusFail = 0,
opStatusWarning = 1,
@ -33,10 +34,8 @@ enum OpFailStatus {
class oEvent;
class oBase;
#define MEOSDB_API
int MEOSDB_API getMeosVersion();
// bool MEOSDB_API msSynchronizeList(oEvent *, oListId lid);
int MEOSDB_API msSynchronizeUpdate(oBase *);
int MEOSDB_API msSynchronizeRead(oBase *obj);
int MEOSDB_API msRemove(oBase *obj);
@ -50,6 +49,7 @@ class oBase;
bool MEOSDB_API msReConnect();
int MEOSDB_API msListCompetitions(oEvent *oe);
void resetSynchTimes();
int getListMask(oEvent &oe);

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -428,6 +428,7 @@
<ClInclude Include="oListInfo.h" />
<ClInclude Include="onlineinput.h" />
<ClInclude Include="onlineresults.h" />
<ClInclude Include="oRunner.h" />
<ClInclude Include="parser.h" />
<ClInclude Include="pdfwriter.h" />
<ClInclude Include="prefseditor.h" />
@ -459,7 +460,6 @@
<ClInclude Include="oFreeImport.h" />
<ClInclude Include="oFreePunch.h" />
<ClInclude Include="oPunch.h" />
<ClInclude Include="oRunner.h" />
<ClInclude Include="ospeaker.h" />
<ClInclude Include="oTeam.h" />
<ClInclude Include="progress.h" />

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,7 +30,7 @@
//V35: abcdef
//V36: abcdef
int getMeosBuild() {
string revision("$Rev: 935 $");
string revision("$Rev: 972 $");
return 174 + atoi(revision.substr(5, string::npos).c_str());
}
@ -42,16 +42,16 @@ int getMeosBuild() {
//V33: abcdefghij
//V34: abcdfge
wstring getMeosDate() {
wstring date(L"$Date: 2019-10-05 21:53:12 +0200 (lö, 05 okt 2019) $");
wstring date(L"$Date: 2020-01-18 15:14:04 +0100 (lö, 18 jan 2020) $");
return date.substr(7,10);
}
wstring getBuildType() {
return L"Update 3"; // No parantheses (...)
return L"Beta 1"; // No parantheses (...)
}
wstring getMajorVersion() {
return L"3.6";
return L"3.7";
}
wstring getMeosFullVersion() {
@ -103,7 +103,6 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
supp.emplace_back(L"Hans Carlstedt, Sävedalens AIK");
supp.emplace_back(L"IFK Mora OK");
supp.emplace_back(L"Attunda OK");
supp.emplace_back(L"OK Tyr, Karlstad");
supp.emplace_back(L"Siguldas Takas, Latvia");
supp.emplace_back(L"Eric Teutsch, Ottawa Orienteering Club, Canada");
supp.emplace_back(L"Silkeborg OK, Denmark");
@ -142,6 +141,13 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
supp.emplace_back(L"TJ Slávia Farmaceut Bratislava");
supp.emplace_back(L"OK Tyr, Karlstad");
supp.emplace_back(L"Magnus Thornell, Surahammars SOK");
supp.emplace_back(L"Mariager Fjord OK");
supp.emplace_back(L"Nässjö OK");
supp.emplace_back(L"Ringsjö OK");
supp.emplace_back(L"Big Foot Orienteers");
supp.emplace_back(L"Bay Area Orienteering Club");
supp.emplace_back(L"Finspångs SOK");
supp.emplace_back(L"OK Gorm, Denmark");
supp.emplace_back(L"Nyköpings OK");
reverse(supp.begin(), supp.end());
}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -95,7 +95,7 @@ void oListParam::serialize(xmlparser &xml,
xml.writeBool("Large", useLargeSize);
xml.writeBool("PageBreak", pageBreak);
xml.writeBool("HideHeader", !showHeader);
xml.write("AgeFilter", int(ageFilter));
xml.writeBool("ShowNamedSplits", showInterTimes);
xml.writeBool("ShowInterTitle", showInterTitle);
xml.writeBool("ShowSplits", showSplitTimes);
@ -162,7 +162,7 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
showInterTitle = xml.getObjectBool("ShowInterTitle");
inputNumber = xml.getObjectInt("InputNumber");
nextList = xml.getObjectInt("NextList");
ageFilter = AgeFilter(xml.getObjectInt("AgeFilter"));
xmlobject bg = xml.getObject("BGColor");
if (bg)
bgColor = bg.getInt();
@ -366,7 +366,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
li.lp = par;
gdiFonts normal, header, small, italic;
double s_factor;
oe->calculateResults({}, oEvent::ResultType::ClassResult, false);
map<pair<gdiFonts, int>, int> fontHeight;
for (size_t k = 0; k < fontFaces.size(); k++) {
@ -405,6 +405,8 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
li.rogainingResults = false;
li.calculateLiveResults = false;
li.calcCourseClassResults = false;
li.calcCourseResults = false;
if (par.useControlIdResultFrom > 0 || par.useControlIdResultTo > 0)
li.needPunches = oListInfo::PunchMode::SpecificPunch;
const bool isPunchList = mList.listSubType == oListInfo::EBaseTypeCoursePunches ||
@ -449,7 +451,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
if (mp.type == lTeamPlace || mp.type == lRunnerPlace || mp.type == lRunnerGeneralPlace) {
if (!li.calcResults) {
oe->calculateResults(set<int>(), oEvent::ResultType::ClassResult);
oe->calculateTeamResults(false);
oe->calculateTeamResults(set<int>(), oEvent::ResultType::ClassResult);
}
li.calcResults = true;
}
@ -458,7 +460,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|| mp.type == lRunnerGeneralPlace) {
if (!li.calcTotalResults) {
oe->calculateResults(set<int>(), oEvent::ResultType::TotalResult);
oe->calculateTeamResults(true);
oe->calculateTeamResults(set<int>(), oEvent::ResultType::TotalResult);
}
li.calcTotalResults = true;
}
@ -472,6 +474,12 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
li.calcCourseClassResults = true;
}
else if (mp.type == lRunnerCoursePlace) {
if (!li.calcCourseResults)
oe->calculateResults(set<int>(), oEvent::ResultType::ClassCourseResult);
li.calcCourseResults = true;
}
else if (mp.type == lRunnerTempTimeAfter || mp.type == lRunnerTempTimeStatus) {
if (li.needPunches == oListInfo::PunchMode::NoPunch)
li.needPunches = oListInfo::PunchMode::SpecificPunch;
@ -791,8 +799,18 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
li.supportFrom = supportFromControl;
li.supportTo = supportToControl;
li.resType = getResultType();
if (!resultModule.empty() || li.calcResults || li.calcCourseClassResults || li.calcTotalResults)
if (!resultModule.empty() || li.calcResults || li.calcCourseClassResults
|| li.calcTotalResults || li.calcCourseResults)
hasResults_ = true;
if (li.sortOrder == SortOrder::CourseResult) {
li.replaceType(EPostType::lRunnerPlace, EPostType::lRunnerCoursePlace, true);
}
if (li.sortOrder == SortOrder::ClassCourseResult) {
li.replaceType(EPostType::lRunnerPlace, EPostType::lRunnerClassCoursePlace, true);
}
}
void Position::indent(int ind) {
@ -1080,7 +1098,7 @@ void MetaList::save(xmlparser &xml, const oEvent *oe) const {
xml.write("ResultModule", ttw);
try {
wstring srcFile;
GeneralResult &gr = oe->getGeneralResult(resultModule, srcFile);
GeneralResult &gr = *oe->getGeneralResult(resultModule, srcFile);
DynamicResult &dr = dynamic_cast<DynamicResult &>(gr);
if (!dr.isBuiltIn()) {
string ot = dr.getTag();
@ -1158,7 +1176,7 @@ void MetaList::load(const xmlobject &xDef) {
// string db = "Loaded res mod: " + dr.getTag() + ", h=" + itos(dr.getHashCode())+ "\n";
// OutputDebugString(db.c_str());
wstring file = L"*";
dynamicResults[k] = GeneralResultCtr(file, new DynamicResult(dr));
dynamicResults[k] = GeneralResultCtr(file, make_shared<DynamicResult>(dr));
}
supportFromControl = xDef.getObjectBool("SupportFrom");
supportToControl = xDef.getObjectBool("SupportTo");
@ -1302,7 +1320,7 @@ void MetaList::load(const xmlobject &xDef) {
void MetaList::getDynamicResults(vector<DynamicResultRef> &resultModules) const {
resultModules.resize(dynamicResults.size());
for (size_t k = 0; k < dynamicResults.size(); k++) {
resultModules[k].res = dynamic_cast<DynamicResult *>(dynamicResults[k].ptr);
resultModules[k].res = dynamic_pointer_cast<DynamicResult>(dynamicResults[k].ptr);
resultModules[k].ctr = const_cast<MetaList *>(this);
}
}
@ -1320,7 +1338,7 @@ const wstring &MetaList::getListInfo(const oEvent &oe) const {
if (!resultModule.empty()) {
wstring f;
try {
GeneralResult &res = oe.getGeneralResult(resultModule, f);
GeneralResult &res = *oe.getGeneralResult(resultModule, f);
DynamicResult &dres = dynamic_cast<DynamicResult &>(res);
return dres.getDescription();
}
@ -1349,7 +1367,7 @@ void MetaList::retagResultModule(const string &newTag, bool retagStoredModule) {
if (retagStoredModule) {
for (size_t k = 0; k < dynamicResults.size(); k++) {
DynamicResult *res = dynamic_cast<DynamicResult *>(dynamicResults[k].ptr);
DynamicResult *res = dynamic_cast<DynamicResult *>(dynamicResults[k].ptr.get());
if (res && res->getTag() == oldTag) {
res->setTag(newTag);
}
@ -1359,7 +1377,7 @@ void MetaList::retagResultModule(const string &newTag, bool retagStoredModule) {
bool MetaList::updateResultModule(const DynamicResult &dr, bool updateSimilar) {
for (size_t k = 0; k < dynamicResults.size(); k++) {
DynamicResult *res = dynamic_cast<DynamicResult *>(dynamicResults[k].ptr);
DynamicResult *res = dynamic_cast<DynamicResult *>(dynamicResults[k].ptr.get());
if (res) {
const string &tag1 = res->getTag();
const string &tag2 = dr.getTag();
@ -1387,6 +1405,12 @@ bool MetaListContainer::updateResultModule(const DynamicResult &dr, bool updateS
}
}
auto f = freeResultModules.find(dr.getTag());
if (f != freeResultModules.end()) {
f->second.ptr = make_shared<DynamicResult>(dr);
changed = true;
}
if (changed && owner)
owner->updateChanged();
@ -1685,6 +1709,7 @@ void MetaList::initSymbols() {
typeToSymbol[lRunnerLostTime] = L"RunnerTimeLost";
typeToSymbol[lRunnerPlace] = L"RunnerPlace";
typeToSymbol[lRunnerClassCoursePlace] = L"RunnerClassCoursePlace";
typeToSymbol[lRunnerCoursePlace] = L"RunnerCoursePlace";
typeToSymbol[lRunnerStart] = L"RunnerStart";
typeToSymbol[lRunnerCheck] = L"RunnerCheck";
typeToSymbol[lRunnerStartCond] = L"RunnerStartCond";
@ -1848,6 +1873,7 @@ void MetaList::initSymbols() {
orderToSymbol[ClassStartTime] = "ClassStartTime";
orderToSymbol[ClassStartTimeClub] = "ClassStartTimeClub";
orderToSymbol[ClassResult] = "ClassResult";
orderToSymbol[ClassDefaultResult] = "ClassDefaultResult";
orderToSymbol[ClassCourseResult] = "ClassCourseResult";
orderToSymbol[SortByName] = "SortNameOnly";
orderToSymbol[SortByLastName] = "SortLastNameOnly";
@ -2005,6 +2031,13 @@ void MetaListContainer::save(MetaListType type, xmlparser &xml, const oEvent *oe
it->second.serialize(xml, *this, id2Ix);
}
}
for (auto res : freeResultModules) {
DynamicResult *dr = dynamic_cast<DynamicResult *>(res.second.ptr.get());
if (dr) {
dr->save(xml);
}
}
}
bool MetaListContainer::load(MetaListType type, const xmlobject &xDef, bool ignoreOld) {
@ -2014,9 +2047,11 @@ bool MetaListContainer::load(MetaListType type, const xmlobject &xDef, bool igno
xDef.getObjects("MeOSListDefinition", xList);
wstring majVer = getMajorVersion();
bool hasSkipped = false;
if (xList.empty() && strcmp(xDef.getName(), "MeOSListDefinition") == 0)
bool pushLevel = false;
if (xList.empty() && strcmp(xDef.getName(), "MeOSListDefinition") == 0) {
xList.push_back(xDef);
pushLevel = true;
}
wstring err;
for (size_t k = 0; k<xList.size(); k++) {
xmlattrib ver = xList[k].getAttrib("version");
@ -2088,9 +2123,26 @@ bool MetaListContainer::load(MetaListType type, const xmlobject &xDef, bool igno
it->second.nextList = 0; // Clear relation
}
}
if (!pushLevel) {
xDef.getObjects("MeOSResultCalculationSet", xList);
decltype(freeResultModules) copy;
freeResultModules.swap(copy);
for (auto res : xList) {
GeneralResultCtr ctr;
auto dr = make_shared<DynamicResult>();
dr->load(res);
if (copy.count(dr->getTag())) {
DynamicResult &oldResult = dynamic_cast<DynamicResult&>(*copy[dr->getTag()].ptr);
oldResult = *dr;
dr = dynamic_pointer_cast<DynamicResult>(copy[dr->getTag()].ptr);
}
freeResultModules.emplace(dr->getTag(), GeneralResultCtr(dr->getTag().c_str(), dr->getName(false), dr));
}
if (owner)
owner->updateChanged();
}
if (!err.empty())
throw meosException(err);
@ -2769,3 +2821,53 @@ void MetaListContainer::synchronizeTo(MetaListContainer &dst) const {
}
}
}
void MetaListContainer::getGeneralResults(vector<DynamicResultRef> &rmAll) {
for (int k = 0; k < getNumLists(); k++) {
vector<DynamicResultRef> rm;
getList(k).getDynamicResults(rm);
if (!isExternal(k)) {
for (size_t j = 0; j < rm.size(); j++) {
if (rm[j].res)
rm[j].res->setReadOnly();
}
}
rmAll.insert(rmAll.end(), rm.begin(), rm.end());
}
for (auto &res : freeResultModules) {
auto dynRes = dynamic_pointer_cast<DynamicResult, GeneralResult>(res.second.ptr);
dynRes->retaggable(false);
if (dynRes) {
rmAll.emplace_back(dynRes, nullptr);
}
}
}
wstring DynamicResultRef::getAnnotation() const {
if (ctr)
return ctr->getListName();
else
return L"";
}
void MetaListContainer::updateGeneralResult(string tag, const shared_ptr<DynamicResult> &res) {
bool changed = false;
if (!res) {
changed = freeResultModules.count(tag) > 0;
freeResultModules.erase(tag);
}
else {
auto rm = freeResultModules.find(tag);
if (rm == freeResultModules.end())
changed = true;
else
changed = rm->second.ptr.get() != res.get();
assert(tag == res->getTag());
freeResultModules.emplace(tag, GeneralResultCtr(tag.c_str(), res->getName(false), res));
}
if (changed && owner)
owner->updateChanged();
}

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -143,10 +143,12 @@ public:
};
struct DynamicResultRef {
DynamicResultRef(const DynamicResult *resIn, MetaList *ctrIn) : res(resIn), ctr(ctrIn) {}
DynamicResultRef() : res(0), ctr(0) {}
const DynamicResult *res;
DynamicResultRef(const shared_ptr<DynamicResult> &resIn, MetaList *ctrIn) : res(resIn), ctr(ctrIn) {}
DynamicResultRef() : ctr(0) {}
shared_ptr<DynamicResult> res;
MetaList *ctr;
wstring getAnnotation() const;
};
class MetaList {
@ -277,8 +279,6 @@ public:
return *this;
}
void getExistingTypes(vector< pair<string, size_t> > &types) const;
const wstring &getListName() const {return listName;}
oListInfo::EBaseType getListType() const;
@ -353,8 +353,10 @@ private:
mutable map<EStdListType, int> globalIndex;
mutable map<string, EStdListType> tagIndex;
mutable map<string, EStdListType> uniqueIndex;
map<int, oListParam> listParam;
map<string, GeneralResultCtr> freeResultModules;
oEvent *owner;
public:
@ -399,6 +401,9 @@ public:
bool isInternal(int index) const {return data[index].first == InternalList;}
bool isExternal(int index) const {return data[index].first == ExternalList;}
void updateGeneralResult(string tag, const shared_ptr<DynamicResult> &res);
void getGeneralResults(vector<DynamicResultRef> &resMod);
void save(MetaListType type, xmlparser &xml, const oEvent *oe) const;
/** Returns true if all lists where loaded, false if some list was in a unnsupported version and ignoreOld was set.
Throws if some list was incorrect. */

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -66,13 +66,23 @@ int methodCB(gdioutput *gdi, int type, void *data) {
throw meosException("Unexpected error");
}
void MethodEditor::show(TabBase *dst, gdioutput &gdi) {
gdi.clearPage(false);
origin = dst;
show(gdi);
}
void MethodEditor::show(gdioutput &gdi) {
oe->loadGeneralResults(true);
oe->loadGeneralResults(true, true);
gdi.setRestorePoint("BeginMethodEdit");
gdi.pushX();
gdi.setCX(gdi.getCX() + gdi.scaleLength(6));
int bx = gdi.getCX();
int by = gdi.getCY();
if (currentResult)
gdi.addString("", boldLarge, makeDash(L"Result Module - X#") + currentResult->getName(true));
else
@ -100,10 +110,23 @@ void MethodEditor::show(gdioutput &gdi) {
#ifdef _DEBUG
gdi.addButton("WriteDoc", "#WriteDoc", methodCB);
#endif
gdi.popX();
gdi.dropLine(2);
gdi.fillDown();
int dx = gdi.getCX();
int dy = gdi.getCY();
RECT rc;
int off = gdi.scaleLength(6);
rc.left = bx - 2 * off;
rc.right = dx + 2 * off;
rc.top = by - off;
rc.bottom = dy + off;
gdi.addRectangle(rc, colorWindowBar);
gdi.popX();
if (currentResult) {
gdi.dropLine(0.5);
if (currentResult->getTag().empty())
@ -205,6 +228,11 @@ string MethodEditor::uniqueTag(const string &tag) const {
return tag + un + itos(iter);
}
void makeScore(wstring &str, const pair<int, int> &score) {
int64_t v = int64_t(score.first) * (1LL << 32) + int64_t(score.second);
str = itow(v);
}
int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
if (type == GUI_BUTTON) {
ButtonInfo bi = dynamic_cast<ButtonInfo &>(data);
@ -271,7 +299,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
wstring path = fileNameSource.empty() ? getInternalPath(currentResult->getTag()) : fileNameSource;
currentResult->save(path);
fileNameSource = path;
oe->loadGeneralResults(true);
oe->loadGeneralResults(true, true);
makeDirty(gdi, ClearDirty);
currentResult->save(fileName);
@ -308,7 +336,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
oe->synchronize(false);
oe->getListContainer().updateResultModule(*currentResult, doUpdate);
oe->loadGeneralResults(true);
oe->loadGeneralResults(true, true);
oe->synchronize(true);
@ -324,7 +352,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
wstring rm = path + L".removed";
DeleteFile(rm.c_str());
_wrename(path.c_str(), rm.c_str());
oe->loadGeneralResults(true);
oe->loadGeneralResults(true, true);
makeDirty(gdi, ClearDirty);
setCurrentResult(0, L"");
gdi.clearPage(false);
@ -373,6 +401,19 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
//oe->getListContainer().getLists(lists);
vector< pair<int, pair<string, wstring> > > tagNameList;
oe->getGeneralResults(true, tagNameList, true);
map<string, wstring> tag2ClassUsage;
vector<pClass> cls;
oe->getClasses(cls, false);
for (pClass c : cls) {
string rt = c->getResultModuleTag();
if (!rt.empty()) {
wstring &n = tag2ClassUsage[rt];
if (n.empty())
n = L" | " + c->getName();
else
n += L", \x2026";
}
}
for (size_t k = 0; k < tagNameList.size(); k++) {
string tag = tagNameList[k].second.first;
string utag = DynamicResult::undecorateTag(tag);
@ -383,6 +424,8 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
if (listIx.size() > 0) {
n += L" *";
}
else if (tag2ClassUsage.count(tag))
n += tag2ClassUsage[tag];
lists.push_back(make_pair(n, tagNameList[k].first));
}
@ -400,7 +443,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
if (!lists.empty()) {
wstring srcFile;
bool ro = dynamic_cast<DynamicResult &>(oe->getGeneralResult(tagNameList.front().second.first, srcFile)).isReadOnly();
bool ro = dynamic_cast<DynamicResult &>(*oe->getGeneralResult(tagNameList.front().second.first, srcFile)).isReadOnly();
gdi.setInputStatus("DoOpen", !ro);
}
else {
@ -427,8 +470,9 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
}
if (ix < tagNameList.size()) {
wstring srcFile;
DynamicResult &drIn = dynamic_cast<DynamicResult &>(oe->getGeneralResult(tagNameList[ix].second.first, srcFile));
dr = load(gdi, tagNameList[ix].second.first, bi.id == "DoOpenCopy");
/*wstring srcFile;
DynamicResult &drIn = dynamic_cast<DynamicResult &>(*oe->getGeneralResult(tagNameList[ix].second.first, srcFile));
wasLoadedBuiltIn = drIn.isReadOnly();
dr = new DynamicResult(drIn);
if (bi.id == "DoOpenCopy") {
@ -437,17 +481,8 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
setCurrentResult(dr, L"");
}
else
setCurrentResult(dr, srcFile);
setCurrentResult(dr, srcFile);*/
}
if (bi.id == "DoOpen")
makeDirty(gdi, ClearDirty);
else
makeDirty(gdi, MakeDirty);
gdi.clearPage(false);
show(gdi);
if (dr) dr->compile(true);
}
}
else if (bi.id == "CancelReload") {
@ -461,7 +496,11 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
setCurrentResult(0, L"");
makeDirty(gdi, ClearDirty);
currentIndex = -1;
gdi.getTabs().get(TListTab)->loadPage(gdi);
if (origin) {
auto oc = origin;
origin = nullptr;
oc->loadPage(gdi);
}
return 0;
}
else if (bi.id == "SaveSource") {
@ -519,16 +558,19 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
int xp = gdi.getCX();
int yp = gdi.getCY();
int diff = gdi.scaleLength(3);
const int w[5] = {200, 70, 70, 70, 85};
int w[5] = {200, 70, 70, 70, 135};
for (int i = 0; i < 5; i++)
w[i] = gdi.scaleLength(w[i]);
set<wstring> errors;
currentResult->prepareCalculations(*oe, tr.size()>0, inputNumber);
currentResult->prepareCalculations(*oe, false, {}, rr, tr, inputNumber);
for (size_t k = 0; k < rr.size(); k++) {
int txp = xp;
int wi = 0;
gdi.addStringUT(yp, txp, 0, rr[k]->getCompleteIdentification(), w[wi]-diff);
txp += w[wi++];
currentResult->prepareCalculations(*rr[k]);
currentResult->prepareCalculations(*rr[k], false);
int rt = 0, pt = 0;
RunnerStatus st = StatusUnknown;
{
@ -595,8 +637,8 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
wstring err;
wstring str;
try {
int score = currentResult->score(*rr[k], st, rt, pt, false);
str = itow(score);
pair<int,int> score = currentResult->score(*rr[k], st, rt, pt, false);
makeScore(str, score);
}
catch (meosException &ex) {
err = ex.wwhat();
@ -630,7 +672,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
int wi = 0;
gdi.addStringUT(yp, txp, 0, tr[k]->getName(), w[wi]-diff);
txp += w[wi++];
currentResult->prepareCalculations(*tr[k]);
currentResult->prepareCalculations(*tr[k], false);
int rt = 0, pt = 0;
RunnerStatus st = StatusUnknown;
{
@ -696,8 +738,8 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
wstring err;
wstring str;
try {
int score = currentResult->score(*tr[k], st, rt, pt);
str = itow(score);
auto score = currentResult->score(*tr[k], st, rt, pt);
makeScore(str, score);
}
catch (meosException &ex) {
err = ex.wwhat();
@ -732,7 +774,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
gdi.enableInput("CancelSource");
gdi.getBaseInfo("SaveSource").setExtra(lbi.data);
if (!gdi.hasField("Source")) {
if (!gdi.hasWidget("Source")) {
gdi.fillRight();
gdi.restore("TestRule", false);
gdi.pushX();
@ -742,8 +784,8 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
methodCB, L"Source code:").setFont(gdi, monoText);
gdi.fillDown();
gdi.setCX(gdi.getCX() + gdi.getLineHeight());
gdi.addListBox("Symbols", 450, 300-20, methodCB, L"Available symbols:");
gdi.setTabStops("Symbols", 180);
gdi.addListBox("Symbols", 600, 300-20, methodCB, L"Available symbols:");
gdi.setTabStops("Symbols", 250);
gdi.addString("SymbInfo", gdi.getCY(), gdi.getCX(), 0, "", 350, 0);
gdi.popX();
gdi.setCY(gdi.getHeight());
@ -776,7 +818,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
}
wstring srcFile;
if (ix < tagNameList.size()) {
bool ro = dynamic_cast<DynamicResult &>(oe->getGeneralResult(tagNameList[ix].second.first, srcFile)).isReadOnly();
bool ro = dynamic_cast<DynamicResult &>(*oe->getGeneralResult(tagNameList[ix].second.first, srcFile)).isReadOnly();
gdi.setInputStatus("DoOpen", !ro);
}
else
@ -866,7 +908,7 @@ void MethodEditor::makeDirty(gdioutput &gdi, DirtyFlag inside) {
else if (inside == ClearDirty)
dirtyInt = false;
if (gdi.hasField("SaveInside")) {
if (gdi.hasWidget("SaveInside")) {
gdi.setInputStatus("SaveInside", dirtyInt);
gdi.setInputStatus("Remove", resultIsInstalled());
}
@ -888,7 +930,7 @@ bool MethodEditor::checkSave(gdioutput &gdi) {
}
void MethodEditor::checkChangedSave(gdioutput &gdi) {
if (gdi.hasField("Source")) {
if (gdi.hasWidget("Source")) {
gdi.getText("Source");
if (dynamic_cast<InputInfo &>(gdi.getBaseInfo("Source")).changed() &&
gdi.ask(L"Save changes in rule code?")) {
@ -952,11 +994,18 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
gdi_new->clearPage(false);
gdi_new->setData("MethodEditorClz", this);
gdioutput &gdi = *gdi_new;
currentResult->prepareCalculations(*oe, isTeam, inputNumber);
vector<pRunner> rr;
vector<pTeam> tt;
oe->getRunners(art->getClassId(true), 0, rr);
if (isTeam)
oe->getTeams(art->getClassId(true), tt, false);
currentResult->prepareCalculations(*oe, false, {art->getClassId(true)}, rr, tt, inputNumber);
gdi_new->addString("", fontMediumPlus, "Debug Output");
if (!isTeam) {
oRunner &r = *pRunner(art);
currentResult->prepareCalculations(r);
currentResult->prepareCalculations(r, false);
int rt = 0, pt = 0;
RunnerStatus st = StatusUnknown;
gdi.dropLine();
@ -994,11 +1043,13 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
gdi.addString("", 0, L"Points Calculation Failed: X#" + err).setColor(colorRed);
}
if (currentResult->hasMethod(DynamicResult::MDeduceRPoints))
currentResult->debugDumpVariables(gdi, true);
currentResult->debugDumpVariables(gdi, false);
try {
int score = currentResult->score(r, st, rt, pt, false);
gdi.addStringUT(1, "ComputedScore: " + itos(score)).setColor(colorGreen);
auto score = currentResult->score(r, st, rt, pt, false);
wstring str;
makeScore(str, score);
gdi.addStringUT(1, L"ComputedScore: " + str).setColor(colorGreen);
}
catch (meosException &ex) {
currentResult->debugDumpVariables(gdi, true);
@ -1010,7 +1061,7 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
}
else {
oTeam &t = *pTeam(art);
currentResult->prepareCalculations(t);
currentResult->prepareCalculations(t, false);
int rt = 0, pt = 0;
RunnerStatus st = StatusUnknown;
gdi.dropLine();
@ -1048,11 +1099,13 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
gdi.addString("", 0, L"Points Calculation Failed: X#" + err).setColor(colorRed);
}
if (currentResult->hasMethod(DynamicResult::MDeduceTPoints))
currentResult->debugDumpVariables(gdi, true);
currentResult->debugDumpVariables(gdi, false);
try {
int score = currentResult->score(t, st, rt, pt);
gdi.addStringUT(1, "ComputedScore:" + itos(score)).setColor(colorGreen);
auto score = currentResult->score(t, st, rt, pt);
wstring str;
makeScore(str, score);
gdi.addStringUT(1, L"ComputedScore:" + str).setColor(colorGreen);
}
catch (meosException &ex) {
currentResult->debugDumpVariables(gdi, true);
@ -1066,3 +1119,31 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
gdi.addButton("CloseWindow", "Stäng", methodCB);
gdi.refresh();
}
DynamicResult *MethodEditor::load(gdioutput &gdi, const string &tag, bool forceLoadCopy) {
DynamicResult *dr;
wstring srcFile;
DynamicResult &drIn = dynamic_cast<DynamicResult &>(*oe->getGeneralResult(tag, srcFile));
wasLoadedBuiltIn = drIn.isReadOnly();
dr = new DynamicResult(drIn);
if (forceLoadCopy || wasLoadedBuiltIn) {
dr->setTag(uniqueTag("result"));
dr->setName(lang.tl("Copy of ") + dr->getName(false));
setCurrentResult(dr, L"");
}
else
setCurrentResult(dr, srcFile);
if (forceLoadCopy || wasLoadedBuiltIn)
makeDirty(gdi, MakeDirty);
else
makeDirty(gdi, ClearDirty);
gdi.clearPage(false);
show(gdi);
if (dr) dr->compile(true);
return dr;
}

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
Copyright (C) 2009-2020 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,6 +30,8 @@ class oEvent;
#include <vector>
class TabBase;
class MethodEditor {
private:
enum SaveType {NotSaved, SavedInside, SavedFile};
@ -41,7 +43,7 @@ private:
bool dirtyInt;
bool wasLoadedBuiltIn;
enum DirtyFlag {MakeDirty, ClearDirty, NoTouch};
TabBase *origin = nullptr;
/// Check (and autosave) if there are unsaved changes in a dialog box
void checkUnsaved(gdioutput &gdi);
@ -65,11 +67,17 @@ private:
int inputNumber;
void debug(gdioutput &gdi, int id, bool isTeam);
void show(gdioutput &gdi);
public:
MethodEditor(oEvent *oe);
virtual ~MethodEditor();
void show(gdioutput &gdi);
void show(TabBase *dst, gdioutput &gdi);
bool isShown(TabBase *tab) const { return origin == tab; }
DynamicResult *load(gdioutput &gdi, const string &tag, bool forceLoadCopy);
friend int methodCB(gdioutput*, int, void *);
};

Some files were not shown because too many files have changed in this diff Show More