MeOS version 3.6.1089

This commit is contained in:
Erik Melin 2019-07-31 13:14:41 +02:00
parent a4e2689418
commit 06a6c4ff67
23 changed files with 632 additions and 369 deletions

View File

@ -7,7 +7,6 @@
const wstring _EmptyWString=L"";
const string _EmptyString="";
const string _VacantName="Vakant";
const string _UnkownName="N.N.";
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@ -1252,6 +1252,7 @@ X (Y deltagare, grupp Z, W) = X (Y závodníků, skupina Z, W)
X har startat = X odstartovalo
X kontroller = X kontrol
X meter = X metrů
X m = X m
X poäng fattas = X bodů chybí
X rader kunde inte raderas = X řádků nemůže být smazáno
X senaste = X nejnovějších

View File

@ -2303,6 +2303,7 @@ X har redan ett resultat. Vi du fortsätta? = X har allerede et resultat. Vil du
X har startat = X er startet
X kontroller = X poster
X meter = X meter
X m = X m
X och Y[N by N] = X og Y
X p = X p
X platser. Startar Y = X pladser. Starter Y

View File

@ -1252,7 +1252,8 @@ X (Saknar e-post) = X (Has no e-mail)
X (Y deltagare, grupp Z, W) = X (Y competitors, group Z, W)
X har startat = X started
X kontroller = X controls
X meter = X meter
X meter = X meters
X m = X m
X poäng fattas = X points missing
X rader kunde inte raderas = X row(s) could not be deleted
X senaste = X latest
@ -2432,3 +2433,6 @@ Kunde inte öppna databasen (X) = Could not connect to database (X)
Kunde inte ladda upp löpardatabasen (X) = Could not upload runner database (X)
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
X anmälda = X entries

View File

@ -1254,6 +1254,7 @@ X (Y deltagare, grupp Z, W) = X (Y coureurs, groupe Z, W)
X har startat = X est parti
X kontroller = X postes
X meter = X mètres
X m = X m
X poäng fattas = X points manquant
X rader kunde inte raderas = X lignes ne peuvent être effacées
X senaste = X derniers

View File

@ -390,9 +390,9 @@ void MeosSQL::upgradeDB(const string &db, oDataContainer const * dc) {
query.execute(sql);
}
}
else if (db == "oRunner") {
else if (db == "oRunner" || db == "oTeam") {
if (!eCol.count("InputTime")) {
string sql = "ALTER TABLE oRunner ";
string sql = "ALTER TABLE " + db + " ";
sql += "ADD COLUMN " + C_INT("InputTime");
sql += "ADD COLUMN " + C_INT("InputStatus");
sql += "ADD COLUMN " + C_INT("InputPoints");
@ -522,7 +522,7 @@ bool MeosSQL::openDB(oEvent *oe)
query << C_START("oCard")
<< C_INT("CardNo")
<< C_UINT("ReadId")
<< C_STRING("Punches", 1024) << C_END();
<< C_STRING("Punches", 16*190) << C_END();
query.execute();
@ -558,7 +558,6 @@ bool MeosSQL::openDB(oEvent *oe)
// Ugrade oRunner
upgradeDB("oControl", oe->oControlData);
query.reset();
query << C_START("oCourse")
<< C_STRING("Name")
@ -577,6 +576,7 @@ bool MeosSQL::openDB(oEvent *oe)
<< C_INT("Club") << C_INT("Class")
<< C_INT("StartTime") << C_INT("FinishTime")
<< C_INT("Status") << C_INT("StartNo")
<< C_INT("InputTime") << C_INT("InputStatus") << C_INT("InputPoints") << C_INT("InputPlace")
<< oe->oTeamData->generateSQLDefinition() << C_END();
query.execute();
@ -1165,7 +1165,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
while (row = res.fetch_row()) {
oControl c(oe, row["Id"]);
storeControl(row, c);
oe->Controls.push_back(c);
oe->addControl(c);
oe->sqlUpdateControls = max(c.sqlUpdated, oe->sqlUpdateControls);
oe->sqlCounterControls = max(c.counter, oe->sqlCounterControls);
@ -1191,7 +1191,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
set<int> tmp;
while (row = res.fetch_row()) {
oCourse c(oe, row["Id"]);
storeCourse(row, c, tmp);
storeCourse(row, c, tmp, false);
oe->addCourse(c);
oe->sqlUpdateCourses = max(c.sqlUpdated, oe->sqlUpdateCourses);
@ -1216,7 +1216,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
Row row;
while (row = res.fetch_row()) {
oClass c(oe, row["Id"]);
storeClass(row, c, false);
storeClass(row, c, false, false);
c.changed = false;
c.reChanged = false;
@ -1277,7 +1277,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
Row row;
while (row = res.fetch_row()) {
oRunner r(oe, row["Id"]);
storeRunner(row, r, false, false, false);
storeRunner(row, r, false, false, false, false);
assert(!r.changed);
oe->addRunner(r, false);
@ -1309,7 +1309,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
while (row = res.fetch_row()) {
oTeam t(oe, row["Id"]);
storeTeam(row, t, false);
storeTeam(row, t, false, false);
pTeam at = oe->addTeam(t, false);
@ -1427,6 +1427,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
}
oe->runnerDB->setDataDate(dateTime);
processMissingObjects();
return retValue;
}
@ -1512,7 +1513,7 @@ void MeosSQL::storePunch(const Row &row, oFreePunch &p, bool rehash)
}
OpFailStatus MeosSQL::storeClass(const Row &row, oClass &c,
bool readCourses)
bool readCourses, bool allowSubRead)
{
OpFailStatus success = opStatusOK;
@ -1525,9 +1526,11 @@ OpFailStatus MeosSQL::storeClass(const Row &row, oClass &c,
set<int> cid;
vector<vector<int>> multip;
oClass::parseCourses(multi, multip, cid);
int classCourse = row["Course"];
if (classCourse != 0)
cid.insert(classCourse);
if (!readCourses) {
for (set<int>::iterator clsIt = cid.begin(); clsIt != cid.end(); ++clsIt) {
if (!c.oe->getCourse(*clsIt))
@ -1535,12 +1538,26 @@ OpFailStatus MeosSQL::storeClass(const Row &row, oClass &c,
}
}
if (readCourses)
if (readCourses) {
if (allowSubRead) {
success = min(success, syncReadClassCourses(&c, cid, readCourses));
}
else {
// Cannot read from database here. Add implicitly added courses
for (int x : cid) {
if (c.oe->getCourse(x) == nullptr) {
oCourse oc(c.oe, x);
oc.setImplicitlyCreated();
addedFromDatabase(c.oe->addCourse(oc));
}
}
}
}
if (classCourse != 0)
c.Course = c.oe->getCourse(classCourse);
else
c.Course = 0;
c.Course = nullptr;
c.importCourses(multip);
@ -1559,8 +1576,8 @@ OpFailStatus MeosSQL::storeClass(const Row &row, oClass &c,
}
OpFailStatus MeosSQL::storeCourse(const Row &row, oCourse &c,
set<int> &readControls)
{
set<int> &readControls,
bool allowSubRead) {
OpFailStatus success = opStatusOK;
c.Name = fromUTF((string)row["Name"]);
@ -1573,12 +1590,16 @@ OpFailStatus MeosSQL::storeCourse(const Row &row, oCourse &c,
// Might have been created during last call.
// Then just read to update
if (!c.Controls[i]->existInDB()) {
c.Controls[i]->setImplicitlyCreated();
if (allowSubRead) {
c.Controls[i]->changed = false;
success = min(success, syncRead(true, c.Controls[i]));
}
else
addedFromDatabase(c.Controls[i]);
}
else {
readControls.insert(c.Controls[i]->getId());
//success = min(success, syncRead(false, c.Controls[i]));
}
}
}
@ -1598,7 +1619,8 @@ OpFailStatus MeosSQL::storeCourse(const Row &row, oCourse &c,
OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
bool readCourseCard,
bool readClassClub,
bool readRunners)
bool readRunners,
bool allowSubRead)
{
OpFailStatus success = opStatusOK;
oEvent *oe=r.oe;
@ -1637,10 +1659,15 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
set<int> controlIds;
if (!r.Course) {
oCourse oc(oe, row["Course"]);
oc.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncReadCourse(true, &oc, controlIds));
if (!oc.isRemoved()) {
r.Course = oe->addCourse(oc);
addedFromDatabase(r.Course);
}
else if (readCourseCard)
}
else if (readCourseCard && allowSubRead)
success = min(success, syncReadCourse(false, r.Course, controlIds));
if (readCourseCard)
@ -1653,10 +1680,15 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
if (!r.Class) {
oClass oc(oe, row["Class"]);
oc.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncRead(true, &oc, readClassClub));
if (!oc.isRemoved()) {
r.Class = oe->addClass(oc);
addedFromDatabase(r.Class);
}
else if (readClassClub)
}
else if (readClassClub && allowSubRead)
success = min(success, syncRead(false, r.Class, true));
if (r.tInTeam && r.tInTeam->Class!=r.Class)
@ -1669,10 +1701,15 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
if (!r.Club) {
oClub oc(oe, row["Club"]);
oc.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncRead(true, &oc));
if (!oc.isRemoved()) {
r.Club = oe->addClub(oc);
addedFromDatabase(r.Club);
}
else if (readClassClub)
}
else if (readClassClub && allowSubRead)
success = min(success, syncRead(false, r.Club));
}
else r.Club=0;
@ -1684,12 +1721,18 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
if (!r.Card){
oCard oc(oe, row["Card"]);
oe->Cards.push_back(oc);
r.Card = &oe->Cards.back();
oc.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncRead(true, &oc));
if (!oc.isRemoved()) {
r.Card = oe->addCard(oc);
r.Card->changed = false;
success = min(success, syncRead(true, r.Card));
}
else if (readCourseCard)
else {
addedFromDatabase(r.Card);
}
}
else if (readCourseCard && allowSubRead)
success = min(success, syncRead(false, r.Card));
}
else r.Card=0;
@ -1713,10 +1756,18 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
pRunner pr = oe->getRunner(rid, 0);
if (pr==0) {
oRunner or(oe, rid);
or.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncRead(true, &or, false, readCourseCard));
if (!or.isRemoved()) {
pr = oe->addRunner(or , false);
addedFromDatabase(pr);
}
else
else {
r.multiRunnerId[i] = 0;
}
}
else if (allowSubRead)
success = min(success, syncRead(false, pr, false, readCourseCard));
}
}
@ -1732,7 +1783,7 @@ OpFailStatus MeosSQL::storeRunner(const Row &row, oRunner &r,
}
OpFailStatus MeosSQL::storeTeam(const Row &row, oTeam &t,
bool readRecursive)
bool readRecursive, bool allowSubRead)
{
oEvent *oe=t.oe;
OpFailStatus success = opStatusOK;
@ -1749,6 +1800,12 @@ OpFailStatus MeosSQL::storeTeam(const Row &row, oTeam &t,
t.tStartTime = t.startTime = row["StartTime"];
t.FinishTime = row["FinishTime"];
t.tStatus = t.status = RunnerStatus(int(row["Status"]));
t.inputTime = row["InputTime"];
t.inputPoints = row["InputPoints"];
t.inputStatus = RunnerStatus(int(row["InputStatus"]));
t.inputPlace = row["InputPlace"];
storeData(t.getDI(), row, oe->dataRevision);
if (oldSno != t.StartNo || oldBib != t.getBib())
@ -1768,10 +1825,15 @@ OpFailStatus MeosSQL::storeTeam(const Row &row, oTeam &t,
if (!t.Class) {
oClass oc(oe, classId);
oc.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncRead(true, &oc, readRecursive));
if (!oc.isRemoved()) {
t.Class = oe->addClass(oc);
addedFromDatabase(t.Class);
}
else if (readRecursive)
}
else if (readRecursive && allowSubRead)
success = min(success, syncRead(false, t.Class, readRecursive));
}
else t.Class=0;
@ -1782,10 +1844,15 @@ OpFailStatus MeosSQL::storeTeam(const Row &row, oTeam &t,
if (!t.Club) {
oClub oc(oe, clubId);
oc.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncRead(true, &oc));
if (!oc.isRemoved()) {
t.Club = oe->addClub(oc);
addedFromDatabase(t.Club);
}
else if (readRecursive)
}
else if (readRecursive && allowSubRead)
success = min(success, syncRead(false, t.Club));
}
else t.Club = 0;
@ -1798,19 +1865,24 @@ OpFailStatus MeosSQL::storeTeam(const Row &row, oTeam &t,
for (size_t k=0;k<rns.size(); k++) {
if (rns[k]>0) {
pRns[k] = oe->getRunner(rns[k], 0);
if (!pRns[k]) {
oRunner or(oe, rns[k]);
or.setImplicitlyCreated();
if (allowSubRead)
success = min(success, syncRead(true, &or, readRecursive, readRecursive));
if (or.sName.empty()) {
or.sName = L"@AutoCorrection";
oRunner::getRealName(or.sName, or.tRealName);
}
if (!or.isRemoved()) {
pRns[k] = oe->addRunner(or , false);
addedFromDatabase(pRns[k]);
assert(pRns[k] && !pRns[k]->changed);
}
else if (readRecursive)
}
else if (readRecursive && allowSubRead)
success = min(success, syncRead(false, pRns[k]));
}
}
@ -1936,6 +2008,9 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oRunner *r)
}
string MeosSQL::andWhereOld(oBase *ob) {
if (ob->sqlUpdated.empty())
return " AND Counter!=" + itos(ob->counter);
else
return " AND (Counter!=" + itos(ob->counter) + " OR Modified!='" + ob->sqlUpdated + "')";
}
@ -1967,7 +2042,7 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oRunner *r, bool readClassClub, b
if (r->changed)
success=opStatusWarning;
success = min (success, storeRunner(row, *r, readCourseCard, readClassClub, true));
success = min (success, storeRunner(row, *r, readCourseCard, readClassClub, true, true));
r->oe->dataRevision++;
r->Modified.update();
@ -2105,7 +2180,11 @@ OpFailStatus MeosSQL::syncUpdate(oTeam *t, bool forceWriteAll) {
<< " Class=" << t->getClassId(false) << ", "
<< " Club=" << t->getClubId() << ", "
<< " StartNo=" << t->getStartNo() << ", "
<< " Status=" << t->status
<< " Status=" << t->status << ", "
<< " InputTime=" << t->inputTime << ", "
<< " InputStatus=" << t->inputStatus << ", "
<< " InputPoints=" << t->inputPoints << ", "
<< " InputPlace=" << t->inputPlace
<< t->getDI().generateSQLSet(forceWriteAll);
//wstring str = L"write team " + t->sName + L"\n";
@ -2147,7 +2226,7 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oTeam *t, bool readRecursive)
if (t->changed)
success=opStatusWarning;
storeTeam(row, *t, readRecursive);
storeTeam(row, *t, readRecursive, true);
t->oe->dataRevision++;
t->Modified.update();
t->changed = false;
@ -2236,7 +2315,7 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oClass *c, bool readCourses)
if (c->changed)
success=opStatusWarning;
storeClass(row, *c, readCourses);
storeClass(row, *c, readCourses, true);
c->oe->dataRevision++;
c->Modified.update();
c->changed = false;
@ -2296,8 +2375,10 @@ OpFailStatus MeosSQL::syncReadClassCourses(oClass *c, const set<int> &courses,
pCourse pc = oe->getCourse(id);
if (!pc) {
oCourse oc(oe, id);
oc.setImplicitlyCreated();
success = min(success, syncReadCourse(true, &oc, controlIds));
oe->addCourse(oc);
if (!oc.isRemoved())
addedFromDatabase(oe->addCourse(oc));
}
else if (pc->changed || isOld(counter, modified, pc)) {
success = min(success, syncReadCourse(false, pc, controlIds));
@ -2576,7 +2657,7 @@ OpFailStatus MeosSQL::syncReadCourse(bool forceRead, oCourse *c, set<int> &readC
if (c->changed)
success = opStatusWarning;
storeCourse(row, *c, readControls);
storeCourse(row, *c, readControls, true);
c->oe->dataRevision++;
c->Modified.update();
c->changed=false;
@ -2771,6 +2852,12 @@ OpFailStatus MeosSQL::syncUpdate(mysqlpp::Query &updateqry,
Result res=query.store();
if (res && res.num_rows()==0)
setId = true;
else if (ob->isImplicitlyCreated()) {
return opStatusWarning;//XXX Should we read this object?
}
}
else {
assert(!ob->isImplicitlyCreated());
}
query.reset();
@ -3729,3 +3816,97 @@ int MeosSQL::getModifiedMask(oEvent &oe) {
}
return -1;
}
void MeosSQL::addedFromDatabase(oBase *object) {
assert(object);
if (object && !object->existInDB()) {
missingObjects.push_back(object);
}
}
void MeosSQL::processMissingObjects() {
if (!missingObjects.empty()) {
auto cpyMissing = missingObjects;
missingObjects.clear();
for (oBase *obj : cpyMissing) {
obj->changed = true;
syncRead(true, obj);
obj->changed = false;
assert(obj->existInDB());
{
oRunner *r = dynamic_cast<oRunner *>(obj);
if (r && r->getName().empty()) {
r->setName(L"@AutoCorrection", false);
syncUpdate(r, false);
}
}
{
oTeam *t = dynamic_cast<oTeam *>(obj);
if (t && t->getName().empty()) {
t->setName(L"@AutoCorrection", false);
syncUpdate(t, false);
}
}
{
oClass *cls = dynamic_cast<oClass *>(obj);
if (cls && cls->getName().empty()) {
cls->setName(L"@AutoCorrection");
syncUpdate(cls, false);
}
}
{
oCourse *crs = dynamic_cast<oCourse *>(obj);
if (crs && crs->getName().empty()) {
crs->setName(L"@AutoCorrection");
syncUpdate(crs, false);
}
}
{
oClub *clb = dynamic_cast<oClub *>(obj);
if (clb && clb->getName().empty()) {
clb->setName(L"@AutoCorrection");
syncUpdate(clb, false);
}
}
}
}
missingObjects.clear();
}
OpFailStatus MeosSQL::syncRead(bool forceRead, oBase *obj) {
OpFailStatus ret = OpFailStatus::opStatusFail;
if (typeid(*obj) == typeid(oRunner)) {
ret = syncRead(forceRead, (oRunner *)obj);
}
else if (typeid(*obj) == typeid(oClass)) {
ret = syncRead(forceRead, (oClass *)obj);
}
else if (typeid(*obj) == typeid(oCourse)) {
ret = syncRead(forceRead, (oCourse *)obj);
}
else if (typeid(*obj) == typeid(oControl)) {
ret = syncRead(forceRead, (oControl *)obj);
}
else if (typeid(*obj) == typeid(oClub)) {
ret = syncRead(forceRead, (oClub *)obj);
}
else if (typeid(*obj) == typeid(oCard)) {
ret = syncRead(forceRead, (oCard *)obj);
}
else if (typeid(*obj) == typeid(oFreePunch)) {
ret = syncRead(forceRead, (oFreePunch *)obj, true);
}
else if (typeid(*obj) == typeid(oTeam)) {
ret = syncRead(forceRead, (oTeam *)obj);
}
else if (typeid(*obj) == typeid(oEvent)) {
ret = SyncRead((oEvent *)obj);
}
else
throw std::exception("Database error");
processMissingObjects();
return ret;
}

View File

@ -58,6 +58,8 @@ protected:
string CmpDataBase;
void alert(const string &s);
vector<oBase *> missingObjects;
string errorMessage;
string serverName;
@ -94,16 +96,19 @@ protected:
void storePunch(const mysqlpp::Row &row, oFreePunch &p, bool rehash);
OpFailStatus storeTeam(const mysqlpp::Row &row, oTeam &t,
bool readRecursive);
bool readRecursive, bool allowSubRead);
OpFailStatus storeRunner(const mysqlpp::Row &row, oRunner &r,
bool readCourseCard,
bool readClassClub,
bool readRunners);
bool readRunners,
bool allowSubRead);
OpFailStatus storeCourse(const mysqlpp::Row &row, oCourse &c,
set<int> &readControls);
set<int> &readControls,
bool allowSubRead);
OpFailStatus storeClass(const mysqlpp::Row &row, oClass &c,
bool readCourses);
bool readCourses,
bool allowSubRead);
void getColumns(const string &table, set<string> &output);
@ -120,9 +125,13 @@ protected:
mysqlpp::ResNSel updateCounter(const char *oTable, int id, mysqlpp::Query *updateqry);
string selectUpdated(const char *oTable, const string &updated, int counter);
void addedFromDatabase(oBase *object);
public:
bool dropDatabase(oEvent *oe);
bool checkConnection(oEvent *oe);
void processMissingObjects();
bool repairTables(const string &db, vector<string> &output);
@ -179,6 +188,10 @@ public:
OpFailStatus syncUpdate(oTeam *t, bool forceWriteAll);
OpFailStatus syncRead(bool forceRead, oTeam *t);
/** General interface. TypeId lookup */
OpFailStatus syncRead(bool forceRead, oBase *c);
int getModifiedMask(oEvent &oe);
MeosSQL(void);

View File

@ -74,25 +74,36 @@ bool MEOSDB_API msSynchronizeList(oEvent *oe, oListId lid)
nSynchList++;
if (nSynchList % 100 == 99)
OutputDebugString(L"Synchronized 100 lists\n");
bool ret = false;
switch (lid) {
case oListId::oLRunnerId:
ret = msql.syncListRunner(oe);
break;
case oListId::oLClassId:
ret = msql.syncListClass(oe);
break;
case oListId::oLCourseId:
ret = msql.syncListCourse(oe);
break;
case oListId::oLControlId:
ret = msql.syncListControl(oe);
break;
case oListId::oLClubId:
ret = msql.syncListClub(oe);
break;
case oListId::oLCardId:
ret = msql.syncListCard(oe);
break;
case oListId::oLPunchId:
ret = msql.syncListPunch(oe);
break;
case oListId::oLTeamId:
ret = msql.syncListTeam(oe);
break;
}
if (lid == oListId::oLRunnerId)
return msql.syncListRunner(oe);
else if (lid == oListId::oLClassId)
return msql.syncListClass(oe);
else if (lid == oListId::oLCourseId)
return msql.syncListCourse(oe);
else if (lid == oListId::oLControlId)
return msql.syncListControl(oe);
else if (lid == oListId::oLClubId)
return msql.syncListClub(oe);
else if (lid == oListId::oLCardId)
return msql.syncListCard(oe);
else if (lid == oListId::oLPunchId)
return msql.syncListPunch(oe);
else if (lid == oListId::oLTeamId)
return msql.syncListTeam(oe);
return false;
msql.processMissingObjects();
return ret;
}
int MEOSDB_API msSynchronizeUpdate(oBase *obj)
@ -134,34 +145,7 @@ int MEOSDB_API msSynchronizeRead(oBase *obj)
if (nSynchEnt % 100 == 99)
OutputDebugString(L"Synchronized 100 entities\n");
if (typeid(*obj)==typeid(oRunner)){
return msql.syncRead(false, (oRunner *) obj );
}
else if (typeid(*obj)==typeid(oClass)){
return msql.syncRead(false, (oClass *) obj);
}
else if (typeid(*obj)==typeid(oCourse)){
return msql.syncRead(false, (oCourse *) obj);
}
else if (typeid(*obj)==typeid(oControl)){
return msql.syncRead(false, (oControl *) obj);
}
else if (typeid(*obj)==typeid(oClub)){
return msql.syncRead(false, (oClub *) obj);
}
else if (typeid(*obj)==typeid(oCard)){
return msql.syncRead(false, (oCard *) obj);
}
else if (typeid(*obj)==typeid(oFreePunch)){
return msql.syncRead(false, (oFreePunch *) obj, true);
}
else if (typeid(*obj)==typeid(oTeam)){
return msql.syncRead(false, (oTeam *) obj);
}
else if (typeid(*obj)==typeid(oEvent)){
return msql.SyncRead((oEvent *) obj);
}
return 0;
return msql.syncRead(false, obj);
}
// Removes (marks it as removed) an entry from the database.

View File

@ -30,7 +30,7 @@
//V35: abcdef
//V36: abcdef
int getMeosBuild() {
string revision("$Rev: 912 $");
string revision("$Rev: 915 $");
return 174 + atoi(revision.substr(5, string::npos).c_str());
}
@ -42,12 +42,12 @@ int getMeosBuild() {
//V33: abcdefghij
//V34: abcdfge
wstring getMeosDate() {
wstring date(L"$Date: 2019-06-16 10:37:59 +0200 (sö, 16 jun 2019) $");
wstring date(L"$Date: 2019-07-30 07:05:51 +0200 (ti, 30 jul 2019) $");
return date.substr(7,10);
}
wstring getBuildType() {
return L"Update 1"; // No parantheses (...)
return L"Update 2"; // No parantheses (...)
}
wstring getMajorVersion() {
@ -60,7 +60,7 @@ wstring getMeosFullVersion() {
if (getBuildType().empty())
swprintf_s(bf, L"Version X#%s.%d, %s", maj.c_str(), getMeosBuild(), getMeosDate().c_str());
else
swprintf_s(bf, L"Version X#%s.%d, %s %s", maj.c_str(), getMeosBuild(), getBuildType().c_str(), getMeosDate().c_str());
swprintf_s(bf, L"Version X#%s.%d, %s, %s", maj.c_str(), getMeosBuild(), getBuildType().c_str(), getMeosDate().c_str());
return bf;
}
@ -133,5 +133,8 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
supp.emplace_back(L"Kexholm SK");
supp.emplace_back(L"Utby IK");
supp.emplace_back(L"JWOC 2019");
developSupp.emplace_back(L"OK Nackhe");
supp.emplace_back(L"OK Rodhen");
reverse(supp.begin(), supp.end());
}

View File

@ -101,17 +101,20 @@ protected:
TimeStamp Modified;
string sqlUpdated; //SQL TIMESTAMP
int counter;
oEvent *oe;
bool Removed;
// True if the object is incorrect and needs correction
// An example is if id changed as we wrote. Then owner
// needs to be updated.
bool correctionNeeded;
bool correctionNeeded = false;
oEvent *oe;
bool Removed;
private:
//Used for selections, etc.
int _objectmarker;
bool implicitlyAdded = false;
bool addedToEvent = false;
protected:
/// Mark the object as changed (on client) and that it needs synchronize to server
virtual void updateChanged();
@ -165,6 +168,11 @@ public:
bool existInDB() const { return !sqlUpdated.empty(); }
void setImplicitlyCreated() { implicitlyAdded = true; }
bool isImplicitlyCreated() const { return implicitlyAdded; }
bool isAddedToEvent() const { return addedToEvent; }
void addToEvent() { addedToEvent = true; }
oDataInterface getDI();
oDataConstInterface getDCI() const;

View File

@ -487,7 +487,7 @@ bool oCard::setPunchTime(const pPunch punch, const wstring &time)
pCard oEvent::getCard(int Id) const
{
{ // Do allow removed cards
if (Id < int(Cards.size() / 2)) {
for (oCardList::const_iterator it = Cards.begin(); it != Cards.end(); ++it){
if (it->Id==Id)
@ -514,18 +514,17 @@ void oEvent::getCards(vector<pCard> &c) {
}
}
pCard oEvent::addCard(const oCard &oc)
{
if (oc.Id<=0)
return 0;
Cards.push_back(oc);
Cards.back().addToEvent();
return &Cards.back();
}
pCard oEvent::getCardByNumber(int cno) const
{
oCardList::const_reverse_iterator it;

View File

@ -716,6 +716,7 @@ pClass oEvent::addClass(const wstring &pname, int CourseId, int classId)
c.Course=getCourse(CourseId);
Classes.push_back(c);
Classes.back().addToEvent();
Classes.back().synchronize();
updateTabs();
return &Classes.back();
@ -732,8 +733,9 @@ pClass oEvent::addClass(oClass &c)
}
Classes.push_back(c);
Classes.back().addToEvent();
if (!Classes.back().existInDB()) {
if (!Classes.back().existInDB() && !c.isImplicitlyCreated()) {
Classes.back().changed = true;
Classes.back().synchronize();
}

View File

@ -233,7 +233,7 @@ pClub oEvent::addClub(const wstring &pname, int createId) {
oClub c(this, createId);
c = *dbClub;
c.Id = createId;
Clubs.push_back(c);
return addClub(c);
}
else {
if (createId==0)
@ -241,11 +241,8 @@ pClub oEvent::addClub(const wstring &pname, int createId) {
oClub c(this, createId);
c.setName(pname);
Clubs.push_back(c);
return addClub(c);
}
Clubs.back().synchronize();
clubIdIndex[Clubs.back().Id]=&Clubs.back();
return &Clubs.back();
}
pClub oEvent::addClub(const oClub &oc)
@ -254,6 +251,8 @@ pClub oEvent::addClub(const oClub &oc)
return clubIdIndex[oc.Id];
Clubs.push_back(oc);
Clubs.back().addToEvent();
if (!oc.existInDB())
Clubs.back().synchronize();

View File

@ -64,7 +64,7 @@
#include "Table.h"
//Version of database
int oEvent::dbVersion = 82;
int oEvent::dbVersion = 83;
class RelativeTimeFormatter : public oDataDefiner {
string name;
@ -610,7 +610,7 @@ pControl oEvent::addControl(int Id, int Number, const wstring &Name)
oControl c(this);
c.set(Id, Number, Name);
Controls.push_back(c);
addControl(c);
oe->updateTabs();
return &Controls.back();
@ -636,6 +636,8 @@ pControl oEvent::addControl(const oControl &oc)
qFreeControlId = max (qFreeControlId, Id);
Controls.push_back(oc);
oe->Controls.back().addToEvent();
return &Controls.back();
}
@ -1181,9 +1183,8 @@ bool oEvent::open(const xmlparser &xml) {
oControl c(this);
c.set(&*it);
if (c.Id>0 && knownControls.count(c.Id) == 0) {
Controls.push_back(c);
knownControls.insert(c.Id);
if (c.Id>0 && knownControls.insert(c.Id).second) {
addControl(c);
}
}
}
@ -1227,6 +1228,7 @@ bool oEvent::open(const xmlparser &xml) {
c.Set(&*it);
if (c.Id>0 && knownClass.count(c.Id) == 0) {
Classes.push_back(c);
Classes.back().addToEvent();
knownClass.insert(c.Id);
}
}
@ -1249,7 +1251,7 @@ bool oEvent::open(const xmlparser &xml) {
oClub c(this);
c.set(*it);
if (c.Id>0)
addClub(c);//Clubs.push_back(c);
addClub(c);
}
}
}
@ -1341,7 +1343,7 @@ bool oEvent::open(const xmlparser &xml) {
oCard c(this);
c.Set(*it);
assert(c.Id>=0);
Cards.push_back(c);
addCard(c);
}
}
}
@ -1576,8 +1578,9 @@ pCourse oEvent::addCourse(const oCourse &oc)
qFreeCourseId=max(qFreeCourseId, oc.getId());
pCourse pc = &Courses.back();
pc->addToEvent();
if (!pc->existInDB()) {
if (!pc->existInDB() && !pc->isImplicitlyCreated()) {
pc->updateChanged();
pc->synchronize();
}
@ -1609,7 +1612,7 @@ void oEvent::autoRemoveTeam(pRunner pr)
if (pr->tInTeam) {
// A team may have more than this runner -> do not remove
bool canRemove = true;
const vector<pRunner> &runners = pr->tInTeam->Runners;
const auto &runners = pr->tInTeam->Runners;
for (size_t k = 0; k<runners.size(); k++) {
if (runners[k] && runners[k]->sName != pr->sName)
canRemove = false;
@ -1726,6 +1729,14 @@ pRunner oEvent::addRunner(const oRunner &r, bool updateStartNo) {
Runners.push_back(r);
pRunner pr=&Runners.back();
pr->addToEvent();
for (size_t i = 0; i < pr->multiRunner.size(); i++) {
if (pr->multiRunner[i]) {
assert(pr->multiRunner[i]->tParentRunner == nullptr || pr->multiRunner[i]->tParentRunner == &r);
pr->multiRunner[i]->tParentRunner = pr;
}
}
//cardToRunnerHash.reset();
if (cardToRunnerHash && r.getCardNo() != 0) {
@ -1743,7 +1754,7 @@ pRunner oEvent::addRunner(const oRunner &r, bool updateStartNo) {
pr->Card->tOwner = pr;
if (HasDBConnection) {
if (!pr->existInDB())
if (!pr->existInDB() && !pr->isImplicitlyCreated())
pr->synchronize();
}
if (needUpdate)
@ -2041,6 +2052,7 @@ pCard oEvent::allocateCard(pRunner owner)
c.tOwner = owner;
Cards.push_back(c);
pCard newCard = &Cards.back();
newCard->addToEvent();
return newCard;
}
@ -2152,7 +2164,7 @@ bool oEvent::sortTeams(SortOrder so, int leg, bool linearLeg) {
// Count number of races with results
int numResult = 0;
int lastClassHeat = 0;
for (pRunner r : it->Runners) {
for (auto &r : it->Runners) {
if (r && (r->prelStatusOK() ||
(r->tStatus != StatusUnknown && r->tStatus != StatusDNS && r->tStatus != StatusCANCEL))) {
@ -2266,7 +2278,7 @@ bool oEvent::sortTeams(SortOrder so, int leg, bool linearLeg, vector<const oTeam
// Count number of races with results
int numResult = 0;
int lastClassHeat = 0;
for (pRunner r : it->Runners) {
for (auto &r : it->Runners) {
if (r && (r->prelStatusOK() ||
(r->tStatus != StatusUnknown && r->tStatus != StatusDNS && r->tStatus != StatusCANCEL))) {
@ -2675,7 +2687,7 @@ void oEvent::removeRunner(const vector<int> &ids)
// Reset team runner (this should not happen)
if (it->tInTeam) {
if (it->tInTeam->Runners[it->tLeg]==&*it)
it->tInTeam->Runners[it->tLeg] = 0;
it->tInTeam->Runners[it->tLeg] = nullptr;
}
oRunnerList::iterator next = it;

View File

@ -629,7 +629,7 @@ public:
enum PredefinedTypes {PNoSettings, PPool, PForking, PPoolDrawn, PHunting,
PPatrol, PPatrolOptional, PPatrolOneSI, PRelay, PTwinRelay,
PYouthRelay, PNoMulti};
PYouthRelay, PTwoRacesNoOrder, PNoMulti};
void fillPredefinedCmp(gdioutput &gdi, const string &name) const;

View File

@ -651,7 +651,7 @@ bool oEvent::readSynchronize(const CompetitionInfo &ci)
pRunner r = it->Runners[i];
if (r != 0) {
if (usedInTeam[r->Id]) {
it->Runners[i] = 0; // Reset duplicate runners
it->Runners[i] = nullptr; // Reset duplicate runners
it->updateChanged();
teamCorrected = true;
if (r->tInTeam == &*it)

View File

@ -442,7 +442,6 @@ bool oEvent::isInPunchHash(int card, int code, int time) {
return readPunchHash.count(make_pair(p1, p2)) > 0;
}
pFreePunch oEvent::addFreePunch(int time, int type, int card, bool updateStartFinish) {
if (time > 0 && isInPunchHash(card, type, time))
return 0;
@ -450,6 +449,7 @@ pFreePunch oEvent::addFreePunch(int time, int type, int card, bool updateStartFi
punches.push_back(ofp);
pFreePunch fp=&punches.back();
fp->addToEvent();
oFreePunch::rehashPunches(*this, card, fp);
insertIntoPunchHash(card, type, time);
@ -519,6 +519,7 @@ pFreePunch oEvent::addFreePunch(oFreePunch &fp) {
insertIntoPunchHash(fp.CardNo, fp.Type, fp.Time);
punches.push_back(fp);
pFreePunch fpz=&punches.back();
fpz->addToEvent();
oFreePunch::rehashPunches(*this, fp.CardNo, fpz);
if (!fpz->existInDB() && HasDBConnection) {
@ -618,43 +619,6 @@ void oEvent::getPunchesForRunner(int runnerId, bool doSort, vector<pFreePunch> &
pRunner r = getRunner(runnerId, 0);
if (r == 0)
return;
/*
// Get times for when other runners used this card
vector< pair<int, int> > times;
int refCno = r->getCardNo();
for (auto it = Runners.begin(); it != Runners.end(); ++it) {
if (it->Id == runnerId)
continue;
if (it->Card && it->getCardNo() == refCno) {
pair<int, int> t = it->Card->getTimeRange();
if (it->getStartTime() > 0)
t.first = min(it->getStartTime(), t.first);
if (it->getFinishTime() > 0)
t.second = max(it->getFinishTime(), t.second);
times.push_back(t);
}
}
for (oFreePunchList::const_iterator it = punches.begin(); it != punches.end(); ++it) {
if (it->CardNo == refCno) {
if (it->isRemoved() || it->isHiredCard())
continue;
bool other = false;
int t = it->Time;
for (size_t k = 0; k<times.size(); k++) {
if (t >= times[k].first && t <= times[k].second)
other = true;
}
if (!other)
runnerPunches.push_back(pFreePunch(&*it));
}
}
*/
//Lazy setup
oFreePunch::rehashPunches(*oe, 0, 0);

View File

@ -582,9 +582,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
}
}
// Clear markers
for (r_it=Runners.begin(); r_it != Runners.end(); ++r_it)
r_it->_objectmarker=0;
map<int, int> objectMarkers;
//List all competitors not in a team.
if (oe->hasTeam()) {
@ -596,7 +594,9 @@ void oEvent::generatePreReport(gdioutput &gdi) {
if (pc){
for(unsigned i=0;i<pc->getNumStages();i++){
pRunner r=t_it->getRunner(i);
if (r) r->_objectmarker++;
if (r) {
++objectMarkers[r->getId()];
}
}
}
}
@ -605,7 +605,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
gdi.addString("", 1, "Löpare som förekommer i mer än ett lag:");
bool any = false;
for (r_it=Runners.begin(); r_it != Runners.end(); ++r_it){
if (r_it->_objectmarker>1) {
if (objectMarkers[r_it->getId()] > 1) {
wstring name = r_it->getClass(true) + L": " + r_it->getName();
if (!r_it->getClub().empty())
name += L" (" + r_it->getClub() + L")";
@ -627,7 +627,7 @@ void oEvent::generatePreReport(gdioutput &gdi) {
for (r_it=Runners.begin(); r_it != Runners.end(); ++r_it) {
if (r_it->isRemoved())
continue;
if (r_it->_objectmarker==0){ //Only consider runners not in a team.
if (objectMarkers.count(r_it->getId()) == 0){ //Only consider runners not in a team.
gdi.addStringUT(y, x+tab[0], 0, r_it->getClass(true), tab[1]-tab[0]);
wstring name = r_it->getName();
if (!r_it->getClub().empty())

View File

@ -191,21 +191,21 @@ oRunner::~oRunner()
{
if (tInTeam){
for(unsigned i=0;i<tInTeam->Runners.size(); i++)
if (tInTeam->Runners[i] && tInTeam->Runners[i]==this)
tInTeam->Runners[i]=0;
if (tInTeam->Runners[i] && tInTeam->Runners[i]->getId() == Id)
tInTeam->Runners[i] = nullptr;
tInTeam=0;
}
for (size_t k=0;k<multiRunner.size(); k++) {
if (multiRunner[k])
multiRunner[k]->tParentRunner=0;
if (multiRunner[k] && multiRunner[k]->tParentRunner == this)
multiRunner[k]->tParentRunner = nullptr;
}
if (tParentRunner) {
for (size_t k=0;k<tParentRunner->multiRunner.size(); k++)
if (tParentRunner->multiRunner[k] == this)
tParentRunner->multiRunner[k]=0;
tParentRunner->multiRunner[k] = nullptr;
}
delete tAdaptedCourse;
@ -2200,6 +2200,7 @@ void oRunner::updateStartNo(int no) {
tInTeam->synchronize(true);
for (pRunner r : tInTeam->Runners) {
if (r)
r->synchronize(true);
}
}
@ -2302,12 +2303,14 @@ void oRunner::setCardNo(int cno, bool matchCard, bool updateFromDatabase)
int oldNo = getCardNo();
cardNumber = cno;
if (oe->cardToRunnerHash && cno != 0 && !isTemporaryObject) {
if (oe->cardToRunnerHash && cno != 0 && isAddedToEvent() && !isTemporaryObject) {
oe->cardToRunnerHash->emplace(cno, this);
}
if (isAddedToEvent()) {
oFreePunch::rehashPunches(*oe, oldNo, 0);
oFreePunch::rehashPunches(*oe, cardNumber, 0);
}
if (matchCard && !Card) {
pCard c = oe->getCardByNumber(cno);
@ -2862,21 +2865,23 @@ pRunner oEvent::getRunnerByBibOrStartNo(const wstring &bib, bool findWithoutCard
if (t.getStartNo()==sno || stringMatch(t.getBib(), bib)) {
if (!findWithoutCardNo) {
for (int leg=0; leg<t.getNumRunners(); leg++) {
if (t.Runners[leg] && t.Runners[leg]->getCardNo() > 0 && t.Runners[leg]->getStatus()==StatusUnknown)
return t.Runners[leg];
pRunner r = t.Runners[leg];
if (r && r->getCardNo() > 0 && r->getStatus()==StatusUnknown)
return r;
}
}
else {
for (int leg=0; leg<t.getNumRunners(); leg++) {
if (t.Runners[leg] && t.Runners[leg]->getCardNo() == 0 && t.Runners[leg]->needNoCard() == false)
return t.Runners[leg];
pRunner r = t.Runners[leg];
if (r && r->getCardNo() == 0 && r->needNoCard() == false)
return r;
}
}
}
}
}
}
return 0;
return nullptr;
}
pRunner oEvent::getRunnerByName(const wstring &pname, const wstring &pclub) const
@ -3027,7 +3032,7 @@ void oRunner::createMultiRunner(bool createMaster, bool sync)
{
if (tDuplicateLeg)
return; //Never allow chains.
bool allowCreate = true;
if (multiRunnerId.size()>0) {
multiRunner.resize(multiRunnerId.size() - 1);
for (size_t k=0;k<multiRunner.size();k++) {
@ -3044,8 +3049,10 @@ void oRunner::createMultiRunner(bool createMaster, bool sync)
if (multiRunner[k]->Id != multiRunnerId[k])
markForCorrection();
}
else if (multiRunnerId[k]>0)
else if (multiRunnerId[k] > 0) {
markForCorrection();
allowCreate = false;
}
assert(multiRunner[k]);
}
@ -3072,19 +3079,20 @@ void oRunner::createMultiRunner(bool createMaster, bool sync)
multiRunner[k]->tParentRunner = 0;
if (multiRunner[k]->tInTeam && size_t(multiRunner[k]->tLeg)<multiRunner[k]->tInTeam->Runners.size()) {
if (multiRunner[k]->tInTeam->Runners[multiRunner[k]->tLeg] == multiRunner[k])
multiRunner[k]->tInTeam->Runners[multiRunner[k]->tLeg] = 0;
multiRunner[k]->tInTeam->Runners[multiRunner[k]->tLeg] = nullptr;
}
}
}
multiRunner.resize(ndup-1);
for (int k = 1; k < ndup; k++) {
if (!multiRunner[k-1]) {
if (!multiRunner[k - 1] && allowCreate) {
update = true;
multiRunner[k - 1] = oe->addRunner(sName, getClubId(),
getClassId(false), 0, 0, false);
multiRunner[k - 1]->tDuplicateLeg = k;
multiRunner[k - 1]->tParentRunner = this;
multiRunner[k - 1]->cardNumber = 0;
if (sync)
multiRunner[k - 1]->synchronize();
@ -3111,6 +3119,13 @@ pRunner oRunner::getPredecessor() const
}
bool oRunner::apply(bool sync, pRunner src, bool setTmpOnly) {
for (size_t k = 0; k < multiRunner.size(); k++) {
if (multiRunner[k] && multiRunner[k]->isRemoved()) {
multiRunner[k]->tParentRunner = nullptr;
multiRunner[k] = nullptr;
}
}
createMultiRunner(false, sync);
if (sync) {
for (size_t k = 0; k < multiRunner.size(); k++) {

View File

@ -159,7 +159,7 @@ string oTeam::getRunners() const
for(m=0;m<Runners.size();m++){
if (Runners[m]){
sprintf_s(bf, 16, "%d;", Runners[m]->Id);
sprintf_s(bf, 16, "%d;", Runners[m]->getId());
str+=bf;
}
else str+="0;";
@ -185,39 +185,42 @@ void oTeam::decodeRunners(const string &rns, vector<int> &rid)
}
}
void oTeam::importRunners(const vector<int> &rns)
{
void oTeam::importRunners(const vector<int> &rns) {
Runners.resize(rns.size());
for (size_t n=0;n<rns.size(); n++) {
if (rns[n] > 0)
Runners[n] = oe->getRunner(rns[n], 0);
else
Runners[n] = 0;
Runners[n] = nullptr;
pRunner r = Runners[n];
if (r) {
r->tInTeam = this;
r->tLeg = n;
}
}
}
void oTeam::importRunners(const vector<pRunner> &rns)
{
// Unlink old runners
for (size_t k = rns.size(); k<Runners.size(); k++) {
if (Runners[k] && Runners[k]->tInTeam == this) {
Runners[k]->tInTeam = 0;
Runners[k]->tLeg = 0;
for (size_t k = 0; k<Runners.size(); k++) {
pRunner r = Runners[k];
if (r && r->tInTeam == this) {
r->tInTeam = 0;
r->tLeg = 0;
}
}
Runners.resize(rns.size());
for (size_t n = 0; n < rns.size(); n++) {
if (Runners[n] && rns[n] != Runners[n]) {
if (Runners[n]->tInTeam == this) {
Runners[n]->tInTeam = 0;
Runners[n]->tLeg = 0;
}
}
Runners[n] = rns[n];
if (rns[n] && isAddedToEvent()) {
rns[n]->tInTeam = this;
rns[n]->tLeg = n;
}
}
}
void oEvent::removeTeam(int Id)
{
@ -249,9 +252,10 @@ void oTeam::setRunner(unsigned i, pRunner r, bool sync)
return;
int oldRaceId = 0;
if (Runners[i]) {
oldRaceId = Runners[i]->getDCI().getInt("RaceId");
Runners[i]->getDI().setInt("RaceId", 0);
pRunner tr = Runners[i];
if (tr) {
oldRaceId = tr->getDCI().getInt("RaceId");
tr->getDI().setInt("RaceId", 0);
}
setRunnerInternal(i, r);
@ -293,16 +297,17 @@ void oTeam::setRunnerInternal(int k, pRunner r)
return;
}
if (Runners[k]) {
assert(Runners[k]->tInTeam == 0 || Runners[k]->tInTeam == this);
Runners[k]->tInTeam = 0;
Runners[k]->tLeg = 0;
pRunner rOld = Runners[k];
if (rOld) {
assert(rOld->tInTeam == 0 || rOld->tInTeam == this);
rOld->tInTeam = 0;
rOld->tLeg = 0;
}
// Reset old team
if (r && r->tInTeam) {
if (r->tInTeam->Runners[r->tLeg] != 0) {
r->tInTeam->Runners[r->tLeg] = 0;
if (r->tInTeam->Runners[r->tLeg]) {
r->tInTeam->Runners[r->tLeg] = nullptr;
r->tInTeam->updateChanged();
if (r->tInTeam != this)
r->tInTeam->synchronize(true);
@ -311,11 +316,11 @@ void oTeam::setRunnerInternal(int k, pRunner r)
Runners[k] = r;
if (Runners[k]) {
Runners[k]->tInTeam = this;
Runners[k]->tLeg = k;
if (Class && (Runners[k]->Class==nullptr || Class->getLegType(k) != LTGroup))
Runners[k]->setClassId(getClassId(false), false);
if (r) {
r->tInTeam = this;
r->tLeg = k;
if (Class && (r->Class==nullptr || Class->getLegType(k) != LTGroup))
r->setClassId(getClassId(false), false);
}
updateChanged();
}
@ -764,11 +769,9 @@ bool oTeam::compareSNO(const oTeam &a, const oTeam &b) {
b.sName.c_str(), b.sName.length()) == CSTR_LESS_THAN;
}
bool oTeam::isRunnerUsed(int Id) const
{
bool oTeam::isRunnerUsed(int rId) const {
for(unsigned i=0;i<Runners.size(); i++) {
if (Runners[i] && Runners[i]->Id==Id)
if (Runners[i] && Runners[i]->getId() == rId)
return true;
}
return false;
@ -830,13 +833,14 @@ void oTeam::quickApply() {
if (Class && Runners.size()!=size_t(Class->getNumStages())) {
for (size_t k = Class->getNumStages(); k < Runners.size(); k++) {
if (Runners[k] && Runners[k]->tInTeam) {
Runners[k]->tInTeam = 0;
Runners[k]->tLeg = 0;
Runners[k]->tLegEquClass = 0;
if (Runners[k]->Class == Class)
Runners[k]->Class = 0;
Runners[k]->updateChanged();
pRunner tr = Runners[k];
if (tr && tr->tInTeam) {
tr->tInTeam = 0;
tr->tLeg = 0;
tr->tLegEquClass = 0;
if (tr->Class == Class)
tr->Class = 0;
tr->updateChanged();
}
}
Runners.resize(Class->getNumStages());
@ -844,8 +848,16 @@ void oTeam::quickApply() {
for (size_t i = 0; i < Runners.size(); i++) {
if (Runners[i]) {
if (Runners[i]->tInTeam && Runners[i]->tInTeam!=this) {
Runners[i]->tInTeam->correctRemove(Runners[i]);
if (Runners[i]->isRemoved()) {
// Could happen for database not in sync / invalid manual modification
Runners[i]->tInTeam = nullptr;
Runners[i]->tLeg = 0;
Runners[i] = nullptr;
}
auto tit = Runners[i]->tInTeam;
if (tit && tit!=this) {
tit->correctRemove(Runners[i]);
}
Runners[i]->tInTeam=this;
Runners[i]->tLeg=i;
@ -853,8 +865,6 @@ void oTeam::quickApply() {
}
}
bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
if (unsigned(status) >= 100)
status = StatusUnknown; // Enforce correct status
@ -866,13 +876,14 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
if (Class && Runners.size()!=size_t(Class->getNumStages())) {
for (size_t k = Class->getNumStages(); k < Runners.size(); k++) {
if (Runners[k] && Runners[k]->tInTeam) {
Runners[k]->tInTeam = 0;
Runners[k]->tLeg = 0;
Runners[k]->tLegEquClass = 0;
if (Runners[k]->Class == Class)
Runners[k]->Class = 0;
Runners[k]->updateChanged();
auto tr = Runners[k];
if (tr && tr->tInTeam) {
tr->tInTeam = nullptr;
tr->tLeg = 0;
tr->tLegEquClass = 0;
if (tr->Class == Class)
tr->Class = 0;
tr->updateChanged();
}
}
Runners.resize(Class->getNumStages());
@ -881,7 +892,15 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
BibMode bibMode = (BibMode)-1;
tNumRestarts = 0;
vector<int> availableStartTimes;
for (size_t i=0;i<Runners.size(); i++) {
for (size_t i_c=0;i_c<Runners.size(); i_c++) {
const size_t i = i_c;
if (Runners[i] && Runners[i]->isRemoved()) {
// Could happen for database not in sync / invalid manual modification
Runners[i]->tInTeam = nullptr;
Runners[i]->tLeg = 0;
Runners[i] = nullptr;
}
if (!sync && i>0 && source!=0 && Runners[i-1] == source)
return true;
if (!Runners[i] && Class) {
@ -899,14 +918,15 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
if (lr == i && Runners[i]->tParentRunner) {
pRunner parent = Runners[i]->tParentRunner;
for (size_t kk = 0; kk<parent->multiRunner.size(); ++kk) {
if (parent->multiRunner[kk] == Runners[i]) {
if (Runners[i] == parent->multiRunner[kk]) {
pRunner tr = Runners[i];
parent->multiRunner.erase(parent->multiRunner.begin() + kk);
Runners[i]->tParentRunner = 0;
Runners[i]->tDuplicateLeg = 0;
tr->tParentRunner = 0;
tr->tDuplicateLeg = 0;
parent->markForCorrection();
parent->updateChanged();
Runners[i]->markForCorrection();
Runners[i]->updateChanged();
tr->markForCorrection();
tr->updateChanged();
break;
}
}
@ -918,65 +938,66 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
if (Runners[i]) {
for (size_t k=0;k<i; k++)
if (Runners[i] == Runners[k])
Runners[i] = 0;
Runners[i] = nullptr;
}
if (Runners[i]) {
pClass actualClass = Runners[i]->getClassRef(true);
pRunner tr = Runners[i];
pClass actualClass = tr->getClassRef(true);
if (actualClass == nullptr)
actualClass = Class;
if (Runners[i]->tInTeam && Runners[i]->tInTeam!=this) {
Runners[i]->tInTeam->correctRemove(Runners[i]);
if (tr->tInTeam && tr->tInTeam!=this) {
tr->tInTeam->correctRemove(tr);
}
//assert(Runners[i]->tInTeam==0 || Runners[i]->tInTeam==this);
Runners[i]->tInTeam = this;
Runners[i]->tLeg = i;
tr->tInTeam = this;
tr->tLeg = i;
if (Class) {
int unused;
Class->splitLegNumberParallel(i, Runners[i]->tLegEquClass, unused);
Class->splitLegNumberParallel(i, tr->tLegEquClass, unused);
}
else {
Runners[i]->tLegEquClass = i;
tr->tLegEquClass = i;
}
if (actualClass == Class)
Runners[i]->setStartNo(StartNo, setTmpOnly);
if (!bib.empty() && Runners[i]->isChanged()) {
tr->setStartNo(StartNo, setTmpOnly);
if (!bib.empty() && tr->isChanged()) {
if (bibMode == -1 && Class)
bibMode = Class->getBibMode();
if (bibMode == BibSame)
Runners[i]->setBib(bib, 0, false, setTmpOnly);
tr->setBib(bib, 0, false, setTmpOnly);
else if (bibMode == BibAdd) {
wchar_t pattern[32], bf[32];
int ibib = oClass::extractBibPattern(bib, pattern) + i;
swprintf_s(bf, pattern, ibib);
Runners[i]->setBib(bf, 0, false, setTmpOnly);
tr->setBib(bf, 0, false, setTmpOnly);
}
else if (bibMode == BibLeg) {
wstring rbib = bib + L"-" + Class->getLegNumber(i);
Runners[i]->setBib(rbib, 0, false, setTmpOnly);
tr->setBib(rbib, 0, false, setTmpOnly);
}
}
LegTypes legType = Class ? Class->getLegType(i) : LTIgnore;
if (Runners[i]->Class!=Class && legType != LTGroup) {
Runners[i]->Class=Class;
Runners[i]->updateChanged();
if (tr->Class!=Class && legType != LTGroup) {
tr->Class=Class;
tr->updateChanged();
}
Runners[i]->tNeedNoCard=false;
tr->tNeedNoCard=false;
if (Class) {
pClass pc=Class;
//Ignored runners need no SI-card (used by SI assign function)
if (legType == LTIgnore) {
Runners[i]->tNeedNoCard=true;
tr->tNeedNoCard=true;
if (lastStatus != StatusUnknown) {
Runners[i]->setStatus(max(Runners[i]->tStatus, lastStatus), false, setTmpOnly);
tr->setStatus(max(tr->tStatus, lastStatus), false, setTmpOnly);
}
}
else
lastStatus = Runners[i]->getStatus();
lastStatus = tr->getStatus();
StartTypes st = actualClass == pc ? pc->getStartType(i) : actualClass->getStartType(0);
LegTypes lt = legType;
@ -987,27 +1008,27 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
}
if (lt==LTIgnore || lt==LTExtra) {
if (st != STDrawn)
Runners[i]->setStartTime(lastStartTime, false, setTmpOnly);
Runners[i]->tUseStartPunch = (st == STDrawn);
tr->setStartTime(lastStartTime, false, setTmpOnly);
tr->tUseStartPunch = (st == STDrawn);
}
else { //Calculate start time.
switch (st) {
case STDrawn: //Do nothing
if (lt==LTParallel || lt==LTParallelOptional) {
Runners[i]->setStartTime(lastStartTime, false, setTmpOnly);
Runners[i]->tUseStartPunch=false;
tr->setStartTime(lastStartTime, false, setTmpOnly);
tr->tUseStartPunch=false;
}
else
lastStartTime = Runners[i]->getStartTime();
lastStartTime = tr->getStartTime();
break;
case STTime: {
bool prs = false;
if (Runners[i] && Runners[i]->Card && freeStart) {
pCourse crs = Runners[i]->getCourse(false);
if (tr && tr->Card && freeStart) {
pCourse crs = tr->getCourse(false);
int startType = crs ? crs->getStartPunchType() : oPunch::PunchStart;
oPunch *pnc = Runners[i]->Card->getPunchByType(startType);
oPunch *pnc = tr->Card->getPunchByType(startType);
if (pnc && pnc->getAdjustedTime() > 0) {
prs = true;
lastStartTime = pnc->getAdjustedTime();
@ -1020,8 +1041,8 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
else
lastStartTime = actualClass->getStartData(0); // Qualification/final classes
}
Runners[i]->setStartTime(lastStartTime, false, setTmpOnly);
Runners[i]->tUseStartPunch=false;
tr->setStartTime(lastStartTime, false, setTmpOnly);
tr->tUseStartPunch=false;
}
}
break;
@ -1080,19 +1101,19 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
int rope=pc->getRopeTime(i);
if (((restart > 0 && rope > 0 && (ft == 0 || ft > rope)) || (ft == 0 && restart > 0)) &&
!preventRestart() && !Runners[i]->preventRestart()) {
!preventRestart() && !tr->preventRestart()) {
ft = restart; //Runner in restart
tNumRestarts++;
}
if (ft > 0)
Runners[i]->setStartTime(ft, false, setTmpOnly);
Runners[i]->tUseStartPunch=false;
tr->setStartTime(ft, false, setTmpOnly);
tr->tUseStartPunch=false;
lastStartTime=ft;
}
else {//The else below should only be run by mistake (for an incomplete team)
Runners[i]->setStartTime(Class->getRestartTime(i), false, setTmpOnly);
Runners[i]->tUseStartPunch=false;
tr->setStartTime(Class->getRestartTime(i), false, setTmpOnly);
tr->tUseStartPunch=false;
}
}
break;
@ -1121,7 +1142,7 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
}
if (restart > 0 && rope > 0 && (lastStartTime > rope) &&
!preventRestart() && !Runners[i]->preventRestart()) {
!preventRestart() && !tr->preventRestart()) {
lastStartTime = restart; //Runner in restart
tNumRestarts++;
}
@ -1140,7 +1161,7 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
setStart = true;
}
if (Runners[i]->getFinishTime()>0) {
if (tr->getFinishTime()>0) {
setStart = true;
if (lastStartTime == 0)
lastStartTime = pc->getRestartTime(i);
@ -1151,15 +1172,15 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
else
lastStartTime=0;
Runners[i]->tUseStartPunch=false;
Runners[i]->setStartTime(lastStartTime, false, setTmpOnly);
tr->tUseStartPunch=false;
tr->setStartTime(lastStartTime, false, setTmpOnly);
}
break;
}
}
size_t nextNonPar = i+1;
while (nextNonPar < Runners.size() && pc->isOptional(nextNonPar) && Runners[nextNonPar] == 0)
while (nextNonPar < Runners.size() && pc->isOptional(nextNonPar) && !Runners[nextNonPar])
nextNonPar++;
int nextBaseLeg = nextNonPar;
@ -1168,11 +1189,11 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
// Extra finish time is used to split extra legs to parallel legs
if (lt == LTExtra || pc->getLegType(i+1) == LTExtra) {
if (Runners[i]->getFinishTime()>0) {
if (tr->getFinishTime()>0) {
if (extraFinishTime <= 0)
extraFinishTime = Runners[i]->getFinishTime();
extraFinishTime = tr->getFinishTime();
else
extraFinishTime = min(extraFinishTime, Runners[i]->getFinishTime());
extraFinishTime = min(extraFinishTime, tr->getFinishTime());
}
}
else
@ -1181,7 +1202,7 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
//Add available start times for parallel
if (nextNonPar < Runners.size()) {
st=pc->getStartType(nextNonPar);
int finishTime = Runners[i]->getFinishTime();
int finishTime = tr->getFinishTime();
if (lt == LTExtra)
finishTime = extraFinishTime;
@ -1207,7 +1228,7 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
}
}
if (sync)
Runners[i]->synchronize(true);
tr->synchronize(true);
}
}
@ -1259,8 +1280,8 @@ void oTeam::evaluate(bool sync)
void oTeam::correctRemove(pRunner r) {
for(unsigned i=0;i<Runners.size(); i++)
if (r != 0 && Runners[i] == r) {
Runners[i] = 0;
r->tInTeam = 0;
Runners[i] = nullptr;
r->tInTeam = nullptr;
r->tLeg = 0;
r->tLegEquClass = 0;
correctionNeeded = true;
@ -1454,7 +1475,7 @@ void oTeam::fillSpeakerObject(int leg, int courseControlId, int previousControlC
}
}
map<int, int>::iterator mapit=Runners[leg]->priority.find(courseControlId);
auto mapit = Runners[leg]->priority.find(courseControlId);
if (mapit != Runners[leg]->priority.end())
spk.priority = mapit->second;
else
@ -1502,8 +1523,7 @@ void oTeam::fillSpeakerObject(int leg, int courseControlId, int previousControlC
spk.status = spk.finishStatus;
}
int oTeam::getTimeAfter(int leg) const
{
int oTeam::getTimeAfter(int leg) const {
if (leg == -1)
leg = Runners.size() - 1;
@ -1576,8 +1596,7 @@ oDataContainer &oTeam::getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &s
return *oe->oTeamData;
}
pRunner oTeam::getRunner(unsigned leg) const
{
pRunner oTeam::getRunner(unsigned leg) const {
if (leg==-1)
leg=Runners.size()-1;
@ -1927,7 +1946,6 @@ bool oTeam::inputData(int id, const wstring &input,
setRunner(ix, r, true);
output = r->getName();
}
}
}
}
@ -2138,7 +2156,7 @@ bool oTeam::checkValdParSetup() {
// Move to where a runner is needed
Runners[k] = Runners[k+m];
Runners[k]->tLeg = k;
Runners[k+m] = 0;
Runners[k+m] = nullptr;
updateChanged();
cor = true;
k+=m;

View File

@ -54,7 +54,7 @@ private:
void propagateClub();
protected:
//pRunner Runners[maxRunnersTeam];
vector<pRunner> Runners;
void setRunnerInternal(int k, pRunner r);

View File

@ -160,15 +160,17 @@ pTeam oEvent::addTeam(const wstring &pname, int ClubId, int ClassId)
bibStartNoToRunnerTeam.clear();
Teams.push_back(t);
teamById[t.Id] = &Teams.back();
pTeam pt = &Teams.back();
pt->addToEvent();
teamById[t.Id] = pt;
oe->updateTabs();
Teams.back().StartNo = ++nextFreeStartNo; // Need not be unique
Teams.back().getEntryDate(false);// Store entry time
Teams.back().apply(false, 0, false);
Teams.back().updateChanged();
return &Teams.back();
pt->StartNo = ++nextFreeStartNo; // Need not be unique
pt->getEntryDate(false);// Store entry time
pt->apply(false, 0, false);
pt->updateChanged();
return pt;
}
pTeam oEvent::addTeam(const oTeam &t, bool autoAssignStartNo) {
@ -181,6 +183,15 @@ pTeam oEvent::addTeam(const oTeam &t, bool autoAssignStartNo) {
Teams.push_back(t);
pTeam pt = &Teams.back();
pt->addToEvent();
for (size_t i = 0; i < pt->Runners.size(); i++) {
if (pt->Runners[i]) {
assert(pt->Runners[i]->tInTeam == nullptr || pt->Runners[i]->tInTeam == &t);
pt->Runners[i]->tInTeam = pt;
}
}
teamById[pt->Id] = pt;
if (pt->StartNo == 0 && autoAssignStartNo) {
@ -306,10 +317,10 @@ bool oTeam::matchTeam(int number, const wchar_t *s_lc) const
void oEvent::fillPredefinedCmp(gdioutput &gdi, const string &name) const
{
bool hasPatrol = getMeOSFeatures().hasFeature(MeOSFeatures::Patrol);
bool hasMulti = getMeOSFeatures().hasFeature(MeOSFeatures::MultipleRaces);
bool hasRelay = getMeOSFeatures().hasFeature(MeOSFeatures::Relay);
bool hasForked = getMeOSFeatures().hasFeature(MeOSFeatures::ForkedIndividual);
bool hasPatrol = true;// getMeOSFeatures().hasFeature(MeOSFeatures::Patrol);
bool hasMulti = true;//getMeOSFeatures().hasFeature(MeOSFeatures::MultipleRaces);
bool hasRelay = true;//getMeOSFeatures().hasFeature(MeOSFeatures::Relay);
bool hasForked = true;//getMeOSFeatures().hasFeature(MeOSFeatures::ForkedIndividual);
gdi.clearList(name);
gdi.addItem(name, lang.tl("Endast en bana"), PNoMulti);
@ -328,8 +339,10 @@ void oEvent::fillPredefinedCmp(gdioutput &gdi, const string &name) const
}
if (hasRelay)
gdi.addItem(name, lang.tl("Stafett"), PRelay);
if (hasMulti)
if (hasMulti) {
gdi.addItem(name, lang.tl("Tvåmannastafett"), PTwinRelay);
gdi.addItem(name, lang.tl("Flera lopp i valfri ordning"), PTwoRacesNoOrder);
}
if (hasRelay)
gdi.addItem(name, lang.tl("Extralöparstafett"), PYouthRelay);
}
@ -386,6 +399,11 @@ void oEvent::setupRelayInfo(PredefinedTypes type, bool &useNLeg, bool &useStart)
useStart = true;
break;
case PTwoRacesNoOrder:
useStart = false;
useNLeg = true;
break;
default:
throw std::exception("Bad setup number");
}
@ -424,7 +442,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
if (crs) {
cls.addStageCourse(0, crsId, -1);
}
getMeOSFeatures().useFeature(MeOSFeatures::ForkedIndividual, true, *this);
oe->synchronize(true);
break;
case PPoolDrawn:
@ -439,6 +458,9 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
if (crs) {
cls.addStageCourse(0, crsId, -1);
}
getMeOSFeatures().useFeature(MeOSFeatures::ForkedIndividual, true, *this);
oe->synchronize(true);
break;
case PPatrol:
@ -460,6 +482,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
cls.addStageCourse(1, crsId, -1);
}
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::Patrol, true, *this);
oe->synchronize(true);
break;
case PPatrolOptional:
@ -481,6 +505,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
cls.addStageCourse(1, crsId, -1);
}
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::Patrol, true, *this);
oe->synchronize(true);
break;
case PPatrolOneSI:
@ -503,6 +529,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
}
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::Patrol, true, *this);
oe->synchronize(true);
break;
case PRelay:
@ -521,6 +549,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
cls.setRopeTime(k, L"-");
}
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::Relay, true, *this);
oe->synchronize(true);
break;
case PTwinRelay:
@ -543,6 +573,27 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
}
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::Relay, true, *this);
getMeOSFeatures().useFeature(MeOSFeatures::MultipleRaces, true, *this);
oe->synchronize(true);
oe->synchronize(true);
break;
case PTwoRacesNoOrder:
cls.setNumStages(nleg);
for (int k = 0; k<nleg; k++) {
cls.setLegType(k, LTSum);
cls.setStartType(k, STDrawn, false);
cls.setStartData(k, L"-");
cls.setRestartTime(k, L"-");
cls.setRopeTime(k, L"-");
if (k > 0)
cls.setLegRunner(k, 0);
}
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::MultipleRaces, true, *this);
oe->synchronize(true);
break;
case PYouthRelay:
@ -577,6 +628,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
}
}
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::Relay, true, *this);
oe->synchronize(true);
break;
case PHunting: {
@ -595,6 +648,8 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
cls.setRopeTime(1, formatTimeHMS(t+1800));
cls.setLegRunner(1, 0);
cls.setCoursePool(false);
getMeOSFeatures().useFeature(MeOSFeatures::Relay, true, *this);
oe->synchronize(true);
break;
}
default:

View File

@ -1248,6 +1248,7 @@ X (Y deltagare, grupp Z, W) = X (Y deltagare, grupp Z, W)
X har startat = X har startat
X kontroller = X kontroller
X meter = X meter
X m = X m
X poäng fattas = X poäng fattas
X rader kunde inte raderas = X rad(er) kunde inte raderas
X senaste = X senaste
@ -2440,3 +2441,6 @@ Kunde inte öppna databasen (X) = Kunde inte öppna databasen (X)
Kunde inte ladda upp löpardatabasen (X) = Kunde inte ladda upp löpardatabasen (X)
Runner check time = Checktid
ClassNumEntries = Antal anmälda i klassen
Flera lopp i valfri ordning = Flera lopp i valfri ordning
Knockout sammanställning = Knockout sammanställning
X anmälda = X anmälda