MeOS version 3.5.795.

This commit is contained in:
erikmelin 2017-10-29 18:48:54 +01:00
parent a13eef041a
commit 89eec34633
77 changed files with 2792 additions and 628 deletions

View File

@ -189,6 +189,7 @@ static void getStyle(const map< pair<gdiFonts, string>, pair<string, string> > &
bool gdioutput::writeHTML(const wstring &file, const wstring &title, int refreshTimeOut) const bool gdioutput::writeHTML(const wstring &file, const wstring &title, int refreshTimeOut) const
{ {
checkWriteAccess(file);
ofstream fout(file.c_str()); ofstream fout(file.c_str());
if (fout.bad()) if (fout.bad())
@ -294,6 +295,7 @@ bool sortTL_X(const TextInfo *a, const TextInfo *b)
bool gdioutput::writeTableHTML(const wstring &file, bool gdioutput::writeTableHTML(const wstring &file,
const wstring &title, int refreshTimeOut) const const wstring &title, int refreshTimeOut) const
{ {
checkWriteAccess(file);
ofstream fout(file.c_str()); ofstream fout(file.c_str());
if (fout.bad()) if (fout.bad())

92
code/RestService.cpp Normal file
View File

@ -0,0 +1,92 @@
#include "stdafx.h"
#include "RestService.h"
#include "meos_util.h"
#include "restserver.h"
int AutomaticCB(gdioutput *gdi, int type, void *data);
RestService::RestService() : AutoMachine("RestService"), port(-1) {
}
RestService::~RestService() {
if (server) {
server->stop();
RestServer::remove(server);
}
}
void RestService::save(oEvent &oe, gdioutput &gdi) {
if (!server)
server = RestServer::construct();
int port = gdi.getTextNo("Port");
if (port > 0 && port < 65536)
server->startService(port);
else
throw std::exception("Invalid port number");
}
void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
if (port == -1)
port = oe.getPropertyInt("ServicePort", 2009);
settingsTitle(gdi, "MeOS Informationsserver REST-API");
startCancelInterval(gdi, "Save", created, IntervalNone, L"");
if (!server)
gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"Testa genom http://localhost:[PORT]/meos");
else
gdi.addString("", 0, "Server startad på X#" + itos(port));
gdi.popX();
gdi.addString("", 10, "help:rest");
}
void RestService::status(gdioutput &gdi) {
gdi.pushX();
gdi.addString("", 1, name);
/*if (!baseFile.empty()) {
gdi.fillRight();
gdi.pushX();
gdi.addString("", 0, L"Destination: X#" + baseFile);
if (interval>0) {
gdi.popX();
gdi.dropLine(1);
gdi.addString("", 0, "Säkerhetskopierar om: ");
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign, (GetTickCount() - timeout) / 1000);
}
gdi.popX();
}*/
if (server) {
gdi.addString("", 0, "Server startad på port X#" + itos(port));
RestServer::Statistics rs;
server->getStatistics(rs);
gdi.addString("", 0, "Antal förfrågningar: X#" + itos(rs.numRequests));
gdi.addString("", 0, "Genomsnittlig svarstid: X ms#" + itos(rs.averageResponseTime));
gdi.addString("", 0, "Längsta svarstid: X ms#" + itos(rs.maxResponseTime));
}
gdi.dropLine(2);
gdi.fillRight();
gdi.addButton("Stop", "Stoppa automaten", AutomaticCB).setExtra(getId());
gdi.fillDown();
gdi.addButton("InfoService", "Inställningar...", AutomaticCB).setExtra(getId());
gdi.popX();
}
void RestService::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
}
void RestService::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
if (type == GUI_BUTTON) {
ButtonInfo &bi = static_cast<ButtonInfo&>(info);
}
}

48
code/RestService.h Normal file
View File

@ -0,0 +1,48 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2017 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#pragma once
#include "TabAuto.h"
#include <memory>
class RestServer;
class RestService :
public AutoMachine, GuiHandler
{
int port;
shared_ptr<RestServer> server;
public:
void save(oEvent &oe, gdioutput &gdi) override;
void settings(gdioutput &gdi, oEvent &oe, bool created) override;
RestService *clone() const override { return new RestService(*this); }
void status(gdioutput &gdi) override;
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) override;
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) override;
RestService();
~RestService();
};

View File

@ -2140,13 +2140,19 @@ void SportIdent::getInfoString(const wstring &com, vector<wstring> &infov)
} }
} }
static string formatTimeN(int t) {
const wstring &wt = formatTime(t);
string nt(wt.begin(), wt.end());
return nt;
}
vector<string> SICard::codeLogData(int row) const vector<string> SICard::codeLogData(int row) const
{ {
vector<string> log; vector<string> log;
log.push_back(itos(row)); log.push_back(itos(row));
if (readOutTime[0] == 0) if (readOutTime[0] == 0)
log.push_back(getLocalTime()); log.push_back(getLocalTimeN());
else else
log.push_back(readOutTime); log.push_back(readOutTime);
log.push_back(itos(CardNumber)); log.push_back(itos(CardNumber));

View File

@ -35,6 +35,7 @@
#include "classconfiginfo.h" #include "classconfiginfo.h"
#include "onlineresults.h" #include "onlineresults.h"
#include "onlineinput.h" #include "onlineinput.h"
#include "RestService.h"
#include "TabAuto.h" #include "TabAuto.h"
#include "TabSI.h" #include "TabSI.h"
@ -78,6 +79,8 @@ AutoMachine* AutoMachine::construct(Machines ms) {
return new OnlineResults(); return new OnlineResults();
case mSaveBackup: case mSaveBackup:
return new SaveMachine(); return new SaveMachine();
case mInfoService:
return new RestService();
} }
throw meosException("Invalid machine"); throw meosException("Invalid machine");
} }
@ -316,6 +319,9 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
SaveMachine *sm=dynamic_cast<SaveMachine*>(getMachine(bu.getExtraInt())); SaveMachine *sm=dynamic_cast<SaveMachine*>(getMachine(bu.getExtraInt()));
settings(gdi, sm, mSaveBackup); settings(gdi, sm, mSaveBackup);
} }
else if (bu.id == "InfoService") {
settings(gdi, getMachine(bu.getExtraInt()), mInfoService);
}
else if (bu.id=="StartResult") { else if (bu.id=="StartResult") {
#ifndef MEOSDB #ifndef MEOSDB
wstring minute=gdi.getText("Interval"); wstring minute=gdi.getText("Interval");
@ -602,12 +608,14 @@ bool TabAuto::loadPage(gdioutput &gdi)
gdi.addButton("OnlineInput", "Inmatning online", AutomaticCB, "Hämta stämplingar m.m. från nätet"); gdi.addButton("OnlineInput", "Inmatning online", AutomaticCB, "Hämta stämplingar m.m. från nätet");
gdi.popX(); gdi.popX();
gdi.dropLine(2.5); gdi.dropLine(2.5);
gdi.addButton("Splits", "Sträcktider (WinSplits)", AutomaticCB, "Spara sträcktider till en fil för automatisk synkronisering med WinSplits"); gdi.addButton("SaveBackup", "Säkerhetskopiering", AutomaticCB);
gdi.addButton("Prewarning", "Förvarningsröst", AutomaticCB, "tooltip:voice"); gdi.addButton("InfoService", "Informationsserver", AutomaticCB);
gdi.addButton("Punches", "Stämplingstest", AutomaticCB, "Simulera inläsning av stämplar"); gdi.addButton("Punches", "Stämplingstest", AutomaticCB, "Simulera inläsning av stämplar");
gdi.popX(); gdi.popX();
gdi.dropLine(2.5); gdi.dropLine(2.5);
gdi.addButton("SaveBackup", "Säkerhetskopiering", AutomaticCB); gdi.addButton("Splits", "Sträcktider (WinSplits)", AutomaticCB, "Spara sträcktider till en fil för automatisk synkronisering med WinSplits");
gdi.addButton("Prewarning", "Förvarningsröst", AutomaticCB, "tooltip:voice");
gdi.fillDown(); gdi.fillDown();
gdi.dropLine(3); gdi.dropLine(3);
@ -682,7 +690,7 @@ void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, bool c
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) { void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
settingsTitle(gdi, "Resultatutskrift / export"); settingsTitle(gdi, "Resultatutskrift / export");
wstring time=created ? L"10:00" : getTimeMSW(interval); wstring time=created ? L"10:00" : getTimeMS(interval);
startCancelInterval(gdi, "StartResult", created, IntervalMinute, time); startCancelInterval(gdi, "StartResult", created, IntervalMinute, time);
if (created) { if (created) {
@ -1097,7 +1105,7 @@ void SaveMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
void SaveMachine::settings(gdioutput &gdi, oEvent &oe, bool created) { void SaveMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
settingsTitle(gdi, "Säkerhetskopiering"); settingsTitle(gdi, "Säkerhetskopiering");
wstring time=created ? L"10:00" : getTimeMSW(interval); wstring time=created ? L"10:00" : getTimeMS(interval);
startCancelInterval(gdi, "StartBackup", created, IntervalMinute, time); startCancelInterval(gdi, "StartBackup", created, IntervalMinute, time);
int cx = gdi.getCX(); int cx = gdi.getCX();

View File

@ -43,6 +43,7 @@ enum Machines {
mOnlineResults, mOnlineResults,
mOnlineInput, mOnlineInput,
mSaveBackup, mSaveBackup,
mInfoService,
}; };
class AutoMachine class AutoMachine

View File

@ -69,6 +69,7 @@ void TabClass::clearCompetitionData() {
storedPredefined = oEvent::PredefinedTypes(-1); storedPredefined = oEvent::PredefinedTypes(-1);
cInfoCache.clear(); cInfoCache.clear();
hasWarnedDirect = false; hasWarnedDirect = false;
hasWarnedStartTime = false;
lastSeedMethod = -1; lastSeedMethod = -1;
lastSeedPreventClubNb = true; lastSeedPreventClubNb = true;
@ -159,8 +160,12 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
gdi.setInputStatus("CommonStartTime", gdi.isChecked(bi.id)); gdi.setInputStatus("CommonStartTime", gdi.isChecked(bi.id));
} }
else if (bi.id == "CoursePool") { else if (bi.id == "CoursePool") {
string strId = "StageCourses_expl"; string strId = "StageCourses_label";
gdi.setTextTranslate(strId, getCourseLabel(gdi.isChecked(bi.id)), true); gdi.setTextTranslate(strId, getCourseLabel(gdi.isChecked(bi.id)), true);
setLockForkingState(gdi, gdi.isChecked("CoursePool"), gdi.isChecked("LockForking"));
}
else if (bi.id == "LockForking") {
setLockForkingState(gdi, gdi.isChecked("CoursePool"), gdi.isChecked(bi.id));
} }
else if (bi.id == "DefineForking") { else if (bi.id == "DefineForking") {
if (!checkClassSelected(gdi)) if (!checkClassSelected(gdi))
@ -390,7 +395,13 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
if (nstages>0 && nstages<41) { if (nstages>0 && nstages<41) {
wstring st=gdi.getText("StartTime"); wstring st=gdi.getText("StartTime");
if (oe->convertAbsoluteTime(st)>0)
int nst = oe->convertAbsoluteTime(st);
if (warnDrawStartTime(gdi, nst)) {
nst = 3600;
st = oe->getAbsTime(nst);
}
if (nst>0)
storedStart = st; storedStart = st;
save(gdi, false); //Clears and reloads save(gdi, false); //Clears and reloads
@ -568,7 +579,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
bool checked = gdi.isChecked("UseAdvanced"); bool checked = gdi.isChecked("UseAdvanced");
oe->setProperty("AdvancedClassSettings", checked); oe->setProperty("AdvancedClassSettings", checked);
save(gdi, true); save(gdi, true);
PostMessage(gdi.getTarget(), WM_USER + 2, TClassTab, 0); PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TClassTab, 0);
} }
else if (bi.id=="SwitchMode") { else if (bi.id=="SwitchMode") {
if (!tableMode) if (!tableMode)
@ -578,7 +589,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
else if (bi.id=="Restart") { else if (bi.id=="Restart") {
save(gdi, true); save(gdi, true);
gdi.clearPage(true); clearPage(gdi, true);
gdi.addString("", 2, "Omstart i stafettklasser"); gdi.addString("", 2, "Omstart i stafettklasser");
gdi.addString("", 10, "help:31661"); gdi.addString("", 10, "help:31661");
gdi.addListBox("RestartClasses", 200, 250, 0, L"Stafettklasser", L"", true); gdi.addListBox("RestartClasses", 200, 250, 0, L"Stafettklasser", L"", true);
@ -662,13 +673,16 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
bool drawCoursebased = drawInfo.coursesTogether; bool drawCoursebased = drawInfo.coursesTogether;
int maxST = 0;
map<int, vector<ClassDrawSpecification> > specs; map<int, vector<ClassDrawSpecification> > specs;
for(size_t k=0; k<cInfo.size(); k++) { for(size_t k=0; k<cInfo.size(); k++) {
const ClassInfo &ci=cInfo[k]; const ClassInfo &ci=cInfo[k];
if (ci.pc) { if (ci.pc) {
// Save settings with class // Save settings with class
ci.pc->synchronize(false); ci.pc->synchronize(false);
ci.pc->setDrawFirstStart(drawInfo.firstStart + drawInfo.baseInterval * ci.firstStart); int stloc = drawInfo.firstStart + drawInfo.baseInterval * ci.firstStart;
maxST = max(maxST, stloc);
ci.pc->setDrawFirstStart(stloc);
ci.pc->setDrawInterval(ci.interval * drawInfo.baseInterval); ci.pc->setDrawInterval(ci.interval * drawInfo.baseInterval);
ci.pc->setDrawVacant(ci.nVacant); ci.pc->setDrawVacant(ci.nVacant);
ci.pc->setDrawNumReserved(ci.nExtra); ci.pc->setDrawNumReserved(ci.nExtra);
@ -685,6 +699,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
specs[ci.classId].push_back(cds); specs[ci.classId].push_back(cds);
} }
if (warnDrawStartTime(gdi, maxST))
return 0;
for (map<int, vector<ClassDrawSpecification> >::iterator it = specs.begin(); for (map<int, vector<ClassDrawSpecification> >::iterator it = specs.begin();
it != specs.end(); ++it) { it != specs.end(); ++it) {
oe->drawList(it->second, soft, pairSize, oEvent::drawAll); oe->drawList(it->second, soft, pairSize, oEvent::drawAll);
@ -692,7 +709,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oe->addAutoBib(); oe->addAutoBib();
gdi.clearPage(false); clearPage(gdi, false);
gdi.addButton("Cancel", "Återgå", ClassesCB); gdi.addButton("Cancel", "Återgå", ClassesCB);
oListParam par; oListParam par;
@ -750,7 +767,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
ClassId = 0; ClassId = 0;
EditChanged=false; EditChanged=false;
gdi.clearPage(true); clearPage(gdi, true);
gdi.addString("", boldLarge, "Lotta flera klasser"); gdi.addString("", boldLarge, "Lotta flera klasser");
gdi.dropLine(); gdi.dropLine();
@ -877,6 +894,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
else if (bi.id == "AutomaticDraw") { else if (bi.id == "AutomaticDraw") {
wstring firstStart = gdi.getText("FirstStart"); wstring firstStart = gdi.getText("FirstStart");
if (warnDrawStartTime(gdi, firstStart))
return 0;
wstring minInterval = gdi.getText("MinInterval"); wstring minInterval = gdi.getText("MinInterval");
wstring vacances = gdi.getText("Vacances"); wstring vacances = gdi.getText("Vacances");
bool lateBefore = false; bool lateBefore = false;
@ -888,7 +908,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
int method = gdi.getSelectedItem("Method").first; int method = gdi.getSelectedItem("Method").first;
bool useSoft = method == DMSOFT; bool useSoft = method == DMSOFT;
gdi.clearPage(true); clearPage(gdi, true);
oe->automaticDrawAll(gdi, firstStart, minInterval, vacances, oe->automaticDrawAll(gdi, firstStart, minInterval, vacances,
lateBefore, useSoft, pairSize); lateBefore, useSoft, pairSize);
oe->addAutoBib(); oe->addAutoBib();
@ -909,7 +929,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
wstring firstStart; wstring firstStart;
firstStart = gdi.getText("FirstStart"); firstStart = gdi.getText("FirstStart");
gdi.clearPage(false); clearPage(gdi, false);
gdi.addString("", boldLarge, "Gemensam start"); gdi.addString("", boldLarge, "Gemensam start");
gdi.dropLine(); gdi.dropLine();
int by = 0; int by = 0;
@ -938,6 +958,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
wstring time = gdi.getText("FirstStart"); wstring time = gdi.getText("FirstStart");
if (warnDrawStartTime(gdi, time))
return 0;
for (set<int>::iterator it = classes.begin(); it!=classes.end();++it) { for (set<int>::iterator it = classes.begin(); it!=classes.end();++it) {
simultaneous(*it, time); simultaneous(*it, time);
} }
@ -973,8 +996,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
} }
gdi.clearPage(false); clearPage(gdi, false);
gdi.addString("", boldLarge, "Lotta flera klasser"); gdi.addString("", boldLarge, "Lotta flera klasser");
gdi.dropLine(0.5); gdi.dropLine(0.5);
@ -1332,12 +1354,16 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (t<=0) if (t<=0)
throw std::exception("Ogiltig första starttid. Måste vara efter nolltid."); throw std::exception("Ogiltig första starttid. Måste vara efter nolltid.");
oEvent::DrawType dtype(oEvent::drawAll); oEvent::DrawType dtype(oEvent::drawAll);
if (bi.id=="DoDrawAfter") if (bi.id=="DoDrawAfter")
dtype = oEvent::remainingAfter; dtype = oEvent::remainingAfter;
else if (bi.id=="DoDrawBefore") else if (bi.id=="DoDrawBefore")
dtype = oEvent::remainingBefore; dtype = oEvent::remainingBefore;
else {
if (warnDrawStartTime(gdi, t))
return 0;
}
//bool pairwise = false; //bool pairwise = false;
// if (gdi.hasField("Pairwise")) // if (gdi.hasField("Pairwise"))
@ -1427,6 +1453,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oe->generateList(gdi, false, info, true); oe->generateList(gdi, false, info, true);
gdi.refresh(); gdi.refresh();
gdi.setData("ClassPageLoaded", 1);
return 0; return 0;
} }
else if (bi.id=="HandleBibs") { else if (bi.id=="HandleBibs") {
@ -1469,7 +1497,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (EditChanged) if (EditChanged)
gdi.sendCtrlMessage("Save"); gdi.sendCtrlMessage("Save");
gdi.clearPage(false); clearPage(gdi, false);
gdi.addString("", boldLarge, L"Lotta klassen X#"+pc->getName()); gdi.addString("", boldLarge, L"Lotta klassen X#"+pc->getName());
gdi.dropLine(); gdi.dropLine();
@ -1519,7 +1547,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (!pc) if (!pc)
throw std::exception("Class not found"); throw std::exception("Class not found");
gdi.clearPage(false); clearPage(gdi, false);
gdi.addString("", boldLarge, L"Nummerlappar i X#" + pc->getName()); gdi.addString("", boldLarge, L"Nummerlappar i X#" + pc->getName());
gdi.dropLine(); gdi.dropLine();
gdi.setRestorePoint("bib"); gdi.setRestorePoint("bib");
@ -1632,7 +1660,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (!pc) if (!pc)
throw std::exception("Class not found"); throw std::exception("Class not found");
gdi.clearPage(true); clearPage(gdi, true);
gdi.addString("", boldLarge, L"Dela klass: X#" + pc->getName()); gdi.addString("", boldLarge, L"Dela klass: X#" + pc->getName());
gdi.dropLine(); gdi.dropLine();
int tot, fin, dns; int tot, fin, dns;
@ -1682,7 +1710,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
pc->splitClass(ClassSplitMethod(lbi.data), parts, outClass); pc->splitClass(ClassSplitMethod(lbi.data), parts, outClass);
gdi.clearPage(true); clearPage(gdi, true);
gdi.addButton("Cancel", "Återgå", ClassesCB); gdi.addButton("Cancel", "Återgå", ClassesCB);
oListParam par; oListParam par;
@ -1692,6 +1720,21 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oe->generateListInfo(par, gdi.getLineHeight(), info); oe->generateListInfo(par, gdi.getLineHeight(), info);
oe->generateList(gdi, false, info, true); oe->generateList(gdi, false, info, true);
} }
else if (bi.id == "LockAllForks" || bi.id == "UnLockAllForks") {
bool lock = bi.id == "LockAllForks";
vector<pClass> allCls;
oe->getClasses(allCls, true);
for (pClass c : allCls) {
if (c->isRemoved())
continue;
if (!c->hasCoursePool() && c->hasMultiCourse()) {
c->lockedForking(lock);
c->synchronize(true);
}
}
loadPage(gdi);
return 0;
}
else if (bi.id=="Merge") { else if (bi.id=="Merge") {
save(gdi, true); save(gdi, true);
if (!checkClassSelected(gdi)) if (!checkClassSelected(gdi))
@ -1720,7 +1763,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (cls.empty()) if (cls.empty())
throw std::exception("En klass kan inte slås ihop med sig själv."); throw std::exception("En klass kan inte slås ihop med sig själv.");
gdi.clearPage(true);
clearPage(gdi, true);
gdi.addString("", boldLarge, L"Slå ihop klass: X (denna klass behålls)#" + pc->getName()); gdi.addString("", boldLarge, L"Slå ihop klass: X (denna klass behålls)#" + pc->getName());
gdi.dropLine(); gdi.dropLine();
gdi.addString("", 10, "help:12138"); gdi.addString("", 10, "help:12138");
@ -1781,7 +1825,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
throw std::exception("En klass kan inte slås ihop med sig själv."); throw std::exception("En klass kan inte slås ihop med sig själv.");
pc->mergeClass(lbi.data); pc->mergeClass(lbi.data);
gdi.clearPage(true);
clearPage(gdi, true);
gdi.addButton("Cancel", "Återgå", ClassesCB); gdi.addButton("Cancel", "Återgå", ClassesCB);
oListParam par; oListParam par;
@ -2078,7 +2123,7 @@ void TabClass::showClassSettings(gdioutput &gdi)
gdi.addString("C" + itos(id), 0, L"X platser. Startar Y#" + wstring(bf1) + L"#" + bf2); gdi.addString("C" + itos(id), 0, L"X platser. Startar Y#" + wstring(bf1) + L"#" + bf2);
y = gdi.getCY(); y = gdi.getCY();
gdi.addInput(xp+300, y, "S"+itos(id), first, 7, DrawClassesCB); gdi.addInput(xp+300, y, "S"+itos(id), first, 7, DrawClassesCB);
gdi.addInput(xp+300+width, y, "I"+itos(id), formatTimeW(ci.interval*drawInfo.baseInterval), 7, DrawClassesCB); gdi.addInput(xp+300+width, y, "I"+itos(id), formatTime(ci.interval*drawInfo.baseInterval), 7, DrawClassesCB);
gdi.addInput(xp+300+width*2, y, "V"+itos(id), itow(ci.nVacant), 7, DrawClassesCB); gdi.addInput(xp+300+width*2, y, "V"+itos(id), itow(ci.nVacant), 7, DrawClassesCB);
gdi.addInput(xp+300+width*3, y, "R"+itos(id), itow(ci.nExtra), 7, DrawClassesCB); gdi.addInput(xp+300+width*3, y, "R"+itos(id), itow(ci.nExtra), 7, DrawClassesCB);
@ -2245,9 +2290,14 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
if (gdi.hasField("Unordered")) if (gdi.hasField("Unordered"))
gdi.check("Unordered", pc->hasUnorderedLegs()); gdi.check("Unordered", pc->hasUnorderedLegs());
if (gdi.hasField("LockForking")) {
gdi.check("LockForking", pc->lockedForking());
setLockForkingState(gdi, pc->hasCoursePool(), pc->lockedForking());
}
if (gdi.hasField("MCourses")) { if (gdi.hasField("MCourses")) {
oe->fillCourses(gdi, "MCourses", true); oe->fillCourses(gdi, "MCourses", true);
string strId = "StageCourses_expl"; string strId = "StageCourses_label";
gdi.setTextTranslate(strId, getCourseLabel(pc->hasCoursePool()), true); gdi.setTextTranslate(strId, getCourseLabel(pc->hasCoursePool()), true);
} }
@ -2510,6 +2560,9 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
"Knyt löparna till banor från en pool vid målgång."); "Knyt löparna till banor från en pool vid målgång.");
gdi.addCheckbox("Unordered", "Oordnade parallella sträckor", MultiCB, false, gdi.addCheckbox("Unordered", "Oordnade parallella sträckor", MultiCB, false,
"Tillåt löpare inom en parallell grupp att springa gruppens banor i godtycklig ordning."); "Tillåt löpare inom en parallell grupp att springa gruppens banor i godtycklig ordning.");
gdi.addCheckbox("LockForking", "Lås gafflingar", MultiCB, false,
"Markera för att förhindra oavsiktlig ändring av gafflingsnycklar.");
gdi.popX(); gdi.popX();
gdi.fillRight(); gdi.fillRight();
gdi.dropLine(1.7); gdi.dropLine(1.7);
@ -2594,6 +2647,9 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
if (gdi.hasField("Unordered")) if (gdi.hasField("Unordered"))
pc->setUnorderedLegs(gdi.isChecked("Unordered")); pc->setUnorderedLegs(gdi.isChecked("Unordered"));
if (gdi.hasField("LockForking"))
pc->lockedForking(gdi.isChecked("LockForking"));
pc->setAllowQuickEntry(gdi.isChecked("AllowQuickEntry")); pc->setAllowQuickEntry(gdi.isChecked("AllowQuickEntry"));
pc->setNoTiming(gdi.isChecked("NoTiming")); pc->setNoTiming(gdi.isChecked("NoTiming"));
@ -2636,6 +2692,7 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
bool sim = gdi.isChecked("CommonStart"); bool sim = gdi.isChecked("CommonStart");
if (sim) { if (sim) {
pc->setStartType(0, STTime, true); pc->setStartType(0, STTime, true);
if (!warnDrawStartTime(gdi, gdi.getText("CommonStartTime")))
pc->setStartData(0, gdi.getText("CommonStartTime")); pc->setStartData(0, gdi.getText("CommonStartTime"));
} }
else { else {
@ -2728,10 +2785,12 @@ struct ButtonData {
bool TabClass::loadPage(gdioutput &gdi) bool TabClass::loadPage(gdioutput &gdi)
{ {
if (!gdi.hasData("ClassPageLoaded"))
hasWarnedStartTime = false;
oe->checkDB(); oe->checkDB();
oe->checkNecessaryFeatures(); oe->checkNecessaryFeatures();
gdi.selectTab(tabId); gdi.selectTab(tabId);
gdi.clearPage(false); clearPage(gdi, false);
int xp=gdi.getCX(); int xp=gdi.getCX();
const int button_w=gdi.scaleLength(90); const int button_w=gdi.scaleLength(90);
@ -2839,24 +2898,51 @@ bool TabClass::loadPage(gdioutput &gdi)
gdi.dropLine(2); gdi.dropLine(2);
gdi.popX(); gdi.popX();
gdi.fillDown();
gdi.addString("", 1, "Funktioner");
vector<ButtonData> func; vector<ButtonData> func;
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::DrawStartList)) if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::DrawStartList))
func.push_back(ButtonData("Draw", "Lotta / starttider...", false)); func.push_back(ButtonData("Draw", "Lotta / starttider...", false));
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Bib)) if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Bib))
func.push_back(ButtonData("Bibs", "Nummerlappar...", false)); func.push_back(ButtonData("Bibs", "Nummerlappar...", false));
if (cnf.hasTeamClass())
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::DrawStartList))
func.push_back(ButtonData("DrawMode", "Lotta flera klasser", true));
if (cnf.hasTeamClass()) {
func.push_back(ButtonData("Restart", "Omstart...", true)); func.push_back(ButtonData("Restart", "Omstart...", true));
vector<pClass> allCls;
oe->getClasses(allCls, false);
bool unlockedClass = false;
bool lockedClass = false;
if (showAdvanced) {
for (pClass c : allCls) {
if (c->isRemoved())
continue;
if (!c->hasCoursePool() && c->hasMultiCourse()) {
if (c->lockedForking())
lockedClass = true;
else
unlockedClass = true;
}
}
if (unlockedClass) {
func.push_back(ButtonData("LockAllForks", "Lås gafflingar", true));
}
if (lockedClass) {
func.push_back(ButtonData("UnLockAllForks", "Tillåt gafflingsändringar", true));
}
}
}
if (showAdvanced) { if (showAdvanced) {
func.push_back(ButtonData("Merge", "Slå ihop klasser...", false)); func.push_back(ButtonData("Merge", "Slå ihop klasser...", false));
func.push_back(ButtonData("Split", "Dela klassen...", false)); func.push_back(ButtonData("Split", "Dela klassen...", false));
} }
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::DrawStartList))
func.push_back(ButtonData("DrawMode", "Lotta flera klasser", true));
func.push_back(ButtonData("QuickSettings", "Snabbinställningar", true));
if (showAdvanced && oe->getMeOSFeatures().hasFeature(MeOSFeatures::Vacancy)) { if (showAdvanced && oe->getMeOSFeatures().hasFeature(MeOSFeatures::Vacancy)) {
vector<pRunner> rr; vector<pRunner> rr;
@ -2872,22 +2958,40 @@ bool TabClass::loadPage(gdioutput &gdi)
func.push_back(ButtonData("RemoveVacant", "Radera vakanser", true)); func.push_back(ButtonData("RemoveVacant", "Radera vakanser", true));
} }
func.push_back(ButtonData("QuickSettings", "Snabbinställningar", true));
RECT funRect;
funRect.right = gdi.getCX() - 7;
funRect.top = gdi.getCY() - 2;
funRect.left = 0;
gdi.dropLine(0.5);
gdi.fillDown();
gdi.addString("", fontMediumPlus, "Funktioner");
gdi.dropLine(0.3); gdi.dropLine(0.3);
gdi.pushX(); gdi.pushX();
gdi.fillRight(); gdi.fillRight();
int xlimit = gdi.getWidth() - button_w/2;
for (size_t k = 0; k < func.size(); k++) { for (size_t k = 0; k < func.size(); k++) {
ButtonInfo &bi = gdi.addButton(func[k].id, func[k].label, ClassesCB); ButtonInfo &bi = gdi.addButton(func[k].id, func[k].label, ClassesCB);
if (!func[k].global) if (!func[k].global)
bi.isEdit(true); bi.isEdit(true);
if ( k % 2 == 1) { funRect.left = max<int>(funRect.left, gdi.getCX() + 7);
if ( gdi.getCX() > xlimit && k+1 < func.size()) {
gdi.popX(); gdi.popX();
gdi.dropLine(2.5); gdi.dropLine(2.5);
} }
} }
gdi.dropLine(2.5);
funRect.bottom = gdi.getCY();
gdi.addRectangle(funRect, colorLightGreen);
gdi.popX(); gdi.popX();
gdi.dropLine(3); gdi.dropLine(0.5);
gdi.fillRight(); gdi.fillRight();
gdi.addButton("Save", "Spara", ClassesCB).setDefault(); gdi.addButton("Save", "Spara", ClassesCB).setDefault();
gdi.disableInput("Save"); gdi.disableInput("Save");
@ -2988,7 +3092,7 @@ void TabClass::saveClassSettingsTable(gdioutput &gdi) {
} }
void TabClass::prepareForDrawing(gdioutput &gdi) { void TabClass::prepareForDrawing(gdioutput &gdi) {
gdi.clearPage(false); clearPage(gdi, false);
gdi.addString("", 2, "Klassinställningar"); gdi.addString("", 2, "Klassinställningar");
int baseLine = gdi.getCY(); int baseLine = gdi.getCY();
gdi.addString("", 10, "help:59395"); gdi.addString("", 10, "help:59395");
@ -3110,7 +3214,7 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
} }
if (method != DMSimultaneous) if (method != DMSimultaneous)
gdi.addInput("Interval", formatTimeW(interval), 10, 0, L"Startintervall (min):").setSynchData(&lastInterval); gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):").setSynchData(&lastInterval);
if (method == DMRandom || method == DMSOFT || method == DMClumped) if (method == DMRandom || method == DMSOFT || method == DMClumped)
gdi.addInput("Vacanses", itow(vac), 10, 0, L"Antal vakanser:").setSynchData(&lastNumVac); gdi.addInput("Vacanses", itow(vac), 10, 0, L"Antal vakanser:").setSynchData(&lastNumVac);
@ -3204,7 +3308,7 @@ void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, DrawMethod defaul
} }
void TabClass::pursuitDialog(gdioutput &gdi) { void TabClass::pursuitDialog(gdioutput &gdi) {
gdi.clearPage(false); clearPage(gdi, false);
gdi.addString("", boldLarge, "Jaktstart"); gdi.addString("", boldLarge, "Jaktstart");
gdi.dropLine(); gdi.dropLine();
vector<pClass> cls; vector<pClass> cls;
@ -3216,9 +3320,9 @@ void TabClass::pursuitDialog(gdioutput &gdi) {
gdi.fillRight(); gdi.fillRight();
gdi.addInput("MaxAfter", formatTimeW(pSavedDepth), 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart"); gdi.addInput("MaxAfter", formatTime(pSavedDepth), 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart");
gdi.addInput("TimeRestart", L"+" + formatTimeW(pFirstRestart), 8, 0, L"Första omstartstid:", L"Ange tiden relativt klassens första start"); gdi.addInput("TimeRestart", L"+" + formatTime(pFirstRestart), 8, 0, L"Första omstartstid:", L"Ange tiden relativt klassens första start");
gdi.addInput("Interval", formatTimeW(pInterval), 8, 0, L"Startintervall:", L"Ange startintervall för minutstart"); gdi.addInput("Interval", formatTime(pInterval), 8, 0, L"Startintervall:", L"Ange startintervall för minutstart");
wchar_t bf[32]; wchar_t bf[32];
swprintf_s(bf, L"%f", pTimeScaling); swprintf_s(bf, L"%f", pTimeScaling);
gdi.addInput("ScaleFactor", bf, 8, 0, L"Tidsskalning:"); gdi.addInput("ScaleFactor", bf, 8, 0, L"Tidsskalning:");
@ -3917,12 +4021,45 @@ void TabClass::writeDrawInfo(gdioutput &gdi, const DrawInfo &drawInfoIn) {
gdi.setText("Vacances", itow(int(drawInfoIn.vacancyFactor *100.0)) + L"%"); gdi.setText("Vacances", itow(int(drawInfoIn.vacancyFactor *100.0)) + L"%");
gdi.setText("Extra", itow(int(drawInfoIn.extraFactor * 100.0) ) + L"%"); gdi.setText("Extra", itow(int(drawInfoIn.extraFactor * 100.0) ) + L"%");
gdi.setText("BaseInterval", formatTimeW(drawInfoIn.baseInterval)); gdi.setText("BaseInterval", formatTime(drawInfoIn.baseInterval));
gdi.check("AllowNeighbours", drawInfoIn.allowNeighbourSameCourse); gdi.check("AllowNeighbours", drawInfoIn.allowNeighbourSameCourse);
gdi.check("CoursesTogether", drawInfoIn.coursesTogether); gdi.check("CoursesTogether", drawInfoIn.coursesTogether);
gdi.setText("MinInterval", formatTimeW(drawInfoIn.minClassInterval)); gdi.setText("MinInterval", formatTime(drawInfoIn.minClassInterval));
gdi.setText("MaxInterval", formatTimeW(drawInfoIn.maxClassInterval)); gdi.setText("MaxInterval", formatTime(drawInfoIn.maxClassInterval));
gdi.setText("nFields", drawInfoIn.nFields); gdi.setText("nFields", drawInfoIn.nFields);
gdi.setText("FirstStart", oe->getAbsTime(drawInfoIn.firstStart)); gdi.setText("FirstStart", oe->getAbsTime(drawInfoIn.firstStart));
} }
void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockState) {
if (gdi.hasField("DefineForking"))
gdi.setInputStatus("DefineForking", !lockState && !poolState);
if (gdi.hasField("LockForking"))
gdi.setInputStatus("LockForking", !poolState);
int legno = 0;
while (gdi.hasField("@Course" + itos(legno))) {
gdi.setInputStatus("@Course" + itos(legno++), !lockState || poolState);
}
}
bool TabClass::warnDrawStartTime(gdioutput &gdi, const wstring &firstStart) {
int st = oe->getRelativeTime(firstStart);
return warnDrawStartTime(gdi, st);
}
bool TabClass::warnDrawStartTime(gdioutput &gdi, int time) {
if (!hasWarnedStartTime && time > 3600 * 8 && !oe->useLongTimes()) {
bool res = gdi.ask(L"warn:latestarttime#" + itow(time/3600));
if (res)
hasWarnedStartTime = true;
return !res;
}
return false;
}
void TabClass::clearPage(gdioutput &gdi, bool autoRefresh) {
gdi.clearPage(autoRefresh);
gdi.setData("ClassPageLoaded", 1);
}

View File

@ -79,6 +79,12 @@ class TabClass :
void pursuitDialog(gdioutput &gdi); void pursuitDialog(gdioutput &gdi);
bool warnDrawStartTime(gdioutput &gdi, int time);
bool warnDrawStartTime(gdioutput &gdi, const wstring &firstStart);
void static clearPage(gdioutput &gdi, bool autoRefresh);
bool hasWarnedStartTime;
bool hasWarnedDirect; bool hasWarnedDirect;
bool tableMode; bool tableMode;
DrawMethod lastDrawMethod; DrawMethod lastDrawMethod;
@ -137,6 +143,9 @@ class TabClass :
void writeDrawInfo(gdioutput &gdi, const DrawInfo &drawInfo); void writeDrawInfo(gdioutput &gdi, const DrawInfo &drawInfo);
static vector< pair<wstring, size_t> > getPairOptions(); static vector< pair<wstring, size_t> > getPairOptions();
void setLockForkingState(gdioutput &gdi, bool poolState, bool lockState);
public: public:
void clearCompetitionData(); void clearCompetitionData();

View File

@ -119,6 +119,12 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
gdi.setText("Date", oe->getDate()); gdi.setText("Date", oe->getDate());
return 0; return 0;
} }
bool updateTimes = newZT != oldZT && oe->getNumRunners() > 0 && gdi.ask(L"ask:updatetimes");
if (updateTimes) {
int delta = oldZT - newZT;
oe->updateStartTimes(delta);
}
} }
oe->setDate(date); oe->setDate(date);
oe->useLongTimes(longTimes); oe->useLongTimes(longTimes);
@ -380,7 +386,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (bi.id == "CopyLink") { if (bi.id == "CopyLink") {
string url = gdi.narrow(gdi.getText("link")); string url = gdi.narrow(gdi.getText("link"));
if (OpenClipboard(gdi.getHWND())) { if (OpenClipboard(gdi.getHWNDMain())) {
EmptyClipboard(); EmptyClipboard();
HGLOBAL hClipboardData; HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_DDESHARE, hClipboardData = GlobalAlloc(GMEM_DDESHARE,
@ -603,7 +609,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
loadPage(gdi); loadPage(gdi);
} }
else if (bi.id == "Exit") { else if (bi.id == "Exit") {
PostMessage(gdi.getMain(), WM_CLOSE, 0, 0); PostMessage(gdi.getHWNDMain(), WM_CLOSE, 0, 0);
} }
else if (bi.id == "Help") { else if (bi.id == "Help") {
wchar_t fn[MAX_PATH]; wchar_t fn[MAX_PATH];
@ -757,7 +763,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.setWindowTitle(oe->getTitleName()); gdi.setWindowTitle(oe->getTitleName());
if (oe->isClient() && oe->getPropertyInt("UseDirectSocket", true) != 0) { if (oe->isClient() && oe->getPropertyInt("UseDirectSocket", true) != 0) {
oe->getDirectSocket().startUDPSocketThread(gdi.getMain()); oe->getDirectSocket().startUDPSocketThread(gdi.getHWNDMain());
} }
loadConnectionPage(gdi); loadConnectionPage(gdi);
@ -986,7 +992,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
oe->setProperty("UseEventor", 1); oe->setProperty("UseEventor", 1);
else else
oe->setProperty("UseEventor", 2); oe->setProperty("UseEventor", 2);
PostMessage(gdi.getTarget(), WM_USER + 2, TCmpTab, 0); PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TCmpTab, 0);
} }
else if (bi.id == "EventorAPI") { else if (bi.id == "EventorAPI") {
assert(!eventorOrigin.empty()); assert(!eventorOrigin.empty());
@ -1124,7 +1130,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
wstring zipped = getTempFile(); wstring zipped = getTempFile();
zip(zipped.c_str(), 0, fileList); zip(zipped.c_str(), 0, fileList);
ProgressWindow pw(gdi.getTarget()); ProgressWindow pw(gdi.getHWNDTarget());
pw.init(); pw.init();
vector<pair<wstring,wstring> > key; vector<pair<wstring,wstring> > key;
getAPIKey(key); getAPIKey(key);
@ -1192,6 +1198,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
return loadPage(gdi); return loadPage(gdi);
} }
checkReadyForResultExport(gdi, set<int>());
gdi.clearPage(true); gdi.clearPage(true);
gdi.fillDown(); gdi.fillDown();
gdi.dropLine(); gdi.dropLine();
@ -1216,7 +1224,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
wstring zipped = getTempFile(); wstring zipped = getTempFile();
zip(zipped.c_str(), 0, fileList); zip(zipped.c_str(), 0, fileList);
ProgressWindow pw(gdi.getTarget()); ProgressWindow pw(gdi.getHWNDTarget());
pw.init(); pw.init();
vector<pair<wstring,wstring> > key; vector<pair<wstring,wstring> > key;
getAPIKey(key); getAPIKey(key);
@ -1282,7 +1290,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
SYSTEMTIME st; SYSTEMTIME st;
GetLocalTime(&st); GetLocalTime(&st);
st.wYear--; // Include last years competitions st.wYear--; // Include last years competitions
getEventorCompetitions(gdi, convertSystemDateW(st), events); getEventorCompetitions(gdi, convertSystemDate(st), events);
gdi.clearPage(true); gdi.clearPage(true);
gdi.addString("", boldLarge, "Hämta data från Eventor"); gdi.addString("", boldLarge, "Hämta data från Eventor");
@ -1296,7 +1304,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.addSelection("EventorSel", 300, 200); gdi.addSelection("EventorSel", 300, 200);
sort(events.begin(), events.end()); sort(events.begin(), events.end());
st.wYear++; // Restore current time st.wYear++; // Restore current time
wstring now = convertSystemDateW(st); wstring now = convertSystemDate(st);
int selected = 0; // Select next event by default int selected = 0; // Select next event by default
for (int k = events.size()-1; k>=0; k--) { for (int k = events.size()-1; k>=0; k--) {
@ -1500,7 +1508,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.addString("", 1, "Skapar ny tävling"); gdi.addString("", 1, "Skapar ny tävling");
oe->newCompetition(L"New"); oe->newCompetition(L"New");
oe->importXML_EntryData(gdi, tEvent, false, false, noFilter); oe->importXML_EntryData(gdi, tEvent, false, false, noFilter);
oe->setZeroTime(formatTimeHMSW(zeroTime)); oe->setZeroTime(formatTimeHMS(zeroTime));
oe->getDI().setDate("OrdinaryEntry", lastEntry); oe->getDI().setDate("OrdinaryEntry", lastEntry);
if (ci) { if (ci) {
if (!ci->account.empty()) if (!ci->account.empty())
@ -1540,7 +1548,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
switch (startType) { switch (startType) {
case SMCommon: case SMCommon:
oe->automaticDrawAll(gdi, formatTimeHMSW(firstStart), L"0", L"0", false, false, 1); oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"0", L"0", false, false, 1);
drawn = true; drawn = true;
break; break;
@ -1565,7 +1573,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
} }
} }
if (!skip) if (!skip)
oe->automaticDrawAll(gdi, formatTimeHMSW(firstStart), L"2:00", L"2", true, true, 1); oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"2:00", L"2", true, true, 1);
drawn = true; drawn = true;
break; break;
} }
@ -1712,23 +1720,14 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
int filterIndex = gdi.getSelectedItem("Type").first; int filterIndex = gdi.getSelectedItem("Type").first;
vector< pair<wstring, wstring> > ext; vector< pair<wstring, wstring> > ext;
ImportFormats::getExportFilters(bi.id!="BrowseExport", ext); ImportFormats::getExportFilters(bi.id!="BrowseExport", ext);
/*if (bi.id=="BrowseExport") {
ext.push_back(make_pair("IOF Startlista (xml)", "*.xml"));
ext.push_back(make_pair("OE Semikolonseparerad (csv)", "*.csv"));
ext.push_back(make_pair("Webbdokument (html)", "*.html;*.htm"));
}
else {
ext.push_back(make_pair("IOF Resultat (xml)", "*.xml"));
ext.push_back(make_pair("OE Semikolonseparerad (csv)", "*.csv"));
ext.push_back(make_pair("Webbdokument (html)", "*.html"));
}*/
wstring save = gdi.browseForSave(ext, L"xml", filterIndex); wstring save = gdi.browseForSave(ext, L"xml", filterIndex);
if (save.length() > 0) { if (save.length() > 0) {
gdi.setText("Filename", save); gdi.setText("Filename", save);
gdi.selectItemByData("Type", filterIndex); gdi.selectItemByData("Type", filterIndex);
if (gdi.getExtra("Filename")) { wchar_t *fn = gdi.getExtra("Filename");
gdi.enableInput((char *)gdi.getExtra("Filename")); if (fn) {
gdi.enableInput(gdi.narrow(fn).c_str());
} }
} }
} }
@ -1784,6 +1783,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
//bool individual = !gdi.hasField("ExportTeam") || gdi.isChecked("ExportTeam"); //bool individual = !gdi.hasField("ExportTeam") || gdi.isChecked("ExportTeam");
gdi.getSelection("ClassNewEntries", allTransfer); gdi.getSelection("ClassNewEntries", allTransfer);
checkReadyForResultExport(gdi, allTransfer);
ImportFormats::ExportFormats filterIndex = ImportFormats::setExportFormat(*oe, gdi.getSelectedItem("Type").first); ImportFormats::ExportFormats filterIndex = ImportFormats::setExportFormat(*oe, gdi.getSelectedItem("Type").first);
int cSVLanguageHeaderIndex = gdi.getSelectedItem("LanguageType").first; int cSVLanguageHeaderIndex = gdi.getSelectedItem("LanguageType").first;
bool includeSplits = gdi.isChecked("ExportSplitTimes"); bool includeSplits = gdi.isChecked("ExportSplitTimes");
@ -1954,7 +1955,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
} }
if (oe->isClient() && oe->getPropertyInt("UseDirectSocket", true) != 0) { if (oe->isClient() && oe->getPropertyInt("UseDirectSocket", true) != 0) {
oe->getDirectSocket().startUDPSocketThread(gdi.getMain()); oe->getDirectSocket().startUDPSocketThread(gdi.getHWNDMain());
} }
return 0; return 0;
} }
@ -2152,7 +2153,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
int textSize = lbi.data; int textSize = lbi.data;
oe->setProperty("TextSize", textSize); oe->setProperty("TextSize", textSize);
gdi.setFont(textSize, oe->getPropertyString("TextFont", L"Arial")); gdi.setFont(textSize, oe->getPropertyString("TextFont", L"Arial"));
PostMessage(gdi.getTarget(), WM_USER + 2, TCmpTab, 0); PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TCmpTab, 0);
} }
else if (lbi.id == "Language") { else if (lbi.id == "Language") {
lang.get().loadLangResource(lbi.text); lang.get().loadLangResource(lbi.text);
@ -2160,7 +2161,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
oe->setProperty("Language", lbi.text); oe->setProperty("Language", lbi.text);
//gdi.setEncoding(interpetEncoding(lang.tl("encoding"))); //gdi.setEncoding(interpetEncoding(lang.tl("encoding")));
gdi.setFont(oe->getPropertyInt("TextSize", 0), oe->getPropertyString("TextFont", L"Arial")); gdi.setFont(oe->getPropertyInt("TextSize", 0), oe->getPropertyString("TextFont", L"Arial"));
PostMessage(gdi.getTarget(), WM_USER + 2, TCmpTab, 0); PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TCmpTab, 0);
} }
else if (lbi.id == "PreEvent") { else if (lbi.id == "PreEvent") {
gdi.setInputStatus("OpenPre", int(lbi.data)>0); gdi.setInputStatus("OpenPre", int(lbi.data)>0);
@ -2183,8 +2184,9 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
else if (type== GUI_INPUT) { else if (type== GUI_INPUT) {
InputInfo ii=*(InputInfo *)data; InputInfo ii=*(InputInfo *)data;
if (ii.id == "Filename") { if (ii.id == "Filename") {
if (ii.getExtra()) { const wchar_t *fn = ii.getExtra();
gdi.setInputStatus((char *)ii.getExtra(), !ii.text.empty()); if (fn) {
gdi.setInputStatus(gdi.narrow(fn).c_str(), !ii.text.empty());
} }
} }
else if (ii.id == "NumStages") { else if (ii.id == "NumStages") {
@ -2196,8 +2198,9 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
else if (type == GUI_INPUTCHANGE) { else if (type == GUI_INPUTCHANGE) {
InputInfo ii=*(InputInfo *)data; InputInfo ii=*(InputInfo *)data;
if (ii.id == "Filename") { if (ii.id == "Filename") {
if (ii.getExtra()) { const wchar_t *fn = ii.getExtra();
gdi.setInputStatus((char *)ii.getExtra(), !ii.text.empty()); if (fn) {
gdi.setInputStatus(gdi.narrow(fn).c_str(), !ii.text.empty());
} }
} }
} }
@ -2537,7 +2540,6 @@ bool TabCompetition::loadPage(gdioutput &gdi)
} }
gdi.addButton("Settings", "Tävlingsinställningar", CompetitionCB); gdi.addButton("Settings", "Tävlingsinställningar", CompetitionCB);
gdi.addButton("Report", "Tävlingsrapport", CompetitionCB);
gdi.addButton("Features", "MeOS Funktioner", CompetitionCB); gdi.addButton("Features", "MeOS Funktioner", CompetitionCB);
#ifdef _DEBUG #ifdef _DEBUG
@ -2849,7 +2851,7 @@ void TabCompetition::getEventorCompetitions(gdioutput &gdi,
nt -= 24*3600; nt -= 24*3600;
dayOffset = 1; dayOffset = 1;
} }
ci.firstStart = formatTimeHMSW(nt); ci.firstStart = formatTimeHMS(nt);
//TODO: Take dayoffset into account //TODO: Take dayoffset into account
} }
@ -2890,7 +2892,7 @@ void TabCompetition::getEventorCompetitions(gdioutput &gdi,
SYSTEMTIME st; SYSTEMTIME st;
convertDateYMS(breakDate, st, false); convertDateYMS(breakDate, st, false);
__int64 time = SystemTimeToInt64Second(st) - 1; __int64 time = SystemTimeToInt64Second(st) - 1;
breakDate = convertSystemDateW(Int64SecondToSystemTime(time)); breakDate = convertSystemDate(Int64SecondToSystemTime(time));
if (ci.lastNormalEntryDate.empty() || ci.lastNormalEntryDate >= breakDate) if (ci.lastNormalEntryDate.empty() || ci.lastNormalEntryDate >= breakDate)
ci.lastNormalEntryDate = breakDate; ci.lastNormalEntryDate = breakDate;
@ -2917,7 +2919,7 @@ void TabCompetition::getEventorCmpData(gdioutput &gdi, int id,
const wstring &entryFile, const wstring &entryFile,
const wstring &dbFile) const const wstring &dbFile) const
{ {
ProgressWindow pw(gdi.getHWND()); ProgressWindow pw(gdi.getHWNDTarget());
pw.init(); pw.init();
gdi.fillDown(); gdi.fillDown();
gdi.addString("", 1, "Ansluter till Internet").setColor(colorGreen); gdi.addString("", 1, "Ansluter till Internet").setColor(colorGreen);
@ -3981,3 +3983,38 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
else if (changedCardFee) else if (changedCardFee)
oe->applyEventFees(false, false, true, dummy); oe->applyEventFees(false, false, true, dummy);
} }
void TabCompetition::checkReadyForResultExport(gdioutput &gdi, const set<int> &classFilter) {
vector<pRunner> runners;
oe->getRunners(0, 0, runners, true);
int numNoResult = 0;
int numVacant = 0;
for (pRunner r : runners) {
if (!classFilter.empty() && !classFilter.count(r->getClassId()))
continue;
if (r->isVacant())
numVacant++;
else if (r->getStatus() == StatusUnknown && !r->needNoCard())
numNoResult++;
}
if (numVacant > 0) {
if (gdi.ask(L"ask:hasVacant")) {
if (gdi.ask(L"Vill du radera alla vakanser från tävlingen?")) {
if (classFilter.empty())
oe->removeVacanies(0);
else {
for (int c : classFilter)
oe->removeVacanies(c);
}
}
}
}
if (numNoResult > 0) {
gdi.alert(L"warn:missingResult#" + itow(numNoResult));
}
}

View File

@ -116,6 +116,9 @@ class TabCompetition :
set<int> allTransfer; set<int> allTransfer;
void checkReadyForResultExport(gdioutput &gdi, const set<int> &classFilter);
void displayRunners(gdioutput &gdi, const vector<pRunner> &changedClass) const; void displayRunners(gdioutput &gdi, const vector<pRunner> &changedClass) const;
void meosFeatures(gdioutput &gdi, bool newGuide); void meosFeatures(gdioutput &gdi, bool newGuide);

View File

@ -79,18 +79,19 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
const int numVisit = pc->getNumVisitors(true); const int numVisit = pc->getNumVisitors(true);
const int numVisitExp = pc->getNumVisitors(false); const int numVisitExp = pc->getNumVisitors(false);
string info; wstring info;
if (numVisit > 0) { if (numVisit > 0) {
info = "Antal besökare X, genomsnittlig bomtid Y, största bomtid Z#" + info = L"Antal besökare X, genomsnittlig bomtid Y, största bomtid Z#" +
itos(numVisit) + " (" + itos(numVisitExp) + ")#" + getTimeMS(pc->getMissedTimeTotal() / numVisit) + itow(numVisit) + L" (" + itow(numVisitExp) + L")#" + getTimeMS(pc->getMissedTimeTotal() / numVisit) +
"#" + getTimeMS(pc->getMissedTimeMax()); L"#" + getTimeMS(pc->getMissedTimeMax());
} }
else if (numVisitExp > 0) { else if (numVisitExp > 0) {
info = "Förväntat antal besökare: X#" + itos(numVisitExp); info = L"Förväntat antal besökare: X#" + itow(numVisitExp);
} }
gdi.setText("ControlID", itow(pc->getId()), true); gdi.setText("ControlID", itow(pc->getId()), true);
gdi.setText("Info", lang.tl(info), true); wstring winfo = lang.tl(info);
gdi.setText("Info", winfo, true);
gdi.setText("Code", pc->codeNumbers()); gdi.setText("Code", pc->codeNumbers());
gdi.setText("Name", pc->getName()); gdi.setText("Name", pc->getName());
gdi.setText("TimeAdjust", pc->getTimeAdjustS()); gdi.setText("TimeAdjust", pc->getTimeAdjustS());

View File

@ -95,7 +95,7 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
if ( rt > 0 ) { if ( rt > 0 ) {
gdi.selectItemByData("Rogaining", 1); gdi.selectItemByData("Rogaining", 1);
gdi.enableInput("TimeLimit"); gdi.enableInput("TimeLimit");
gdi.setText("TimeLimit", formatTimeHMSW(rt)); gdi.setText("TimeLimit", formatTimeHMS(rt));
gdi.enableInput("PointReduction"); gdi.enableInput("PointReduction");
gdi.setText("PointReduction", itow(pc->getRogainingPointsPerMinute())); gdi.setText("PointReduction", itow(pc->getRogainingPointsPerMinute()));
gdi.enableInput("ReductionPerMinute"); gdi.enableInput("ReductionPerMinute");
@ -506,7 +506,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
int interval = 2*60; int interval = 2*60;
int vac = 1; int vac = 1;
gdi.addInput("FirstStart", oe->getAbsTime(firstStart), 10, 0, L"Första start:"); gdi.addInput("FirstStart", oe->getAbsTime(firstStart), 10, 0, L"Första start:");
gdi.addInput("Interval", formatTimeW(interval), 10, 0, L"Startintervall (min):"); gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):");
gdi.addInput("Vacances", itow(vac), 10, 0, L"Antal vakanser:"); gdi.addInput("Vacances", itow(vac), 10, 0, L"Antal vakanser:");
gdi.fillDown(); gdi.fillDown();
gdi.popX(); gdi.popX();

View File

@ -49,9 +49,11 @@
#include "methodeditor.h" #include "methodeditor.h"
#include "MeOSFeatures.h" #include "MeOSFeatures.h"
#include "liveresult.h" #include "liveresult.h"
#include "animationdata.h"
#include <algorithm> #include <algorithm>
const static int CUSTOM_OFFSET = 10; const static int CUSTOM_OFFSET = 10;
const static int NUMTEXTSAMPLE = 13;
TabList::TabList(oEvent *poe):TabBase(poe) TabList::TabList(oEvent *poe):TabBase(poe)
{ {
@ -172,7 +174,7 @@ int TabList::baseButtons(gdioutput &gdi, int extraButtons) {
return ypos; return ypos;
} }
void TabList::generateList(gdioutput &gdi) void TabList::generateList(gdioutput &gdi, bool forceUpdate)
{ {
if (currentList.getListCode() == EFixedLiveResult) { if (currentList.getListCode() == EFixedLiveResult) {
liveResult(gdi, currentList); liveResult(gdi, currentList);
@ -187,7 +189,6 @@ void TabList::generateList(gdioutput &gdi)
"FullScreenLive", "Fullskärm", ListsCB, "Visa listan i fullskärm", true, false); "FullScreenLive", "Fullskärm", ListsCB, "Visa listan i fullskärm", true, false);
} }
SelectedList = "GeneralList"; SelectedList = "GeneralList";
return; return;
} }
@ -195,7 +196,7 @@ void TabList::generateList(gdioutput &gdi)
int oX = 0; int oX = 0;
int oY = 0; int oY = 0;
if (gdi.hasData("GeneralList")) { if (gdi.hasData("GeneralList")) {
if (!currentList.needRegenerate(*oe)) if (!forceUpdate && !currentList.needRegenerate(*oe))
return; return;
gdi.takeShownStringsSnapshot(); gdi.takeShownStringsSnapshot();
oX = gdi.GetOffsetX(); oX = gdi.GetOffsetX();
@ -209,6 +210,17 @@ void TabList::generateList(gdioutput &gdi)
gdi.setRestorePoint("GeneralList"); gdi.setRestorePoint("GeneralList");
currentList.setCallback(ownWindow ? 0 : openRunnerTeamCB); currentList.setCallback(ownWindow ? 0 : openRunnerTeamCB);
const auto &par = currentList.getParam();
int bgColor = par.bgColor;
if (bgColor == -1 && par.screenMode == 1) {
bgColor = RGB(255, 255, 255);
}
gdi.setColorMode(bgColor,
-1,
par.fgColor,
par.bgImage);
try { try {
oe->generateList(gdi, !noReEvaluate, currentList, false); oe->generateList(gdi, !noReEvaluate, currentList, false);
} }
@ -216,8 +228,15 @@ void TabList::generateList(gdioutput &gdi)
wstring err = lang.tl(ex.wwhat()); wstring err = lang.tl(ex.wwhat());
gdi.addString("", 1, L"List Error: X#" + err).setColor(colorRed); gdi.addString("", 1, L"List Error: X#" + err).setColor(colorRed);
} }
bool wasAnimation = false;
if (par.screenMode == 1 && !par.lockUpdate) {
setAnimationMode(gdi);
wasAnimation = true;
}
else {
gdi.setOffset(oX, oY, false); gdi.setOffset(oX, oY, false);
}
int currentWidth = gdi.getWidth(); int currentWidth = gdi.getWidth();
gdi.setData("GeneralList", currentWidth); gdi.setData("GeneralList", currentWidth);
@ -237,13 +256,17 @@ void TabList::generateList(gdioutput &gdi)
baseY += 2*(3+gdi.getButtonHeight()); baseY += 2*(3+gdi.getButtonHeight());
} }
baseY += 3 + gdi.getButtonHeight(); /*baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(120),
"AutoScroll", "Automatisk skroll", ListsCB, "Rulla upp och ner automatiskt", true, false); "AutoScroll", "Automatisk skroll", ListsCB, "Rulla upp och ner automatiskt", true, false);
baseY += 3 + gdi.getButtonHeight(); baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(120), gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(120),
"FullScreen", "Fullskärm", ListsCB, "Visa listan i fullskärm", true, false); "FullScreen", "Fullskärm", ListsCB, "Visa listan i fullskärm", true, false);
*/
baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(120),
"ListDesign", "Utseende...", ListsCB, "Justera visningsinställningar", true, false);
if (!currentList.getParam().saved && !oe->isReadOnly()) { if (!currentList.getParam().saved && !oe->isReadOnly()) {
baseY += 3 + gdi.getButtonHeight(); baseY += 3 + gdi.getButtonHeight();
@ -260,12 +283,14 @@ void TabList::generateList(gdioutput &gdi)
gdi.setOnClearCb(ListsCB); gdi.setOnClearCb(ListsCB);
SelectedList="GeneralList"; SelectedList="GeneralList";
if (!wasAnimation) {
if (abs(int(currentWidth - storedWidth)) < 5) { if (abs(int(currentWidth - storedWidth)) < 5) {
gdi.refreshSmartFromSnapshot(true); gdi.refreshSmartFromSnapshot(true);
} }
else else
gdi.refresh(); gdi.refresh();
} }
}
int TabList::listCB(gdioutput &gdi, int type, void *data) int TabList::listCB(gdioutput &gdi, int type, void *data)
{ {
@ -335,22 +360,24 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
gdi.openDoc(file.c_str()); gdi.openDoc(file.c_str());
} }
} }
else if (bi.id == "ListDesign") {
gdioutput *gdi_settings = getExtraWindow("list_settings", true);
if (!gdi_settings) {
gdi_settings = createExtraWindow("list_settings", lang.tl("Inställningar"), gdi.scaleLength(600), gdi.scaleLength(400));
}
if (gdi_settings) {
loadSettings(*gdi_settings, gdi.getTag());
}
}
else if (bi.id == "Window" || bi.id == "AutoScroll" || else if (bi.id == "Window" || bi.id == "AutoScroll" ||
bi.id == "FullScreen" || bi.id == "FullScreenLive") { bi.id == "FullScreen" || bi.id == "FullScreenLive") {
gdioutput *gdi_new; gdioutput *gdi_new;
TabList *tl_new = this; TabList *tl_new = this;
if (!ownWindow) { if (!ownWindow) {
gdi_new = createExtraWindow(uniqueTag("list"), makeDash(L"MeOS - ") + currentList.getName(), gdi.getWidth() + 64 + gdi.scaleLength(120)); auto nw = makeOwnWindow(gdi);
if (gdi_new) { if (nw.first) {
TabList &tl = dynamic_cast<TabList &>(*gdi_new->getTabs().get(TListTab)); tl_new = nw.second;
tl.currentList = currentList; gdi_new = nw.first;
tl.SelectedList = SelectedList;
tl.ownWindow = true;
tl.loadPage(*gdi_new);
tl_new = &tl;
SelectedList = "";
currentList = oListInfo();
loadPage(gdi);
} }
} }
else else
@ -1129,6 +1156,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (type==GUI_CLEAR) { else if (type==GUI_CLEAR) {
offsetY=gdi.GetOffsetY(); offsetY=gdi.GetOffsetY();
offsetX=gdi.GetOffsetX(); offsetX=gdi.GetOffsetX();
leavingList(gdi.getTag());
return true; return true;
} }
else if (type == GUI_LINK) { else if (type == GUI_LINK) {
@ -1192,6 +1220,24 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
return 0; return 0;
} }
pair<gdioutput *, TabList *> TabList::makeOwnWindow(gdioutput &gdi) {
gdioutput *gdi_new = createExtraWindow(uniqueTag("list"), makeDash(L"MeOS - ") + currentList.getName(), gdi.getWidth() + 64 + gdi.scaleLength(120));
TabList *tl_new = 0;
if (gdi_new) {
TabList &tl = dynamic_cast<TabList &>(*gdi_new->getTabs().get(TListTab));
tl.currentList = currentList;
tl.SelectedList = SelectedList;
tl.ownWindow = true;
tl.loadPage(*gdi_new);
tl_new = &tl;
changeListSettingsTarget(gdi, *gdi_new);
SelectedList = "";
currentList = oListInfo();
loadPage(gdi);
}
return make_pair(gdi_new, tl_new);
}
void TabList::enableFromTo(oEvent &oe, gdioutput &gdi, bool from, bool to) { void TabList::enableFromTo(oEvent &oe, gdioutput &gdi, bool from, bool to) {
vector< pair<wstring, size_t> > d; vector< pair<wstring, size_t> > d;
oe.fillControls(d, oEvent::CTCourseControl); oe.fillControls(d, oEvent::CTCourseControl);
@ -1376,6 +1422,272 @@ void TabList::makeFromTo(gdioutput &gdi) {
gdi.dropLine(3); gdi.dropLine(3);
} }
class ListSettings : public GuiHandler {
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
string target;
if (!gdi.getData("target", target))
return;
gdioutput *dest_gdi = getExtraWindow(target, false);
if (!dest_gdi)
return;
TabBase *tb = dest_gdi->getTabs().get(TabType::TListTab);
if (tb) {
TabList *list = dynamic_cast<TabList *>(tb);
list->handleListSettings(gdi, info, type, *dest_gdi);
}
}
};
ListSettings settingsClass;
void TabList::changeListSettingsTarget(gdioutput &oldWindow, gdioutput &newWindow) {
gdioutput *gdi_settings = getExtraWindow("list_settings", true);
if (gdi_settings) {
string oldTag;
gdi_settings->getData("target", oldTag);
if (oldWindow.getTag() == oldTag)
gdi_settings->setData("target", newWindow.getTag());
}
}
void TabList::leavingList(const string &wnd) {
gdioutput *gdi_settings = getExtraWindow("list_settings", true);
if (gdi_settings) {
string oldTag;
gdi_settings->getData("target", oldTag);
if (wnd == oldTag)
gdi_settings->closeWindow();
}
}
static void addAnimationSettings(gdioutput &gdi, oListParam &dst) {
DWORD cx, cy;
gdi.getData("xmode", cx);
gdi.getData("ymode", cy);
gdi.setCX(cx);
gdi.setCY(cy);
gdi.pushX();
gdi.fillRight();
gdi.addInput("Time", itow(dst.timePerPage), 5, 0, L"Visningstid:");
gdi.addSelection("NPage", 70, 200, 0, L"Sidor per skärm:");
for (int i = 1; i <= 8; i++)
gdi.addItem("NPage", itow(i), i);
if (dst.nColumns == 0)
dst.nColumns = 1;
gdi.selectItemByData("NPage", dst.nColumns);
gdi.addInput("Margin", itow(dst.margin) + L" %", 5, 0, L"Marginal:");
gdi.dropLine(1);
gdi.addCheckbox("Animate", "Animation", 0, dst.animate);
}
static void saveAnimationSettings(gdioutput &gdi, oListParam &dst) {
dst.timePerPage = gdi.getTextNo("Time");
dst.nColumns = gdi.getSelectedItem("NPage").first;
dst.animate = gdi.isChecked("Animate");
dst.margin = gdi.getTextNo("Margin");
}
void TabList::loadSettings(gdioutput &gdi, string targetTag) {
gdi.clearPage(false);
gdi.setCX(10);
gdi.setCY(15);
gdi.setColorMode(RGB(242, 240, 250));
gdi.setData("target", targetTag);
settingsTarget = targetTag;
gdi.addString("", fontMediumPlus, L"Visningsinställningar för 'X'#" + currentList.getName());
gdi.dropLine(0.5);
gdi.addSelection("Background", 200, 100, 0, L"Bakgrund:").setHandler(&settingsClass);
gdi.addItem("Background", lang.tl("Standard"), 0);
gdi.addItem("Background", lang.tl("Färg"), 1);
//gdi.addItem("Background", lang.tl("Bild"), 2);
tmpSettingsParam = currentList.getParam();
int bgColor = currentList.getParam().bgColor;
int fgColor = currentList.getParam().fgColor;
bool useColor = bgColor != -1;
gdi.selectItemByData("Background", useColor ? 1 : 0);
gdi.pushX();
gdi.fillRight();
gdi.addButton("BGColor", "Bakgrundsfärg...").setHandler(&settingsClass).setExtra(bgColor);
gdi.setInputStatus("BGColor", useColor);
gdi.addButton("FGColor", "Textfärg...").setHandler(&settingsClass).setExtra(fgColor);
gdi.popX();
gdi.dropLine(3);
gdi.addSelection("Mode", 200, 100, 0, L"Visning:").setHandler(&settingsClass);
gdi.addItem("Mode", lang.tl("Fönster"), 0);
gdi.addItem("Mode", lang.tl("Fönster (rullande)"), 3);
gdi.addItem("Mode", lang.tl("Fullskärm (sidvis)"), 1);
gdi.addItem("Mode", lang.tl("Fullskärm (rullande)"), 2);
gdi.selectItemByData("Mode", tmpSettingsParam.screenMode);
gdi.popX();
gdi.dropLine(3);
gdi.setData("xmode", gdi.getCX());
gdi.setData("ymode", gdi.getCY());
gdi.dropLine(3);
gdi.addButton("ApplyList", "Verkställ").setHandler(&settingsClass);
if (tmpSettingsParam.screenMode == 1)
addAnimationSettings(gdi, tmpSettingsParam);
RECT rc;
rc.left = gdi.getWidth() + gdi.scaleLength(80);
rc.right = rc.left + gdi.scaleLength(150);
rc.top = 20;
gdi.addString("", rc.top, rc.left, 1, "Exempel");
rc.top += (gdi.getLineHeight() * 3) / 2;
rc.bottom = rc.top + gdi.scaleLength(200);
gdi.addRectangle(rc, bgColor != -1 ? GDICOLOR(bgColor) : GDICOLOR(colorTransparent)).id = "Background";
string val = "123. Abc MeOS";
int key = rand()%12;
for (int i = 0; i < NUMTEXTSAMPLE; i++) {
gdi.addString("Sample" + itos(i), rc.top + 3 + gdi.getLineHeight()*i,
rc.left + 3 + 5*i, i == 0 ? boldText : normalText, "#" + val).setColor(GDICOLOR(fgColor));
string val2 = val;
for (int j = 0; j < 13; j++) {
val2[j] = val[((j+1)*(key+1)) % 13];
}
val = val2;
}
gdi.refresh();
}
void TabList::handleListSettings(gdioutput &gdi, BaseInfo &info, GuiEventType type, gdioutput &dest_gdi) {
if (type == GUI_BUTTON) {
ButtonInfo bi = static_cast<ButtonInfo&>(info);
if (bi.id == "BGColor") {
wstring c = oe->getPropertyString("Colors", L"");
int res = gdi.selectColor(c, bi.getExtraInt());
if (res > -1) {
info.setExtra(res);
oe->setProperty("Colors", c);
RectangleInfo &rc = gdi.getRectangle("Background");
rc.setColor(GDICOLOR(res));
gdi.refreshFast();
}
}
else if (bi.id == "FGColor") {
wstring c = oe->getPropertyString("Colors", L"");
int inC = bi.getExtraInt();
if (inC == -1)
inC = RGB(255,255,255);
int res = gdi.selectColor(c, inC);
if (res > -1) {
info.setExtra(res);
oe->setProperty("Colors", c);
for (int i = 0; i < NUMTEXTSAMPLE; i++) {
BaseInfo &bi = gdi.getBaseInfo(("Sample" + itos(i)).c_str());
dynamic_cast<TextInfo &>(bi).setColor(GDICOLOR(res));
}
gdi.refreshFast();
}
}
else if (bi.id == "ApplyList") {
oListParam &param = currentList.getParam();
param.lockUpdate = true;
int type = gdi.getSelectedItem("Background").first;
if (type == 1)
param.bgColor = gdi.getExtraInt("BGColor");
else
param.bgColor = -1;
param.fgColor = gdi.getExtraInt("FGColor");
param.screenMode = gdi.getSelectedItem("Mode").first;
if (param.screenMode == 1) {
saveAnimationSettings(gdi, param);
}
TabList *dest = this;
gdioutput *dgdi = &dest_gdi;
int mode = param.screenMode;
if (param.screenMode == 2 || param.screenMode == 3) {
dgdi->alert("help:fullscreen");
}
if ((mode==1 || mode==2) && !dest_gdi.isFullScreen()) {
// Require fullscreen
if (!ownWindow) {
auto nw = makeOwnWindow(dest_gdi);
dest = nw.second;
dgdi = nw.first;
}
dgdi->setFullScreen(true);
dest->hideButtons = true;
}
else if ((mode == 0 || mode == 3) && dest_gdi.isFullScreen()) {
dest_gdi.setFullScreen(false);
hideButtons = false;
}
if (mode == 2 || mode == 3) {
if (!dest->ownWindow) {
auto nw = makeOwnWindow(dest_gdi);
dest = nw.second;
dgdi = nw.first;
}
dest->hideButtons = true;
int h = dgdi->setHighContrastMaxWidth();
dest->loadPage(*dgdi);
double sec = 6.0;
double delta = h * 20. / (1000. * sec);
dgdi->setAutoScroll(delta);
}
else {
dest->loadPage(*dgdi);
}
dest->currentList.getParam().lockUpdate = false;
param.lockUpdate = false;
SetForegroundWindow(dgdi->getHWNDMain());
SetWindowPos(dgdi->getHWNDMain(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
if (mode == 1) {
dest->setAnimationMode(*dgdi);
dgdi->refresh();
dest->generateList(*dgdi, true);
}
if (param.screenMode == 2 || param.screenMode == 3) {
gdi.closeWindow();
}
}
}
else if (type == GUI_LISTBOX) {
ListBoxInfo lbi = static_cast<ListBoxInfo&>(info);
if (lbi.id == "Background") {
gdi.setInputStatus("BGColor", lbi.data == 1);
BaseInfo &bi = gdi.getBaseInfo("BGColor");
if (lbi.data == 1 && bi.getExtraInt() == -1)
bi.setExtra(int(RGB(255,255,255)));
RectangleInfo &rc = gdi.getRectangle("Background");
rc.setColor(GDICOLOR(lbi.data == 1 ? bi.getExtraInt() : colorTransparent));
gdi.refreshFast();
}
else if (lbi.id == "Mode") {
if (lbi.data == 1) {
addAnimationSettings(gdi, tmpSettingsParam);
}
else {
if (gdi.hasField("Time"))
saveAnimationSettings(gdi, tmpSettingsParam);
gdi.removeControl("Time");
gdi.removeControl("NPage");
gdi.removeControl("Margin");
gdi.removeControl("Animate");
}
gdi.refresh();
}
}
}
void TabList::settingsResultList(gdioutput &gdi) void TabList::settingsResultList(gdioutput &gdi)
{ {
lastFilledResultClassType = -1; lastFilledResultClassType = -1;
@ -1569,6 +1881,7 @@ bool TabList::loadPage(gdioutput &gdi)
if (cnf.hasIndividual()) { if (cnf.hasIndividual()) {
gdi.addButton("StartIndividual", "Individuell", ListsCB); gdi.addButton("StartIndividual", "Individuell", ListsCB);
checkWidth(gdi); checkWidth(gdi);
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs))
gdi.addButton("StartClub", "Klubbstartlista", ListsCB); gdi.addButton("StartClub", "Klubbstartlista", ListsCB);
} }
@ -1611,8 +1924,11 @@ bool TabList::loadPage(gdioutput &gdi)
if (cnf.hasIndividual()) { if (cnf.hasIndividual()) {
gdi.addButton("ResultIndividual", "Individuell", ListsCB); gdi.addButton("ResultIndividual", "Individuell", ListsCB);
checkWidth(gdi); checkWidth(gdi);
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
gdi.addButton("ResultClub", "Klubbresultat", ListsCB); gdi.addButton("ResultClub", "Klubbresultat", ListsCB);
checkWidth(gdi); checkWidth(gdi);
}
gdi.addButton("ResultIndSplit", "Sträcktider", ListsCB); gdi.addButton("ResultIndSplit", "Sträcktider", ListsCB);
checkWidth(gdi); checkWidth(gdi);
@ -2098,3 +2414,9 @@ void TabList::clearCompetitionData() {
listEditor = 0; listEditor = 0;
methodEditor = 0; methodEditor = 0;
} }
void TabList::setAnimationMode(gdioutput &gdi) {
auto par = currentList.getParam();
gdi.setAnimationMode(make_shared<AnimationData>(gdi, par.timePerPage, par.nColumns,
par.margin, par.animate));
}

View File

@ -48,7 +48,7 @@ protected:
static void createListButtons(gdioutput &gdi); static void createListButtons(gdioutput &gdi);
void generateList(gdioutput &gdi); void generateList(gdioutput &gdi, bool forceUpdate = false);
void selectGeneralList(gdioutput &gdi, EStdListType type); void selectGeneralList(gdioutput &gdi, EStdListType type);
int offsetY; int offsetY;
@ -78,6 +78,15 @@ private:
TabList(const TabList &); TabList(const TabList &);
const TabList &operator = (const TabList &); const TabList &operator = (const TabList &);
string settingsTarget;
oListParam tmpSettingsParam;
void changeListSettingsTarget(gdioutput &oldWindow, gdioutput &newWindow);
void leavingList(const string &wnd);
pair<gdioutput *, TabList *> makeOwnWindow(gdioutput &gdi);
/** Set animation mode*/
void setAnimationMode(gdioutput &gdi);
public: public:
bool loadPage(gdioutput &gdi); bool loadPage(gdioutput &gdi);
bool loadPage(gdioutput &gdi, const string &command); bool loadPage(gdioutput &gdi, const string &command);
@ -94,6 +103,8 @@ public:
void rebuildList(gdioutput &gdi); void rebuildList(gdioutput &gdi);
void settingsResultList(gdioutput &gdi); void settingsResultList(gdioutput &gdi);
void loadSettings(gdioutput &gdi, string targetTag);
void handleListSettings(gdioutput &gdi, BaseInfo &info, GuiEventType type, gdioutput &dest_gdi);
enum PrintSettingsSelection { enum PrintSettingsSelection {
Splits = 0, Splits = 0,
StartInfo = 1, StartInfo = 1,

View File

@ -199,7 +199,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
gdi.setText("Team", L""); gdi.setText("Team", L"");
} }
gdi.setText("TimeAdjust", getTimeMSW(r->getTimeAdjustment())); gdi.setText("TimeAdjust", getTimeMS(r->getTimeAdjustment()));
gdi.setText("PointAdjust", -r->getPointAdjustment()); gdi.setText("PointAdjust", -r->getPointAdjustment());
#ifdef _DEBUG #ifdef _DEBUG
@ -216,22 +216,22 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
r->getLegTimeAfterAcc(afterAcc); r->getLegTimeAfterAcc(afterAcc);
r->getLegPlacesAcc(placeAcc); r->getLegPlacesAcc(placeAcc);
string out; wstring out;
for (size_t k = 0; k<delta.size(); k++) { for (size_t k = 0; k<delta.size(); k++) {
out += itos(place[k]); out += itow(place[k]);
if (k<placeAcc.size()) if (k<placeAcc.size())
out += " (" + itos(placeAcc[k]) + ")"; out += L" (" + itow(placeAcc[k]) + L")";
if (after[k]>0) if (after[k]>0)
out+= " +" + getTimeMS(after[k]); out+= L" +" + getTimeMS(after[k]);
if (k<afterAcc.size() && afterAcc[k]>0) if (k<afterAcc.size() && afterAcc[k]>0)
out+= " (+" + getTimeMS(afterAcc[k]) + ")"; out+= L" (+" + getTimeMS(afterAcc[k]) + L")";
if (delta[k]>0) if (delta[k]>0)
out+= " B: " + getTimeMS(delta[k]); out+= L" B: " + getTimeMS(delta[k]);
out += " | "; out += L" | ";
} }
gdi.restore("fantom", false); gdi.restore("fantom", false);
@ -805,6 +805,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
for (size_t k=0; k<unknown.size(); k++) { for (size_t k=0; k<unknown.size(); k++) {
if (unknown[k]->getStatus()==StatusUnknown) { if (unknown[k]->getStatus()==StatusUnknown) {
unknown[k]->setStatus(StatusDNS, true, false); unknown[k]->setStatus(StatusDNS, true, false);
unknown[k]->setFlag(oAbstractRunner::FlagAutoDNS, true);
unknown[k]->synchronize(true); unknown[k]->synchronize(true);
} }
} }
@ -813,6 +814,21 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
clearInForestData(); clearInForestData();
showInForestList(gdi); showInForestList(gdi);
} }
else if (bi.id == "UndoSetDNS") {
vector<pRunner> runners;
oe->getRunners(0, 0, runners, true);
for (pRunner r : runners) {
if (r->getStatus() == StatusDNS && r->hasFlag(oAbstractRunner::FlagAutoDNS)) {
r->setStatus(StatusUnknown, true, false);
r->setFlag(oAbstractRunner::FlagAutoDNS, false);
r->synchronize(true);
}
}
//Reevaluate and synchronize all
oe->reEvaluateAll(set<int>(), true);
clearInForestData();
showInForestList(gdi);
}
else if (bi.id=="SetUnknown") { else if (bi.id=="SetUnknown") {
for (size_t k=0; k<known_dns.size(); k++) { for (size_t k=0; k<known_dns.size(); k++) {
if (known_dns[k]->getStatus()==StatusDNS) { if (known_dns[k]->getStatus()==StatusDNS) {
@ -842,7 +858,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
pRunner r=oe->getRunner(runnerId, 0); pRunner r=oe->getRunner(runnerId, 0);
if (!r) return 0; if (!r) return 0;
gdioutput gdiprint(2.0, gdi.getHWND(), splitPrinter, gdi.getCP()); gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
if (bi.getExtraInt() == 0) if (bi.getExtraInt() == 0)
r->printSplits(gdiprint); r->printSplits(gdiprint);
else else
@ -917,6 +933,14 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
selectRunner(gdi, 0); selectRunner(gdi, 0);
} }
} }
}
else if (bi.id == "Economy") {
if (!runnerId)
return 0;
pRunner r = oe->getRunner(runnerId, 0);
gdioutput *settings = createExtraWindow("ecosettings", L"Economy for X#" + r->getName(), 400, 200);
} }
else if (bi.id=="NoStart") { else if (bi.id=="NoStart") {
if (!runnerId) if (!runnerId)
@ -938,8 +962,8 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
pRunner rr = r->getMultiRunner(k); pRunner rr = r->getMultiRunner(k);
if (rr) { if (rr) {
rr->setStartTime(0, true, false); rr->setStartTime(0, true, false);
rr->setStartNo(0, false); //rr->setStartNo(0, false);
rr->setStatus(StatusDNS, true, false); rr->setStatus(StatusCANCEL, true, false);
rr->setCardNo(0, false); rr->setCardNo(0, false);
} }
} }
@ -1051,7 +1075,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
} }
runnerId = bi.data; runnerId = bi.data;
//loadPage(gdi); //loadPage(gdi);
PostMessage(gdi.getTarget(), WM_USER + 2, TRunnerTab, 0); PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TRunnerTab, 0);
} }
else if (bi.id=="RClass") { else if (bi.id=="RClass") {
gdi.selectItemByData("RCourse", 0); gdi.selectItemByData("RCourse", 0);
@ -1318,7 +1342,8 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
} }
} }
r->getDI().setDate("EntryDate", getLocalDateW()); r->getDI().setDate("EntryDate", getLocalDate());
r->getDI().setInt("EntryTime", getLocalAbsTime());
r->addClassDefaultFee(false); r->addClassDefaultFee(false);
int cardFee = 0; int cardFee = 0;
@ -1329,8 +1354,6 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
else else
r->getDI().setInt("CardFee", 0); r->getDI().setInt("CardFee", 0);
if (cardFee < 0) if (cardFee < 0)
cardFee = 0; cardFee = 0;
fee = r->getDCI().getInt("Fee"); fee = r->getDCI().getInt("Fee");
@ -1482,7 +1505,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
if (t->statusOK()) { if (t->statusOK()) {
tInfo += L", " + t->getRunningTimeS() + lang.tl(".S Placering: ") + t->getPlaceS(); tInfo += L", " + t->getRunningTimeS() + lang.tl(".S Placering: ") + t->getPlaceS();
if (t->getTimeAfter(-1) > 0) if (t->getTimeAfter(-1) > 0)
tInfo += L", +" + formatTimeW(t->getTimeAfter(-1)); tInfo += L", +" + formatTime(t->getTimeAfter(-1));
} }
else if (t->getStatus() != StatusUnknown) { else if (t->getStatus() != StatusUnknown) {
tInfo += L" " + t->getStatusS(); tInfo += L" " + t->getStatusS();
@ -1640,7 +1663,7 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
GDICOLOR color = colorDefault; GDICOLOR color = colorDefault;
if (k < int(after.size()) ) { if (k < int(after.size()) ) {
if (after[k] > 0) if (after[k] > 0)
split += L" (" + itow(place[k]) + L", +" + getTimeMSW(after[k]) + L")"; split += L" (" + itow(place[k]) + L", +" + getTimeMS(after[k]) + L")";
else if (place[k] == 1) else if (place[k] == 1)
split += lang.tl(" (sträckseger)"); split += lang.tl(" (sträckseger)");
else if (place[k] > 0) else if (place[k] > 0)
@ -1656,7 +1679,7 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
wstring pl = placeAcc[k] > 0 ? itow(placeAcc[k]) : L"-"; wstring pl = placeAcc[k] > 0 ? itow(placeAcc[k]) : L"-";
if (k < int(afterAcc.size()) ) { if (k < int(afterAcc.size()) ) {
if (afterAcc[k] > 0) if (afterAcc[k] > 0)
split += L" (" + pl + L", +" + getTimeMSW(afterAcc[k]) + L")"; split += L" (" + pl + L", +" + getTimeMS(afterAcc[k]) + L")";
else if (placeAcc[k] == 1) else if (placeAcc[k] == 1)
split += lang.tl(" (ledare)"); split += lang.tl(" (ledare)");
else if (placeAcc[k] > 0) else if (placeAcc[k] > 0)
@ -1666,7 +1689,7 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
} }
if (k < int(delta.size()) && delta[k] > 0 ) { if (k < int(delta.size()) && delta[k] > 0 ) {
gdi.addString("", yp + 3*lh, cx, fontMedium, "Bomtid: X#" + getTimeMS(delta[k])); gdi.addString("", yp + 3*lh, cx, fontMedium, L"Bomtid: X#" + getTimeMS(delta[k]));
color = (delta[k] > bestTime * 0.5 && delta[k]>60 ) ? color = (delta[k] > bestTime * 0.5 && delta[k]>60 ) ?
colorMediumDarkRed : colorMediumRed; colorMediumDarkRed : colorMediumRed;
@ -1724,9 +1747,9 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
int st = r->getStartTime(); int st = r->getStartTime();
gdi.addString("", yp + lh, cx, normalText, L"Klocktid: X#" + oe->getAbsTime(t), limit); gdi.addString("", yp + lh, cx, normalText, L"Klocktid: X#" + oe->getAbsTime(t), limit);
if (st > 0 && t > st) { if (st > 0 && t > st) {
string split = formatTimeHMS(t-st); wstring split = formatTimeHMS(t-st);
if (lastT>0 && st != lastT && lastT < t) if (lastT>0 && st != lastT && lastT < t)
split += " (" + getTimeMS(t-lastT) + ")"; split += L" (" + getTimeMS(t-lastT) + L")";
gdi.addStringUT(yp + 2*lh, cx, normalText, split, limit); gdi.addStringUT(yp + 2*lh, cx, normalText, split, limit);
} }
} }
@ -1925,7 +1948,8 @@ void TabRunner::showInForestList(gdioutput &gdi)
gdi.popX(); gdi.popX();
clearInForestData(); clearInForestData();
oe->analyseDNS(unknown_dns, known_dns, known, unknown); bool hasDNS;
oe->analyseDNS(unknown_dns, known_dns, known, unknown, hasDNS);
oe->setupCardHash(false); oe->setupCardHash(false);
if (!unknown.empty()) { if (!unknown.empty()) {
gdi.dropLine(); gdi.dropLine();
@ -1933,9 +1957,16 @@ void TabRunner::showInForestList(gdioutput &gdi)
gdi.addString("", 1, "Löpare, Status Okänd, som saknar registrering"); gdi.addString("", 1, "Löpare, Status Okänd, som saknar registrering");
listRunners(gdi, unknown, true); listRunners(gdi, unknown, true);
} }
else {
if (hasDNS) {
BaseInfo &bi = gdi.getBaseInfo("SetDNS");
bi.id = "UndoSetDNS";
gdi.setTextTranslate(bi.id, L"Återställ <Ej Start> till <Status Okänd>");
}
else { else {
gdi.disableInput("SetDNS"); gdi.disableInput("SetDNS");
} }
}
if (!known.empty()) { if (!known.empty()) {
gdi.dropLine(); gdi.dropLine();
@ -2349,16 +2380,19 @@ bool TabRunner::loadPage(gdioutput &gdi)
} }
gdi.fillRight(); gdi.fillRight();
gdi.addSelection("RClass", 150, 300, RunnerCB, L"Klass:"); gdi.addSelection("RClass", 130, 300, RunnerCB, L"Klass:");
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterNone); oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterNone);
gdi.addItem("RClass", lang.tl("Ingen klass"), 0); gdi.addItem("RClass", lang.tl("Ingen klass"), 0);
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy)) {
gdi.fillDown();
gdi.addInput("Fee", L"", 4, 0, L"Avgift:");
//gdi.addButton("Economy", "@" + itos(131), RunnerCB, "Ekonomi...");
}
else {
gdi.fillDown(); gdi.fillDown();
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy))
gdi.addInput("Fee", L"", 6, 0, L"Avgift:");
else
gdi.dropLine(3); gdi.dropLine(3);
}
gdi.dropLine(0.4); gdi.dropLine(0.4);

View File

@ -948,7 +948,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
throw meosException("Löparen hittades inte"); throw meosException("Löparen hittades inte");
bool useNow = gdi.getExtraInt("FinishTime") == 1; bool useNow = gdi.getExtraInt("FinishTime") == 1;
wstring time = useNow ? getLocalTimeOnlyW() : gdi.getText("FinishTime"); wstring time = useNow ? getLocalTimeOnly() : gdi.getText("FinishTime");
int relTime = oe->getRelativeTime(time); int relTime = oe->getRelativeTime(time);
if (relTime <= 0) { if (relTime <= 0) {
@ -1097,7 +1097,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
} }
else if (bi.id == "NC") { else if (bi.id == "NC") {
NC = bi.data; NC = bi.data;
PostMessage(gdi.getTarget(), WM_USER + 2, TSITab, 0); PostMessage(gdi.getHWNDTarget(), WM_USER + 2, TSITab, 0);
} }
} }
else if (type == GUI_LINK) { else if (type == GUI_LINK) {
@ -1473,7 +1473,7 @@ void TabSI::showReadCards(gdioutput &gdi, vector<SICard> &cards)
SportIdent &TabSI::getSI(const gdioutput &gdi) { SportIdent &TabSI::getSI(const gdioutput &gdi) {
if (!gSI) { if (!gSI) {
HWND hWnd=gdi.getMain(); HWND hWnd=gdi.getHWNDMain();
gSI = new SportIdent(hWnd, 0); gSI = new SportIdent(hWnd, 0);
gSI->setZeroTime(gEvent->getZeroTimeNum()); gSI->setZeroTime(gEvent->getZeroTimeNum());
} }
@ -2681,7 +2681,7 @@ void TabSI::generateSplits(const pRunner r, gdioutput &gdi)
while(checkpPrintQueue(gdi)); while(checkpPrintQueue(gdi));
} }
else { else {
gdioutput gdiprint(2.0, gdi.getHWND(), splitPrinter, gdi.getCP()); gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
vector<int> mp; vector<int> mp;
r->evaluateCard(true, mp); r->evaluateCard(true, mp);
r->printSplits(gdiprint); r->printSplits(gdiprint);
@ -2692,7 +2692,7 @@ void TabSI::generateSplits(const pRunner r, gdioutput &gdi)
void TabSI::generateStartInfo(gdioutput &gdi, const oRunner &r) { void TabSI::generateStartInfo(gdioutput &gdi, const oRunner &r) {
if (printStartInfo) { if (printStartInfo) {
gdioutput gdiprint(2.0, gdi.getHWND(), splitPrinter, gdi.getCP()); gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
r.printStartInfo(gdiprint); r.printStartInfo(gdiprint);
printProtected(gdi, gdiprint); printProtected(gdi, gdiprint);
//gdiprint.print(splitPrinter, oe, false, true); //gdiprint.print(splitPrinter, oe, false, true);
@ -3023,7 +3023,7 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const { void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
SICard &c = getCard(cardId); SICard &c = getCard(cardId);
if (c.readOutTime[0] == 0) if (c.readOutTime[0] == 0)
strcpy_s(c.readOutTime, getLocalTime().c_str()); strcpy_s(c.readOutTime, getLocalTimeN().c_str());
gdi.pushX(); gdi.pushX();
gdi.fillRight(); gdi.fillRight();
@ -3066,10 +3066,10 @@ void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
int start = NOTIME; int start = NOTIME;
if (c.CheckPunch.Code != -1) if (c.CheckPunch.Code != -1)
gdi.addString("", 0, "Check: X#" + formatTimeHMS(c.CheckPunch.Time)); gdi.addString("", 0, L"Check: X#" + formatTimeHMS(c.CheckPunch.Time));
if (c.StartPunch.Code != -1) { if (c.StartPunch.Code != -1) {
gdi.addString("", 0, "Start: X#" + formatTimeHMS(c.StartPunch.Time)); gdi.addString("", 0, L"Start: X#" + formatTimeHMS(c.StartPunch.Time));
start = c.StartPunch.Time; start = c.StartPunch.Time;
} }
int xp = gdi.getCX(); int xp = gdi.getCX();
@ -3088,9 +3088,9 @@ void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
if (start != NOTIME) { if (start != NOTIME) {
int legTime = analyzePunch(c.Punch[k], start, accTime, days); int legTime = analyzePunch(c.Punch[k], start, accTime, days);
if (legTime > 0) if (legTime > 0)
gdi.addStringUT(cy, xp5-gdi.scaleLength(10), textRight, formatTimeW(legTime)); gdi.addStringUT(cy, xp5-gdi.scaleLength(10), textRight, formatTime(legTime));
gdi.addStringUT(cy, xp5 + gdi.scaleLength(40), textRight, formatTimeW(days*3600*24 + accTime)); gdi.addStringUT(cy, xp5 + gdi.scaleLength(40), textRight, formatTime(days*3600*24 + accTime));
} }
else { else {
start = c.Punch[k].Time; start = c.Punch[k].Time;
@ -3104,11 +3104,11 @@ void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
if (start != NOTIME) { if (start != NOTIME) {
int legTime = analyzePunch(c.FinishPunch, start, accTime, days); int legTime = analyzePunch(c.FinishPunch, start, accTime, days);
if (legTime > 0) if (legTime > 0)
gdi.addStringUT(cy, xp5-gdi.scaleLength(10), textRight, formatTimeW(legTime)); gdi.addStringUT(cy, xp5-gdi.scaleLength(10), textRight, formatTime(legTime));
gdi.addStringUT(cy, xp5 + gdi.scaleLength(40), textRight, formatTimeW(days*3600*24 + accTime)); gdi.addStringUT(cy, xp5 + gdi.scaleLength(40), textRight, formatTime(days*3600*24 + accTime));
} }
gdi.addString("", 1, L"Time: X#" + formatTimeW(days*3600*24 + accTime)); gdi.addString("", 1, L"Time: X#" + formatTime(days*3600*24 + accTime));
} }
if (forPrinter) { if (forPrinter) {
@ -3143,7 +3143,7 @@ int TabSI::analyzePunch(SIPunch &p, int &start, int &accTime, int &days) {
} }
void TabSI::generateSplits(int cardId, gdioutput &gdi) { void TabSI::generateSplits(int cardId, gdioutput &gdi) {
gdioutput gdiprint(2.0, gdi.getHWND(), splitPrinter, gdi.getCP()); gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
printCard(gdiprint, cardId, true); printCard(gdiprint, cardId, true);
printProtected(gdi, gdiprint); printProtected(gdi, gdiprint);
} }
@ -3196,7 +3196,7 @@ void TabSI::createCompetitionFromCards(gdioutput &gdi) {
if (zeroTime < 0) if (zeroTime < 0)
zeroTime += 3600 * 24; zeroTime += 3600 * 24;
zeroTime -= zeroTime % 1800; zeroTime -= zeroTime % 1800;
oe->setZeroTime(formatTimeW(zeroTime)); oe->setZeroTime(formatTime(zeroTime));
int course = 0; int course = 0;
for (size_t k = 0; k < cards.size(); k++) { for (size_t k = 0; k < cards.size(); k++) {
@ -3570,7 +3570,7 @@ bool TabSI::checkpPrintQueue(gdioutput &gdi) {
return false; // Wait a little longer return false; // Wait a little longer
} }
gdioutput gdiprint(2.0, gdi.getHWND(), splitPrinter, gdi.getCP()); gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
vector<int> mp; vector<int> mp;
for (size_t m = 0; m < printLen && !printPunchRunnerIdQueue.empty(); m++) { for (size_t m = 0; m < printLen && !printPunchRunnerIdQueue.empty(); m++) {
int rid = printPunchRunnerIdQueue.front().second; int rid = printPunchRunnerIdQueue.front().second;

View File

@ -662,7 +662,7 @@ void TabSpeaker::splitAnalysis(gdioutput &gdi, int xp, int yp, pRunner r)
else else
first = false; first = false;
timeloss += pc->getControlOrdinal(j) + L". " + formatTimeW(delta[j]); timeloss += pc->getControlOrdinal(j) + L". " + formatTime(delta[j]);
} }
if (timeloss.length() > charlimit || (!timeloss.empty() && !first && j+1 == delta.size())) { if (timeloss.length() > charlimit || (!timeloss.empty() && !first && j+1 == delta.size())) {
gdi.addStringUT(yp, xp, 0, timeloss).setColor(colorDarkRed); gdi.addStringUT(yp, xp, 0, timeloss).setColor(colorDarkRed);
@ -876,7 +876,7 @@ int TabSpeaker::processListBox(gdioutput &gdi, const ListBoxInfo &bu)
} }
} }
else if (bu.id == "MultiStage") { else if (bu.id == "MultiStage") {
getSpeakerMonitor()->useTotalResults(gdi.isChecked(bu.id)); getSpeakerMonitor()->useTotalResults(bu.data != 0);
updateTimeLine(gdi); updateTimeLine(gdi);
} }
else if (bu.id == "DetailLevel") { else if (bu.id == "DetailLevel") {
@ -1087,7 +1087,7 @@ void TabSpeaker::storeManualTime(gdioutput &gdi)
wstring time=gdi.getText("Time"); wstring time=gdi.getText("Time");
if (time.empty()) if (time.empty())
time=getLocalTimeOnlyW(); time=getLocalTimeOnly();
int itime=oe->getRelativeTime(time); int itime=oe->getRelativeTime(time);
@ -1240,7 +1240,7 @@ void TabSpeaker::importSettings(gdioutput &gdi, multimap<string, wstring> &setti
selectedControl.clear(); selectedControl.clear();
int ctrl = 0, leg = 0, total = 0; int ctrl = 0, leg = 0, total = 0;
for (auto s : settings) { for (auto &s : settings) {
if (s.first == "currentClass") { if (s.first == "currentClass") {
if (s.second == L"@Events") { if (s.second == L"@Events") {
classId = -1; classId = -1;
@ -1312,11 +1312,11 @@ void TabSpeaker::loadSettings(vector< multimap<string, wstring> > &settings) {
xmlList xmlsettings; xmlList xmlsettings;
sp.getObjects(xmlsettings); sp.getObjects(xmlsettings);
for (auto s : xmlsettings) { for (auto &s : xmlsettings) {
settings.push_back(multimap<string, wstring>()); settings.push_back(multimap<string, wstring>());
xmlList allS; xmlList allS;
s.getObjects(allS); s.getObjects(allS);
for (auto prop : allS) { for (auto &prop : allS) {
settings.back().insert(make_pair(prop.getName(), prop.getw())); settings.back().insert(make_pair(prop.getName(), prop.getw()));
} }
} }
@ -1326,9 +1326,9 @@ void TabSpeaker::saveSettings(const vector< multimap<string, wstring> > &setting
xmlparser d; xmlparser d;
d.openOutput(getSpeakerSettingsFile().c_str(), false); d.openOutput(getSpeakerSettingsFile().c_str(), false);
d.startTag("Speaker"); d.startTag("Speaker");
for (auto s : settings) { for (auto &s : settings) {
d.startTag("SpeakerWindow"); d.startTag("SpeakerWindow");
for (auto prop : s) { for (auto &prop : s) {
d.write(prop.first.c_str(), prop.second); d.write(prop.first.c_str(), prop.second);
} }
d.endTag(); d.endTag();

View File

@ -270,7 +270,7 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
gdi.setText("Start", t->getStartTimeS()); gdi.setText("Start", t->getStartTimeS());
gdi.setText("Finish",t->getFinishTimeS()); gdi.setText("Finish",t->getFinishTimeS());
gdi.setText("Time", t->getRunningTimeS()); gdi.setText("Time", t->getRunningTimeS());
gdi.setText("TimeAdjust", getTimeMSW(t->getTimeAdjustment())); gdi.setText("TimeAdjust", getTimeMS(t->getTimeAdjustment()));
gdi.setText("PointAdjust", -t->getPointAdjustment()); gdi.setText("PointAdjust", -t->getPointAdjustment());
gdi.selectItemByData("Status", t->getStatus()); gdi.selectItemByData("Status", t->getStatus());
} }
@ -342,11 +342,11 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
RunnerStatus sIn = (RunnerStatus)lbi.data; RunnerStatus sIn = (RunnerStatus)lbi.data;
// Must be done AFTER all runners are set. But setting runner can modify status, so decide here. // Must be done AFTER all runners are set. But setting runner can modify status, so decide here.
bool setDNS = (sIn == StatusDNS) && (t->getStatus()!=StatusDNS); bool setDNS = (sIn == StatusDNS || sIn == StatusCANCEL) && (t->getStatus() != sIn);
bool checkStatus = (sIn != t->getStatus()); bool checkStatus = (sIn != t->getStatus());
if (sIn == StatusUnknown && t->getStatus() == StatusDNS) if (sIn == StatusUnknown && (t->getStatus() == StatusDNS || t->getStatus() == StatusCANCEL))
t->setTeamNoStart(false); t->setTeamNoStart(false, StatusDNS);
else if ((RunnerStatus)lbi.data != t->getStatus()) else if ((RunnerStatus)lbi.data != t->getStatus())
t->setStatus((RunnerStatus)lbi.data, true, false); t->setStatus((RunnerStatus)lbi.data, true, false);
@ -464,7 +464,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
} }
if (setDNS) if (setDNS)
t->setTeamNoStart(true); t->setTeamNoStart(true, sIn);
if (t->checkValdParSetup()) { if (t->checkValdParSetup()) {
gdi.alert("Laguppställningen hade fel, som har rättats"); gdi.alert("Laguppställningen hade fel, som har rättats");
@ -662,7 +662,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
selectTeam(gdi, t); selectTeam(gdi, t);
} }
else if (bi.id == "Browse") { else if (bi.id == "Browse") {
const char *target = (const char *)bi.getExtra(); const wchar_t *target = bi.getExtra();
vector< pair<wstring, wstring> > ext; vector< pair<wstring, wstring> > ext;
ext.push_back(make_pair(L"Laguppställning", L"*.csv;*.txt")); ext.push_back(make_pair(L"Laguppställning", L"*.csv;*.txt"));
wstring fileName = gdi.browseForOpen(ext, L"csv"); wstring fileName = gdi.browseForOpen(ext, L"csv");

View File

@ -33,6 +33,7 @@
#include "gdiconstants.h" #include "gdiconstants.h"
#include "meosexception.h" #include "meosexception.h"
#include "recorder.h" #include "recorder.h"
#include "oDataContainer.h"
extern HINSTANCE hInst; extern HINSTANCE hInst;
const char *tId="_TABLE_SEL"; const char *tId="_TABLE_SEL";
@ -103,9 +104,9 @@ void Table::clearCellSelection(gdioutput *gdi) {
upperCol = -1; upperCol = -1;
lowerCol = -1; lowerCol = -1;
if (gdi) { if (gdi) {
HDC hDC = GetDC(gdi->getTarget()); HDC hDC = GetDC(gdi->getHWNDTarget());
clearSelectionBitmap(gdi, hDC); clearSelectionBitmap(gdi, hDC);
ReleaseDC(gdi->getTarget(), hDC); ReleaseDC(gdi->getHWNDTarget(), hDC);
} }
} }
@ -567,7 +568,7 @@ bool Table::mouseMove(gdioutput &gdi, int x, int y)
if (row!=-1) if (row!=-1)
col=getColumn(x); col=getColumn(x);
HWND hWnd=gdi.getTarget(); HWND hWnd=gdi.getHWNDTarget();
if (colSelected!=-1) { if (colSelected!=-1) {
TableCell &cell=Data[0].cells[colSelected]; TableCell &cell=Data[0].cells[colSelected];
@ -673,7 +674,7 @@ bool Table::mouseLeftUp(gdioutput &gdi, int x, int y)
if (hdcCompatible) { if (hdcCompatible) {
TableCell &cell=Data[0].cells[colSelected]; TableCell &cell=Data[0].cells[colSelected];
HWND hWnd=gdi.getTarget(); HWND hWnd=gdi.getHWNDTarget();
HDC hDC=GetDC(hWnd); HDC hDC=GetDC(hWnd);
stopMoveCell(hDC, cell, x-startX, y-startY); stopMoveCell(hDC, cell, x-startX, y-startY);
ReleaseDC(hWnd, hDC); ReleaseDC(hWnd, hDC);
@ -691,7 +692,7 @@ bool Table::mouseLeftUp(gdioutput &gdi, int x, int y)
} }
else { else {
moveColumn(colSelected, highCol); moveColumn(colSelected, highCol);
InvalidateRect(gdi.getTarget(), 0, false); InvalidateRect(gdi.getHWNDTarget(), 0, false);
colSelected=-1; colSelected=-1;
return true; return true;
} }
@ -726,7 +727,7 @@ void Table::selection(gdioutput &gdi, const wstring &text, int data) {
reloadRow(id); reloadRow(id);
RECT rc; RECT rc;
getRowRect(selectionRow, rc); getRowRect(selectionRow, rc);
InvalidateRect(gdi.getTarget(), &rc, false); InvalidateRect(gdi.getHWNDTarget(), &rc, false);
} }
#ifndef MEOSDB #ifndef MEOSDB
@ -868,7 +869,7 @@ bool Table::mouseLeftDown(gdioutput &gdi, int x, int y) {
hEdit=CreateWindowEx(0, L"EDIT", Titles[highCol].filter.c_str(), hEdit=CreateWindowEx(0, L"EDIT", Titles[highCol].filter.c_str(),
WS_TABSTOP|WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL|WS_BORDER, WS_TABSTOP|WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL|WS_BORDER,
rc.left+105, rc.top, tableWidth-105, (rc.bottom-rc.top-1), gdi.getTarget(), rc.left+105, rc.top, tableWidth-105, (rc.bottom-rc.top-1), gdi.getHWNDTarget(),
0, hInst, 0); 0, hInst, 0);
drawFilterLabel=true; drawFilterLabel=true;
SendMessage(hEdit, EM_SETSEL, 0, -1); SendMessage(hEdit, EM_SETSEL, 0, -1);
@ -877,8 +878,8 @@ bool Table::mouseLeftDown(gdioutput &gdi, int x, int y) {
gdi.refresh(); gdi.refresh();
} }
else { else {
SetFocus(gdi.getHWND()); SetFocus(gdi.getHWNDTarget());
SetCapture(gdi.getTarget()); SetCapture(gdi.getHWNDTarget());
lowerCol = getColumn(x); lowerCol = getColumn(x);
lowerRow = getRow(y); lowerRow = getRow(y);
startSelect = true; startSelect = true;
@ -954,7 +955,7 @@ bool Table::editCell(gdioutput &gdi, int row, int col) {
else if (cell.type==cellEdit) { else if (cell.type==cellEdit) {
hEdit=CreateWindowEx(0, L"EDIT", cell.contents.c_str(), hEdit=CreateWindowEx(0, L"EDIT", cell.contents.c_str(),
WS_TABSTOP|WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL|WS_BORDER, WS_TABSTOP|WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL|WS_BORDER,
rc.left, rc.top, rc.right-rc.left+1, (rc.bottom-rc.top), gdi.getTarget(), rc.left, rc.top, rc.right-rc.left+1, (rc.bottom-rc.top), gdi.getHWNDTarget(),
0, hInst, 0); 0, hInst, 0);
SendMessage(hEdit, EM_SETSEL, 0, -1); SendMessage(hEdit, EM_SETSEL, 0, -1);
SetFocus(hEdit); SetFocus(hEdit);
@ -1276,7 +1277,7 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
RECT desktop, target; RECT desktop, target;
GetClientRect(GetDesktopWindow(), &desktop); GetClientRect(GetDesktopWindow(), &desktop);
GetClientRect(gdi.getTarget(), &target); GetClientRect(gdi.getHWNDTarget(), &target);
int marginPixel = (desktop.bottom - desktop.top) - (target.bottom - target.top); int marginPixel = (desktop.bottom - desktop.top) - (target.bottom - target.top);
int margin = max(5, (marginPixel + rowHeight) / rowHeight); int margin = max(5, (marginPixel + rowHeight) / rowHeight);
@ -1398,7 +1399,7 @@ void Table::restoreSelection(gdioutput &gdi, HDC hDC) {
rc.right -= gdi.OffsetX; rc.right -= gdi.OffsetX;
rc.top -= gdi.OffsetY; rc.top -= gdi.OffsetY;
rc.bottom -= gdi.OffsetY; rc.bottom -= gdi.OffsetY;
InvalidateRect(gdi.getTarget(), &rc, false); InvalidateRect(gdi.getHWNDTarget(), &rc, false);
partialCell = false; partialCell = false;
} }
else if (hdcCompatibleCell) { else if (hdcCompatibleCell) {
@ -1598,7 +1599,7 @@ void Table::setTableText(gdioutput &gdi, int editRow, int editCol, const wstring
reloadRow(Data[editRow].id); reloadRow(Data[editRow].id);
RECT rc; RECT rc;
getRowRect(editRow, rc); getRowRect(editRow, rc);
InvalidateRect(gdi.getTarget(), &rc, false); InvalidateRect(gdi.getHWNDTarget(), &rc, false);
} }
const wstring &Table::getTableText(gdioutput &gdi, int editRow, int editCol) { const wstring &Table::getTableText(gdioutput &gdi, int editRow, int editCol) {
@ -1802,6 +1803,8 @@ void Table::resetColumns()
void Table::update() void Table::update()
{ {
for (auto &dd : dataDefiners)
dd.second->prepare(oe);
int oldSort = PrevSort; int oldSort = PrevSort;
Data.clear(); Data.clear();
sortIndex.clear(); sortIndex.clear();
@ -1821,7 +1824,6 @@ void Table::update()
for (size_t k=0;k<nTitles;k++) for (size_t k=0;k<nTitles;k++)
filter(k, Titles[k].filter, true); filter(k, Titles[k].filter, true);
PrevSort = -1; PrevSort = -1;
if (oldSort != -1) if (oldSort != -1)
sort(oldSort); sort(oldSort);
@ -1980,7 +1982,7 @@ void Table::importClipboard(gdioutput &gdi)
throw std::exception("Operationen stöds ej"); throw std::exception("Operationen stöds ej");
wstring str; wstring str;
if (OpenClipboard(gdi.getHWND()) != false) { if (OpenClipboard(gdi.getHWNDMain()) != false) {
HANDLE data = GetClipboardData(CF_UNICODETEXT); HANDLE data = GetClipboardData(CF_UNICODETEXT);
if (data) { if (data) {
@ -2187,7 +2189,7 @@ void Table::autoAdjust(gdioutput &gdi) {
initEmpty(); initEmpty();
if (Titles.empty()) if (Titles.empty())
return; return;
HDC hDC = GetDC(gdi.getTarget()); HDC hDC = GetDC(gdi.getHWNDTarget());
RECT rc = {0,0,0,0}; RECT rc = {0,0,0,0};
TextInfo ti; TextInfo ti;
wstring filterText = lang.tl("Urval..."); wstring filterText = lang.tl("Urval...");
@ -2241,7 +2243,7 @@ void Table::autoAdjust(gdioutput &gdi) {
Titles[columns[k]].baseWidth += dx; Titles[columns[k]].baseWidth += dx;
} }
} }
ReleaseDC(gdi.getTarget(), hDC); ReleaseDC(gdi.getHWNDTarget(), hDC);
updateDimension(gdi); updateDimension(gdi);
} }
@ -2323,3 +2325,7 @@ void TableRow::setObject(oBase &obj) {
cells[k].owner = &obj; cells[k].owner = &obj;
} }
} }
void Table::addDataDefiner(const string &key, const oDataDefiner *definer) {
dataDefiners[key] = definer;
}

View File

@ -104,6 +104,7 @@ public:
}; };
class gdioutput; class gdioutput;
class oDataDefiner;
struct ColInfo struct ColInfo
{ {
@ -244,7 +245,10 @@ protected:
void getRowRect(int row, RECT &rc) const; void getRowRect(int row, RECT &rc) const;
bool compareRow(int indexA, int indexB) const; bool compareRow(int indexA, int indexB) const;
map<string, const oDataDefiner *> dataDefiners;
public: public:
void addDataDefiner(const string &key, const oDataDefiner *definer);
void setTableText(gdioutput &gdi, int editRow, int editCol, const wstring &bf); void setTableText(gdioutput &gdi, int editRow, int editCol, const wstring &bf);
const wstring &getTableText(gdioutput &gdi, int editRow, int editCol); const wstring &getTableText(gdioutput &gdi, int editRow, int editCol);

228
code/animationdata.cpp Normal file
View File

@ -0,0 +1,228 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2017 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include "StdAfx.h"
#include "animationdata.h"
#include "meos_util.h"
#include "Printer.h"
AnimationData::AnimationData(gdioutput &gdi, int timePerPage, int nCol,
int marginPercent, bool animate) :
nCol(nCol), animate(animate), page(-1), gdiRef(0) {
lastTime = 0;
nextTime = 0;
timeOut = timePerPage;
doAnimation = true;
PageInfo pageInfo;
errorState = false;
gdi.getTargetDimension(width, height);
margin = (width * marginPercent) / 100;
double w = (gdi.getWidth() + 20) *nCol + margin;
double s = width / w;
if ((fabs(s - 1.0) > 1e-3)) {
gdi.scaleSize(s, true, false);
}
pageInfo.topMargin = 20;
pageInfo.scaleX = 1.0f;
pageInfo.scaleY = 1.0f;
pageInfo.leftMargin = 20;
pageInfo.bottomMargin = 30;
pageInfo.pageY = float(height-margin);
pageInfo.printHeader = false;
pageInfo.yMM2PrintC = pageInfo.xMM2PrintC = 1;
pageInfo.xMM2PrintK = 0;
pageInfo.yMM2PrintK = 0;
list<RectangleInfo> rectangles;
pageInfo.renderPages(gdi.getTL(), rectangles, false, pages);
}
AnimationData::~AnimationData() {
if (animationThread && animationThread->joinable()) {
animationThread->join();
animationThread.reset();
}
if (gdiRef) {
gdiRef->removeHandler(this);
}
}
bool AnimationData::takeOver(shared_ptr<AnimationData> &other) {
delayedTakeOver = other;
return true;
}
void AnimationData::takeOverInternal(shared_ptr<AnimationData> &other) {
pages.swap(other->pages);
width = other->width;
height = other->height;
nCol = other->nCol;
margin = other->margin;
animate = other->animate;
}
void AnimationData::renderPage(HDC hDC, gdioutput &gdi, DWORD time) {
bool addTextAnimation = false;
if (doAnimation) {
if (page == -1)
page = 0;
else
page++;
addTextAnimation = true;
nextTime = time + timeOut;
lastTime = time;
gdiRef = &gdi;
gdi.addTimeoutMilli(timeOut, "AnimationData", 0).setHandler(this);
doAnimation = false;
}
if (animationThread && animationThread->joinable()) {
if (!addTextAnimation)
return; // Ignore repaint
if (animationThread) {
animationThread->join();
animationThread.reset();
}
}
if (delayedTakeOver && addTextAnimation) {
takeOverInternal(delayedTakeOver);
delayedTakeOver.reset();
}
size_t sp = nCol * page;
if (sp >= pages.size()) {
sp = 0;
page = 0;
}
int count = 1;
for (size_t i = sp; i < sp + nCol && i < pages.size(); i++) {
int currentRow = 0;
for (auto &text : pages[i].text) {
if (text.ti.yp != currentRow) {
currentRow = text.ti.yp;
count++;
}
}
}
int atime = 400;
if (count < 30)
atime = 800;
else if (count < 50)
atime = 500;
int delay = addTextAnimation && animate ? atime / count : 0;
if (delay == 0 || errorState == true) {
doRender(hDC, gdi, sp, delay);
errorState = false;
}
else {
animationThread = make_shared<std::thread>(&AnimationData::threadRender, this, &gdi, sp, delay);
}
}
void AnimationData::threadRender(gdioutput *gdi, size_t sp, int delay) {
HWND hWnd = gdi->getHWNDTarget();
HDC hDC = GetDC(hWnd);
int x, y;
gdi->getTargetDimension(x, y);
RECT rc;
rc.left = 0;
rc.right = x;
rc.top = 0;
rc.bottom = y;
gdi->drawBackground(hDC, rc);
try {
doRender(hDC, *gdi, sp, delay);
}
catch (...) {
errorState = true;
}
ReleaseDC(hWnd, hDC);
// End thread and notify that it has ended
}
void AnimationData::doRender(HDC hDC, gdioutput &gdi, size_t sp, int delay) {
for (size_t i = sp; i < sp + nCol && i < pages.size(); i++) {
renderSubPage(hDC, gdi, pages[i], margin / 2 + ((i - sp) * width) / nCol, 0, delay);
if (i + 1 < sp + nCol) {
int x = margin / 2 + ((i + 1 - sp) * width) / nCol - 10;
SelectObject(hDC, GetStockObject(DC_BRUSH));
HLS fg, bg;
fg.RGBtoHLS(gdi.getFGColor());
bg.RGBtoHLS(gdi.getBGColor());
if (bg.lightness > fg.lightness)
fg.lighten(1.3);
else
fg.lighten(1.0 / 1.3);
SetDCBrushColor(hDC, fg.HLStoRGB());
Rectangle(hDC, x - 1, 20, x + 1, height - 20);
}
}
}
void AnimationData::renderSubPage(HDC hDC, gdioutput &gdi, RenderedPage &page, int x, int y, int animateDelay) {
int ox = gdi.GetOffsetX();
int oy = gdi.GetOffsetY();
int top = 10000;
for (const auto &text : page.text) {
if (!text.ti.isFormatInfo()) {
top = min<int>(top, text.ti.yp);
}
}
gdi.SetOffsetY(-y+top-margin/2);
gdi.SetOffsetX(-x);
int currentRow = 0;
for (auto &text : page.text) {
if (animateDelay>0 && text.ti.yp != currentRow) {
Sleep(animateDelay);
currentRow = text.ti.yp;
}
gdi.RenderString(text.ti, hDC);
}
gdi.SetOffsetY(ox);
gdi.SetOffsetX(oy);
}
void AnimationData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
if (pages.size() > size_t(nCol) || delayedTakeOver) {
doAnimation = true;
gdi.refreshFast();
}
gdiRef = &gdi;
gdi.addTimeoutMilli(timeOut, "AnimationData", 0).setHandler(this);
}

64
code/animationdata.h Normal file
View File

@ -0,0 +1,64 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2017 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include "gdioutput.h"
#include <thread>
#include <atomic>
class AnimationData : public GuiHandler {
vector<RenderedPage> pages;
int width;
int height;
int nCol;
int margin;
bool animate;
int page;
DWORD lastTime;
DWORD nextTime;
DWORD timeOut;
bool doAnimation;
atomic_bool errorState;
gdioutput *gdiRef;
void renderSubPage(HDC hDC, gdioutput &gdi, RenderedPage &page, int x, int y, int animationDelay);
void doRender(HDC hDC, gdioutput &gdi, size_t sp, int delay);
shared_ptr<thread> animationThread;
shared_ptr<AnimationData> delayedTakeOver;
void takeOverInternal(shared_ptr<AnimationData> &other);
void threadRender(gdioutput *gdi, size_t sp, int delay);
public:
AnimationData(gdioutput &gdi, int timePerPage, int nCol,
int marginPercent, bool animate);
~AnimationData();
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);
bool takeOver(shared_ptr<AnimationData> &other);
void renderPage(HDC hDC, gdioutput &gdi, DWORD time);
};

View File

@ -416,7 +416,7 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
bool csvparser::openOutput(const wstring &filename) bool csvparser::openOutput(const wstring &filename)
{ {
//Startnr;Bricka;Databas nr.;Efternamn;Förnamn;År;K;Block;ut;Start;Mål;Tid;Status;Klubb nr.;Namn;Ort;Land;Klass nr.;Kort;Lång;Num1;Num2;Num3;Text1;Text2;Text3;Adr. namn;Gata;Rad 2;Post nr.;Ort;Tel;Fax;E-post;Id/Club;Hyrd;Startavgift;Betalt;Bana nr.;Bana;km;Hm;Bana kontroller checkWriteAccess(filename);
fout.open(filename); fout.open(filename);
if (fout.bad()) if (fout.bad())

View File

@ -65,7 +65,7 @@ Antal: %d = Number: %d
Antal: X = Number: X Antal: X = Number: X
Antalet rader i urklipp får inte plats i selektionen = The number of rows on the clipboard does not fit the selection Antalet rader i urklipp får inte plats i selektionen = The number of rows on the clipboard does not fit the selection
Använd Eventor = Use Eventor Använd Eventor = Use Eventor
Använd banpool = Use course pooli Använd banpool = Use course pool
Använd funktioner för fleretappsklass = Use functions for multi stage class Använd funktioner för fleretappsklass = Use functions for multi stage class
Använd första kontrollen som start = Use first control as start Använd första kontrollen som start = Use first control as start
Använd löpardatabasen = Use runner database Använd löpardatabasen = Use runner database
@ -350,8 +350,8 @@ Hantera brickor = Manage Cards
Hantera flera etapper = Manage Several Stages Hantera flera etapper = Manage Several Stages
Hantera jaktstart = Handle Pursuit Hantera jaktstart = Handle Pursuit
Hantera klubbar och ekonomi = Manage clubs and economy Hantera klubbar och ekonomi = Manage clubs and economy
Hantera kvar-i-skogen = Handle Remaining Runners Hantera kvar-i-skogen = Manage Remaining Runners
Hantera löparbrickor = Handle Runner Cards Hantera löparbrickor = Manage Runner Cards
Hemsida = Homepage Hemsida = Homepage
Hjälp = Help Hjälp = Help
Hoppar över stafettklass: X = Skipping relay class: X Hoppar över stafettklass: X = Skipping relay class: X
@ -1172,7 +1172,7 @@ Varning: Inget kontonummer angivet (Se tävlingsinställningar) = Warning: No ac
Varning: Inget sista betalningsdatum angivet (Se tävlingsinställningar) = Warning: payment due not given (See Competition Settings) Varning: Inget sista betalningsdatum angivet (Se tävlingsinställningar) = Warning: payment due not given (See Competition Settings)
Varning: deltagare med blankt namn påträffad. MeOS kräver att alla deltagare har ett namn, och tilldelar namnet 'N.N.' = Warning: A competitor without name was found. MeOS requires a name, and has assigned the name 'N.N.' Varning: deltagare med blankt namn påträffad. MeOS kräver att alla deltagare har ett namn, och tilldelar namnet 'N.N.' = Warning: A competitor without name was found. MeOS requires a name, and has assigned the name 'N.N.'
Varning: lag utan namn påträffat. MeOS kräver att alla lag har ett namn, och tilldelar namnet 'N.N.' = Warning: A team without name was found. MeOS requires a name and has assigned the name 'N.N.' Varning: lag utan namn påträffat. MeOS kräver att alla lag har ett namn, och tilldelar namnet 'N.N.' = Warning: A team without name was found. MeOS requires a name and has assigned the name 'N.N.'
Verkställ = Confirm Verkställ = Apply
Version X = Version X Version X = Version X
Vi stöder MeOS = We support MeOS Vi stöder MeOS = We support MeOS
Viktiga händelser = Important events Viktiga händelser = Important events
@ -1870,7 +1870,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) 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, 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 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\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\nNTP = Not Taking Part
Placering = Place Placering = Place
Resultat från tidigare etapper = Results from Earlier Stages Resultat från tidigare etapper = Results from Earlier Stages
Input Results = Input Results Input Results = Input Results
@ -2252,3 +2252,35 @@ Spara fönster- och speakerinställningar på datorn = Save windows and settings
ask:loadspeaker = Do you wish to re-create previously saved windows on this computer? ask:loadspeaker = Do you wish to re-create previously saved windows on this computer?
Återskapa = Re-create Återskapa = Re-create
Återskapa tidigare sparade fönster- och speakerinställningar = Re-create previously saved windows and settings Återskapa tidigare sparade fönster- och speakerinställningar = Re-create previously saved windows and settings
Inkludera resultat från tidigare etapper = Include results from all stages
Animation = Animation
Bakgrund = Background
Bakgrundsfärg = Background color
Fullskärm (rullande) = Full screen (rolling)
Fullskärm (sidvis) = Full screen (page by page)
Fönster = Window
Fönster (rullande) = Window (rolling)
Justera visningsinställningar = Adjust view settings
Marginal = Margin
Sidor per skärm = Pages per screen
Textfärg = Text color
Utseende = Appearance
Visningsinställningar för 'X' = View settings for 'X'
Visningstid = Show time
Visning = Display mode
ask:hasVacant = There are still vacancies.\n\nDo you wish to remove all vacancies before exporting results?
warn:missingResult = X competitors are still missing results and are therefore excluded.\n\nYou should manage competitors in forest to assign status <DNS> to remaining runners.
Återställ <Ej Start> till <Status Okänd> = Reset <DNS> to <Unknown>
Återbud[status] = Cancelled
Lås gafflingar = Lock forkings
Markera för att förhindra oavsiktlig ändring av gafflingsnycklar = Check to prevent unintentional altering of forking keys
Tillåt gafflingsändringar = Allow forking modification
ask:updatetimes = Do you wish to keep all currently assigned start times, if possible? Answer no to move the competition in time.
X har en tid (Y) som inte är kompatibel med förändringen = X has a time (Y) that is incompatible with this change
warn:latestarttime = Using start times more than X hours after the zero time is not recommended, since older SI cards only has a 12 hour clock.\n\nDo you wish to proceed anyway?
Anm. tid = Entry time
RunnerEntryDate = Competitor's entry date
RunnerEntryTime = Competitor's entry time
RunnerPaid = Paid amount
RunnerPayMethod = Payment method
EntryTime = Entry Time

View File

@ -74,5 +74,6 @@ enum GDICOLOR {colorBlack = RGB(0,0,0),
colorMediumRed = RGB(255,200,200), colorMediumRed = RGB(255,200,200),
colorMediumDarkRed = RGB(240,120,120), colorMediumDarkRed = RGB(240,120,120),
colorWindowBar = -2, colorWindowBar = -2,
colorDefault = -1}; colorDefault = -1,
colorTransparent = -3};

View File

@ -55,6 +55,7 @@
#include "gdiimpl.h" #include "gdiimpl.h"
#include "Printer.h" #include "Printer.h"
#include "recorder.h" #include "recorder.h"
#include "animationdata.h"
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Construction/Destruction // Construction/Destruction
@ -133,6 +134,10 @@ void gdioutput::constructor(double _scale)
lockUpDown = false; lockUpDown = false;
Background = 0; Background = 0;
backgroundColor1 = -1;
backgroundColor2 = -1;
foregroundColor = -1;
backgroundImage = -1;
toolbar = 0; toolbar = 0;
initCommon(_scale, L"Arial"); initCommon(_scale, L"Arial");
@ -190,12 +195,12 @@ int transformX(int x, double scale) {
return int((x-40) * scale + 0.5) + 40; return int((x-40) * scale + 0.5) + 40;
} }
void gdioutput::scaleSize(double scale_) { void gdioutput::scaleSize(double scale_, bool allowSmallScale, bool doRefresh) {
if (fabs(scale_ - 1.0) < 1e-4) if (fabs(scale_ - 1.0) < 1e-4)
return; // No scaling return; // No scaling
double ns = scale*scale_; double ns = scale*scale_;
if (ns + 1e-6 < 1.0 ) { if (!allowSmallScale && ns + 1e-6 < 1.0 ) {
ns = 1.0; ns = 1.0;
scale_ = 1.0; scale_ = 1.0;
} }
@ -273,8 +278,17 @@ void gdioutput::scaleSize(double scale_) {
r.sOY = int (r.sOY * scale_ + 0.5); r.sOY = int (r.sOY * scale_ + 0.5);
} }
if (doRefresh) {
refresh(); refresh();
} }
else {
HDC hDC = GetDC(hWndTarget);
for (auto &ti : TL) {
calcStringSize(ti, hDC);
}
ReleaseDC(hWndTarget, hDC);
}
}
void gdioutput::initCommon(double _scale, const wstring &font) void gdioutput::initCommon(double _scale, const wstring &font)
{ {
@ -317,16 +331,7 @@ const GDIImplFontSet & gdioutput::loadFont(const wstring &font) {
relScale = enumeratedFonts[fontIx[k].second].getRelScale(); relScale = enumeratedFonts[fontIx[k].second].getRelScale();
} }
} }
/*vector<string> res;
split(font, ";", res);
double locScale = 1.0;
if (res.empty() || res.size() > 2)
throw meosException("Cannot load font: " + font);
if (res.size() == 2) {
locScale = atof(res[1].c_str());
if (!(locScale>0.001 && locScale < 100))
throw meosException("Cannot scale font with factor: " + res[1]);
}*/
wstring faceName; wstring faceName;
double locScale = getLocalScale(font, faceName); double locScale = getLocalScale(font, faceName);
@ -351,9 +356,11 @@ gdioutput::~gdioutput()
{ {
while(!timers.empty()) { while(!timers.empty()) {
KillTimer(hWndTarget, (UINT_PTR)&timers.back()); KillTimer(hWndTarget, (UINT_PTR)&timers.back());
timers.back().setWnd = 0;
timers.back().parent = 0; timers.back().parent = 0;
timers.pop_back(); timers.pop_back();
} }
animationData.reset();
deleteFonts(); deleteFonts();
@ -397,6 +404,18 @@ void gdioutput::fetchPrinterSettings(PrinterObject &po) const {
void gdioutput::drawBackground(HDC hDC, RECT &rc) void gdioutput::drawBackground(HDC hDC, RECT &rc)
{ {
if (backgroundColor1 != -1) {
SelectObject(hDC, GetStockObject(NULL_PEN));
SelectObject(hDC, GetStockObject(DC_BRUSH));
SetDCBrushColor(hDC, backgroundColor1);
Rectangle(hDC, -1, -1, rc.right + 1, rc.bottom + 1);
return;
}
else if (!backgroundImage.empty()) {
// TODO
}
GRADIENT_RECT gr[1]; GRADIENT_RECT gr[1];
SelectObject(hDC, GetStockObject(NULL_PEN)); SelectObject(hDC, GetStockObject(NULL_PEN));
@ -575,20 +594,16 @@ void gdioutput::draw(HDC hDC, RECT &rc, RECT &drawArea)
return; return;
} }
list<RectangleInfo>::iterator rit; if (animationData) {
int page = 0;
animationData->renderPage(hDC, *this, GetTickCount());
return;
}
SelectObject(hDC,GetStockObject(DC_BRUSH)); SelectObject(hDC,GetStockObject(DC_BRUSH));
for(rit=Rectangles.begin();rit!=Rectangles.end(); ++rit){ for (auto &rit : Rectangles)
if (rit->drawBorder) renderRectangle(hDC, 0, rit);
SelectObject(hDC, GetStockObject(BLACK_PEN));
else
SelectObject(hDC, GetStockObject(NULL_PEN));
SetDCBrushColor(hDC, rit->color);
RECT rect_rc=rit->rc;
OffsetRect(&rect_rc, -OffsetX, -OffsetY);
Rectangle(hDC, rect_rc.left, rect_rc.top, rect_rc.right, rect_rc.bottom);
}
if (useTables) if (useTables)
for(list<TableInfo>::iterator tit=Tables.begin();tit!=Tables.end(); ++tit){ for(list<TableInfo>::iterator tit=Tables.begin();tit!=Tables.end(); ++tit){
@ -641,11 +656,17 @@ void gdioutput::renderRectangle(HDC hDC, RECT *clipRegion, const RectangleInfo &
SelectObject(hDC, GetStockObject(BLACK_PEN)); SelectObject(hDC, GetStockObject(BLACK_PEN));
else else
SelectObject(hDC, GetStockObject(NULL_PEN)); SelectObject(hDC, GetStockObject(NULL_PEN));
SetDCBrushColor(hDC, ri.color);
if (ri.color == colorTransparent)
SelectObject(hDC, GetStockObject(NULL_BRUSH));
else {
SetDCBrushColor(hDC, ri.color);
}
RECT rect_rc=ri.rc; RECT rect_rc=ri.rc;
OffsetRect(&rect_rc, -OffsetX, -OffsetY); OffsetRect(&rect_rc, -OffsetX, -OffsetY);
Rectangle(hDC, rect_rc.left, rect_rc.top, rect_rc.right, rect_rc.bottom); Rectangle(hDC, rect_rc.left, rect_rc.top, rect_rc.right, rect_rc.bottom);
if (ri.color == colorTransparent)
SelectObject(hDC, GetStockObject(DC_BRUSH));
} }
void gdioutput::updateStringPosCache() { void gdioutput::updateStringPosCache() {
@ -723,6 +744,7 @@ void CALLBACK gdiTimerProc(HWND hWnd, UINT a, UINT_PTR ptr, DWORD b) {
wstring msg; wstring msg;
KillTimer(hWnd, ptr); KillTimer(hWnd, ptr);
TimerInfo *it = (TimerInfo *)ptr; TimerInfo *it = (TimerInfo *)ptr;
it->setWnd = 0;
try { try {
if (it->parent) { if (it->parent) {
it->parent->timerProc(*it, b); it->parent->timerProc(*it, b);
@ -745,25 +767,49 @@ void CALLBACK gdiTimerProc(HWND hWnd, UINT a, UINT_PTR ptr, DWORD b) {
} }
} }
int TimerInfo::globalTimerId = 0;
void gdioutput::timerProc(TimerInfo &timer, DWORD timeout) { void gdioutput::timerProc(TimerInfo &timer, DWORD timeout) {
int timerId = timer.timerId;
if (timer.handler) if (timer.handler)
timer.handler->handle(*this, timer, GUI_TIMER); timer.handler->handle(*this, timer, GUI_TIMER);
else if (timer.callBack) else if (timer.callBack)
timer.callBack(this, GUI_TIMER, &timer); timer.callBack(this, GUI_TIMER, &timer);
for (list<TimerInfo>::iterator it = timers.begin(); it != timers.end(); ++it) { remove_if(timers.begin(), timers.end(), [timerId](TimerInfo &x) {return x.getId() == timerId; });
if (&*it == &timer) {
timers.erase(it);
return;
} }
void gdioutput::removeHandler(GuiHandler *h) {
for (auto &it : timers) {
if (it.handler == h)
it.handler = 0;
}
for (auto &it : BI) {
if (it.handler == h)
it.handler = 0;
}
for (auto &it : II) {
if (it.handler == h)
it.handler = 0;
}
for (auto &it : TL) {
if (it.handler == h)
it.handler = 0;
}
for (auto &it : LBI) {
if (it.handler == h)
it.handler = 0;
} }
} }
void gdioutput::removeTimeoutMilli(const string &id) { void gdioutput::removeTimeoutMilli(const string &id) {
for (list<TimerInfo>::iterator it = timers.begin(); it != timers.end(); ++it) { for (list<TimerInfo>::iterator it = timers.begin(); it != timers.end(); ++it) {
if (it->id == id) { if (it->id == id) {
UINT_PTR ptr = (UINT_PTR)&*it;
KillTimer(hWndTarget, ptr);
timers.erase(it); timers.erase(it);
return; return;
} }
@ -775,12 +821,17 @@ TimerInfo &gdioutput::addTimeoutMilli(int timeOut, const string &id, GUICALLBACK
removeTimeoutMilli(id); removeTimeoutMilli(id);
timers.push_back(TimerInfo(this, cb)); timers.push_back(TimerInfo(this, cb));
timers.back().id = id; timers.back().id = id;
//timers.back().data = 0;
SetTimer(hWndTarget, (UINT_PTR)&timers.back(), timeOut, gdiTimerProc); SetTimer(hWndTarget, (UINT_PTR)&timers.back(), timeOut, gdiTimerProc);
timers.back().setWnd = hWndTarget;
return timers.back(); return timers.back();
} }
TimerInfo:: ~TimerInfo() {
handler = 0;
callBack = 0;
if (setWnd)
KillTimer(setWnd, (UINT_PTR)this);
}
TextInfo &gdioutput::addStringUT(int yp, int xp, int format, const string &text, TextInfo &gdioutput::addStringUT(int yp, int xp, int format, const string &text,
int xlimit, GUICALLBACK cb, const wchar_t *fontFace) { int xlimit, GUICALLBACK cb, const wchar_t *fontFace) {
return addStringUT(yp, xp, format, widen(text), xlimit, cb, fontFace); return addStringUT(yp, xp, format, widen(text), xlimit, cb, fontFace);
@ -953,8 +1004,21 @@ ButtonInfo &gdioutput::addButton(int x, int y, const string &id, const string &t
ButtonInfo &gdioutput::addButton(int x, int y, const string &id, const wstring &text, GUICALLBACK cb, ButtonInfo &gdioutput::addButton(int x, int y, const string &id, const wstring &text, GUICALLBACK cb,
const wstring &tooltip) const wstring &tooltip)
{ {
SIZE size; HANDLE bm = 0;
int width = 0;
if (text[0] == '@') {
HINSTANCE hInst = GetModuleHandle(0);//(HINSTANCE)GetWindowLong(hWndTarget, GWL_HINSTANCE);
int ir = _wtoi(text.c_str() + 1);
// bm = LoadImage(hInst, MAKEINTRESOURCE(ir), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
bm = LoadBitmap(hInst, MAKEINTRESOURCE(ir));// , IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
SIZE size;
size.cx = 24;
//GetBitmapDimensionEx(bm, &size);
width = size.cx+4;
}
else {
SIZE size;
HDC hDC = GetDC(hWndTarget); HDC hDC = GetDC(hWndTarget);
SelectObject(hDC, getGUIFont()); SelectObject(hDC, getGUIFont());
wstring ttext = lang.tl(text); wstring ttext = lang.tl(text);
@ -962,11 +1026,17 @@ ButtonInfo &gdioutput::addButton(int x, int y, const string &id, const wstring &
capitalizeWords(ttext); capitalizeWords(ttext);
GetTextExtentPoint32(hDC, ttext.c_str(), ttext.length(), &size); GetTextExtentPoint32(hDC, ttext.c_str(), ttext.length(), &size);
ReleaseDC(hWndTarget, hDC); ReleaseDC(hWndTarget, hDC);
int width = size.cx+scaleLength(30); width = size.cx + scaleLength(30);
if (text != L"...") if (text != L"...")
width = max<int>(width, scaleLength(75)); width = max<int>(width, scaleLength(75));
}
ButtonInfo &bi=addButton(x, y, width, id, text, cb, tooltip, false, false); ButtonInfo &bi=addButton(x, y, width, id, text, cb, tooltip, false, false);
if (bm != 0) {
SendMessage(bi.hWnd, BM_SETIMAGE, IMAGE_BITMAP, LPARAM(bm));
}
return bi; return bi;
} }
@ -1015,6 +1085,10 @@ ButtonInfo &gdioutput::addButton(int x, int y, int w, const string &id,
bool AbsPos, bool hasState) bool AbsPos, bool hasState)
{ {
int style = hasState ? BS_CHECKBOX|BS_PUSHLIKE : BS_PUSHBUTTON; int style = hasState ? BS_CHECKBOX|BS_PUSHLIKE : BS_PUSHBUTTON;
if (text[0] == '@')
style |= BS_BITMAP;
ButtonInfo bi; ButtonInfo bi;
wstring ttext = lang.tl(text); wstring ttext = lang.tl(text);
if (lang.capitalizeWords()) if (lang.capitalizeWords())
@ -1369,7 +1443,7 @@ void gdioutput::synchronizeListScroll(const string &id1, const string &id2)
ListBoxInfo &gdioutput::addListBox(int x, int y, const string &id, int width, int height, GUICALLBACK cb, ListBoxInfo &gdioutput::addListBox(int x, int y, const string &id, int width, int height, GUICALLBACK cb,
const wstring &explanation, const wstring &tooltip, bool multiple) { const wstring &explanation, const wstring &tooltip, bool multiple) {
if (explanation.length()>0) { if (explanation.length()>0) {
addString(id+"_expl", y, x, 0, explanation); addString(id+"_label", y, x, 0, explanation);
y+=lineHeight; y+=lineHeight;
} }
ListBoxInfo lbi; ListBoxInfo lbi;
@ -1461,7 +1535,7 @@ ListBoxInfo &gdioutput::addSelection(int x, int y, const string &id, int width,
GUICALLBACK cb, const wstring &explanation, const wstring &tooltip) GUICALLBACK cb, const wstring &explanation, const wstring &tooltip)
{ {
if (explanation.length()>0) { if (explanation.length()>0) {
addString("", y, x, 0, explanation); addString(id + "_label", y, x, 0, explanation);
y+=lineHeight; y+=lineHeight;
} }
@ -1504,7 +1578,7 @@ ListBoxInfo &gdioutput::addCombo(const string &id, int width, int height, GUICAL
ListBoxInfo &gdioutput::addCombo(int x, int y, const string &id, int width, int height, GUICALLBACK cb, ListBoxInfo &gdioutput::addCombo(int x, int y, const string &id, int width, int height, GUICALLBACK cb,
const wstring &explanation, const wstring &tooltip) { const wstring &explanation, const wstring &tooltip) {
if (explanation.length()>0) { if (explanation.length()>0) {
addString("", y, x, 0, explanation); addString(id + "_label", y, x, 0, explanation);
y+=lineHeight; y+=lineHeight;
} }
@ -1697,18 +1771,19 @@ bool gdioutput::getSelectedItem(ListBoxInfo &lbi) {
} }
int gdioutput::getItemDataByName(const char *id, const char *name) const{ int gdioutput::getItemDataByName(const char *id, const char *name) const{
wstring wname = recodeToWide(name);
list<ListBoxInfo>::const_iterator it; list<ListBoxInfo>::const_iterator it;
for(it = LBI.begin(); it != LBI.end(); ++it){ for(it = LBI.begin(); it != LBI.end(); ++it){
if (it->id==id) { if (it->id==id) {
if (it->IsCombo) { if (it->IsCombo) {
int ix = SendMessage(it->hWnd, CB_FINDSTRING, -1, LPARAM(name)); int ix = SendMessage(it->hWnd, CB_FINDSTRING, -1, LPARAM(wname.c_str()));
if (ix >= 0) { if (ix >= 0) {
return SendMessage(it->hWnd, CB_GETITEMDATA, ix, 0); return SendMessage(it->hWnd, CB_GETITEMDATA, ix, 0);
} }
return -1; return -1;
} }
else { else {
int ix = SendMessage(it->hWnd, LB_FINDSTRING, -1, LPARAM(name)); int ix = SendMessage(it->hWnd, LB_FINDSTRING, -1, LPARAM(wname.c_str()));
if (ix >= 0) { if (ix >= 0) {
return SendMessage(it->hWnd, LB_GETITEMDATA, ix, 0); return SendMessage(it->hWnd, LB_GETITEMDATA, ix, 0);
} }
@ -2441,8 +2516,6 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
return 0;*/ return 0;*/
} }
else if (iMessage == WM_CTLCOLOREDIT) { else if (iMessage == WM_CTLCOLOREDIT) {
//for (list<InputInfo>::const_iterator it = II.begin(); it != II.end(); ++it) {
// if (it->hWnd == HWND(lParam)) {
unordered_map<HWND, InputInfo*>::iterator it = iiByHwnd.find(HWND(lParam)); unordered_map<HWND, InputInfo*>::iterator it = iiByHwnd.find(HWND(lParam));
if (it != iiByHwnd.end()) { if (it != iiByHwnd.end()) {
InputInfo &ii = *it->second; InputInfo &ii = *it->second;
@ -2460,9 +2533,11 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
return LRESULT(GetStockObject(DC_BRUSH)); return LRESULT(GetStockObject(DC_BRUSH));
} }
} }
return 0; return 0;
} }
else if (iMessage == WM_DESTROY) {
canClear();// Ignore return value
}
return 0; return 0;
} }
@ -2747,6 +2822,7 @@ void gdioutput::doEscape()
} }
void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) { void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
animationData.reset();
lockUpDown = false; lockUpDown = false;
hasAnyTimer = false; hasAnyTimer = false;
enableTables(); enableTables();
@ -2757,6 +2833,7 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
while(!timers.empty()) { while(!timers.empty()) {
KillTimer(hWndTarget, (UINT_PTR)&timers.back()); KillTimer(hWndTarget, (UINT_PTR)&timers.back());
timers.back().setWnd = 0;
timers.back().parent = 0; timers.back().parent = 0;
timers.pop_back(); timers.pop_back();
} }
@ -2845,6 +2922,12 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
renderOptimize=true; renderOptimize=true;
backgroundColor1 = -1;
backgroundColor2 = -1;
foregroundColor = -1;
backgroundImage = -1;
setRestorePoint(); setRestorePoint();
if (autoRefresh) if (autoRefresh)
@ -3152,6 +3235,32 @@ bool gdioutput::getData(const string &id, DWORD &data) const
return false; return false;
} }
void gdioutput::setData(const string &id, const string &data) {
for (auto &it : DataInfo) {
if (it.id == id) {
it.sdata = data;
return;
}
}
DataStore ds;
ds.id = id;
ds.sdata = data;
DataInfo.push_front(ds);
return;
}
bool gdioutput::getData(const string &id, string &out) const {
for (auto &it : DataInfo) {
if (it.id == id) {
out = it.sdata;
return true;
}
}
out.clear();
return false;
}
void *gdioutput::getData(const string &id) const { void *gdioutput::getData(const string &id) const {
list<DataStore>::const_iterator it; list<DataStore>::const_iterator it;
for (it = DataInfo.begin(); it != DataInfo.end(); ++it){ for (it = DataInfo.begin(); it != DataInfo.end(); ++it){
@ -4095,6 +4204,8 @@ void gdioutput::formatString(const TextInfo &ti, HDC hDC) const
SetTextColor(hDC, RGB(255,0,0)); SetTextColor(hDC, RGB(255,0,0));
else if (ti.highlight) else if (ti.highlight)
SetTextColor(hDC, RGB(64,64,128)); SetTextColor(hDC, RGB(64,64,128));
else if (ti.color == 0 && foregroundColor != -1)
SetTextColor(hDC, foregroundColor);
else else
SetTextColor(hDC, ti.color); SetTextColor(hDC, ti.color);
} }
@ -4488,6 +4599,9 @@ bool gdioutput::removeControl(const string &id)
if (it->id==id) { if (it->id==id) {
DestroyWindow(it->hWnd); DestroyWindow(it->hWnd);
biByHwnd.erase(it->hWnd); biByHwnd.erase(it->hWnd);
if (it->isCheckbox)
removeString("T" + id);
BI.erase(it); BI.erase(it);
return true; return true;
} }
@ -4500,6 +4614,7 @@ bool gdioutput::removeControl(const string &id)
if (lit->id==id) { if (lit->id==id) {
DestroyWindow(lit->hWnd); DestroyWindow(lit->hWnd);
lbiByHwnd.erase(lit->hWnd); lbiByHwnd.erase(lit->hWnd);
removeString(id + "_label");
if (lit->writeLock) if (lit->writeLock)
hasCleared = true; hasCleared = true;
LBI.erase(lit); LBI.erase(lit);
@ -4515,6 +4630,7 @@ bool gdioutput::removeControl(const string &id)
DestroyWindow(iit->hWnd); DestroyWindow(iit->hWnd);
iiByHwnd.erase(iit->hWnd); iiByHwnd.erase(iit->hWnd);
II.erase(iit); II.erase(iit);
removeString(id + "_label");
return true; return true;
} }
++iit; ++iit;
@ -4843,7 +4959,11 @@ RectangleInfo &RectangleInfo::changeDimension(gdioutput &gdi, int dx, int dy) {
RectangleInfo &gdioutput::addRectangle(RECT &rc, GDICOLOR color, bool drawBorder, bool addFirst) { RectangleInfo &gdioutput::addRectangle(RECT &rc, GDICOLOR color, bool drawBorder, bool addFirst) {
RectangleInfo ri; RectangleInfo ri;
ri.rc = rc; ri.rc.left = min<int>(rc.left, rc.right);
ri.rc.right = max<int>(rc.left, rc.right);
ri.rc.top = min<int>(rc.top, rc.bottom);
ri.rc.bottom = max<int>(rc.top, rc.bottom);
if (color==colorDefault) if (color==colorDefault)
ri.color = GetSysColor(COLOR_INFOBK); ri.color = GetSysColor(COLOR_INFOBK);
else if (color == colorWindowBar) { else if (color == colorWindowBar) {
@ -4861,7 +4981,7 @@ RectangleInfo &gdioutput::addRectangle(RECT &rc, GDICOLOR color, bool drawBorder
} }
int ex = scaleLength(5); int ex = scaleLength(5);
updatePos(rc.left, rc.top, rc.right-rc.left+ex, rc.bottom-rc.top+ex); updatePos(ri.rc.left, ri.rc.top, ri.rc.right-ri.rc.left+ex, ri.rc.bottom-ri.rc.top+ex);
if (addFirst) { if (addFirst) {
Rectangles.push_front(ri); Rectangles.push_front(ri);
return Rectangles.front(); return Rectangles.front();
@ -5022,6 +5142,12 @@ void gdioutput::scrollToBottom()
bool gdioutput::clipOffset(int PageX, int PageY, int &MaxOffsetX, int &MaxOffsetY) bool gdioutput::clipOffset(int PageX, int PageY, int &MaxOffsetX, int &MaxOffsetY)
{ {
if (animationData) {
MaxOffsetX = 0;
MaxOffsetY = 0;
return false;
}
if (highContrast) if (highContrast)
setHighContrastMaxWidth(); setHighContrastMaxWidth();
@ -5732,10 +5858,38 @@ void gdioutput::storeAutoPos(double pos) {
} }
void gdioutput::setFullScreen(bool useFullScreen) { void gdioutput::setFullScreen(bool useFullScreen) {
if (useFullScreen && !fullScreen) {
SetWindowLong(hWndTarget, GWL_STYLE, WS_POPUP | WS_BORDER); SetWindowLong(hWndTarget, GWL_STYLE, WS_POPUP | WS_BORDER);
ShowWindow(hWndTarget, SW_MAXIMIZE); ShowWindow(hWndTarget, SW_MAXIMIZE);
UpdateWindow(hWndTarget); UpdateWindow(hWndTarget);
fullScreen = true; }
else if (fullScreen) {
SetWindowLong(hWndTarget, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
ShowWindow(hWndTarget, SW_NORMAL);
UpdateWindow(hWndTarget);
}
fullScreen = useFullScreen;
}
void gdioutput::setColorMode(DWORD bgColor1, DWORD bgColor2,
DWORD fgColor, const wstring &bgImage) {
backgroundColor1 = bgColor1;
backgroundColor2 = bgColor2;
foregroundColor = fgColor;
backgroundImage = bgImage;
}
DWORD gdioutput::getFGColor() const {
return foregroundColor != -1 ? foregroundColor : 0;
}
DWORD gdioutput::getBGColor() const {
return backgroundColor1 != -1 ? backgroundColor1 : RGB(255,255,255);
}
DWORD gdioutput::getBGColor2() const {
return backgroundColor2;
}
const wstring &gdioutput::getBGImage() const {
return backgroundImage;
} }
bool gdioutput::hasCommandLock() const { bool gdioutput::hasCommandLock() const {
@ -6249,7 +6403,7 @@ InputInfo &InputInfo::setFont(gdioutput &gdi, gdiFonts font) {
void gdioutput::copyToClipboard(const string &html, const wstring &txt) const { void gdioutput::copyToClipboard(const string &html, const wstring &txt) const {
if (OpenClipboard(getHWND()) != false) { if (OpenClipboard(getHWNDMain()) != false) {
EmptyClipboard(); EmptyClipboard();
size_t len = html.length() + 1; size_t len = html.length() + 1;
@ -6659,3 +6813,42 @@ void gdioutput::getVirtualScreenSize(RECT &rc) {
rc.top = 0; rc.top = 0;
rc.bottom = py; rc.bottom = py;
} }
DWORD gdioutput::selectColor(wstring &def, DWORD input) {
CHOOSECOLOR cc;
memset(&cc, 0, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.hwndOwner = getHWNDMain();
cc.rgbResult = COLORREF(input);
if (GDICOLOR(input) != colorDefault)
cc.Flags |= CC_RGBINIT;
COLORREF staticColor[16];
memset(staticColor, 0, 16 * sizeof(COLORREF));
const wchar_t *end = def.c_str() + def.length();
const wchar_t * pEnd = def.c_str();
int pix = 0;
while (pEnd < end && pix < 16) {
staticColor[pix++] = wcstol(pEnd, (wchar_t **)&pEnd, 16);
}
cc.lpCustColors = staticColor;
if (ChooseColor(&cc)) {
wstring co;
for (int ix = 0; ix < 16; ix++) {
wchar_t bf[16];
swprintf_s(bf, L"%x ", staticColor[ix]);
co += bf;
}
swap(def,co);
return cc.rgbResult;
}
return -1;
}
void gdioutput::setAnimationMode(shared_ptr<AnimationData> &data) {
if (animationData && animationData->takeOver(data))
return;
animationData = data;
}

View File

@ -63,6 +63,7 @@ class FixedTabs;
struct PageInfo; struct PageInfo;
struct RenderedPage; struct RenderedPage;
class AnimationData;
typedef int (*GUICALLBACK)(gdioutput *gdi, int type, void *data); typedef int (*GUICALLBACK)(gdioutput *gdi, int type, void *data);
@ -70,7 +71,7 @@ enum GDICOLOR;
enum KeyCommandCode; enum KeyCommandCode;
enum gdiFonts; enum gdiFonts;
#include "gdistructures.h" #include "gdistructures.h"
#include <memory>
#define START_YP 30 #define START_YP 30
#define NOTIMEOUT 0x0AAAAAAA #define NOTIMEOUT 0x0AAAAAAA
@ -238,6 +239,12 @@ protected:
bool lockRefresh; bool lockRefresh;
bool fullScreen; bool fullScreen;
bool hideBG; bool hideBG;
DWORD backgroundColor1;
DWORD backgroundColor2;
wstring backgroundImage;
DWORD foregroundColor;
mutable bool commandLock; mutable bool commandLock;
mutable DWORD commandUnlockTime; mutable DWORD commandUnlockTime;
@ -271,6 +278,8 @@ protected:
pair<Recorder *, bool> recorder; pair<Recorder *, bool> recorder;
list< pair<const SubCommand *, string> > subCommands; list< pair<const SubCommand *, string> > subCommands;
shared_ptr<AnimationData> animationData;
int defaultCodePage; int defaultCodePage;
public: public:
// Return the bounding dimension of the desktop // Return the bounding dimension of the desktop
@ -279,6 +288,7 @@ public:
void getWindowsPosition(RECT &rc) const; void getWindowsPosition(RECT &rc) const;
void setWindowsPosition(const RECT &rc); void setWindowsPosition(const RECT &rc);
void initRecorder(Recorder *rec); void initRecorder(Recorder *rec);
Recorder &getRecorder(); Recorder &getRecorder();
string dbPress(const string &id, int extra); string dbPress(const string &id, int extra);
@ -332,6 +342,16 @@ public:
bool isFullScreen() const {return fullScreen;} bool isFullScreen() const {return fullScreen;}
void setFullScreen(bool useFullScreen); void setFullScreen(bool useFullScreen);
void setColorMode(DWORD bgColor1, DWORD bgColor2 = -1,
DWORD fgColor = -1, const wstring &bgImage = L"");
DWORD getFGColor() const;
DWORD getBGColor() const;
DWORD getBGColor2() const;
const wstring &getBGImage() const;
void setAnimationMode(shared_ptr<AnimationData> &mode);
void setAutoScroll(double speed); void setAutoScroll(double speed);
void getAutoScroll(double &speed, double &pos) const; void getAutoScroll(double &speed, double &pos) const;
void storeAutoPos(double pos); void storeAutoPos(double pos);
@ -394,8 +414,8 @@ public:
void getSelection(const string &id, set<int> &selection); void getSelection(const string &id, set<int> &selection);
HWND getTarget() const {return hWndTarget;} HWND getHWNDTarget() const {return hWndTarget;}
HWND getMain() const {return hWndAppMain;} HWND getHWNDMain() const {return hWndAppMain;}
void scrollToBottom(); void scrollToBottom();
void scrollTo(int x, int y); void scrollTo(int x, int y);
@ -456,7 +476,6 @@ public:
void drawBoxes(HDC hDC, RECT &rc); void drawBoxes(HDC hDC, RECT &rc);
void drawBox(HDC hDC, InfoBox &Box, RECT &pos); void drawBox(HDC hDC, InfoBox &Box, RECT &pos);
void addInfoBox(string id, wstring text, int TimeOut=0, GUICALLBACK cb=0); void addInfoBox(string id, wstring text, int TimeOut=0, GUICALLBACK cb=0);
HWND getHWND() const {return hWndTarget;}
void updateObjectPositions(); void updateObjectPositions();
void drawBackground(HDC hDC, RECT &rc); void drawBackground(HDC hDC, RECT &rc);
void renderRectangle(HDC hDC, RECT *clipRegion, const RectangleInfo &ri); void renderRectangle(HDC hDC, RECT *clipRegion, const RectangleInfo &ri);
@ -516,7 +535,13 @@ public:
void setTabStops(const string &Name, int t1, int t2=-1); void setTabStops(const string &Name, int t1, int t2=-1);
void setData(const string &id, DWORD data); void setData(const string &id, DWORD data);
void setData(const string &id, void *data); void setData(const string &id, void *data);
void setData(const string &id, const string &data);
void *getData(const string &id) const; void *getData(const string &id) const;
bool getData(const string &id, string &out) const;
DWORD selectColor(wstring &def, DWORD input);
void autoRefresh(bool flag) {manualUpdate = !flag;} void autoRefresh(bool flag) {manualUpdate = !flag;}
@ -618,7 +643,7 @@ public:
LRESULT ProcessMsg(UINT iMessage, LPARAM lParam, WPARAM wParam); LRESULT ProcessMsg(UINT iMessage, LPARAM lParam, WPARAM wParam);
void setWindow(HWND hWnd){hWndTarget=hWnd;} void setWindow(HWND hWnd){hWndTarget=hWnd;}
void scaleSize(double scale); void scaleSize(double scale, bool allowSmallScale = false, bool doRefresh = true);
ButtonInfo &addButton(const string &id, const wstring &text, GUICALLBACK cb = 0, ButtonInfo &addButton(const string &id, const wstring &text, GUICALLBACK cb = 0,
const wstring &tooltip = L""); const wstring &tooltip = L"");
@ -713,6 +738,8 @@ public:
TimerInfo &addTimeoutMilli(int timeOut, const string &id, GUICALLBACK cb); TimerInfo &addTimeoutMilli(int timeOut, const string &id, GUICALLBACK cb);
void timerProc(TimerInfo &timer, DWORD timeout); void timerProc(TimerInfo &timer, DWORD timeout);
void removeHandler(GuiHandler *h);
void draw(HDC hDC, RECT &windowArea, RECT &drawArea); void draw(HDC hDC, RECT &windowArea, RECT &drawArea);
void closeWindow(); void closeWindow();

View File

@ -25,6 +25,7 @@
#include <cassert> #include <cassert>
#include "guihandler.h" #include "guihandler.h"
#include "gdifonts.h"
class BaseInfo class BaseInfo
{ {
@ -151,6 +152,8 @@ public:
TextInfo &setColor(GDICOLOR c) {color = c; return *this;} TextInfo &setColor(GDICOLOR c) {color = c; return *this;}
TextInfo &changeFont(const wstring &fnt) {font = fnt; return *this;} //Note: size not updated TextInfo &changeFont(const wstring &fnt) {font = fnt; return *this;} //Note: size not updated
bool isFormatInfo() const { return format == pageNewPage || format == pagePageInfo; }
int getHeight() {return int(textRect.bottom-textRect.top);} int getHeight() {return int(textRect.bottom-textRect.top);}
gdiFonts getGdiFont() const {return gdiFonts(format & 0xFF);} gdiFonts getGdiFont() const {return gdiFonts(format & 0xFF);}
// Sets absolute print coordinates in [mm] // Sets absolute print coordinates in [mm]
@ -183,6 +186,8 @@ public:
HWND getControlWindow() const {throw std::exception("Unsupported");} HWND getControlWindow() const {throw std::exception("Unsupported");}
friend class gdioutput;
}; };
class ButtonInfo : public BaseInfo class ButtonInfo : public BaseInfo
@ -330,8 +335,12 @@ private:
class DataStore class DataStore
{ {
public: public:
DataStore() {
data = 0;
}
string id; string id;
void *data; void *data;
string sdata;
}; };
class EventInfo : public BaseInfo class EventInfo : public BaseInfo
@ -355,12 +364,17 @@ public:
class TimerInfo : public BaseInfo class TimerInfo : public BaseInfo
{ {
private: private:
static int globalTimerId;
int timerId;
DWORD dataInt; DWORD dataInt;
wstring dataString; wstring dataString;
gdioutput *parent; gdioutput *parent;
TimerInfo(gdioutput *gdi, GUICALLBACK cb) : parent(gdi), callBack(cb) {} TimerInfo(gdioutput *gdi, GUICALLBACK cb) : parent(gdi), callBack(cb), setWnd(0), timerId(++globalTimerId) {}
HWND setWnd;
public: public:
~TimerInfo();
int getId() const { return timerId; }
BaseInfo &setExtra(const wchar_t *e) {return BaseInfo::setExtra(e);} BaseInfo &setExtra(const wchar_t *e) {return BaseInfo::setExtra(e);}
BaseInfo &setExtra(int e) {return BaseInfo::setExtra(e);} BaseInfo &setExtra(int e) {return BaseInfo::setExtra(e);}

View File

@ -699,6 +699,8 @@ RunnerStatus DynamicResult::toStatus(int status) const {
return StatusDNF; return StatusDNF;
case StatusDNS: case StatusDNS:
return StatusDNS; return StatusDNS;
case StatusCANCEL:
return StatusCANCEL;
case StatusNotCompetiting: case StatusNotCompetiting:
return StatusNotCompetiting; return StatusNotCompetiting;
case StatusDQ: case StatusDQ:
@ -798,9 +800,9 @@ void DynamicResult::save(xmlparser &xml) const {
xml.write("Tag", gdioutput::widen(tag)); xml.write("Tag", gdioutput::widen(tag));
xml.write("Description", description); xml.write("Description", description);
if (origin.empty()) if (origin.empty())
origin = gEvent->getName() + L" (" + getLocalDateW() + L")"; origin = gEvent->getName() + L" (" + getLocalDate() + L")";
xml.write("Origin", origin); xml.write("Origin", origin);
xml.write("Date", getLocalTimeW()); xml.write("Date", getLocalTime());
// xml.write("Tag", tag); // xml.write("Tag", tag);
// xml.write("UID", getUniqueId()); // xml.write("UID", getUniqueId());
@ -975,6 +977,7 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("StatusMP", "Status code for a missing punch", false); parser.declareSymbol("StatusMP", "Status code for a missing punch", false);
parser.declareSymbol("StatusDNF", "Status code for not finishing", false); parser.declareSymbol("StatusDNF", "Status code for not finishing", false);
parser.declareSymbol("StatusDNS", "Status code for not starting", false); parser.declareSymbol("StatusDNS", "Status code for not starting", false);
parser.declareSymbol("StatusCANCEL", "Status code for cancelled entry", false);
parser.declareSymbol("StatusMAX", "Status code for a time over the maximum", false); parser.declareSymbol("StatusMAX", "Status code for a time over the maximum", false);
parser.declareSymbol("StatusDQ", "Status code for disqualification", false); parser.declareSymbol("StatusDQ", "Status code for disqualification", false);
parser.declareSymbol("StatusNotCompetiting", "Status code for not competing", false); parser.declareSymbol("StatusNotCompetiting", "Status code for not competing", false);
@ -1016,6 +1019,7 @@ void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inp
parser.addSymbol("StatusOK", StatusOK); parser.addSymbol("StatusOK", StatusOK);
parser.addSymbol("StatusMP", StatusMP); parser.addSymbol("StatusMP", StatusMP);
parser.addSymbol("StatusDNF", StatusDNF); parser.addSymbol("StatusDNF", StatusDNF);
parser.addSymbol("StatusCANCEL", StatusCANCEL);
parser.addSymbol("StatusDNS", StatusDNS); parser.addSymbol("StatusDNS", StatusDNS);
parser.addSymbol("StatusMAX", StatusMAX); parser.addSymbol("StatusMAX", StatusMAX);
parser.addSymbol("StatusDQ", StatusDQ); parser.addSymbol("StatusDQ", StatusDQ);

View File

@ -65,6 +65,7 @@ int InfoBase::convertRelativeTime(const oBase &elem, int t) {
InfoCompetition::InfoCompetition(int id) : InfoBase(id) { InfoCompetition::InfoCompetition(int id) : InfoBase(id) {
forceComplete = true; forceComplete = true;
includeTotal = false;
} }
InfoRadioControl::InfoRadioControl(int id) : InfoBase(id) { InfoRadioControl::InfoRadioControl(int id) : InfoBase(id) {
@ -93,7 +94,7 @@ InfoTeam::InfoTeam(int id) : InfoBaseCompetitor(id) {
} }
bool InfoCompetition::synchronize(oEvent &oe, const set<int> &includeCls, const set<int> &ctrls) { bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &includeCls, const set<int> &ctrls) {
bool changed = false; bool changed = false;
if (oe.getName() != name) { if (oe.getName() != name) {
name = oe.getName(); name = oe.getName();
@ -118,6 +119,9 @@ bool InfoCompetition::synchronize(oEvent &oe, const set<int> &includeCls, const
if (changed) if (changed)
needCommit(*this); needCommit(*this);
if (onlyCmp)
return changed;
vector<pControl> ctrl; vector<pControl> ctrl;
oe.getControls(ctrl, true); oe.getControls(ctrl, true);
set<int> knownId; set<int> knownId;
@ -422,24 +426,42 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
return ch; return ch;
} }
bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) { bool InfoCompetitor::synchronize(bool useTotalResults, oRunner &r) {
bool ch = synchronizeBase(r); bool ch = synchronizeBase(r);
changeTotalSt = r.getEvent()->hasPrevStage() || r.getLegNumber()>0; // Always write full attributes changeTotalSt = r.getEvent()->hasPrevStage() || r.getLegNumber()>0; // Always write full attributes
int s = r.getTotalStatusInput();
int s = StatusOK;
int legInput = 0;
pTeam t = r.getTeam();
if (useTotalResults) {
legInput = r.getTotalTimeInput() * 10;
s = r.getTotalStatusInput();
}
else if (t && r.getLegNumber() > 0) {
legInput = t->getLegRunningTime(r.getLegNumber() - 1, false);
s = t->getLegStatus(r.getLegNumber() - 1, false);
}
if (totalStatus != s) { if (totalStatus != s) {
totalStatus = s; totalStatus = s;
ch = true; ch = true;
changeTotalSt = true; changeTotalSt = true;
} }
int legInput = r.getTotalTimeInput() * 10;
if (legInput != inputTime) { if (legInput != inputTime) {
inputTime = legInput; inputTime = legInput;
ch = true; ch = true;
changeTotalSt = true; changeTotalSt = true;
} }
return ch;
}
bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
bool useTotalResults = cmp.includeTotalResults();
bool ch = synchronize(useTotalResults, r);
vector<RadioTime> newRT; vector<RadioTime> newRT;
if (r.getClassId() > 0) { if (r.getClassId() > 0) {
const vector<int> &radios = cmp.getControls(r.getClassId(), r.getLegNumber()); const vector<int> &radios = cmp.getControls(r.getClassId(), r.getLegNumber());

View File

@ -114,9 +114,10 @@ class InfoClass : public InfoBase {
int sortOrder; int sortOrder;
vector< vector<int> > radioControls; vector< vector<int> > radioControls;
vector<int> linearLegNumberToActual; vector<int> linearLegNumberToActual;
public:
bool synchronize(oClass &c, const set<int> &ctrls); bool synchronize(oClass &c, const set<int> &ctrls);
void serialize(xmlbuffer &xml, bool diffOnly) const; void serialize(xmlbuffer &xml, bool diffOnly) const;
public:
InfoClass(int id); InfoClass(int id);
virtual ~InfoClass() {} virtual ~InfoClass() {}
@ -166,10 +167,12 @@ class InfoCompetitor : public InfoBaseCompetitor {
int inputTime; int inputTime;
int totalStatus; int totalStatus;
bool synchronize(const InfoCompetition &cmp, oRunner &c); bool synchronize(const InfoCompetition &cmp, oRunner &c);
void serialize(xmlbuffer &xml, bool diffOnly) const;
bool changeTotalSt; bool changeTotalSt;
bool changeRadio; bool changeRadio;
public: public:
bool synchronize(bool useTotalResults, oRunner &c);
void serialize(xmlbuffer &xml, bool diffOnly) const;
InfoCompetitor(int id); InfoCompetitor(int id);
virtual ~InfoCompetitor() {} virtual ~InfoCompetitor() {}
@ -197,6 +200,8 @@ private:
protected: protected:
bool forceComplete; bool forceComplete;
bool includeTotal;
list<InfoBase *> toCommit; list<InfoBase *> toCommit;
map<int, InfoRadioControl> controls; map<int, InfoRadioControl> controls;
@ -206,13 +211,20 @@ protected:
map<int, InfoTeam> teams; map<int, InfoTeam> teams;
void needCommit(InfoBase &obj); void needCommit(InfoBase &obj);
public:
void serialize(xmlbuffer &xml, bool diffOnly) const; void serialize(xmlbuffer &xml, bool diffOnly) const;
public: bool includeTotalResults() const {return includeTotal;}
const vector<int> &getControls(int classId, int legNumber) const; void includeTotalResults(bool inc) {includeTotal = inc;}
bool synchronize(oEvent &oe, const set<int> &classes, const set<int> &ctrls);
const vector<int> &getControls(int classId, int legNumber) const;
bool synchronize(oEvent &oe, bool onlyCmp, const set<int> &classes, const set<int> &ctrls);
bool synchronize(oEvent &oe) {
set<int> dmy;
return synchronize(oe, true, dmy, dmy);
}
void getCompleteXML(xmlbuffer &xml); void getCompleteXML(xmlbuffer &xml);
void getDiffXML(xmlbuffer &xml); void getDiffXML(xmlbuffer &xml);

View File

@ -1150,7 +1150,7 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
wstring dateStr; wstring dateStr;
date.getObjectString("Date", dateStr); date.getObjectString("Date", dateStr);
oe.setDate(dateStr); oe.setDate(dateStr);
string timeStr; wstring timeStr;
date.getObjectString("Time", timeStr); date.getObjectString("Time", timeStr);
if (!timeStr.empty()) { if (!timeStr.empty()) {
int t = convertAbsoluteTimeISO(timeStr); int t = convertAbsoluteTimeISO(timeStr);
@ -1158,7 +1158,7 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
int zt = t - 3600; int zt = t - 3600;
if (zt < 0) if (zt < 0)
zt += 3600*24; zt += 3600*24;
oe.setZeroTime(formatTimeHMSW(zt)); oe.setZeroTime(formatTimeHMS(zt));
} }
} }
//oe.setZeroTime(...); //oe.setZeroTime(...);
@ -1347,6 +1347,14 @@ pTeam IOF30Interface::readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
wstring entryTime; wstring entryTime;
xTeam.getObjectString("EntryTime", entryTime); xTeam.getObjectString("EntryTime", entryTime);
di.setDate("EntryDate", entryTime); di.setDate("EntryDate", entryTime);
size_t tpos = entryTime.find_first_of(L"T");
if (tpos != -1) {
wstring timeString = entryTime.substr(tpos+1);
int t = convertAbsoluteTimeISO(timeString);
if (t >= 0)
di.setInt("EntryTime", t);
}
} }
double fee = 0, paid = 0, taxable = 0, percentage = 0; double fee = 0, paid = 0, taxable = 0, percentage = 0;
@ -1485,7 +1493,7 @@ void IOF30Interface::prescanEntry(xmlobject &xo, set<int> &stages) {
if (races.empty()) if (races.empty())
stages.insert(-1);// All stages.insert(-1);// All
else { else {
for (auto race : races) { for (auto &race : races) {
int r = race.getInt(); int r = race.getInt();
if (r > 0) if (r > 0)
stages.insert(r); stages.insert(r);
@ -1497,7 +1505,7 @@ bool IOF30Interface::matchStageFilter(const set<int> &stageFilter, const xmlList
if (stageFilter.empty() || races.empty()) if (stageFilter.empty() || races.empty())
return true; return true;
for (auto r : races) { for (auto &r : races) {
if (stageFilter.count(r.getInt())) if (stageFilter.count(r.getInt()))
return true; return true;
} }
@ -1580,6 +1588,14 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
wstring entryTime; wstring entryTime;
xo.getObjectString("EntryTime", entryTime); xo.getObjectString("EntryTime", entryTime);
di.setDate("EntryDate", entryTime); di.setDate("EntryDate", entryTime);
size_t tpos = entryTime.find_first_of(L"T");
if (tpos != -1) {
wstring timeString = entryTime.substr(tpos+1);
int t = convertAbsoluteTimeISO(timeString);
if (t >= 0)
di.setInt("EntryTime", t);
}
double fee = 0, paid = 0, taxable = 0, percentage = 0; double fee = 0, paid = 0, taxable = 0, percentage = 0;
wstring currency; wstring currency;
@ -2064,7 +2080,7 @@ void IOF30Interface::FeeInfo::add(IOF30Interface::FeeInfo &fi) {
convertDateYMS(fi.toTime, st, false); convertDateYMS(fi.toTime, st, false);
__int64 sec = SystemTimeToInt64Second(st); __int64 sec = SystemTimeToInt64Second(st);
sec -= 3600; sec -= 3600;
fi.toTime = convertSystemDateW(Int64SecondToSystemTime(sec)); fi.toTime = convertSystemDate(Int64SecondToSystemTime(sec));
} }
} }
//if (fi.fromTime.empty() || (fi.fromTime < toTime && !toTime.empty())) //if (fi.fromTime.empty() || (fi.fromTime < toTime && !toTime.empty()))
@ -2270,7 +2286,7 @@ void IOF30Interface::setupRelayClass(pClass pc, const vector<LegInfo> &legs) {
wstring IOF30Interface::getCurrentTime() const { wstring IOF30Interface::getCurrentTime() const {
// Don't call this method at midnight! // Don't call this method at midnight!
return getLocalDateW() + L"T" + getLocalTimeOnlyW(); return getLocalDate() + L"T" + getLocalTimeOnly();
} }
int IOF30Interface::parseISO8601Time(const xmlobject &xo) { int IOF30Interface::parseISO8601Time(const xmlobject &xo) {
@ -2488,6 +2504,8 @@ wstring formatStatus(RunnerStatus st) {
return L"OK"; return L"OK";
case StatusDNS: case StatusDNS:
return L"DidNotStart"; return L"DidNotStart";
case StatusCANCEL:
return L"Cancelled";
case StatusMP: case StatusMP:
return L"MissingPunch"; return L"MissingPunch";
case StatusDNF: case StatusDNF:
@ -2647,7 +2665,9 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
writeCourse(xml, *crs); writeCourse(xml, *crs);
const vector<SplitData> &sp = r.getSplitTimes(unrollLoops); const vector<SplitData> &sp = r.getSplitTimes(unrollLoops);
if (r.getStatus()>0 && r.getStatus() != StatusDNS && r.getStatus() != StatusNotCompetiting) { if (r.getStatus()>0 && r.getStatus() != StatusDNS &&
r.getStatus() != StatusCANCEL &&
r.getStatus() != StatusNotCompetiting) {
int nc = crs->getNumControls(); int nc = crs->getNumControls();
bool hasRogaining = crs->hasRogaining(); bool hasRogaining = crs->hasRogaining();
int firstControl = crs->useFirstAsStart() ? 1 : 0; int firstControl = crs->useFirstAsStart() ? 1 : 0;

View File

@ -298,7 +298,13 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
ButtonInfo &biSrc = dynamic_cast<ButtonInfo &>(data); ButtonInfo &biSrc = dynamic_cast<ButtonInfo &>(data);
if (bi.id == "Color") { if (bi.id == "Color") {
CHOOSECOLOR cc; wstring c = oe->getPropertyString("Colors", L"");
int res = gdi.selectColor(c, bi.getExtraInt());
if (res >= -1) {
biSrc.setExtra(res);
oe->setProperty("Colors", c);
}
/*CHOOSECOLOR cc;
memset(&cc, 0, sizeof(cc)); memset(&cc, 0, sizeof(cc));
cc.lStructSize = sizeof(cc); cc.lStructSize = sizeof(cc);
cc.hwndOwner = gdi.getHWND(); cc.hwndOwner = gdi.getHWND();
@ -317,8 +323,6 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
staticColor[pix++] = strtol(pEnd,(char **)&pEnd,16); staticColor[pix++] = strtol(pEnd,(char **)&pEnd,16);
} }
//vector<string> splitvector;
//split(c, ";", splitvector);
cc.lpCustColors = staticColor; cc.lpCustColors = staticColor;
if (ChooseColor(&cc)) { if (ChooseColor(&cc)) {
data.setExtra((int)cc.rgbResult); data.setExtra((int)cc.rgbResult);
@ -330,7 +334,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
co += bf; co += bf;
} }
oe->setProperty("Colors", co); oe->setProperty("Colors", co);
} }*/
} }
if ( bi.id.substr(0, 8) == "EditPost" ) { if ( bi.id.substr(0, 8) == "EditPost" ) {
int id = atoi(bi.id.substr(8).c_str()); int id = atoi(bi.id.substr(8).c_str());

View File

@ -313,12 +313,12 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
if (screenSize == 1) { if (screenSize == 1) {
gdi.restore("LiveResult", false); gdi.restore("LiveResult", false);
wstring font = getFont(gdi, timerScale); wstring font = getFont(gdi, timerScale);
gdi.addString("", h/2, w/2, boldHuge|textCenter, formatTimeW(rt), 0, 0, font.c_str()).setColor(colorGreen); gdi.addString("", h/2, w/2, boldHuge|textCenter, formatTime(rt), 0, 0, font.c_str()).setColor(colorGreen);
gdi.addTimeout(5, 0).setHandler(this); gdi.addTimeout(5, 0).setHandler(this);
} }
else if (screenSize == 2) { else if (screenSize == 2) {
string id = "timer" + itos(runner2ScreenPos[rToFinish->getId()]); string id = "timer" + itos(runner2ScreenPos[rToFinish->getId()]);
BaseInfo *bi = gdi.setText(id, formatTimeW(rt), false); BaseInfo *bi = gdi.setText(id, formatTime(rt), false);
wstring font = getFont(gdi, timerScale * 0.6); wstring font = getFont(gdi, timerScale * 0.6);
if (bi) { if (bi) {
@ -388,7 +388,7 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
int ht = ti.textRect.bottom - ti.textRect.top; int ht = ti.textRect.bottom - ti.textRect.top;
gdi.addStringUT(y, 30 + ht * 2 , fontLarge, r->getName(), 0, 0, font.c_str()); gdi.addStringUT(y, 30 + ht * 2 , fontLarge, r->getName(), 0, 0, font.c_str());
//int w = gdi.getWidth(); //int w = gdi.getWidth();
gdi.addStringUT(y, w - 4 * ht, fontLarge, formatTimeW(res.time), 0, 0, font.c_str()); gdi.addStringUT(y, w - 4 * ht, fontLarge, formatTime(res.time), 0, 0, font.c_str());
gdi.refreshSmartFromSnapshot(false); gdi.refreshSmartFromSnapshot(false);
resYPos += int (ht * 1.1); resYPos += int (ht * 1.1);
showResultList++; showResultList++;

View File

@ -63,8 +63,7 @@
#include "autotask.h" #include "autotask.h"
#include "meosexception.h" #include "meosexception.h"
#include "parser.h" #include "parser.h"
#include "restserver.h"
#include "restbed/restbed"
gdioutput *gdi_main=0; gdioutput *gdi_main=0;
oEvent *gEvent=0; oEvent *gEvent=0;
@ -162,6 +161,8 @@ void mainMessageLoop(HACCEL hAccelTable, DWORD time) {
while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0 ) { while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0 ) {
if (bRet == -1) if (bRet == -1)
return; return;
if (gEvent != 0)
RestServer::computeRequested(*gEvent);
if (hAccelTable == 0 || !TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { if (hAccelTable == 0 || !TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg); TranslateMessage(&msg);
@ -174,19 +175,6 @@ void mainMessageLoop(HACCEL hAccelTable, DWORD time) {
} }
} }
void post_method_handler(const shared_ptr< restbed::Session > session)
{
using namespace restbed;
const auto request = session->get_request();
size_t content_length = request->get_header("Content-Length", 0);
session->fetch(content_length, [request](const shared_ptr< Session > session, const Bytes & body)
{
fprintf(stdout, "%.*s\n", (int)body.size(), body.data());
session->close(restbed::OK, "Hello, World!", { { "Content-Length", "13" },{ "Connection", "close" } });
});
}
int APIENTRY WinMain(HINSTANCE hInstance, int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, HINSTANCE hPrevInstance,
@ -195,20 +183,6 @@ int APIENTRY WinMain(HINSTANCE hInstance,
{ {
atexit(dumpLeaks); // atexit(dumpLeaks); //
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
/*{
using namespace restbed;
auto resource = make_shared< Resource >();
resource->set_path("/resource");
resource->set_method_handler("GET", post_method_handler);
Service service;
auto settings = make_shared< Settings >();
settings->set_port(1984);
service.publish(resource);
service.start(settings);
}*/
if (strstr(lpCmdLine, "-s") != 0) { if (strstr(lpCmdLine, "-s") != 0) {
Setup(true, false); Setup(true, false);
@ -226,9 +200,10 @@ int APIENTRY WinMain(HINSTANCE hInstance,
RunnerStatusOrderMap[StatusMP] = 2; RunnerStatusOrderMap[StatusMP] = 2;
RunnerStatusOrderMap[StatusDNF] = 3; RunnerStatusOrderMap[StatusDNF] = 3;
RunnerStatusOrderMap[StatusDQ] = 4; RunnerStatusOrderMap[StatusDQ] = 4;
RunnerStatusOrderMap[StatusDNS] = 5; RunnerStatusOrderMap[StatusCANCEL] = 5;
RunnerStatusOrderMap[StatusUnknown] = 6; RunnerStatusOrderMap[StatusDNS] = 6;
RunnerStatusOrderMap[StatusNotCompetiting] = 7; RunnerStatusOrderMap[StatusUnknown] = 7;
RunnerStatusOrderMap[StatusNotCompetiting] = 8;
lang.init(); lang.init();
StringCache::getInstance().init(); StringCache::getInstance().init();
@ -413,7 +388,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
for (size_t k = 0; k<gdi_extra.size(); k++) { for (size_t k = 0; k<gdi_extra.size(); k++) {
if (gdi_extra[k]) { if (gdi_extra[k]) {
DestroyWindow(gdi_extra[k]->getHWND()); DestroyWindow(gdi_extra[k]->getHWNDMain());
if (k < gdi_extra.size()) { if (k < gdi_extra.size()) {
delete gdi_extra[k]; delete gdi_extra[k];
gdi_extra[k] = 0; gdi_extra[k] = 0;
@ -555,7 +530,7 @@ LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
gdi = gdi_main; gdi = gdi_main;
HWND hWnd = gdi ? gdi->getHWND() : 0; HWND hWnd = gdi ? gdi->getHWNDTarget() : 0;
bool ctrlPressed = (GetKeyState(VK_CONTROL) & 0x8000) == 0x8000; bool ctrlPressed = (GetKeyState(VK_CONTROL) & 0x8000) == 0x8000;
bool shiftPressed = (GetKeyState(VK_SHIFT) & 0x8000) == 0x8000; bool shiftPressed = (GetKeyState(VK_SHIFT) & 0x8000) == 0x8000;
@ -740,7 +715,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
void destroyExtraWindows() { void destroyExtraWindows() {
for (size_t k = 1; k<gdi_extra.size(); k++) { for (size_t k = 1; k<gdi_extra.size(); k++) {
if (gdi_extra[k]) { if (gdi_extra[k]) {
DestroyWindow(gdi_extra[k]->getHWND()); DestroyWindow(gdi_extra[k]->getHWNDMain());
} }
} }
} }
@ -768,7 +743,7 @@ gdioutput *getExtraWindow(const string &tag, bool toForeGround) {
for (size_t k = 0; k<gdi_extra.size(); k++) { for (size_t k = 0; k<gdi_extra.size(); k++) {
if (gdi_extra[k] && gdi_extra[k]->hasTag(tag)) { if (gdi_extra[k] && gdi_extra[k]->hasTag(tag)) {
if (toForeGround) if (toForeGround)
SetForegroundWindow(gdi_extra[k]->getHWND()); SetForegroundWindow(gdi_extra[k]->getHWNDMain());
return gdi_extra[k]; return gdi_extra[k];
} }
} }
@ -791,7 +766,7 @@ gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x,
for (size_t k = 0; k<gdi_extra.size(); k++) { for (size_t k = 0; k<gdi_extra.size(); k++) {
if (gdi_extra[k]) { if (gdi_extra[k]) {
HWND hWnd = gdi_extra[k]->getHWND(); HWND hWnd = gdi_extra[k]->getHWNDTarget();
RECT rc; RECT rc;
if (GetWindowRect(hWnd, &rc)) { if (GetWindowRect(hWnd, &rc)) {
xp = max<int>(rc.left + 16, xp); xp = max<int>(rc.left + 16, xp);
@ -829,6 +804,9 @@ gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x,
gdi_main->cmdAnswers.pop_front(); gdi_main->cmdAnswers.pop_front();
} }
} }
else {
gdi->initRecorder(&gdi_main->getRecorder());
}
SetWindowLong(hWnd, GWL_USERDATA, gdi_extra.size()); SetWindowLong(hWnd, GWL_USERDATA, gdi_extra.size());
currentFocusIx = gdi_extra.size(); currentFocusIx = gdi_extra.size();
gdi_extra.push_back(gdi); gdi_extra.push_back(gdi);

View File

@ -35,6 +35,11 @@ namespace MeOSUtil {
int useHourFormat = true; int useHourFormat = true;
} }
string convertSystemTimeN(const SYSTEMTIME &st);
string convertSystemDateN(const SYSTEMTIME &st);
string convertSystemTimeOnlyN(const SYSTEMTIME &st);
DWORD mainThreadId = -1; DWORD mainThreadId = -1;
StringCache &StringCache::getInstance() { StringCache &StringCache::getInstance() {
DWORD id = GetCurrentThreadId(); DWORD id = GetCurrentThreadId();
@ -45,29 +50,33 @@ StringCache &StringCache::getInstance() {
return globalStringCache; return globalStringCache;
} }
string getLocalTime() { string getLocalTimeN() {
SYSTEMTIME st;
GetLocalTime(&st);
return convertSystemTimeN(st);
}
string getLocalDateN()
{
SYSTEMTIME st;
GetLocalTime(&st);
return convertSystemDateN(st);
}
wstring getLocalTime() {
SYSTEMTIME st; SYSTEMTIME st;
GetLocalTime(&st); GetLocalTime(&st);
return convertSystemTime(st); return convertSystemTime(st);
} }
string getLocalDate() wstring getLocalDate() {
{
SYSTEMTIME st; SYSTEMTIME st;
GetLocalTime(&st); GetLocalTime(&st);
return convertSystemDate(st); return convertSystemDate(st);
} }
wstring getLocalTimeW() { int getLocalAbsTime() {
SYSTEMTIME st; return convertAbsoluteTimeHMS(getLocalTimeOnly(), -1);
GetLocalTime(&st);
return convertSystemTimeW(st);
}
wstring getLocalDateW() {
SYSTEMTIME st;
GetLocalTime(&st);
return convertSystemDateW(st);
} }
int getThisYear() { int getThisYear() {
@ -114,20 +123,20 @@ wstring getLocalTimeFileName()
return bf; return bf;
} }
string getLocalTimeOnly() string getLocalTimeOnlyN()
{
SYSTEMTIME st;
GetLocalTime(&st);
return convertSystemTimeOnlyN(st);
}
wstring getLocalTimeOnly()
{ {
SYSTEMTIME st; SYSTEMTIME st;
GetLocalTime(&st); GetLocalTime(&st);
return convertSystemTimeOnly(st); return convertSystemTimeOnly(st);
} }
wstring getLocalTimeOnlyW()
{
SYSTEMTIME st;
GetLocalTime(&st);
return convertSystemTimeOnlyW(st);
}
int getRelativeDay() { int getRelativeDay() {
SYSTEMTIME st; SYSTEMTIME st;
GetLocalTime(&st); GetLocalTime(&st);
@ -169,7 +178,7 @@ SYSTEMTIME Int64SecondToSystemTime(__int64 time) {
return st; return st;
} }
//2014-11-03 07:02:00 //2014-11-03 07:02:00
string convertSystemTime(const SYSTEMTIME &st) string convertSystemTimeN(const SYSTEMTIME &st)
{ {
char bf[32]; char bf[32];
sprintf_s(bf, "%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, sprintf_s(bf, "%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
@ -179,7 +188,7 @@ string convertSystemTime(const SYSTEMTIME &st)
} }
//2014-11-03 07:02:00 //2014-11-03 07:02:00
wstring convertSystemTimeW(const SYSTEMTIME &st) wstring convertSystemTime(const SYSTEMTIME &st)
{ {
wchar_t bf[32]; wchar_t bf[32];
swprintf_s(bf, L"%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, swprintf_s(bf, L"%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
@ -188,7 +197,7 @@ wstring convertSystemTimeW(const SYSTEMTIME &st)
return bf; return bf;
} }
string convertSystemTimeOnly(const SYSTEMTIME &st) string convertSystemTimeOnlyN(const SYSTEMTIME &st)
{ {
char bf[32]; char bf[32];
sprintf_s(bf, "%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond); sprintf_s(bf, "%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond);
@ -196,14 +205,14 @@ string convertSystemTimeOnly(const SYSTEMTIME &st)
return bf; return bf;
} }
wstring convertSystemTimeOnlyW(const SYSTEMTIME &st) { wstring convertSystemTimeOnly(const SYSTEMTIME &st) {
wchar_t bf[32]; wchar_t bf[32];
swprintf_s(bf, L"%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond); swprintf_s(bf, L"%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond);
return bf; return bf;
} }
string convertSystemDate(const SYSTEMTIME &st) string convertSystemDateN(const SYSTEMTIME &st)
{ {
char bf[32]; char bf[32];
sprintf_s(bf, "%d-%02d-%02d", st.wYear, st.wMonth, st.wDay); sprintf_s(bf, "%d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
@ -211,7 +220,7 @@ string convertSystemDate(const SYSTEMTIME &st)
return bf; return bf;
} }
wstring convertSystemDateW(const SYSTEMTIME &st) wstring convertSystemDate(const SYSTEMTIME &st)
{ {
wchar_t bf[32]; wchar_t bf[32];
swprintf_s(bf, L"%d-%02d-%02d", st.wYear, st.wMonth, st.wDay); swprintf_s(bf, L"%d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
@ -219,7 +228,7 @@ wstring convertSystemDateW(const SYSTEMTIME &st)
return bf; return bf;
} }
string formatDate(int m, bool useIsoFormat) { string formatDateN(int m, bool useIsoFormat) {
char bf[24]; char bf[24];
if (m > 0 && m < 30000101) { if (m > 0 && m < 30000101) {
sprintf_s(bf, 24, "%d-%02d-%02d", m/(100*100), (m/100)%100, m%100); sprintf_s(bf, 24, "%d-%02d-%02d", m/(100*100), (m/100)%100, m%100);
@ -231,7 +240,7 @@ string formatDate(int m, bool useIsoFormat) {
return bf; return bf;
} }
wstring formatDateW(int m, bool useIsoFormat) { wstring formatDate(int m, bool useIsoFormat) {
wchar_t bf[24]; wchar_t bf[24];
if (m > 0 && m < 30000101) { if (m > 0 && m < 30000101) {
swprintf_s(bf, 24, L"%d-%02d-%02d", m/(100*100), (m/100)%100, m%100); swprintf_s(bf, 24, L"%d-%02d-%02d", m/(100*100), (m/100)%100, m%100);
@ -320,11 +329,6 @@ bool myIsSpace(wchar_t b) {
return iswspace(b) != 0 || b == 0x00A0 || b == 0x2007 || b == 0x202F; return iswspace(b) != 0 || b == 0x00A0 || b == 0x2007 || b == 0x202F;
} }
//Absolute time string to absolute time int
int convertAbsoluteTimeHMS(const wstring &m, int daysZeroTime) {
string sm(m.begin(), m.end());
return convertAbsoluteTimeHMS(sm, daysZeroTime);
}
//Absolute time string to absolute time int //Absolute time string to absolute time int
int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) { int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) {
@ -408,10 +412,10 @@ int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) {
return t; return t;
} }
//Absolute time string to absolute time int
int convertAbsoluteTimeISO(const wstring &m) { int convertAbsoluteTimeHMS(const wstring &m, int daysZeroTime) {
string mn(m.begin(), m.end()); string sm(m.begin(), m.end());
return convertAbsoluteTimeISO(mn); return convertAbsoluteTimeHMS(sm, daysZeroTime);
} }
//Absolute time string to absolute time int //Absolute time string to absolute time int
@ -450,6 +454,15 @@ int convertAbsoluteTimeISO(const string &m)
sStr = tmp.substr(0, 2); sStr = tmp.substr(0, 2);
for (int i = 0; i < 2; i++) {
if (hStr[i] < '0' || hStr[i] > '9')
return -1;
if (mStr[i] < '0' || mStr[i] > '9')
return -1;
if (sStr[i] < '0' || sStr[i] > '9')
return -1;
}
int hour = atoi(hStr.c_str()); int hour = atoi(hStr.c_str());
if (hour<0 || hour>23) if (hour<0 || hour>23)
return -1; return -1;
@ -469,9 +482,9 @@ int convertAbsoluteTimeISO(const string &m)
return t; return t;
} }
int convertAbsoluteTimeMS(const wstring &m) { int convertAbsoluteTimeISO(const wstring &m) {
string mn(m.begin(), m.end()); string mn(m.begin(), m.end());
return convertAbsoluteTimeMS(mn); return convertAbsoluteTimeISO(mn);
} }
// Parse +-MM:SS or +-HH:MM:SS // Parse +-MM:SS or +-HH:MM:SS
@ -524,29 +537,25 @@ int convertAbsoluteTimeMS(const string &m)
return sign*t; return sign*t;
} }
//Generate +-MM:SS or +-HH:MM:SS int convertAbsoluteTimeMS(const wstring &m) {
const wstring &getTimeMSW(int m) { string mn(m.begin(), m.end());
wstring &res = StringCache::getInstance().wget(); return convertAbsoluteTimeMS(mn);
const string tr = getTimeMS(m);
res.clear();
res.insert(res.begin(), tr.begin(), tr.end());
return res;
} }
//Generate +-MM:SS or +-HH:MM:SS //Generate +-MM:SS or +-HH:MM:SS
const string &getTimeMS(int m) { const wstring &getTimeMS(int m) {
char bf[32]; wchar_t bf[32];
int am = abs(m); int am = abs(m);
if (am < 3600 || !MeOSUtil::useHourFormat) if (am < 3600 || !MeOSUtil::useHourFormat)
sprintf_s(bf, "-%02d:%02d", am/60, am%60); swprintf_s(bf, L"-%02d:%02d", am/60, am%60);
else if (am < 3600*48) else if (am < 3600*48)
sprintf_s(bf, "-%02d:%02d:%02d", am/3600, (am/60)%60, am%60); swprintf_s(bf, L"-%02d:%02d:%02d", am/3600, (am/60)%60, am%60);
else { else {
m = 0; m = 0;
bf[0] = BYTE(0x96); bf[0] = 0x2013;
bf[1] = 0; bf[1] = 0;
} }
string &res = StringCache::getInstance().get(); wstring &res = StringCache::getInstance().wget();
if (m<0) if (m<0)
res = bf; // with minus res = bf; // with minus
else else
@ -555,7 +564,7 @@ const string &getTimeMS(int m) {
return res; return res;
} }
const wstring &formatTimeW(int rt) { const wstring &formatTime(int rt) {
wstring &res = StringCache::getInstance().wget(); wstring &res = StringCache::getInstance().wget();
if (rt>0 && rt<3600*999) { if (rt>0 && rt<3600*999) {
wchar_t bf[16]; wchar_t bf[16];
@ -588,25 +597,15 @@ const string &formatTimeN(int rt) {
return res; return res;
} }
const wstring &formatTimeHMSW(int m) { const wstring &formatTimeHMS(int rt) {
wstring &res = StringCache::getInstance().wget(); wstring &res = StringCache::getInstance().wget();
const string tr = formatTimeHMS(m);
res.clear();
res.insert(res.begin(), tr.begin(), tr.end());
return res;
}
const string &formatTimeHMS(int rt) {
string &res = StringCache::getInstance().get();
if (rt>=0) { if (rt>=0) {
char bf[32]; wchar_t bf[32];
sprintf_s(bf, 16, "%02d:%02d:%02d", rt/3600,(rt/60)%60, rt%60); swprintf_s(bf, 16, L"%02d:%02d:%02d", rt/3600,(rt/60)%60, rt%60);
res = bf; res = bf;
return res; return res;
} }
char ret[2] = {char(0x96), 0}; wchar_t ret[2] = {0x2013, 0};
res = ret; res = ret;
return res; return res;
} }
@ -2170,3 +2169,17 @@ void wide2String(const wstring &in, string &out) {
out.clear(); out.clear();
out.insert(out.begin(), in.begin(), in.end());// XXX Simple extend out.insert(out.begin(), in.begin(), in.end());// XXX Simple extend
} }
void checkWriteAccess(const wstring &file) {
if (_waccess(file.c_str(), 4) == 0)
return;
auto h = CreateFile(file.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
if (h == INVALID_HANDLE_VALUE) {
wchar_t absPath[260];
_wfullpath(absPath, file.c_str(), 260);
throw meosException(wstring(L"Du saknar behörighet att skriva till 'X'.#") + absPath);
}
CloseHandle(h);
}

View File

@ -52,20 +52,26 @@ public:
} }
}; };
string convertSystemTimeN(const SYSTEMTIME &st);
/*
string convertSystemTime(const SYSTEMTIME &st); string convertSystemTime(const SYSTEMTIME &st);
string convertSystemTimeOnly(const SYSTEMTIME &st); string convertSystemTimeOnly(const SYSTEMTIME &st);
string convertSystemDate(const SYSTEMTIME &st); string convertSystemDate(const SYSTEMTIME &st);
string getLocalTime(); string getLocalTime();
string getLocalDate(); string getLocalDate();
string getLocalTimeOnly(); string getLocalTimeOnly();
*/
string getLocalTimeN();
wstring convertSystemTimeW(const SYSTEMTIME &st); wstring convertSystemTime(const SYSTEMTIME &st);
wstring convertSystemTimeOnlyW(const SYSTEMTIME &st); wstring convertSystemTimeOnly(const SYSTEMTIME &st);
wstring convertSystemDateW(const SYSTEMTIME &st); wstring convertSystemDate(const SYSTEMTIME &st);
wstring getLocalTimeW(); wstring getLocalTime();
wstring getLocalDateW(); wstring getLocalDate();
wstring getLocalTimeOnlyW(); wstring getLocalTimeOnly();
// Returns time in seconds after midnight
int getLocalAbsTime();
// Get a day number after a fixed day some time ago... // Get a day number after a fixed day some time ago...
int getRelativeDay(); int getRelativeDay();
@ -73,13 +79,11 @@ int getRelativeDay();
/// Get time and date in a format that forms a part of a filename /// Get time and date in a format that forms a part of a filename
wstring getLocalTimeFileName(); wstring getLocalTimeFileName();
const wstring &getTimeMSW(int m); const wstring &getTimeMS(int m);
const wstring &formatTimeW(int rt); const wstring &formatTime(int rt);
const wstring &formatTimeHMSW(int rt); const wstring &formatTimeHMS(int rt);
const string &getTimeMS(int m); //const string &formatTimeN(int rt);
const string &formatTimeN(int rt);
const string &formatTimeHMS(int rt);
wstring formatTimeIOF(int rt, int zeroTime); wstring formatTimeIOF(int rt, int zeroTime);
int convertDateYMS(const string &m, bool checkValid); int convertDateYMS(const string &m, bool checkValid);
@ -93,8 +97,8 @@ int convertDateYMS(const wstring &m, SYSTEMTIME &st, bool checkValid);
void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &meosDate); void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &meosDate);
// Format number date 20160421 -> 2016-04-21 (if iso) or according to a custom format otherwise // Format number date 20160421 -> 2016-04-21 (if iso) or according to a custom format otherwise
string formatDate(int m, bool useIsoFormat); //string formatDate(int m, bool useIsoFormat);
wstring formatDateW(int m, bool useIsoFormat); wstring formatDate(int m, bool useIsoFormat);
__int64 SystemTimeToInt64Second(const SYSTEMTIME &st); __int64 SystemTimeToInt64Second(const SYSTEMTIME &st);
SYSTEMTIME Int64SecondToSystemTime(__int64 time); SYSTEMTIME Int64SecondToSystemTime(__int64 time);
@ -107,15 +111,16 @@ int convertAbsoluteTimeMS(const wstring &m);
int convertAbsoluteTimeISO(const wstring &m); int convertAbsoluteTimeISO(const wstring &m);
//Returns a time converted from +/-MM:SS or NOTIME, in seconds //Returns a time converted from +/-MM:SS or NOTIME, in seconds
int convertAbsoluteTimeMS(const string &m); //int convertAbsoluteTimeMS(const string &m);
// Parses a time on format HH:MM:SS+01:00Z or HHMMSS+0100Z (but ignores time zone) // Parses a time on format HH:MM:SS+01:00Z or HHMMSS+0100Z (but ignores time zone)
int convertAbsoluteTimeISO(const string &m); //int convertAbsoluteTimeISO(const string &m);
/** Returns a time converted from HH:MM:SS or -1, in seconds /** Returns a time converted from HH:MM:SS or -1, in seconds
@param m time to convert @param m time to convert
@param daysZeroTime -1 do not support days syntax, positive interpret days w.r.t the specified zero time. @param daysZeroTime -1 do not support days syntax, positive interpret days w.r.t the specified zero time.
*/ */
int convertAbsoluteTimeHMS(const string &m, int daysZeroTime); int convertAbsoluteTimeHMS(const string &m, int daysZeroTime);
/** Returns a time converted from HH:MM:SS or -1, in seconds /** Returns a time converted from HH:MM:SS or -1, in seconds
@param m time to convert @param m time to convert
@param daysZeroTime -1 do not support days syntax, positive interpret days w.r.t the specified zero time. @param daysZeroTime -1 do not support days syntax, positive interpret days w.r.t the specified zero time.
@ -123,7 +128,7 @@ int convertAbsoluteTimeHMS(const string &m, int daysZeroTime);
int convertAbsoluteTimeHMS(const wstring &m, int daysZeroTime); int convertAbsoluteTimeHMS(const wstring &m, int daysZeroTime);
const vector<string> &split(const string &line, const string &separators, vector<string> &split_vector); const vector<string> &split(const string &line, const string &separators, vector<string> &split_vector);
const string &unsplit(const vector<string> &split_vector, const string &separators, string &line); //const string &unsplit(const vector<string> &split_vector, const string &separators, string &line);
const vector<wstring> &split(const wstring &line, const wstring &separators, vector<wstring> &split_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); const wstring &unsplit(const vector<wstring> &split_vector, const wstring &separators, wstring &line);
@ -289,3 +294,5 @@ namespace MeOSUtil {
void string2Wide(const string &in, wstring &out); void string2Wide(const string &in, wstring &out);
void wide2String(const wstring &in, string &out); void wide2String(const wstring &in, string &out);
void checkWriteAccess(const wstring &file);

View File

@ -840,7 +840,7 @@ OpFailStatus MeosSQL::uploadRunnerDB(oEvent *oe)
return opStatusFail; return opStatusFail;
int errorCount = 0; int errorCount = 0;
int totErrorCount = 0; int totErrorCount = 0;
ProgressWindow pw(oe->hWnd()); ProgressWindow pw(oe->gdiBase().getHWNDTarget());
try { try {
const vector<oDBClubEntry> &cdb = oe->runnerDB->getClubDB(true); const vector<oDBClubEntry> &cdb = oe->runnerDB->getClubDB(true);
size_t size = cdb.size(); size_t size = cdb.size();
@ -1000,7 +1000,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
if (!oe->Id) return SyncUpdate(oe); if (!oe->Id) return SyncUpdate(oe);
ProgressWindow pw(oe->hWnd()); ProgressWindow pw(oe->gdiBase().getHWNDTarget());
try { try {
con.select_db("MeOSMain"); con.select_db("MeOSMain");

View File

@ -239,6 +239,7 @@
</Bscmake> </Bscmake>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="animationdata.cpp" />
<ClCompile Include="autotask.cpp" /> <ClCompile Include="autotask.cpp" />
<ClCompile Include="classconfiginfo.cpp" /> <ClCompile Include="classconfiginfo.cpp" />
<ClCompile Include="csvparser.cpp"> <ClCompile Include="csvparser.cpp">
@ -340,6 +341,8 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='test|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='test|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<ClCompile Include="recorder.cpp" /> <ClCompile Include="recorder.cpp" />
<ClCompile Include="restserver.cpp" />
<ClCompile Include="RestService.cpp" />
<ClCompile Include="RunnerDB.cpp" /> <ClCompile Include="RunnerDB.cpp" />
<ClCompile Include="socket.cpp" /> <ClCompile Include="socket.cpp" />
<ClCompile Include="speakermonitor.cpp" /> <ClCompile Include="speakermonitor.cpp" />
@ -386,6 +389,7 @@
<ClCompile Include="zip.cpp" /> <ClCompile Include="zip.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="animationdata.h" />
<ClInclude Include="autotask.h" /> <ClInclude Include="autotask.h" />
<ClInclude Include="classconfiginfo.h" /> <ClInclude Include="classconfiginfo.h" />
<ClInclude Include="gdiconstants.h" /> <ClInclude Include="gdiconstants.h" />
@ -417,6 +421,8 @@
<ClInclude Include="prefseditor.h" /> <ClInclude Include="prefseditor.h" />
<ClInclude Include="Printer.h" /> <ClInclude Include="Printer.h" />
<ClInclude Include="recorder.h" /> <ClInclude Include="recorder.h" />
<ClInclude Include="restserver.h" />
<ClInclude Include="RestService.h" />
<ClInclude Include="socket.h" /> <ClInclude Include="socket.h" />
<ClInclude Include="speakermonitor.h" /> <ClInclude Include="speakermonitor.h" />
<ClInclude Include="subcommand.h" /> <ClInclude Include="subcommand.h" />
@ -479,6 +485,9 @@
<None Include="meos.ico" /> <None Include="meos.ico" />
<None Include="small.ico" /> <None Include="small.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Image Include="bmp00001.bmp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>

View File

@ -29,7 +29,7 @@
//V33: abcde //V33: abcde
//V35: abc //V35: abc
int getMeosBuild() { int getMeosBuild() {
string revision("$Rev: 611 $"); string revision("$Rev: 621 $");
return 174 + atoi(revision.substr(5, string::npos).c_str()); return 174 + atoi(revision.substr(5, string::npos).c_str());
} }
@ -41,7 +41,7 @@ int getMeosBuild() {
//V33: abcdefghij //V33: abcdefghij
//V34: abcdfg //V34: abcdfg
wstring getMeosDate() { wstring getMeosDate() {
wstring date(L"$Date: 2017-08-28 20:32:01 +0200 (må, 28 aug 2017) $"); wstring date(L"$Date: 2017-10-21 22:43:38 +0200 (lö, 21 okt 2017) $");
return date.substr(7,10); return date.substr(7,10);
} }
@ -176,4 +176,5 @@ void getSupporters(vector<string> &supp)
supp.push_back("Timrå SOK"); supp.push_back("Timrå SOK");
supp.push_back("Åke Larsson, OK Hedströmmen"); supp.push_back("Åke Larsson, OK Hedströmmen");
supp.push_back("Avesta OK"); supp.push_back("Avesta OK");
supp.push_back("Motionsorientering Göteborg");
} }

View File

@ -43,6 +43,7 @@ const int MAXLISTPARAMID = 10000000;
using namespace tr1; using namespace tr1;
oListParam::oListParam() { oListParam::oListParam() {
lockUpdate = false;
listCode = EStdResultList; //Just need a default listCode = EStdResultList; //Just need a default
cb = 0; cb = 0;
legNumber = 0; legNumber = 0;
@ -59,6 +60,15 @@ oListParam::oListParam() {
nextList = 0; // No linked list nextList = 0; // No linked list
previousList = 0; previousList = 0;
relayLegIndex = -1; relayLegIndex = -1;
bgColor = -1;
fgColor = -1;
bgColor2 = -1;
nColumns = 0;
animate = true;
timePerPage = 8000;
margin = 5;
screenMode = 0;
} }
void oListParam::serialize(xmlparser &xml, void oListParam::serialize(xmlparser &xml,
@ -90,6 +100,24 @@ void oListParam::serialize(xmlparser &xml,
if (res != idToIndex.end()) if (res != idToIndex.end())
xml.write("NextList", res->second); xml.write("NextList", res->second);
} }
if (bgColor != -1)
xml.write("BGColor", itos(bgColor));
if (bgColor2 != -1)
xml.write("BGColor2", itos(bgColor2));
if (fgColor != -1)
xml.write("FGColor", itos(fgColor));
xml.write("Image", bgImage);
xml.write("ScreenMode", screenMode);
if (nColumns != 0) {
xml.write("NumColumns", itos(nColumns));
xml.writeBool("Animate", animate);
xml.write("TimePerPage", timePerPage);
xml.write("Margin", margin);
}
xml.endTag(); xml.endTag();
} }
@ -120,6 +148,32 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
showInterTitle = xml.getObjectBool("ShowInterTitle"); showInterTitle = xml.getObjectBool("ShowInterTitle");
inputNumber = xml.getObjectInt("InputNumber"); inputNumber = xml.getObjectInt("InputNumber");
nextList = xml.getObjectInt("NextList"); nextList = xml.getObjectInt("NextList");
xmlobject bg = xml.getObject("BGColor");
if (bg)
bgColor = bg.getInt();
xmlobject bg2 = xml.getObject("BGColor2");
if (bg2)
bgColor2 = bg2.getInt();
xmlobject fg = xml.getObject("FGColor");
if (fg)
fgColor = fg.getInt();
xml.getObjectString("Image", bgImage);
int nColumns = xml.getObjectInt("NumColumns");
screenMode = xml.getObjectInt("ScreenMode");
animate = xml.getObjectBool("Animate");
if (xml.got("TimePerPage"))
timePerPage = xml.getObjectInt("TimePerPage");
if (xml.got("Margin"))
timePerPage = xml.getObjectInt("Margin");
saved = true; saved = true;
} }
@ -961,7 +1015,7 @@ void MetaList::save(xmlparser &xml, const oEvent *oe) const {
// xml.write("Title", defaultTitle); // xml.write("Title", defaultTitle);
xml.write("ListName", listName); xml.write("ListName", listName);
if (listOrigin.empty()) if (listOrigin.empty())
listOrigin = gEvent->getName() + L" (" + getLocalDateW() + L")"; listOrigin = gEvent->getName() + L" (" + getLocalDate() + L")";
xml.write("ListOrigin", listOrigin); xml.write("ListOrigin", listOrigin);
xml.write("Tag", tag); xml.write("Tag", tag);
xml.write("UID", getUniqueId()); xml.write("UID", getUniqueId());
@ -1604,6 +1658,10 @@ void MetaList::initSymbols() {
typeToSymbol[lRunnerNationality] = L"RunnerNationality"; typeToSymbol[lRunnerNationality] = L"RunnerNationality";
typeToSymbol[lRunnerPhone] = L"RunnerPhone"; typeToSymbol[lRunnerPhone] = L"RunnerPhone";
typeToSymbol[lRunnerFee] = L"RunnerFee"; typeToSymbol[lRunnerFee] = L"RunnerFee";
typeToSymbol[lRunnerPaid] = L"RunnerPaid";
typeToSymbol[lRunnerPayMethod] = L"RunnerPayMethod";
typeToSymbol[lRunnerEntryDate] = L"RunnerEntryDate";
typeToSymbol[lRunnerEntryTime] = L"RunnerEntryTime";
typeToSymbol[lTeamName] = L"TeamName"; typeToSymbol[lTeamName] = L"TeamName";
typeToSymbol[lTeamStart] = L"TeamStart"; typeToSymbol[lTeamStart] = L"TeamStart";
@ -1719,6 +1777,7 @@ void MetaList::initSymbols() {
orderToSymbol[SortByFinishTimeReverse] = "FinishTimeReverse"; orderToSymbol[SortByFinishTimeReverse] = "FinishTimeReverse";
orderToSymbol[ClassFinishTime] = "ClassFinishTime"; orderToSymbol[ClassFinishTime] = "ClassFinishTime";
orderToSymbol[SortByStartTime] = "StartTime"; orderToSymbol[SortByStartTime] = "StartTime";
orderToSymbol[SortByEntryTime] = "EntryTime";
orderToSymbol[ClassPoints] = "ClassPoints"; orderToSymbol[ClassPoints] = "ClassPoints";
orderToSymbol[ClassTotalResult] = "ClassTotalResult"; orderToSymbol[ClassTotalResult] = "ClassTotalResult";
orderToSymbol[ClassTeamLegResult] = "ClassTeamLegResult"; orderToSymbol[ClassTeamLegResult] = "ClassTeamLegResult";

View File

@ -556,7 +556,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
wstring str; wstring str;
try { try {
rt = currentResult->deduceTime(*rr[k], rr[k]->getStartTime()); rt = currentResult->deduceTime(*rr[k], rr[k]->getStartTime());
str = formatTimeW(rt); str = formatTime(rt);
} }
catch (meosException &ex) { catch (meosException &ex) {
err = ex.wwhat(); err = ex.wwhat();
@ -657,7 +657,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
wstring str; wstring str;
try { try {
rt = currentResult->deduceTime(*tr[k]); rt = currentResult->deduceTime(*tr[k]);
str = formatTimeW(rt); str = formatTime(rt);
} }
catch (meosException &ex) { catch (meosException &ex) {
err = ex.wwhat(); err = ex.wwhat();
@ -976,7 +976,7 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
try { try {
rt = currentResult->deduceTime(r, r.getStartTime()); rt = currentResult->deduceTime(r, r.getStartTime());
gdi.addStringUT(1, L"ComputedTime: " + formatTimeW(rt)).setColor(colorGreen); gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen);
} }
catch (meosException &ex) { catch (meosException &ex) {
wstring err = lang.tl(ex.wwhat()); wstring err = lang.tl(ex.wwhat());
@ -1030,7 +1030,7 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
try { try {
rt = currentResult->deduceTime(t); rt = currentResult->deduceTime(t);
gdi.addStringUT(1, L"ComputedTime: " + formatTimeW(rt)).setColor(colorGreen); gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen);
} }
catch (meosException &ex) { catch (meosException &ex) {
wstring err = lang.tl(ex.wwhat()); wstring err = lang.tl(ex.wwhat());

View File

@ -31,7 +31,7 @@
MySQLReconnect::MySQLReconnect(const wstring &errorIn) : AutoMachine("MySQL-daemon"), error(errorIn) MySQLReconnect::MySQLReconnect(const wstring &errorIn) : AutoMachine("MySQL-daemon"), error(errorIn)
{ {
timeError = getLocalTimeW(); timeError = getLocalTime();
hThread=0; hThread=0;
} }
@ -110,7 +110,7 @@ void MySQLReconnect::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
} }
else { else {
gdi.addInfoBox("", L"Återansluten mot databasen, tävlingen synkroniserad.", 10000); gdi.addInfoBox("", L"Återansluten mot databasen, tävlingen synkroniserad.", 10000);
timeReconnect = getLocalTimeW(); timeReconnect = getLocalTime();
gdi.setDBErrorState(false); gdi.setDBErrorState(false);
gdi.setWindowTitle(oe->getTitleName()); gdi.setWindowTitle(oe->getTitleName());
interval=0; interval=0;

View File

@ -229,7 +229,7 @@ int TabCompetition::newGuideCB(gdioutput &gdi, int type, void *data)
long long stopT = absT + 23 * 3600; long long stopT = absT + 23 * 3600;
SYSTEMTIME start = Int64SecondToSystemTime(absT); SYSTEMTIME start = Int64SecondToSystemTime(absT);
SYSTEMTIME end = Int64SecondToSystemTime(stopT); SYSTEMTIME end = Int64SecondToSystemTime(stopT);
wstring s = L"Tävlingen måste avgöras mellan X och Y.#" + convertSystemTimeW(start) + L"#" + convertSystemTimeW(end); wstring s = L"Tävlingen måste avgöras mellan X och Y.#" + convertSystemTime(start) + L"#" + convertSystemTime(end);
gdi.setTextTranslate("AllowedInterval", s, true); gdi.setTextTranslate("AllowedInterval", s, true);
} }
} }
@ -261,7 +261,7 @@ void TabCompetition::newCompetitionGuide(gdioutput &gdi, int step) {
gdi.pushX(); gdi.pushX();
gdi.fillRight(); gdi.fillRight();
InputInfo &date = gdi.addInput("Date", getLocalDateW(), 16, NewGuideCB, L"Datum (för första start):"); InputInfo &date = gdi.addInput("Date", getLocalDate(), 16, NewGuideCB, L"Datum (för första start):");
gdi.addInput("FirstStart", L"07:00:00", 12, NewGuideCB, L"Första tillåtna starttid:"); gdi.addInput("FirstStart", L"07:00:00", 12, NewGuideCB, L"Första tillåtna starttid:");
@ -301,6 +301,7 @@ void TabCompetition::newCompetitionGuide(gdioutput &gdi, int step) {
} }
else if (step == 2) { else if (step == 2) {
rc.top = gdi.getCY(); rc.top = gdi.getCY();
oe->updateTabs(true, true);
gdi.fillDown(); gdi.fillDown();
gdi.dropLine(); gdi.dropLine();
gdi.addString("", fontMediumPlus, "Funktioner i MeOS"); gdi.addString("", fontMediumPlus, "Funktioner i MeOS");
@ -391,7 +392,7 @@ void TabCompetition::createCompetition(gdioutput &gdi) {
int t = convertAbsoluteTimeHMS(start, -1); int t = convertAbsoluteTimeHMS(start, -1);
if (t > 0 && t < 3600*24) { if (t > 0 && t < 3600*24) {
t = max(0, t-3600); t = max(0, t-3600);
oe->setZeroTime(formatTimeHMSW(t)); oe->setZeroTime(formatTimeHMS(t));
} }
else else
throw meosException("Ogiltig tid"); throw meosException("Ogiltig tid");

View File

@ -43,7 +43,7 @@ class oDataContainer;
typedef void * pvoid; typedef void * pvoid;
typedef vector< vector<wstring> > * pvectorstr; typedef vector< vector<wstring> > * pvectorstr;
enum RunnerStatus {StatusOK=1, StatusDNS=20, StatusMP=3, enum RunnerStatus {StatusOK=1, StatusDNS=20, StatusCANCEL = 21, StatusMP=3,
StatusDNF=4, StatusDQ=5, StatusMAX=6, StatusDNF=4, StatusDQ=5, StatusMAX=6,
StatusUnknown=0, StatusNotCompetiting=99}; StatusUnknown=0, StatusNotCompetiting=99};
@ -64,6 +64,7 @@ enum SortOrder {ClassStartTime,
SortByFinishTimeReverse, SortByFinishTimeReverse,
SortByStartTime, SortByStartTime,
CourseResult, CourseResult,
SortByEntryTime,
Custom, Custom,
SortEnumLastItem}; SortEnumLastItem};

View File

@ -668,7 +668,7 @@ wstring oCard::getRogainingSplit(int ix, int startTime) const
int t = it->getAdjustedTime(); int t = it->getAdjustedTime();
if (0 == ix--) { if (0 == ix--) {
if (t > 0 && t > startTime) if (t > 0 && t > startTime)
return formatTimeW(t - startTime); return formatTime(t - startTime);
} }
if (it->isUsed) if (it->isUsed)
startTime = t; startTime = t;

View File

@ -1522,7 +1522,7 @@ void oEvent::getNumClassRunners(int id, int leg, int &total, int &finished, int
if (it->tStatus != StatusUnknown) if (it->tStatus != StatusUnknown)
finished++; finished++;
else if (it->tStatus==StatusDNS) else if (it->tStatus==StatusDNS || it->tStatus == StatusCANCEL)
dns++; dns++;
} }
else { else {
@ -1532,7 +1532,7 @@ void oEvent::getNumClassRunners(int id, int leg, int &total, int &finished, int
total++; total++;
if (r->tStatus!=StatusUnknown) if (r->tStatus!=StatusUnknown)
finished++; finished++;
else if (it->tStatus==StatusDNS) else if (it->tStatus==StatusDNS || it->tStatus == StatusCANCEL)
dns++; dns++;
} }
} }
@ -2698,7 +2698,7 @@ void oClass::getStatistics(const set<int> &feeLock, int &entries, int &started)
if (it->getClassId()==Id) { if (it->getClassId()==Id) {
if (feeLock.empty() || feeLock.count(it->getDCI().getInt("Fee"))) { if (feeLock.empty() || feeLock.count(it->getDCI().getInt("Fee"))) {
entries++; entries++;
if (it->getStatus()!= StatusUnknown && it->getStatus()!= StatusDNS) if (it->getStatus()!= StatusUnknown && it->getStatus()!= StatusDNS && it->tStatus != StatusCANCEL)
started++; started++;
} }
} }
@ -4145,3 +4145,11 @@ int oClass::getPreceedingLeg(int leg) const {
} }
return -1; return -1;
} }
bool oClass::lockedForking() const {
return getDCI().getInt("Locked") != 0;
}
void oClass::lockedForking(bool locked) {
getDI().setInt("Locked", locked);
}

View File

@ -262,6 +262,10 @@ public:
static void initClassId(oEvent &oe); static void initClassId(oEvent &oe);
// Return true if forking in the class is locked
bool lockedForking() const;
void lockedForking(bool locked);
// Draw data // Draw data
int getDrawFirstStart() const; int getDrawFirstStart() const;
void setDrawFirstStart(int st); void setDrawFirstStart(int st);

View File

@ -488,13 +488,13 @@ int oControl::getTimeAdjust() const
wstring oControl::getTimeAdjustS() const wstring oControl::getTimeAdjustS() const
{ {
return getTimeMSW(getTimeAdjust()); return getTimeMS(getTimeAdjust());
} }
wstring oControl::getMinTimeS() const wstring oControl::getMinTimeS() const
{ {
if (getMinTime()>0) if (getMinTime()>0)
return getTimeMSW(getMinTime()); return getTimeMS(getMinTime());
else else
return makeDash(L"-"); return makeDash(L"-");
} }
@ -706,7 +706,7 @@ void oEvent::setupControlStatistics() const {
} }
} }
if (!it->isVacant() && it->getStatus() != StatusDNS if (!it->isVacant() && it->getStatus() != StatusDNS && it->getStatus() != StatusCANCEL
&& it->getStatus() != StatusNotCompetiting) { && it->getStatus() != StatusNotCompetiting) {
for (int i = 0; i < nc; i++) { for (int i = 0; i < nc; i++) {
@ -855,9 +855,9 @@ void oControl::addTableRow(Table &table) const {
int nv = getNumVisitors(true); int nv = getNumVisitors(true);
table.set(row++, it, 50, itow(nv), false); table.set(row++, it, 50, itow(nv), false);
table.set(row++, it, 51, nv > 0 ? formatTimeW(getMissedTimeMax()) : L"-", false); table.set(row++, it, 51, nv > 0 ? formatTime(getMissedTimeMax()) : L"-", false);
table.set(row++, it, 52, nv > 0 ? formatTimeW(getMissedTimeTotal()/nv) : L"-", false); table.set(row++, it, 52, nv > 0 ? formatTime(getMissedTimeTotal()/nv) : L"-", false);
table.set(row++, it, 53, nv > 0 ? formatTimeW(getMissedTimeMedian()) : L"-", false); table.set(row++, it, 53, nv > 0 ? formatTime(getMissedTimeMedian()) : L"-", false);
oe->oControlData->fillTableCol(it, table, true); oe->oControlData->fillTableCol(it, table, true);
} }

View File

@ -693,7 +693,7 @@ void oEvent::calculateNumRemainingMaps()
for (oRunnerList::const_iterator it=Runners.begin(); it != Runners.end(); ++it) { for (oRunnerList::const_iterator it=Runners.begin(); it != Runners.end(); ++it) {
if (!it->isRemoved() && it->getStatus() != StatusDNS) { if (!it->isRemoved() && it->getStatus() != StatusDNS && it->getStatus() != StatusCANCEL) {
pCourse pc = it->getCourse(false); pCourse pc = it->getCourse(false);
if (pc) { if (pc) {
if (pc->tMapsRemaining != numeric_limits<int>::min()) if (pc->tMapsRemaining != numeric_limits<int>::min())

View File

@ -322,6 +322,20 @@ bool oDataContainer::setString(oBase *ob, const char *name, const wstring &v)
} }
const wstring &oDataContainer::formatString(const oBase *ob, const char *Name) const {
const oDataInfo *odi = findVariable(Name);
if (odi->dataDefiner) {
return odi->dataDefiner->formatData(ob);
}
else if (odi->Type == oDTString) {
return getString(ob, Name);
}
else if (odi->Type == oDTInt) {
return itow(getInt(ob, Name));
}
throw std::exception("oDataContainer: Formatting failed.");
}
const wstring &oDataContainer::getString(const oBase *ob, const char *Name) const { const wstring &oDataContainer::getString(const oBase *ob, const char *Name) const {
const oDataInfo *odi=findVariable(Name); const oDataInfo *odi=findVariable(Name);
@ -982,6 +996,7 @@ void oDataContainer::buildTableCol(Table *table)
oDataInfo &di=ordered[kk]; oDataInfo &di=ordered[kk];
if (di.dataDefiner) { if (di.dataDefiner) {
table->addDataDefiner(di.Name, di.dataDefiner);
int w = strlen(di.Description)*6; int w = strlen(di.Description)*6;
di.tableIndex = di.dataDefiner->addTableColumn(table, di.Description, w); di.tableIndex = di.dataDefiner->addTableColumn(table, di.Description, w);
} }

View File

@ -34,10 +34,11 @@ class Table;
class oDataDefiner { class oDataDefiner {
public: public:
virtual ~oDataDefiner() {} virtual ~oDataDefiner() {}
virtual const wstring &formatData(oBase *obj) const = 0; virtual const wstring &formatData(const oBase *obj) const = 0;
virtual wstring setData(oBase *obj, const wstring &input) const = 0; virtual wstring setData(oBase *obj, const wstring &input) const = 0;
/** Used to define/add the table column in the table*/ /** Used to define/add the table column in the table*/
virtual int addTableColumn(Table *table, const string &description, int minWidth) const = 0; virtual int addTableColumn(Table *table, const string &description, int minWidth) const = 0;
virtual void prepare(oEvent *oe) const {}
}; };
struct oDataInfo { struct oDataInfo {
@ -160,6 +161,7 @@ public:
bool setString(oBase *ob, const char *name, const wstring &v); bool setString(oBase *ob, const char *name, const wstring &v);
const wstring &getString(const oBase *ob, const char *name) const; const wstring &getString(const oBase *ob, const char *name) const;
const wstring &formatString(const oBase *ob, const char *name) const;
bool setDate(void *data, const char *Name, const wstring &V); bool setDate(void *data, const char *Name, const wstring &V);
const wstring &getDate(const void *data, const char *Name) const; const wstring &getDate(const void *data, const char *Name) const;
@ -236,9 +238,13 @@ public:
else return false; else return false;
} }
inline wstring getString(const char *Name) const inline const wstring &getString(const char *Name) const
{return oDC->getString(oB, Name);} {return oDC->getString(oB, Name);}
inline const wstring &formatString(const oBase *oB, const char *name) const {
return oDC->formatString(oB, name);
}
inline bool setDate(const char *Name, const wstring &Value) inline bool setDate(const char *Name, const wstring &Value)
{ {
if (oDC->setDate(Data, Name, Value)){ if (oDC->setDate(Data, Name, Value)){
@ -327,6 +333,10 @@ public:
inline const wstring &getString(const char *Name) const inline const wstring &getString(const char *Name) const
{return oDC->getString(oB, Name);} {return oDC->getString(oB, Name);}
inline const wstring &formatString(const oBase *oB, const char *name) const {
return oDC->formatString(oB, name);
}
inline const wstring &getDate(const char *Name) const inline const wstring &getDate(const char *Name) const
{return oDC->getDate(Data, Name);} {return oDC->getDate(Data, Name);}

View File

@ -71,7 +71,7 @@ class RelativeTimeFormatter : public oDataDefiner {
public: public:
RelativeTimeFormatter(const char *n) : name(n) {} RelativeTimeFormatter(const char *n) : name(n) {}
const wstring &formatData(oBase *obj) const { const wstring &formatData(const oBase *obj) const {
int t = obj->getDCI().getInt(name); int t = obj->getDCI().getInt(name);
if (t <= 0) if (t <= 0)
return makeDash(L"-"); return makeDash(L"-");
@ -92,9 +92,9 @@ class AbsoluteTimeFormatter : public oDataDefiner {
public: public:
AbsoluteTimeFormatter(const char *n) : name(n) {} AbsoluteTimeFormatter(const char *n) : name(n) {}
const wstring &formatData(oBase *obj) const { const wstring &formatData(const oBase *obj) const {
int t = obj->getDCI().getInt(name); int t = obj->getDCI().getInt(name);
return formatTimeW(t); return formatTime(t);
} }
wstring setData(oBase *obj, const wstring &input) const { wstring setData(oBase *obj, const wstring &input) const {
int t = convertAbsoluteTimeMS(input); int t = convertAbsoluteTimeMS(input);
@ -108,6 +108,49 @@ class AbsoluteTimeFormatter : public oDataDefiner {
} }
}; };
class PayMethodFormatter : public oDataDefiner {
mutable vector< pair<wstring, size_t> > modes;
mutable map<wstring, int> setCodes;
mutable long rev;
public:
PayMethodFormatter() : rev(-1) {}
void prepare(oEvent *oe) const override {
oe->getPayModes(modes);
for (size_t i = 0; i < modes.size(); i++) {
setCodes[canonizeName(modes[i].first.c_str())] = modes[i].second;
}
}
const wstring &formatData(const oBase *ob) const {
if (ob->getEvent()->getRevision() != rev)
prepare(ob->getEvent());
int p = ob->getDCI().getInt("Paid");
if (p == 0)
return lang.tl("Faktura");
else {
int pm = ob->getDCI().getInt("PayMode");
for (size_t i = 0; i < modes.size(); i++) {
if (modes[i].second == pm)
return modes[i].first;
}
return _EmptyWString;
}
}
wstring setData(oBase *ob, const wstring &input) const {
auto res = setCodes.find(canonizeName(input.c_str()));
if (res != setCodes.end()) {
ob->getDI().setInt("PayMode", res->second);
}
return formatData(ob);
}
int addTableColumn(Table *table, const string &description, int minWidth) const {
return table->addColumn(description, max(minWidth, 90), true, true);
}
};
oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi) oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
{ {
readOnly = false; readOnly = false;
@ -275,11 +318,13 @@ oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
oClubData->addVariableEnum("Invoice", 1, "Faktura", eInvoice); oClubData->addVariableEnum("Invoice", 1, "Faktura", eInvoice);
oClubData->addVariableInt("InvoiceNo", oDataContainer::oIS16U, "Fakturanummer"); oClubData->addVariableInt("InvoiceNo", oDataContainer::oIS16U, "Fakturanummer");
static PayMethodFormatter paymentMethod;
oRunnerData=new oDataContainer(oRunner::dataSize); oRunnerData=new oDataContainer(oRunner::dataSize);
oRunnerData->addVariableCurrency("Fee", "Anm. avgift"); oRunnerData->addVariableCurrency("Fee", "Anm. avgift");
oRunnerData->addVariableCurrency("CardFee", "Brickhyra"); oRunnerData->addVariableCurrency("CardFee", "Brickhyra");
oRunnerData->addVariableCurrency("Paid", "Betalat"); oRunnerData->addVariableCurrency("Paid", "Betalat");
oRunnerData->addVariableInt("PayMode", oDataContainer::oIS8U, "Betalsätt"); oRunnerData->addVariableInt("PayMode", oDataContainer::oIS8U, "Betalsätt", &paymentMethod);
oRunnerData->addVariableCurrency("Taxable", "Skattad avgift"); oRunnerData->addVariableCurrency("Taxable", "Skattad avgift");
oRunnerData->addVariableInt("BirthYear", oDataContainer::oIS32, "Födelseår"); oRunnerData->addVariableInt("BirthYear", oDataContainer::oIS32, "Födelseår");
oRunnerData->addVariableString("Bib", 8, "Nummerlapp").zeroSortPadding = 5; oRunnerData->addVariableString("Bib", 8, "Nummerlapp").zeroSortPadding = 5;
@ -287,6 +332,8 @@ oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
//oRunnerData->addVariableInt("VacRank", oDataContainer::oIS16U, "Vak. ranking"); //oRunnerData->addVariableInt("VacRank", oDataContainer::oIS16U, "Vak. ranking");
oRunnerData->addVariableDate("EntryDate", "Anm. datum"); oRunnerData->addVariableDate("EntryDate", "Anm. datum");
static AbsoluteTimeFormatter atf("EntryTime");
oRunnerData->addVariableInt("EntryTime", oDataContainer::oIS32, "Anm. tid", &atf);
vector< pair<wstring,wstring> > sex; vector< pair<wstring,wstring> > sex;
sex.push_back(make_pair(L"M", L"Man")); sex.push_back(make_pair(L"M", L"Man"));
@ -393,6 +440,7 @@ oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
oClassData->addVariableEnum("BibMode", 1, "Nummerlappshantering", bibMode); oClassData->addVariableEnum("BibMode", 1, "Nummerlappshantering", bibMode);
oClassData->addVariableInt("Unordered", oDataContainer::oIS8U, "Oordnade parallella"); oClassData->addVariableInt("Unordered", oDataContainer::oIS8U, "Oordnade parallella");
oClassData->addVariableInt("Heat", oDataContainer::oIS8U, "Heat"); oClassData->addVariableInt("Heat", oDataContainer::oIS8U, "Heat");
oClassData->addVariableInt("Locked", oDataContainer::oIS8U, "Låst gaffling");
oTeamData = new oDataContainer(oTeam::dataSize); oTeamData = new oDataContainer(oTeam::dataSize);
oTeamData->addVariableCurrency("Fee", "Anm. avgift"); oTeamData->addVariableCurrency("Fee", "Anm. avgift");
@ -400,6 +448,7 @@ oEvent::oEvent(gdioutput &gdi):oBase(0), gdibase(gdi)
oTeamData->addVariableInt("PayMode", oDataContainer::oIS8U, "Betalsätt"); oTeamData->addVariableInt("PayMode", oDataContainer::oIS8U, "Betalsätt");
oTeamData->addVariableCurrency("Taxable", "Skattad avgift"); oTeamData->addVariableCurrency("Taxable", "Skattad avgift");
oTeamData->addVariableDate("EntryDate", "Anm. datum"); oTeamData->addVariableDate("EntryDate", "Anm. datum");
oTeamData->addVariableInt("EntryTime", oDataContainer::oIS32, "Anm. tid", &atf);
oTeamData->addVariableString("Nationality", 3, "Nationalitet"); oTeamData->addVariableString("Nationality", 3, "Nationalitet");
oTeamData->addVariableString("Country", 23, "Land"); oTeamData->addVariableString("Country", 23, "Land");
oTeamData->addVariableString("Bib", 8, "Nummerlapp").zeroSortPadding = 5; oTeamData->addVariableString("Bib", 8, "Nummerlapp").zeroSortPadding = 5;
@ -863,7 +912,7 @@ bool oEvent::save(const wstring &fileIn) {
const wchar_t *file = fileIn.c_str(); const wchar_t *file = fileIn.c_str();
xmlparser xml; xmlparser xml;
ProgressWindow pw(gdibase.getHWND()); ProgressWindow pw(gdibase.getHWNDTarget());
if (Runners.size()>200) if (Runners.size()>200)
pw.init(); pw.init();
@ -1019,7 +1068,7 @@ bool oEvent::open(const wstring &file, bool Import)
openFileLock->lockFile(file); openFileLock->lockFile(file);
xmlparser xml; xmlparser xml;
xml.setProgress(gdibase.getHWND()); xml.setProgress(gdibase.getHWNDTarget());
tic(); tic();
string log; string log;
xml.read(file); xml.read(file);
@ -1596,8 +1645,10 @@ pRunner oEvent::addRunner(const wstring &name, int clubId, int classId,
r.setBirthYear(birthYear); r.setBirthYear(birthYear);
pRunner pr = addRunner(r, true); pRunner pr = addRunner(r, true);
if (pr->getDI().getInt("EntryDate") == 0) if (pr->getDI().getInt("EntryDate") == 0 && !pr->isVacant()) {
pr->getDI().setDate("EntryDate", getLocalDateW()); pr->getDI().setDate("EntryDate", getLocalDate());
pr->getDI().setInt("EntryTime", getLocalAbsTime());
}
if (pr->Class) { if (pr->Class) {
int heat = pr->Class->getDCI().getInt("Heat"); int heat = pr->Class->getDCI().getInt("Heat");
if (heat != 0) if (heat != 0)
@ -1640,9 +1691,10 @@ pRunner oEvent::addRunnerFromDB(const pRunner db_r,
memcpy(r.oData, db_r->oData, sizeof(r.oData)); memcpy(r.oData, db_r->oData, sizeof(r.oData));
pRunner pr = addRunner(r, true); pRunner pr = addRunner(r, true);
if (pr->getDI().getInt("EntryDate") == 0) if (pr->getDI().getInt("EntryDate") == 0 && !pr->isVacant()) {
pr->getDI().setDate("EntryDate", getLocalDateW()); pr->getDI().setDate("EntryDate", getLocalDate());
pr->getDI().setInt("EntryTime", getLocalAbsTime());
}
if (r.Class) { if (r.Class) {
int heat = r.Class->getDCI().getInt("Heat"); int heat = r.Class->getDCI().getInt("Heat");
if (heat != 0) if (heat != 0)
@ -2105,7 +2157,7 @@ void oEvent::setDate(const wstring &m)
int d = convertDateYMS(m, true); int d = convertDateYMS(m, true);
if (d <= 0) if (d <= 0)
throw meosException(L"Felaktigt datumformat 'X' (Använd ÅÅÅÅ-MM-DD).#" + m); throw meosException(L"Felaktigt datumformat 'X' (Använd ÅÅÅÅ-MM-DD).#" + m);
Date = formatDateW(d, true); Date = formatDate(d, true);
updateChanged(); updateChanged();
} }
} }
@ -2116,10 +2168,10 @@ const wstring &oEvent::getAbsTime(DWORD time) const {
t = 0; t = 0;
int days = time/(3600*24); int days = time/(3600*24);
if (days <= 0) if (days <= 0)
return formatTimeHMSW(t % (24*3600)); return formatTimeHMS(t % (24*3600));
else { else {
wstring &res = StringCache::getInstance().wget(); wstring &res = StringCache::getInstance().wget();
res = itow(days) + L"D " + formatTimeHMSW(t % (24*3600)); res = itow(days) + L"D " + formatTimeHMS(t % (24*3600));
return res; return res;
} }
} }
@ -2175,7 +2227,7 @@ wstring oEvent::getAbsDateTimeISO(DWORD time, bool includeDate, bool useGMT) con
__int64 sec = SystemTimeToInt64Second(st); __int64 sec = SystemTimeToInt64Second(st);
sec = sec + (extraDay * 3600 * 24); sec = sec + (extraDay * 3600 * 24);
st = Int64SecondToSystemTime(sec); st = Int64SecondToSystemTime(sec);
dateS = convertSystemDateW(st); dateS = convertSystemDate(st);
} }
} }
@ -2986,7 +3038,7 @@ void oEvent::generateMinuteStartlist(gdioutput &gdi) {
continue; continue;
if (!it->Class && blocks[k]!=0) if (!it->Class && blocks[k]!=0)
continue; continue;
if (it->getStatus() == StatusNotCompetiting) if (it->getStatus() == StatusNotCompetiting || it->getStatus() == StatusCANCEL)
continue; continue;
if (LastStartTime!=it->tStartTime) { if (LastStartTime!=it->tStartTime) {
@ -3141,7 +3193,7 @@ bool oEvent::enumerateCompetitions(const wchar_t *file, const wchar_t *filetype)
SYSTEMTIME st; SYSTEMTIME st;
FileTimeToSystemTime(&fd.ftLastWriteTime, &st); FileTimeToSystemTime(&fd.ftLastWriteTime, &st);
ci.Modified=convertSystemTime(st); ci.Modified=convertSystemTimeN(st);
xmlparser xp; xmlparser xp;
try { try {
@ -3345,7 +3397,7 @@ bool oEvent::enumerateBackups(const wstring &file, const wstring &filetype, int
FileTimeToLocalFileTime(&fd.ftLastWriteTime, &localTime); FileTimeToLocalFileTime(&fd.ftLastWriteTime, &localTime);
FileTimeToSystemTime(&localTime, &st); FileTimeToSystemTime(&localTime, &st);
ci.Modified=convertSystemTime(st); ci.Modified=convertSystemTimeN(st);
xmlparser xp; xmlparser xp;
try { try {
@ -3500,6 +3552,7 @@ void oEvent::clear()
punchIndex.clear(); punchIndex.clear();
punches.clear(); punches.clear();
cachedFirstStart.clear();
updateFreeId(); updateFreeId();
@ -3571,7 +3624,7 @@ void oEvent::newCompetition(const wstring &name)
SYSTEMTIME st; SYSTEMTIME st;
GetLocalTime(&st); GetLocalTime(&st);
Date = convertSystemDateW(st); Date = convertSystemDate(st);
ZeroTime = st.wHour*3600; ZeroTime = st.wHour*3600;
Name = name; Name = name;
@ -4035,23 +4088,28 @@ void oEvent::convertTimes(SICard &sic) const
} }
} }
int oEvent::getFirstStart(int ClassId) int oEvent::getFirstStart(int classId) const {
{ auto &cf = cachedFirstStart[classId];
oRunnerList::iterator it=Runners.begin(); if (dataRevision == cf.first)
int MinTime=3600*24; return cf.second;
oRunnerList::const_iterator it=Runners.begin();
int minTime=3600*24;
while(it!=Runners.end()){ while(it!=Runners.end()){
if (ClassId==0 || it->getClassId()==ClassId) if (!it->isRemoved() && classId==0 || it->getClassId()==classId)
if (it->tStartTime<MinTime && it->tStatus==StatusOK && it->tStartTime!=0) if (it->tStartTime < minTime && it->tStatus!=StatusNotCompetiting && it->tStartTime>0)
MinTime=it->tStartTime; minTime = it->tStartTime;
++it; ++it;
} }
if (MinTime==3600*24) if (minTime==3600*24)
MinTime=0; minTime=0;
return MinTime; cf.first = dataRevision;
cf.second = minTime;
return minTime;
} }
bool oEvent::hasRank() const bool oEvent::hasRank() const
@ -4077,7 +4135,7 @@ int oEvent::getMaximalTime() const
wstring oEvent::getMaximalTimeS() const wstring oEvent::getMaximalTimeS() const
{ {
return formatTimeW(getMaximalTime()); return formatTime(getMaximalTime());
} }
@ -4141,19 +4199,24 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
oTeamList::iterator it; oTeamList::iterator it;
for (it=Teams.begin(); it != Teams.end(); ++it) for (it=Teams.begin(); it != Teams.end(); ++it)
it->apply(false, 0, false); it->apply(false, 0, false);
map<int, int> teamStartNo;
if (!firstNumber.empty()) { if (!firstNumber.empty()) {
// Clear out start number temporarily, to not use it for sorting // Clear out start number temporarily, to not use it for sorting
for (it=Teams.begin(); it != Teams.end(); ++it) { for (it=Teams.begin(); it != Teams.end(); ++it) {
if (it->isRemoved())
continue;
if (ClassId==0 || it->getClassId()==ClassId) { if (ClassId==0 || it->getClassId()==ClassId) {
if (it->getClassRef() && it->getClassRef()->getBibMode() != BibFree) { if (it->getClassRef() && it->getClassRef()->getBibMode() != BibFree) {
for (size_t i = 0; i < it->Runners.size(); i++) { for (size_t i = 0; i < it->Runners.size(); i++) {
if (it->Runners[i]) { if (it->Runners[i]) {
//runnerStartNo[it->Runners[i]->getId()] = it->Runners[i]->getStartNo();
it->Runners[i]->setStartNo(0, false); it->Runners[i]->setStartNo(0, false);
it->Runners[i]->setBib(L"", 0, false, false); it->Runners[i]->setBib(L"", 0, false, false);
} }
} }
} }
teamStartNo[it->getId()] = it->getStartNo();
it->setStartNo(0, false); it->setStartNo(0, false);
} }
} }
@ -4166,10 +4229,20 @@ void oEvent::addBib(int ClassId, int leg, const wstring &firstNumber) {
int num = oClass::extractBibPattern(firstNumber, pattern); int num = oClass::extractBibPattern(firstNumber, pattern);
for (it=Teams.begin(); it != Teams.end(); ++it) { for (it=Teams.begin(); it != Teams.end(); ++it) {
if (it->isRemoved())
continue;
if (ClassId == 0 || it->getClassId() == ClassId) { if (ClassId == 0 || it->getClassId() == ClassId) {
wchar_t bib[32]; wchar_t bib[32];
swprintf_s(bib, pattern, num); swprintf_s(bib, pattern, num);
bool lockedStartNo = it->Class && it->Class->lockedForking();
if (lockedStartNo) {
it->setBib(bib, num, false, false);
it->setStartNo(teamStartNo[it->getId()], false);
}
else {
it->setBib(bib, num, true, false); it->setBib(bib, num, true, false);
}
num++; num++;
it->apply(true, 0, false); it->apply(true, 0, false);
} }
@ -4205,6 +4278,7 @@ void oEvent::addAutoBib() {
tit->apply(false, 0, false); tit->apply(false, 0, false);
} }
map<int, int> teamStartNo;
// Clear out start number temporarily, to not use it for sorting // Clear out start number temporarily, to not use it for sorting
for (oTeamList::iterator tit = Teams.begin(); tit != Teams.end(); ++tit) { for (oTeamList::iterator tit = Teams.begin(); tit != Teams.end(); ++tit) {
if (tit->skip()) if (tit->skip())
@ -4212,6 +4286,8 @@ void oEvent::addAutoBib() {
pClass cls = tit->getClassRef(); pClass cls = tit->getClassRef();
if (cls == 0) if (cls == 0)
continue; continue;
teamStartNo[tit->getId()] = tit->getStartNo();
wstring bibInfo = cls->getDCI().getString("Bib"); wstring bibInfo = cls->getDCI().getString("Bib");
bool teamAssign = !bibInfo.empty(); bool teamAssign = !bibInfo.empty();
@ -4313,10 +4389,18 @@ void oEvent::addAutoBib() {
} }
} }
else { else {
bool lockedForking = cls->lockedForking();
for (size_t k = 0; k < tl.size(); k++) { for (size_t k = 0; k < tl.size(); k++) {
wchar_t buff[32]; wchar_t buff[32];
swprintf_s(buff, pattern, number); swprintf_s(buff, pattern, number);
if (lockedForking) {
tl[k]->setBib(buff, number, false, false);
tl[k]->setStartNo(teamStartNo[tl[k]->getId()], false);
}
else {
tl[k]->setBib(buff, number, true, false); tl[k]->setBib(buff, number, true, false);
}
number += interval; number += interval;
tl[k]->apply(true, 0, false); tl[k]->apply(true, 0, false);
} }
@ -4382,6 +4466,7 @@ const vector< pair<wstring, size_t> > &oEvent::fillStatus(vector< pair<wstring,
out.push_back(make_pair(lang.tl(L"-"), StatusUnknown)); out.push_back(make_pair(lang.tl(L"-"), StatusUnknown));
out.push_back(make_pair(lang.tl(L"Godkänd"), StatusOK)); out.push_back(make_pair(lang.tl(L"Godkänd"), StatusOK));
out.push_back(make_pair(lang.tl(L"Ej start"), StatusDNS)); out.push_back(make_pair(lang.tl(L"Ej start"), StatusDNS));
out.push_back(make_pair(lang.tl(L"Återbud[status]"), StatusCANCEL));
out.push_back(make_pair(lang.tl(L"Felst."), StatusMP)); out.push_back(make_pair(lang.tl(L"Felst."), StatusMP));
out.push_back(make_pair(lang.tl(L"Utg."), StatusDNF)); out.push_back(make_pair(lang.tl(L"Utg."), StatusDNF));
out.push_back(make_pair(lang.tl(L"Disk."), StatusDQ)); out.push_back(make_pair(lang.tl(L"Disk."), StatusDQ));
@ -4560,7 +4645,7 @@ void oEvent::assignCardInteractive(gdioutput &gdi, GUICALLBACK cb)
if (it->skip() || it->getCardNo() || it->isVacant() || it->needNoCard()) if (it->skip() || it->getCardNo() || it->isVacant() || it->needNoCard())
continue; continue;
if (it->getStatus() == StatusDNS || it->getStatus() == StatusNotCompetiting) if (it->getStatus() == StatusDNS || it->getStatus() == StatusCANCEL || it->getStatus() == StatusNotCompetiting)
continue; continue;
if (it->Club!=lastClub) { if (it->Club!=lastClub) {
@ -4610,12 +4695,15 @@ void oEvent::calcUseStartSeconds()
const wstring &oEvent::formatStatus(RunnerStatus status) const wstring &oEvent::formatStatus(RunnerStatus status)
{ {
const static wstring stats[8]={L"?", L"Godkänd", L"Ej start", L"Felst.", L"Utg.", L"Disk.", L"Maxtid", L"Deltar ej"}; const static wstring stats[9]={L"?", L"Godkänd", L"Ej start", L"Felst.", L"Utg.", L"Disk.",
L"Maxtid", L"Deltar ej", L"Återbud[status]"};
switch(status) { switch(status) {
case StatusOK: case StatusOK:
return lang.tl(stats[1]); return lang.tl(stats[1]);
case StatusDNS: case StatusDNS:
return lang.tl(stats[2]); return lang.tl(stats[2]);
case StatusCANCEL:
return lang.tl(stats[8]);
case StatusMP: case StatusMP:
return lang.tl(stats[3]); return lang.tl(stats[3]);
case StatusDNF: case StatusDNF:
@ -5501,11 +5589,6 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
} }
} }
HWND oEvent::hWnd() const
{
return gdibase.getHWND();
}
oTimeLine::~oTimeLine() { oTimeLine::~oTimeLine() {
} }
@ -5640,7 +5723,7 @@ wstring oEvent::cloneCompetition(bool cloneRunners, bool cloneTimes,
convertDateYMS(Date, st, false); convertDateYMS(Date, st, false);
__int64 absD = SystemTimeToInt64Second(st); __int64 absD = SystemTimeToInt64Second(st);
absD += 3600*24; absD += 3600*24;
ce.Date = convertSystemDateW(Int64SecondToSystemTime(absD)); ce.Date = convertSystemDate(Int64SecondToSystemTime(absD));
} }
int len = Name.length(); int len = Name.length();
if (len > 2 && isdigit(Name[len-1]) && !isdigit(Name[len-2])) { if (len > 2 && isdigit(Name[len-1]) && !isdigit(Name[len-2])) {
@ -6361,7 +6444,7 @@ bool oEvent::hasNextStage() const {
} }
bool oEvent::hasPrevStage() const { bool oEvent::hasPrevStage() const {
return !getDCI().getString("PreEvent").empty(); return !getDCI().getString("PreEvent").empty() || getStageNumber() > 1;
} }
int oEvent::getNumStages() const { int oEvent::getNumStages() const {
@ -6396,7 +6479,7 @@ void oEvent::changedObject() {
} }
void oEvent::pushDirectChange() { void oEvent::pushDirectChange() {
PostMessage(gdibase.getMain(), WM_USER + 4, 0, 0); PostMessage(gdibase.getHWNDMain(), WM_USER + 4, 0, 0);
} }
int oEvent::getBibClassGap() const { int oEvent::getBibClassGap() const {
@ -6556,3 +6639,120 @@ void oEvent::useDefaultProperties(bool useDefault) {
} }
} }
} }
static void checkValid(oEvent &oe, int &time, int delta, const wstring &name) {
int srcTime = time;
time += delta;
if (time <= 0)
time += 24 * 3600;
if (time > 24 * 3600)
time -= 24 * 3600;
if (time < 0 || time > 22 * 3600) {
throw meosException(L"X har en tid (Y) som inte är kompatibel med förändringen.#" + name + L"#" + oe.getAbsTime(srcTime));
}
}
void oEvent::updateStartTimes(int delta) {
for (int pass = 0; pass <= 1; pass++) {
for (oClass &c : Classes) {
if (c.isRemoved())
continue;
for (unsigned i = 0; i < c.getNumStages(); i++) {
int st = c.getStartData(i);
if (st > 0) {
checkValid(*oe, st, delta, c.getName());
if (pass == 1) {
c.setStartData(i, st);
c.synchronize(true);
}
}
}
}
if (pass == 1)
reEvaluateAll(set<int>(), false);
for (oRunner &r : Runners) {
if (r.isRemoved())
continue;
if (r.Class && r.Class->getStartType(r.getLegNumber()) == STDrawn) {
int st = r.getStartTime();
if (st > 0) {
checkValid(*oe, st, delta, r.getName());
if (pass == 1) {
r.setStartTime(st, true, false, false);
r.synchronize(true);
}
}
}
int ft = r.getFinishTime();
if (ft > 0) {
checkValid(*oe, ft, delta, r.getName());
if (pass == 1) {
r.setFinishTime(ft);
r.synchronize(true);
}
}
}
for (oCard &c : Cards) {
if (c.isRemoved())
continue;
wstring desc = L"Bricka X#" + c.getCardNoString();
for (oPunch &p : c.punches) {
int t = p.Time;
if (t > 0) {
if (c.getOwner() != 0)
checkValid(*oe, t, delta, desc);
else {
// Skip check
t += delta;
if (t <= 0)
t += 24 * 3600;
}
if (pass == 1) {
p.setTimeInt(t, false);
}
}
}
}
for (oTeam &t : Teams) {
if (t.isRemoved())
continue;
if (t.Class && t.Class->getStartType(0) == STDrawn) {
int st = t.getStartTime();
if (st > 0) {
checkValid(*oe, st, delta, t.getName());
if (pass == 1) {
t.setStartTime(st, true, false, false);
t.synchronize(true);
}
}
}
int ft = t.getFinishTime();
if (ft > 0) {
checkValid(*oe, ft, delta, t.getName());
if (pass == 1) {
t.setFinishTime(ft);
t.synchronize(true);
}
}
}
for (oFreePunch &p : punches) {
int t = p.Time;
if (t > 0) {
if (pass == 1) {
t += delta;
if (t <= 0)
t += 24 * 3600;
p.setTimeInt(t, false); // Skip check
}
}
}
}
}

View File

@ -560,9 +560,6 @@ public:
void saveProperties(const wchar_t *file); void saveProperties(const wchar_t *file);
void loadProperties(const wchar_t *file); void loadProperties(const wchar_t *file);
// Get window handle
HWND hWnd() const;
/** Get number of classes*/ /** Get number of classes*/
int getNumClasses() const {return Classes.size();} int getNumClasses() const {return Classes.size();}
@ -799,10 +796,11 @@ protected:
int tClubDataRevision; int tClubDataRevision;
bool readOnly; bool readOnly;
mutable int tLongTimesCached; mutable int tLongTimesCached;
mutable map<int, pair<int, int> > cachedFirstStart; //First start per classid.
map<pair<int, int>, oFreePunch> advanceInformationPunches; map<pair<int, int>, oFreePunch> advanceInformationPunches;
public: public:
void updateStartTimes(int delta);
void useDefaultProperties(bool useDefault); void useDefaultProperties(bool useDefault);
@ -864,7 +862,8 @@ public:
void updateRunnerDatabase(); void updateRunnerDatabase();
void updateRunnerDatabase(pRunner r, map<int, int> &clubIdMap); void updateRunnerDatabase(pRunner r, map<int, int> &clubIdMap);
int getFirstStart(int ClassId=0); /** Returns the first start in a class */
int getFirstStart(int classId = 0) const;
void convertTimes(SICard &sic) const; void convertTimes(SICard &sic) const;
pCard getCard(int Id) const; pCard getCard(int Id) const;
@ -1273,7 +1272,7 @@ public:
bool checkCardUsed(gdioutput &gdi, oRunner &runnerToAssignCard, int CardNo); bool checkCardUsed(gdioutput &gdi, oRunner &runnerToAssignCard, int CardNo);
void analyseDNS(vector<pRunner> &unknown_dns, vector<pRunner> &known_dns, void analyseDNS(vector<pRunner> &unknown_dns, vector<pRunner> &known_dns,
vector<pRunner> &known, vector<pRunner> &unknown); vector<pRunner> &known, vector<pRunner> &unknown, bool &hasSetDNS);
void importOECSV_Data(const wstring &oecsvfile, bool clear); void importOECSV_Data(const wstring &oecsvfile, bool clear);
void importXML_IOF_Data(const wstring &clubfile, const wstring &competitorfile, bool clear); void importXML_IOF_Data(const wstring &clubfile, const wstring &competitorfile, bool clear);

View File

@ -349,10 +349,10 @@ void renderRowSpeakerList(const oSpeakerObject &r, const oSpeakerObject *next_r,
row.push_back(SpeakerString(normalText, r.club)); row.push_back(SpeakerString(normalText, r.club));
if (r.status == StatusOK) { if (r.status == StatusOK) {
row.push_back(SpeakerString(textRight, formatTimeW(r.runningTime.preliminary))); row.push_back(SpeakerString(textRight, formatTime(r.runningTime.preliminary)));
if (r.runningTime.time != r.runningTimeLeg.time) if (r.runningTime.time != r.runningTimeLeg.time)
row.push_back(SpeakerString(textRight, formatTimeW(r.runningTimeLeg.time))); row.push_back(SpeakerString(textRight, formatTime(r.runningTimeLeg.time)));
else else
row.push_back(SpeakerString()); row.push_back(SpeakerString());
@ -1053,7 +1053,7 @@ int oEvent::setupTimeLineEvents(int classId, int currentTime)
continue; continue;
if (!r.Class ||r.Class->Id != classId) if (!r.Class ||r.Class->Id != classId)
continue; continue;
if (r.tStatus == StatusDNS || r.tStatus == StatusNotCompetiting) if (r.tStatus == StatusDNS || r.tStatus == StatusCANCEL || r.tStatus == StatusNotCompetiting)
continue; continue;
// if (r.CardNo == 0) // if (r.CardNo == 0)
// continue; // continue;
@ -1377,7 +1377,7 @@ int oEvent::setupTimeLineEvents(vector<pRunner> &started, const vector< pair<int
int timeAfter = totTime - leaderTime; int timeAfter = totTime - leaderTime;
int deltaTime = timeAfter - r.tTimeAfter; int deltaTime = timeAfter - r.tTimeAfter;
wstring timeS = formatTimeW(time); wstring timeS = formatTime(time);
wstring msg, detail; wstring msg, detail;
getTimeAfterDetail(detail, timeAfter, deltaTime, r.tTimeAfter > 0); getTimeAfterDetail(detail, timeAfter, deltaTime, r.tTimeAfter > 0);
r.tTimeAfter = timeAfter; r.tTimeAfter = timeAfter;
@ -1461,7 +1461,7 @@ int oEvent::setupTimeLineEvents(vector<pRunner> &started, const vector< pair<int
int timeAfter = time - leaderTime; int timeAfter = time - leaderTime;
int deltaTime = timeAfter - r.tInitialTimeAfter; int deltaTime = timeAfter - r.tInitialTimeAfter;
wstring timeS = formatTimeW(time); wstring timeS = formatTime(time);
wstring msg, detail; wstring msg, detail;
getTimeAfterDetail(detail, timeAfter, deltaTime, r.tInitialTimeAfter > 0); getTimeAfterDetail(detail, timeAfter, deltaTime, r.tInitialTimeAfter > 0);

View File

@ -73,6 +73,8 @@ int ConvertStatusToOE(int i)
case StatusOK: case StatusOK:
return 0; return 0;
case StatusDNS: // Ej start case StatusDNS: // Ej start
case StatusCANCEL:
case StatusNotCompetiting:
return 1; return 1;
case StatusDNF: // Utg. case StatusDNF: // Utg.
return 2; return 2;
@ -206,7 +208,7 @@ bool oEvent::exportOECSV(const wchar_t *file, int languageTypeIndex, bool includ
// Excel format HH:MM:SS // Excel format HH:MM:SS
if (it->getRunningTime() > 0) if (it->getRunningTime() > 0)
row[OEtime] = formatTimeHMS(it->getRunningTime()); row[OEtime] = gdibase.recodeToNarrow(formatTimeHMS(it->getRunningTime()));
row[OEstatus] = conv_is(ConvertStatusToOE(it->getStatus())); row[OEstatus] = conv_is(ConvertStatusToOE(it->getStatus()));
row[OEclubno] = conv_is(it->getClubId()); row[OEclubno] = conv_is(it->getClubId());
@ -259,7 +261,7 @@ bool oEvent::exportOECSV(const wchar_t *file, int languageTypeIndex, bool includ
continue; continue;
row.push_back(gdibase.recodeToNarrow(pc->getControl(k)->getIdS())); row.push_back(gdibase.recodeToNarrow(pc->getControl(k)->getIdS()));
if (unsigned(k) < sp.size() && sp[k].time > 0) if (unsigned(k) < sp.size() && sp[k].time > 0)
row.push_back(formatTimeHMS(sp[k].time - it->tStartTime)); row.push_back(gdibase.recodeToNarrow(formatTimeHMS(sp[k].time - it->tStartTime)));
else else
row.push_back("-----"); row.push_back("-----");
} }
@ -276,7 +278,7 @@ bool oEvent::exportOECSV(const wchar_t *file, int languageTypeIndex, bool includ
int t = punch->getAdjustedTime(); int t = punch->getAdjustedTime();
if (it->tStartTime > 0 && t > 0 && t > it->tStartTime) if (it->tStartTime > 0 && t > 0 && t > it->tStartTime)
row.push_back(formatTimeHMS(t - it->tStartTime)); row.push_back(gdibase.recodeToNarrow(formatTimeHMS(t - it->tStartTime)));
else else
return "-----"; return "-----";
} }
@ -1178,7 +1180,7 @@ void oEvent::importXML_IOF_Data(const wstring &clubfile,
{ {
if (!clubfile.empty()) { if (!clubfile.empty()) {
xmlparser xml_club; xmlparser xml_club;
xml_club.setProgress(gdibase.getHWND()); xml_club.setProgress(gdibase.getHWNDTarget());
if (clear) if (clear)
runnerDB->clearClubs(); runnerDB->clearClubs();
@ -1218,7 +1220,7 @@ void oEvent::importXML_IOF_Data(const wstring &clubfile,
if (!competitorfile.empty()) { if (!competitorfile.empty()) {
xmlparser xml_cmp; xmlparser xml_cmp;
xml_cmp.setProgress(gdibase.getHWND()); xml_cmp.setProgress(gdibase.getHWNDTarget());
gdibase.dropLine(); gdibase.dropLine();
gdibase.addString("",0,"Läser löpare..."); gdibase.addString("",0,"Läser löpare...");
gdibase.refresh(); gdibase.refresh();
@ -2270,7 +2272,8 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
if (pc) xml.write("CourseLength", "unit", L"m", pc->getLengthS()); if (pc) xml.write("CourseLength", "unit", L"m", pc->getLengthS());
pCourse pcourse=pc; pCourse pcourse=pc;
if (pcourse && it->getLegStatus(-1, false)>0 && it->getLegStatus(-1, false)!=StatusDNS) { auto legStatus = it->getLegStatus(-1, false);
if (pcourse && legStatus>0 && legStatus!=StatusDNS && legStatus!=StatusCANCEL) {
int no = 1; int no = 1;
bool hasRogaining = pcourse->hasRogaining(); bool hasRogaining = pcourse->hasRogaining();
int startIx = pcourse->useFirstAsStart() ? 1 : 0; int startIx = pcourse->useFirstAsStart() ? 1 : 0;
@ -2375,7 +2378,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
pCourse pcourse=it->getCourse(true); pCourse pcourse=it->getCourse(true);
if (pcourse && it->getStatus()>0 && it->getStatus()!=StatusDNS if (pcourse && it->getStatus()>0 && it->getStatus()!=StatusDNS
&& it->getStatus()!=StatusNotCompetiting) { && it->getStatus()!=StatusNotCompetiting && it->getStatus() != StatusCANCEL) {
bool hasRogaining = pcourse->hasRogaining(); bool hasRogaining = pcourse->hasRogaining();
int no = 1; int no = 1;
int startIx = pcourse->useFirstAsStart() ? 1 : 0; int startIx = pcourse->useFirstAsStart() ? 1 : 0;
@ -2527,7 +2530,7 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldS
} }
pCourse pcourse=pc; pCourse pcourse=pc;
if (pcourse && r->getStatus()>0 && r->getStatus()!=StatusDNS if (pcourse && r->getStatus()>0 && r->getStatus()!=StatusDNS
&& r->getStatus()!=StatusNotCompetiting) { && r->getStatus()!=StatusNotCompetiting && r->getStatus() != StatusCANCEL) {
int no = 1; int no = 1;
bool hasRogaining = pcourse->hasRogaining(); bool hasRogaining = pcourse->hasRogaining();
int startIx = pcourse->useFirstAsStart() ? 1 : 0; int startIx = pcourse->useFirstAsStart() ? 1 : 0;

View File

@ -232,7 +232,7 @@ public:
int w = 0; int w = 0;
TextInfo ti; TextInfo ti;
HDC hDC = GetDC(gdi.getHWND()); HDC hDC = GetDC(gdi.getHWNDTarget());
for (multimap<int, T>::iterator it = words.begin(); it != words.end(); ++it) { for (multimap<int, T>::iterator it = words.begin(); it != words.end(); ++it) {
ti.xp = 0; ti.xp = 0;
@ -247,7 +247,7 @@ public:
} }
} }
ReleaseDC(gdi.getHWND(), hDC); ReleaseDC(gdi.getHWNDTarget(), hDC);
return w; return w;
} }
@ -687,12 +687,12 @@ const wstring &oEvent::formatSpecialStringAux(const oPrintPost &pp, const oListP
case lControlMedianLostTime: case lControlMedianLostTime:
if (ctrl) if (ctrl)
wsptr = &formatTimeW(ctrl->getMissedTimeMedian()); wsptr = &formatTime(ctrl->getMissedTimeMedian());
break; break;
case lControlMaxLostTime: case lControlMaxLostTime:
if (ctrl) if (ctrl)
wsptr = &formatTimeW(ctrl->getMissedTimeMax()); wsptr = &formatTime(ctrl->getMissedTimeMax());
break; break;
case lControlMistakeQuotient: case lControlMistakeQuotient:
@ -896,12 +896,15 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
break; // Common start time, skip break; // Common start time, skip
} }
} }
if (r->startTimeAvailable()) { if (r->getStatus() == StatusCANCEL) {
wsptr = &oEvent::formatStatus(StatusCANCEL);
}
else if (r->startTimeAvailable()) {
if (pp.type != lRunnerStartZero) if (pp.type != lRunnerStartZero)
wsptr = &r->getStartTimeCompact(); wsptr = &r->getStartTimeCompact();
else { else {
int st = r->getStartTime(); int st = r->getStartTime();
wsptr = &getTimeMSW(st-3600); wsptr = &getTimeMS(st-oe->getFirstStart());
} }
} }
else else
@ -1021,7 +1024,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
RunnerStatus ts = r->getTotalStatus(); RunnerStatus ts = r->getTotalStatus();
int rt = r->getTotalRunningTime(); int rt = r->getTotalRunningTime();
if (ts == StatusOK || (ts == StatusUnknown && rt > 0)) { if (ts == StatusOK || (ts == StatusUnknown && rt > 0)) {
wstring vts = formatTimeW(rt) + L" (" + timeStatus + L")"; wstring vts = formatTime(rt) + L" (" + timeStatus + L")";
swap(vts, timeStatus); swap(vts, timeStatus);
} }
else { else {
@ -1105,7 +1108,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
int len = pc->getLength(); int len = pc->getLength();
if (len > 0 && t > 0) { if (len > 0 && t > 0) {
int sperkm = (1000 * t) / len; int sperkm = (1000 * t) / len;
wsptr = &formatTimeW(sperkm); wsptr = &formatTime(sperkm);
} }
} }
} }
@ -1154,7 +1157,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
wsptr = &lang.tl("Struken"); wsptr = &lang.tl("Struken");
else if (r) { else if (r) {
if (r->tempStatus==StatusOK && pc && !pc->getNoTiming()) if (r->tempStatus==StatusOK && pc && !pc->getNoTiming())
wcscpy_s(wbf, formatTimeW(r->tempRT).c_str()); wcscpy_s(wbf, formatTime(r->tempRT).c_str());
else else
wcscpy_s(wbf, formatStatus(r->tempStatus).c_str() ); wcscpy_s(wbf, formatStatus(r->tempStatus).c_str() );
} }
@ -1278,14 +1281,14 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
if (r && !invalidClass) { if (r && !invalidClass) {
int a = r->getTimeAdjustment(); int a = r->getTimeAdjustment();
if (a != 0) if (a != 0)
wsptr = &getTimeMSW(a); wsptr = &getTimeMS(a);
} }
break; break;
case lRunnerRogainingPointOvertime: case lRunnerRogainingPointOvertime:
if (r && !invalidClass) { if (r && !invalidClass) {
int over = r->getRogainingOvertime(); int over = r->getRogainingOvertime();
if (over > 0) if (over > 0)
wsptr = &formatTimeW(over); wsptr = &formatTime(over);
} }
break; break;
@ -1434,6 +1437,27 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
wcscpy_s(wbf, s.c_str()); wcscpy_s(wbf, s.c_str());
} }
break; break;
case lRunnerPaid:
if (r) {
wstring s = formatCurrency(r->getDCI().getInt("Paid"));
wcscpy_s(wbf, s.c_str());
}
break;
case lRunnerPayMethod:
if (r) {
wsptr = &r->getDCI().formatString(r, "PayMode");
}
break;
case lRunnerEntryDate:
if (r && r->getDCI().getInt("EntryDate") > 0) {
wsptr = &r->getDCI().getDate("EntryDate");
}
break;
case lRunnerEntryTime:
if (r) {
wsptr = &formatTime(r->getDCI().getInt("EntryTime"));
}
break;
case lTeamFee: case lTeamFee:
if (t) { if (t) {
wstring s = formatCurrency(t->getTeamFee()); wstring s = formatCurrency(t->getTeamFee());
@ -1469,7 +1493,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
wsptr = &t->Runners[legIndex]->getStartTimeCompact(); wsptr = &t->Runners[legIndex]->getStartTimeCompact();
else { else {
int st = t->Runners[legIndex]->getStartTime(); int st = t->Runners[legIndex]->getStartTime();
wsptr = &getTimeMSW(st-3600); wsptr = &getTimeMS(st-3600);
} }
} }
} }
@ -1544,7 +1568,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
if (t && !invalidClass) { if (t && !invalidClass) {
int over = t->getRogainingOvertime(); int over = t->getRogainingOvertime();
if (over > 0) if (over > 0)
wsptr = &formatTimeW(over); wsptr = &formatTime(over);
} }
break; break;
@ -1562,7 +1586,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
if (t && !invalidClass) { if (t && !invalidClass) {
int a = t->getTimeAdjustment(); int a = t->getTimeAdjustment();
if (a != 0) if (a != 0)
wsptr = &getTimeMSW(a); wsptr = &getTimeMS(a);
} }
break; break;
@ -1863,7 +1887,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
res.swap(out[ix]); res.swap(out[ix]);
if (res.find_first_of('%') != res.npos) { if (res.find_first_of('%') != res.npos) {
wchar_t bf2[256]; wchar_t bf2[256];
swprintf_s(bf2, res.c_str(), itos(nr).c_str()); swprintf_s(bf2, res.c_str(), itow(nr).c_str());
res = bf2; res = bf2;
} }
} }
@ -2274,12 +2298,11 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
GeneralResult *gResult = 0; GeneralResult *gResult = 0;
if (!li.resultModule.empty()) { if (!li.resultModule.empty()) {
wstring src; wstring src;
gResult = &getGeneralResult(li.resultModule, src);
oListInfo::ResultType resType = li.getResultType(); oListInfo::ResultType resType = li.getResultType();
gResult = &getGeneralResult(li.resultModule, src);
gResult->calculateIndividualResults(rlist, resType, li.sortOrder == Custom, li.getParam().getInputNumber()); gResult->calculateIndividualResults(rlist, resType, li.sortOrder == Custom, li.getParam().getInputNumber());
if (li.sortOrder == SortByFinishTime || li.sortOrder == SortByFinishTimeReverse if (li.sortOrder == SortByFinishTime || li.sortOrder == SortByFinishTimeReverse || li.sortOrder == SortByStartTime)
|| li.sortOrder == SortByStartTime)
gResult->sort(rlist, li.sortOrder); gResult->sort(rlist, li.sortOrder);
} }

View File

@ -112,6 +112,10 @@ enum EPostType
lRunnerNationality, lRunnerNationality,
lRunnerPhone, lRunnerPhone,
lRunnerFee, lRunnerFee,
lRunnerPaid,
lRunnerPayMethod,
lRunnerEntryDate,
lRunnerEntryTime,
lTeamName, lTeamName,
lTeamStart, lTeamStart,
@ -294,6 +298,8 @@ struct oListParam {
GUICALLBACK cb; GUICALLBACK cb;
set<int> selection; set<int> selection;
bool lockUpdate; // Temporary prevent animation update
int useControlIdResultTo; int useControlIdResultTo;
int useControlIdResultFrom; int useControlIdResultFrom;
int filterMaxPer; int filterMaxPer;
@ -314,6 +320,18 @@ struct oListParam {
bool useLargeSize; bool useLargeSize;
bool saved; bool saved;
int bgColor;
int bgColor2;
int fgColor;
wstring bgImage;
int nColumns;
bool animate;
int timePerPage;
int margin;
int screenMode;// 0 normal window, 1 = page by page, 2 = scroll
void updateDefaultName(const wstring &pname) const {defaultName = pname;} void updateDefaultName(const wstring &pname) const {defaultName = pname;}
void setCustomTitle(const wstring &t) {title = t;} void setCustomTitle(const wstring &t) {title = t;}
void getCustomTitle(wchar_t *t) const; // 256 size buffer required. Get title if set void getCustomTitle(wchar_t *t) const; // 256 size buffer required. Get title if set
@ -347,8 +365,6 @@ struct oListParam {
return legNumber >= 0 ? legNumber : 1000; return legNumber >= 0 ? legNumber : 1000;
} }
private: private:
int legNumber; int legNumber;
}; };

View File

@ -146,7 +146,7 @@ wstring oPunch::getRunningTime(int startTime) const
{ {
int t = getAdjustedTime(); int t = getAdjustedTime();
if (startTime>0 && t>0 && t>startTime) if (startTime>0 && t>0 && t>startTime)
return formatTimeW(t-startTime); return formatTime(t-startTime);
else else
return makeDash(L"-"); return makeDash(L"-");
} }

View File

@ -47,8 +47,8 @@
oRunner::RaceIdFormatter oRunner::raceIdFormatter; oRunner::RaceIdFormatter oRunner::raceIdFormatter;
const wstring &oRunner::RaceIdFormatter::formatData(oBase *ob) const { const wstring &oRunner::RaceIdFormatter::formatData(const oBase *ob) const {
return itow(dynamic_cast<oRunner *>(ob)->getRaceIdentifier()); return itow(dynamic_cast<const oRunner &>(*ob).getRaceIdentifier());
} }
wstring oRunner::RaceIdFormatter::setData(oBase *ob, const wstring &input) const { wstring oRunner::RaceIdFormatter::setData(oBase *ob, const wstring &input) const {
@ -322,6 +322,7 @@ void oAbstractRunner::addClassDefaultFee(bool resetFees) {
if (isVacant()) { if (isVacant()) {
di.setInt("Fee", 0); di.setInt("Fee", 0);
di.setInt("EntryDate", 0); di.setInt("EntryDate", 0);
di.setInt("EntryTime", 0);
di.setInt("Paid", 0); di.setInt("Paid", 0);
if (typeid(*this)==typeid(oRunner)) if (typeid(*this)==typeid(oRunner))
di.setInt("CardFee", 0); di.setInt("CardFee", 0);
@ -357,7 +358,10 @@ wstring oRunner::getEntryDate(bool useTeamEntryDate) const {
oDataConstInterface dci = getDCI(); oDataConstInterface dci = getDCI();
int date = dci.getInt("EntryDate"); int date = dci.getInt("EntryDate");
if (date == 0) { if (date == 0) {
(const_cast<oRunner *>(this)->getDI()).setDate("EntryDate", getLocalDateW()); auto di = (const_cast<oRunner *>(this)->getDI());
di.setDate("EntryDate", getLocalDate());
di.setInt("EntryTime", convertAbsoluteTimeHMS(getLocalTimeOnly(), -1));
} }
return dci.getDate("EntryDate"); return dci.getDate("EntryDate");
} }
@ -607,12 +611,12 @@ int oAbstractRunner::getRunningTime() const {
const wstring &oAbstractRunner::getRunningTimeS() const const wstring &oAbstractRunner::getRunningTimeS() const
{ {
return formatTimeW(getRunningTime()); return formatTime(getRunningTime());
} }
const wstring &oAbstractRunner::getTotalRunningTimeS() const const wstring &oAbstractRunner::getTotalRunningTimeS() const
{ {
return formatTimeW(getTotalRunningTime()); return formatTime(getTotalRunningTime());
} }
int oAbstractRunner::getTotalRunningTime() const { int oAbstractRunner::getTotalRunningTime() const {
@ -661,6 +665,8 @@ const wchar_t *formatIOFStatus(RunnerStatus s) {
return L"OK"; return L"OK";
case StatusDNS: case StatusDNS:
return L"DidNotStart"; return L"DidNotStart";
case StatusCANCEL:
return L"Cancelled";
case StatusMP: case StatusMP:
return L"MisPunch"; return L"MisPunch";
case StatusDNF: case StatusDNF:
@ -1279,7 +1285,7 @@ bool oRunner::evaluateCard(bool doApply, vector<int> & MissingPunches,
if (*refStatus == StatusMAX && maxTimeStatus == 2) if (*refStatus == StatusMAX && maxTimeStatus == 2)
*refStatus = StatusUnknown; *refStatus = StatusUnknown;
if (OK && (*refStatus==0 || *refStatus==StatusDNS || *refStatus==StatusMP || *refStatus==StatusOK || *refStatus==StatusDNF)) if (OK && (*refStatus==0 || *refStatus==StatusDNS || *refStatus == StatusCANCEL || *refStatus==StatusMP || *refStatus==StatusOK || *refStatus==StatusDNF))
*refStatus = StatusOK; *refStatus = StatusOK;
else *refStatus = RunnerStatus(max(int(StatusMP), int(*refStatus))); else *refStatus = RunnerStatus(max(int(StatusMP), int(*refStatus)));
@ -1816,6 +1822,17 @@ bool oRunner::operator <(const oRunner &c) {
else if (tStartTime > c.tStartTime) else if (tStartTime > c.tStartTime)
return false; return false;
} }
else if (oe->CurrentSortOrder == SortByEntryTime) {
auto dci = getDCI(), cdci = c.getDCI();
int ed = dci.getInt("EntryDate");
int ced = cdci.getInt("EntryDate");
if (ed != ced)
return ed > ced;
int et = dci.getInt("EntryTime");
int cet = cdci.getInt("EntryTime");
if (et != cet)
return et > cet;
}
else if (oe->CurrentSortOrder == ClassPoints) { else if (oe->CurrentSortOrder == ClassPoints) {
if (Class != c.Class) if (Class != c.Class)
return Class->tSortIndex < c.Class->tSortIndex; return Class->tSortIndex < c.Class->tSortIndex;
@ -1944,6 +1961,10 @@ void oAbstractRunner::setClub(const wstring &clubName)
// Vacant clubs have special logic // Vacant clubs have special logic
Class->tResultInfo.clear(); Class->tResultInfo.clear();
} }
if (Club && Club->isVacant()) { // Clear entry date/time for vacant
getDI().setInt("EntryDate", 0);
getDI().setInt("EntryTime", 0);
}
} }
} }
@ -1957,6 +1978,10 @@ pClub oAbstractRunner::setClubId(int clubId)
// Vacant clubs have special logic // Vacant clubs have special logic
Class->tResultInfo.clear(); Class->tResultInfo.clear();
} }
if (Club && Club->isVacant()) { // Clear entry date/time for vacant
getDI().setInt("EntryDate", 0);
getDI().setInt("EntryTime", 0);
}
} }
return Club; return Club;
} }
@ -2263,7 +2288,7 @@ bool oAbstractRunner::setStatus(RunnerStatus st, bool updateSource, bool tmpOnly
int oAbstractRunner::getPrelRunningTime() const int oAbstractRunner::getPrelRunningTime() const
{ {
if (FinishTime>0 && tStatus!=StatusDNS && tStatus!=StatusDNF && tStatus!=StatusNotCompetiting) if (FinishTime>0 && tStatus!=StatusDNS && tStatus != StatusCANCEL && tStatus!=StatusDNF && tStatus!=StatusNotCompetiting)
return getRunningTime(); return getRunningTime();
else if (tStatus==StatusUnknown) else if (tStatus==StatusUnknown)
return oe->getComputerTime()-tStartTime; return oe->getComputerTime()-tStartTime;
@ -2273,7 +2298,7 @@ int oAbstractRunner::getPrelRunningTime() const
wstring oAbstractRunner::getPrelRunningTimeS() const wstring oAbstractRunner::getPrelRunningTimeS() const
{ {
int rt=getPrelRunningTime(); int rt=getPrelRunningTime();
return formatTimeW(rt); return formatTime(rt);
} }
oDataContainer &oRunner::getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const { oDataContainer &oRunner::getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const {
@ -2386,7 +2411,7 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, bool onlyWithNoCard, boo
if (t == range.second) { if (t == range.second) {
pRunner r = range.first->second; pRunner r = range.first->second;
assert(r->getCardNo() == cardNo); assert(r->getCardNo() == cardNo);
if (ignoreRunnersWithNoStart && r->getStatus() == StatusDNS) if (ignoreRunnersWithNoStart && (r->getStatus() == StatusDNS || r->getStatus() == StatusCANCEL))
return 0; return 0;
if (r->getStatus() == StatusNotCompetiting) if (r->getStatus() == StatusNotCompetiting)
return 0; return 0;
@ -2397,7 +2422,7 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, bool onlyWithNoCard, boo
for (hashConstIter it = range.first; it != range.second; ++it) { for (hashConstIter it = range.first; it != range.second; ++it) {
pRunner r = it->second; pRunner r = it->second;
assert(r->getCardNo() == cardNo); assert(r->getCardNo() == cardNo);
if (ignoreRunnersWithNoStart && r->getStatus() == StatusDNS) if (ignoreRunnersWithNoStart && (r->getStatus() == StatusDNS || r->getStatus() == StatusCANCEL))
continue; continue;
if (r->getStatus() == StatusNotCompetiting) if (r->getStatus() == StatusNotCompetiting)
continue; continue;
@ -2411,7 +2436,7 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, bool onlyWithNoCard, boo
for (it=Runners.begin(); it != Runners.end(); ++it) { for (it=Runners.begin(); it != Runners.end(); ++it) {
if (it->skip()) if (it->skip())
continue; continue;
if (ignoreRunnersWithNoStart && it->getStatus() == StatusDNS) if (ignoreRunnersWithNoStart && (it->getStatus() == StatusDNS || it->getStatus() == StatusCANCEL))
continue; continue;
if (it->getStatus() == StatusNotCompetiting) if (it->getStatus() == StatusNotCompetiting)
continue; continue;
@ -2426,7 +2451,7 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, bool onlyWithNoCard, boo
pRunner r = pRunner(&*it); pRunner r = pRunner(&*it);
if (r->CardNo != cardNo || r->isRemoved()) if (r->CardNo != cardNo || r->isRemoved())
continue; continue;
if (ignoreRunnersWithNoStart && r->getStatus() == StatusDNS) if (ignoreRunnersWithNoStart && (r->getStatus() == StatusDNS || r->getStatus() == StatusCANCEL))
continue; continue;
if (r->getStatus() == StatusNotCompetiting) if (r->getStatus() == StatusNotCompetiting)
continue; continue;
@ -2487,7 +2512,7 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, bool onlyWithNoCard, boo
if (!onlyWithNoCard) { if (!onlyWithNoCard) {
//Then try all runners. //Then try all runners.
for (it=Runners.begin(); it != Runners.end(); ++it){ for (it=Runners.begin(); it != Runners.end(); ++it){
if (ignoreRunnersWithNoStart && it->getStatus() == StatusDNS) if (ignoreRunnersWithNoStart && (it->getStatus() == StatusDNS || it->getStatus() == StatusCANCEL))
continue; continue;
if (it->getStatus() == StatusNotCompetiting) if (it->getStatus() == StatusNotCompetiting)
continue; continue;
@ -2509,7 +2534,7 @@ void oEvent::getRunnersByCardNo(int cardNo, bool ignoreRunnersWithNoStart, bool
for (hashConstIter it = range.first; it != range.second; ++it) { for (hashConstIter it = range.first; it != range.second; ++it) {
pRunner r = it->second; pRunner r = it->second;
assert(r->getCardNo() == cardNo); assert(r->getCardNo() == cardNo);
if (ignoreRunnersWithNoStart && r->getStatus() == StatusDNS) if (ignoreRunnersWithNoStart && (r->getStatus() == StatusDNS || r->getStatus() == StatusCANCEL))
continue; continue;
if (skipDuplicates && r->getRaceNo() != 0) if (skipDuplicates && r->getRaceNo() != 0)
continue; continue;
@ -2523,7 +2548,7 @@ void oEvent::getRunnersByCardNo(int cardNo, bool ignoreRunnersWithNoStart, bool
for (oRunnerList::const_iterator it=Runners.begin(); it != Runners.end(); ++it) { for (oRunnerList::const_iterator it=Runners.begin(); it != Runners.end(); ++it) {
if (it->CardNo != cardNo) if (it->CardNo != cardNo)
continue; continue;
if (ignoreRunnersWithNoStart && it->getStatus() == StatusDNS) if (ignoreRunnersWithNoStart && (it->getStatus() == StatusDNS || it->getStatus() == StatusCANCEL))
continue; continue;
if (it->getStatus() == StatusNotCompetiting) if (it->getStatus() == StatusNotCompetiting)
continue; continue;
@ -3310,12 +3335,12 @@ int oRunner::getNamedSplit(int controlNumber) const
wstring oRunner::getSplitTimeS(int controlNumber, bool normalized) const wstring oRunner::getSplitTimeS(int controlNumber, bool normalized) const
{ {
return formatTimeW(getSplitTime(controlNumber, normalized)); return formatTime(getSplitTime(controlNumber, normalized));
} }
wstring oRunner::getNamedSplitS(int controlNumber) const wstring oRunner::getNamedSplitS(int controlNumber) const
{ {
return formatTimeW(getNamedSplit(controlNumber)); return formatTime(getNamedSplit(controlNumber));
} }
int oRunner::getPunchTime(int controlNumber, bool normalized) const int oRunner::getPunchTime(int controlNumber, bool normalized) const
@ -3335,7 +3360,7 @@ int oRunner::getPunchTime(int controlNumber, bool normalized) const
wstring oRunner::getPunchTimeS(int controlNumber, bool normalized) const wstring oRunner::getPunchTimeS(int controlNumber, bool normalized) const
{ {
return formatTimeW(getPunchTime(controlNumber, normalized)); return formatTime(getPunchTime(controlNumber, normalized));
} }
bool oAbstractRunner::isVacant() const bool oAbstractRunner::isVacant() const
@ -3643,7 +3668,7 @@ void oRunner::setBib(const wstring &bib, int bibNumerical, bool updateStartNo, b
void oEvent::analyseDNS(vector<pRunner> &unknown_dns, vector<pRunner> &known_dns, void oEvent::analyseDNS(vector<pRunner> &unknown_dns, vector<pRunner> &known_dns,
vector<pRunner> &known, vector<pRunner> &unknown) vector<pRunner> &known, vector<pRunner> &unknown, bool &hasSetDNS)
{ {
autoSynchronizeLists(true); autoSynchronizeLists(true);
@ -3654,8 +3679,11 @@ void oEvent::analyseDNS(vector<pRunner> &unknown_dns, vector<pRunner> &known_dns
if (!it->isRemoved() && !it->needNoCard()) { if (!it->isRemoved() && !it->needNoCard()) {
if (it->getStatus() == StatusUnknown) if (it->getStatus() == StatusUnknown)
stUnknown.push_back(&*it); stUnknown.push_back(&*it);
else if (it->getStatus() == StatusDNS) else if (it->getStatus() == StatusDNS) {
stDNS.push_back(&*it); stDNS.push_back(&*it);
if (it->hasFlag(oAbstractRunner::FlagAutoDNS))
hasSetDNS = true;
}
} }
} }
@ -3827,7 +3855,7 @@ void oRunner::printSplits(gdioutput &gdi) const {
wstring statInfo = lang.tl("Status: ") + getStatusS() + lang.tl(", Tid: ") + getRunningTimeS(); wstring statInfo = lang.tl("Status: ") + getStatusS() + lang.tl(", Tid: ") + getRunningTimeS();
if (withSpeed && pc && pc->getLength() > 0) { if (withSpeed && pc && pc->getLength() > 0) {
int kmt = (getRunningTime() * 1000) / pc->getLength(); int kmt = (getRunningTime() * 1000) / pc->getLength();
statInfo += L" (" + formatTimeW(kmt) + lang.tl(" min/km") + L")"; statInfo += L" (" + formatTime(kmt) + lang.tl(" min/km") + L")";
} }
if (pc && withSpeed) { if (pc && withSpeed) {
if (pc->legLengths.empty() || *max_element(pc->legLengths.begin(), pc->legLengths.end()) <= 0) if (pc->legLengths.empty() || *max_element(pc->legLengths.begin(), pc->legLengths.end()) <= 0)
@ -3910,14 +3938,14 @@ void oRunner::printSplits(gdioutput &gdi) const {
int st = Card->getSplitTime(getStartTime(), &*it); int st = Card->getSplitTime(getStartTime(), &*it);
if (st>0) if (st>0)
gdi.addStringUT(cy, cx + c2, fontSmall|textRight, formatTimeW(st)); gdi.addStringUT(cy, cx + c2, fontSmall|textRight, formatTime(st));
gdi.addStringUT(cy, cx+c3, fontSmall, it->getTime()); gdi.addStringUT(cy, cx+c3, fontSmall, it->getTime());
int pt = it->getAdjustedTime(); int pt = it->getAdjustedTime();
st = getStartTime(); st = getStartTime();
if (st>0 && pt>0 && pt>st) { if (st>0 && pt>0 && pt>st) {
wstring punchTime = formatTimeW(pt-st); wstring punchTime = formatTime(pt-st);
gdi.addStringUT(cy, cx+c4, fontSmall|textRight, punchTime); gdi.addStringUT(cy, cx+c4, fontSmall|textRight, punchTime);
} }
@ -3944,8 +3972,8 @@ void oRunner::printSplits(gdioutput &gdi) const {
gdi.addString("", cy, cx, fontSmall, "Mål"); gdi.addString("", cy, cx, fontSmall, "Mål");
sp = getSplitTime(splitTimes.size(), false); sp = getSplitTime(splitTimes.size(), false);
if (sp>0) { if (sp>0) {
gdi.addStringUT(cy, cx+c2, fontSmall|textRight, formatTimeW(sp)); gdi.addStringUT(cy, cx+c2, fontSmall|textRight, formatTime(sp));
punchTime = formatTimeW(getRunningTime()); punchTime = formatTime(getRunningTime());
} }
gdi.addStringUT(cy, cx+c3, fontSmall, oe->getAbsTime(it->Time + adjust)); gdi.addStringUT(cy, cx+c3, fontSmall, oe->getAbsTime(it->Time + adjust));
any = true; any = true;
@ -3995,7 +4023,7 @@ void oRunner::printSplits(gdioutput &gdi) const {
sp = getSplitTime(controlLegIndex, false); sp = getSplitTime(controlLegIndex, false);
if (sp>0) { if (sp>0) {
punchTime = getPunchTimeS(controlLegIndex, false); punchTime = getPunchTimeS(controlLegIndex, false);
gdi.addStringUT(cy, cx+c2, fontSmall|textRight, formatTimeW(sp)); gdi.addStringUT(cy, cx+c2, fontSmall|textRight, formatTime(sp));
} }
} }
else { else {
@ -4022,7 +4050,7 @@ void oRunner::printSplits(gdioutput &gdi) const {
int length = pc->legLengths[controlLegIndex]; int length = pc->legLengths[controlLegIndex];
if (length > 0) { if (length > 0) {
int tempo=(sp*1000)/length; int tempo=(sp*1000)/length;
gdi.addStringUT(cy, cx+c5, fontSmall|textRight, formatTimeW(tempo)); gdi.addStringUT(cy, cx+c5, fontSmall|textRight, formatTime(tempo));
} }
} }
@ -4056,7 +4084,7 @@ void oRunner::printSplits(gdioutput &gdi) const {
for (int k = pc->useFirstAsStart() ? 1 : 0; k < last; k++) { for (int k = pc->useFirstAsStart() ? 1 : 0; k < last; k++) {
int missed = getMissedTime(k); int missed = getMissedTime(k);
if (missed>0) { if (missed>0) {
misses.push_back(pc->getControlOrdinal(k) + L"/" + formatTimeW(missed)); misses.push_back(pc->getControlOrdinal(k) + L"/" + formatTime(missed));
} }
} }
if (misses.size()==0) { if (misses.size()==0) {
@ -4728,14 +4756,14 @@ wstring oRunner::getMissedTimeS() const
if (tMissedTime[k]>0) if (tMissedTime[k]>0)
t += tMissedTime[k]; t += tMissedTime[k];
return getTimeMSW(t); return getTimeMS(t);
} }
wstring oRunner::getMissedTimeS(int ctrlNo) const wstring oRunner::getMissedTimeS(int ctrlNo) const
{ {
int t = getMissedTime(ctrlNo); int t = getMissedTime(ctrlNo);
if (t>0) if (t>0)
return getTimeMSW(t); return getTimeMS(t);
else else
return L""; return L"";
} }
@ -4981,7 +5009,7 @@ void oAbstractRunner::setInputTime(const wstring &time) {
wstring oAbstractRunner::getInputTimeS() const { wstring oAbstractRunner::getInputTimeS() const {
if (inputTime > 0) if (inputTime > 0)
return formatTimeW(inputTime); return formatTime(inputTime);
else else
return makeDash(L"-"); return makeDash(L"-");
} }
@ -5352,7 +5380,7 @@ const wstring &oAbstractRunner::TempResult::getPrintPlaceS(bool withDot) const {
} }
const wstring &oAbstractRunner::TempResult::getRunningTimeS(int inputTime) const { const wstring &oAbstractRunner::TempResult::getRunningTimeS(int inputTime) const {
return formatTimeW(getRunningTime() + inputTime); return formatTime(getRunningTime() + inputTime);
} }
const wstring &oAbstractRunner::TempResult::getFinishTimeS(const oEvent *oe) const { const wstring &oAbstractRunner::TempResult::getFinishTimeS(const oEvent *oe) const {
@ -5368,7 +5396,7 @@ const wstring &oAbstractRunner::TempResult::getStartTimeS(const oEvent *oe) cons
const wstring &oAbstractRunner::TempResult::getOutputTime(int ix) const { const wstring &oAbstractRunner::TempResult::getOutputTime(int ix) const {
int t = size_t(ix) < outputTimes.size() ? outputTimes[ix] : 0; int t = size_t(ix) < outputTimes.size() ? outputTimes[ix] : 0;
return formatTimeW(t); return formatTime(t);
} }
int oAbstractRunner::TempResult::getOutputNumber(int ix) const { int oAbstractRunner::TempResult::getOutputNumber(int ix) const {

View File

@ -174,6 +174,7 @@ public:
FlagFeeSpecified = 8, FlagFeeSpecified = 8,
FlagUpdateClass = 16, FlagUpdateClass = 16,
FlagUpdateName = 32, FlagUpdateName = 32,
FlagAutoDNS = 64,
}; };
bool hasFlag(TransferFlags flag) const; bool hasFlag(TransferFlags flag) const;
@ -480,7 +481,7 @@ protected:
class RaceIdFormatter : public oDataDefiner { class RaceIdFormatter : public oDataDefiner {
public: public:
const wstring &formatData(oBase *obj) const; const wstring &formatData(const oBase *obj) const;
wstring setData(oBase *obj, const wstring &input) const; wstring setData(oBase *obj, const wstring &input) const;
int addTableColumn(Table *table, const string &description, int minWidth) const; int addTableColumn(Table *table, const string &description, int minWidth) const;
}; };

View File

@ -574,7 +574,7 @@ wstring oTeam::getLegRunningTimeS(int leg, bool multidayTotal) const
leg = Runners.size()-1; leg = Runners.size()-1;
int rt=getLegRunningTime(leg, multidayTotal); int rt=getLegRunningTime(leg, multidayTotal);
const wstring &bf = formatTimeW(rt); const wstring &bf = formatTime(rt);
if (rt>0) { if (rt>0) {
if ((unsigned(leg)<Runners.size() && Runners[leg] && if ((unsigned(leg)<Runners.size() && Runners[leg] &&
Class && Runners[leg]->getStartTime()==Class->getRestartTime(leg)) || getNumShortening(leg)>0) Class && Runners[leg]->getStartTime()==Class->getRestartTime(leg)) || getNumShortening(leg)>0)
@ -780,20 +780,21 @@ bool oTeam::isRunnerUsed(int Id) const
return false; return false;
} }
void oTeam::setTeamNoStart(bool dns) void oTeam::setTeamNoStart(bool dns, RunnerStatus dnsStatus)
{ {
if (dns) { if (dns) {
setStatus(StatusDNS, true, false); assert(dnsStatus == StatusCANCEL || dnsStatus == StatusDNS);
setStatus(dnsStatus, true, false);
for(unsigned i=0;i<Runners.size(); i++) { for(unsigned i=0;i<Runners.size(); i++) {
if (Runners[i] && Runners[i]->getStatus()==StatusUnknown) { if (Runners[i] && Runners[i]->getStatus()==StatusUnknown) {
Runners[i]->setStatus(StatusDNS, true, false); Runners[i]->setStatus(dnsStatus, true, false);
} }
} }
} }
else { else {
setStatus(StatusUnknown, true, false); setStatus(StatusUnknown, true, false);
for(unsigned i=0;i<Runners.size(); i++) { for(unsigned i=0;i<Runners.size(); i++) {
if (Runners[i] && Runners[i]->getStatus()==StatusDNS) { if (Runners[i] && (Runners[i]->getStatus()==StatusDNS || Runners[i]->getStatus() == StatusCANCEL)) {
Runners[i]->setStatus(StatusUnknown, true, false); Runners[i]->setStatus(StatusUnknown, true, false);
} }
} }
@ -1090,7 +1091,6 @@ bool oTeam::apply(bool sync, pRunner source, bool setTmpOnly) {
else {//The else below should only be run by mistake (for an incomplete team) else {//The else below should only be run by mistake (for an incomplete team)
Runners[i]->setStartTime(Class->getRestartTime(i), false, setTmpOnly); Runners[i]->setStartTime(Class->getRestartTime(i), false, setTmpOnly);
Runners[i]->tUseStartPunch=false; Runners[i]->tUseStartPunch=false;
//Runners[i]->setStatus(StatusDNS);
} }
} }
break; break;
@ -1546,6 +1546,9 @@ wstring oTeam::getLegStartTimeCompact(int leg) const
} }
void oTeam::setBib(const wstring &bib, int bibnumerical, bool updateStartNo, bool setTmpOnly) { void oTeam::setBib(const wstring &bib, int bibnumerical, bool updateStartNo, bool setTmpOnly) {
if (updateStartNo)
updateStartNo = !Class || !Class->lockedForking();
if (setTmpOnly) { if (setTmpOnly) {
tmpStore.bib = bib; tmpStore.bib = bib;
if (updateStartNo) if (updateStartNo)
@ -1745,8 +1748,10 @@ void oEvent::getTeams(int classId, vector<pTeam> &t, bool sort) {
wstring oTeam::getEntryDate(bool dummy) const { wstring oTeam::getEntryDate(bool dummy) const {
oDataConstInterface dci = getDCI(); oDataConstInterface dci = getDCI();
int date = dci.getInt("EntryDate"); int date = dci.getInt("EntryDate");
if (date == 0) { if (date == 0 && !isVacant()) {
(const_cast<oTeam *>(this)->getDI()).setDate("EntryDate", getLocalDateW()); auto di = (const_cast<oTeam *>(this)->getDI());
di.setDate("EntryDate", getLocalDate());
di.setInt("EntryTime", getLocalAbsTime());
} }
return dci.getDate("EntryDate"); return dci.getDate("EntryDate");
} }
@ -1968,14 +1973,14 @@ bool oTeam::inputData(int id, const wstring &input,
case TID_STATUS: { case TID_STATUS: {
RunnerStatus sIn = RunnerStatus(inputId); RunnerStatus sIn = RunnerStatus(inputId);
if (sIn != StatusDNS) { if (sIn != StatusDNS && sIn != StatusCANCEL) {
if (getStatus() == StatusDNS && sIn == StatusUnknown) if ((getStatus() == StatusDNS || getStatus() == StatusCANCEL) && sIn == StatusUnknown)
setTeamNoStart(false); setTeamNoStart(false, StatusUnknown);
else else
setStatus(sIn, true, false); setStatus(sIn, true, false);
} }
else if (getStatus() != StatusDNS) else if (getStatus() != sIn)
setTeamNoStart(true); setTeamNoStart(true, sIn);
apply(true, 0, false); apply(true, 0, false);
RunnerStatus sOut = getStatus(); RunnerStatus sOut = getStatus();

View File

@ -139,7 +139,7 @@ public:
void prepareRemove(); void prepareRemove();
bool skip() const {return isRemoved();} bool skip() const {return isRemoved();}
void setTeamNoStart(bool dns); void setTeamNoStart(bool dns, RunnerStatus dnsStatus); // Set DNS or CANCEL
// If apply is triggered by a runner, don't go further than that runner. // If apply is triggered by a runner, don't go further than that runner.
bool apply(bool sync, pRunner source, bool setTmpOnly); bool apply(bool sync, pRunner source, bool setTmpOnly);

View File

@ -592,9 +592,9 @@ void oEvent::setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstri
cls.setLegType(1, LTSum); cls.setLegType(1, LTSum);
cls.setStartType(1, STHunting, false); cls.setStartType(1, STHunting, false);
int t = convertAbsoluteTimeHMS(start, ZeroTime)+3600; int t = convertAbsoluteTimeHMS(start, ZeroTime)+3600;
cls.setStartData(1, formatTimeHMSW(t)); cls.setStartData(1, formatTimeHMS(t));
cls.setRestartTime(1, formatTimeHMSW(t+1800)); cls.setRestartTime(1, formatTimeHMS(t+1800));
cls.setRopeTime(1, formatTimeHMSW(t+1800)); cls.setRopeTime(1, formatTimeHMS(t+1800));
cls.setLegRunner(1, 0); cls.setLegRunner(1, 0);
cls.setCoursePool(false); cls.setCoursePool(false);
break; break;
@ -733,7 +733,7 @@ void oTeam::checkClassesWithReferences(oEvent &oe, std::set<int> &clsWithRef) {
++pairedUnpairedPerClass[r[k]->getClassId()].second; ++pairedUnpairedPerClass[r[k]->getClassId()].second;
} }
for (auto it : pairedUnpairedPerClass) { for (auto &it : pairedUnpairedPerClass) {
if (it.second.first > it.second.second) if (it.second.first > it.second.second)
clsWithRef.insert(it.first); clsWithRef.insert(it.first);
} }

View File

@ -302,7 +302,7 @@ void OnlineInput::processPunches(oEvent &oe, const xmlList &punches) {
int card = punches[k].getObjectInt("card"); int card = punches[k].getObjectInt("card");
int time = punches[k].getObjectInt("time") / 10; int time = punches[k].getObjectInt("time") / 10;
time = oe.getRelativeTime(formatTimeHMSW(time)); time = oe.getRelativeTime(formatTimeHMS(time));
if (startno.length() > 0) if (startno.length() > 0)
r = oe.getRunnerByBibOrStartNo(startno, false); r = oe.getRunnerByBibOrStartNo(startno, false);

View File

@ -54,6 +54,12 @@ static int OnlineCB(gdioutput *gdi, int type, void *data) {
return ores.processButton(*gdi, bu); return ores.processButton(*gdi, bu);
} }
case GUI_LISTBOX:{ case GUI_LISTBOX:{
ListBoxInfo lbi = *static_cast<ListBoxInfo *>(data);
if (lbi.id == "Format") {
if (gdi->hasField("IncludeTotal")) {
gdi->setInputStatus("IncludeTotal", lbi.data == 1);
}
}
} }
} }
return 0; return 0;
@ -113,13 +119,19 @@ void OnlineResults::settings(gdioutput &gdi, oEvent &oe, bool created) {
// gdi.dropLine(); // gdi.dropLine();
// gdi.addInput("Interval", time, 10, 0, "Uppdateringsintervall (sekunder):"); // gdi.addInput("Interval", time, 10, 0, "Uppdateringsintervall (sekunder):");
gdi.addSelection("Format", 200, 200, 0, L"Exportformat:"); gdi.addSelection("Format", 200, 200, OnlineCB, L"Exportformat:");
gdi.addItem("Format", L"MeOS Online Protocol XML", 1); gdi.addItem("Format", L"MeOS Online Protocol XML", 1);
gdi.addItem("Format", L"IOF XML 2.0.3", 2); gdi.addItem("Format", L"IOF XML 2.0.3", 2);
gdi.addItem("Format", L"IOF XML 3.0", 3); gdi.addItem("Format", L"IOF XML 3.0", 3);
gdi.selectItemByData("Format", dataType); gdi.selectItemByData("Format", dataType);
gdi.addCheckbox("Zip", "Packa stora filer (zip)", 0, zipFile); gdi.addCheckbox("Zip", "Packa stora filer (zip)", 0, zipFile);
if (oe.hasPrevStage()) {
gdi.addCheckbox("IncludeTotal", "Inkludera resultat från tidigare etapper", 0, zipFile);
InfoCompetition &ic = getInfoServer();
gdi.check("IncludeTotal", ic.includeTotalResults());
gdi.setInputStatus("IncludeTotal", dataType == 1);
}
int cx = gdi.getCX(); int cx = gdi.getCX();
gdi.fillRight(); gdi.fillRight();
@ -239,10 +251,13 @@ void OnlineResults::save(oEvent &oe, gdioutput &gdi) {
prefix = gdi.getText("Prefix"); prefix = gdi.getText("Prefix");
exportScript = gdi.getText("ExportScript"); exportScript = gdi.getText("ExportScript");
zipFile = gdi.isChecked("Zip"); zipFile = gdi.isChecked("Zip");
bool includeTotal = gdi.hasField("IncludeTotal") && gdi.isChecked("IncludeTotal");
ListBoxInfo lbi; ListBoxInfo lbi;
gdi.getSelectedItem("Format", lbi); gdi.getSelectedItem("Format", lbi);
dataType = lbi.data; dataType = lbi.data;
if (dataType == 1)
getInfoServer().includeTotalResults(includeTotal);
gdi.getSelection("Classes", classes); gdi.getSelection("Classes", classes);
if (sendToFile) { if (sendToFile) {
@ -334,7 +349,7 @@ void OnlineResults::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
if (!sendToFile && !sendToURL) if (!sendToFile && !sendToURL)
return; return;
ProgressWindow pwMain((sendToURL && ast == SyncNone) ? gdi.getHWND() : 0); ProgressWindow pwMain((sendToURL && ast == SyncNone) ? gdi.getHWNDTarget() : 0);
pwMain.init(); pwMain.init();
wstring t; wstring t;
@ -342,7 +357,7 @@ void OnlineResults::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
InfoCompetition &ic = getInfoServer(); InfoCompetition &ic = getInfoServer();
xmlbuffer xmlbuff; xmlbuffer xmlbuff;
if (dataType == 1) { if (dataType == 1) {
if (ic.synchronize(*oe, classes, controls)) { if (ic.synchronize(*oe, false, classes, controls)) {
lastSync = tick; // If error, avoid to quick retry lastSync = tick; // If error, avoid to quick retry
ic.getDiffXML(xmlbuff); ic.getDiffXML(xmlbuff);
} }
@ -508,7 +523,7 @@ void OnlineResults::formatError(gdioutput &gdi) {
gdi.setRestorePoint("ServerError"); gdi.setRestorePoint("ServerError");
gdi.dropLine(); gdi.dropLine();
gdi.fillDown(); gdi.fillDown();
gdi.addString("", boldText, "Server response X:#" + getLocalTime()).setColor(colorRed); gdi.addString("", boldText, L"Server response X:#" + getLocalTime()).setColor(colorRed);
for (size_t k = 0; k < errorLines.size(); k++) for (size_t k = 0; k < errorLines.size(); k++)
gdi.addStringUT(0, errorLines[k]); gdi.addStringUT(0, errorLines[k]);
gdi.scrollToBottom(); gdi.scrollToBottom();

View File

@ -147,6 +147,7 @@ void pdfwriter::generatePDF(const gdioutput &gdi,
const wstring &pageTitleW, const wstring &pageTitleW,
const wstring &authorW, const wstring &authorW,
const list<TextInfo> &tl) { const list<TextInfo> &tl) {
checkWriteAccess(file);
string pageTitle = gdi.narrow(pageTitleW); // XXX WCS string pageTitle = gdi.narrow(pageTitleW); // XXX WCS
string author = gdi.narrow(authorW); string author = gdi.narrow(authorW);

View File

@ -623,6 +623,11 @@ struct PrintItemInfo {
const TextInfo *ti = dynamic_cast<const TextInfo *>(obj); const TextInfo *ti = dynamic_cast<const TextInfo *>(obj);
return ti && ti->format == pageNewPage; return ti && ti->format == pageNewPage;
} }
bool isNoPrint() const {
const TextInfo *ti = dynamic_cast<const TextInfo *>(obj);
return ti && gdioutput::skipTextRender(ti->format);
}
}; };
void PageInfo::renderPages(const list<TextInfo> &tl, void PageInfo::renderPages(const list<TextInfo> &tl,
@ -645,7 +650,7 @@ void PageInfo::renderPages(const list<TextInfo> &tl,
const TextInfo &text = *it; const TextInfo &text = *it;
if (text.format == 10) if (text.format == 10)
continue; continue;
if (text.format != pageNewPage && text.format != pagePageInfo) { if (!text.isFormatInfo()) {
if (currentYP > text.yp) { if (currentYP > text.yp) {
needSort = true; needSort = true;
} }
@ -740,6 +745,8 @@ void PageInfo::renderPages(const list<TextInfo> &tl,
if (k + 1 < indexedTL.size() && tlp->yp != indexedTL[k+1].yp) { if (k + 1 < indexedTL.size() && tlp->yp != indexedTL[k+1].yp) {
size_t j = k + 1; size_t j = k + 1;
while (j + 1 < indexedTL.size() && indexedTL[j].isNoPrint() && !indexedTL[j].isNewPage())
j++;
// Required new page // Required new page
if (indexedTL[j].isNewPage()) { if (indexedTL[j].isNewPage()) {
@ -819,16 +826,16 @@ wstring PageInfo::pageInfo(const RenderedPage &page) const {
wchar_t bf[256]; wchar_t bf[256];
if (nPagesTotal > 1) { if (nPagesTotal > 1) {
if (!page.info.empty()) if (!page.info.empty())
swprintf_s(bf, L"MeOS %s, %s, (%d/%d)", getLocalTimeW().c_str(), swprintf_s(bf, L"MeOS %s, %s, (%d/%d)", getLocalTime().c_str(),
page.info.c_str(), page.nPage, nPagesTotal);//WCS page.info.c_str(), page.nPage, nPagesTotal);
else else
swprintf_s(bf, L"MeOS %s, (%d/%d)", getLocalTimeW().c_str(), page.nPage, nPagesTotal); swprintf_s(bf, L"MeOS %s, (%d/%d)", getLocalTime().c_str(), page.nPage, nPagesTotal);
} }
else { else {
if (!page.info.empty()) if (!page.info.empty())
swprintf_s(bf, L"MeOS %s, %s", getLocalTimeW().c_str(), page.info.c_str()); swprintf_s(bf, L"MeOS %s, %s", getLocalTime().c_str(), page.info.c_str());
else else
swprintf_s(bf, L"MeOS %s", getLocalTimeW().c_str()); swprintf_s(bf, L"MeOS %s", getLocalTime().c_str());
} }
return bf; return bf;
} }

261
code/restserver.cpp Normal file
View File

@ -0,0 +1,261 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2017 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include "stdafx.h"
#include "oEvent.h"
#include "xmlparser.h"
#include <thread>
#include "restbed/restbed"
#include "meosexception.h"
#include "restserver.h"
#include "infoserver.h"
#include <chrono>
using namespace restbed;
vector< shared_ptr<RestServer> > RestServer::startedServers;
shared_ptr<RestServer> RestServer::construct() {
shared_ptr<RestServer> obj(new RestServer());
startedServers.push_back(obj);
return obj;
}
void RestServer::remove(shared_ptr<RestServer> server) {
// xxx std::remove(startedServers.begin(), startedServers.end(), server);
}
RestServer::RestServer() : hasAnyRequest(false) {
}
RestServer::~RestServer() {
stop();
}
class MeOSResource : public restbed::Resource {
RestServer *server;
public:
MeOSResource(RestServer *server) : server(server) {}
~MeOSResource() {
}
RestServer &getServer() const { return *server; }
};
static void method_handler(const shared_ptr< restbed::Session > session) {
RestServer &server = dynamic_cast<const MeOSResource &>(*session->get_resource()).getServer();
server.handleRequest(session);
}
void RestServer::handleRequest(const shared_ptr<restbed::Session> &session) {
const auto request = session->get_request();
size_t content_length = request->get_header("Content-Length", 0);
chrono::time_point<chrono::system_clock> start, end;
start = chrono::system_clock::now();
auto param = request->get_query_parameters();
auto answer = RestServer::addRequest(param);
{
unique_lock<mutex> mlock(lock);
if (!waitForCompletion.wait_for(mlock, 10s, [answer] {return answer->isCompleted(); })) {
answer->answer = "Error (MeOS): Internal timeout";
}
end = chrono::system_clock::now();
chrono::duration<double> elapsed_seconds = end - start;
responseTimes.push_back(int(1000 * elapsed_seconds.count()));
}
// lock.unlock();
session->fetch(content_length, [request, answer](const shared_ptr< Session > session, const Bytes & body)
{
//fprintf(stdout, "%.*s\n", (int)body.size(), body.data());
/*while (!answer->state) {
std::this_thread::yield();
}*/
session->close(restbed::OK, answer->answer, { { "Content-Length", itos(answer->answer.length()) },{ "Connection", "close" } });
});
}
void RestServer::startThread(int port) {
auto settings = make_shared<Settings>();
settings->set_port(port);
auto resource = make_shared<MeOSResource>(this);
resource->set_path("/meos");
resource->set_method_handler("GET", method_handler);
restService->publish(resource);
restService->start(settings);
}
void RestServer::startService(int port) {
if (service)
throw meosException("Server started");
restService.reset(new restbed::Service());
service = make_shared<thread>(&RestServer::startThread, this, port);
}
void RestServer::stop() {
if (restService)
restService->stop();
if (service && service->joinable())
service->join();
restService.reset();
service.reset();
}
void RestServer::computeRequested(oEvent &ref) {
for (auto &server : startedServers) {
server->compute(ref);
}
}
void RestServer::compute(oEvent &ref) {
auto rq = getRequest();
if (!rq)
return;
if (rq->parameters.empty()) {
rq->answer = "<html><head>"
"<title>MeOS Information Service</title>"
"</head>"
"<body>"
"<h2>MeOS</h2>"
"</body>"
"</html>";
}
else if (rq->parameters.count("get") > 0) {
string what = rq->parameters.find("get")->second;
getData(ref, what, rq->parameters, rq->answer);
}
else {
rq->answer = "Error (MeOS): Unknown request";
}
{
lock_guard<mutex> lg(lock);
rq->state = true;
}
waitForCompletion.notify_all();
}
void RestServer::getData(oEvent &oe, const string &what, const multimap<string, string> &param, string &answer) {
xmlbuffer out;
out.setComplete(true);
if (what == "competition") {
InfoCompetition cmp(0);
cmp.synchronize(oe);
cmp.serialize(out, false);
}
else if (what == "class") {
vector<pClass> cls;
oe.getClasses(cls, true);
for (auto c : cls) {
InfoClass iCls(c->getId());
set<int> ctrl;
iCls.synchronize(*c, ctrl);
iCls.serialize(out, false);
}
}
else if (what == "competitor") {
vector<pRunner> r;
set<int> selection;
if (param.count("id") > 0)
getSelection(param.find("id")->second, selection);
oe.getRunners(selection.size() == 1 ? *selection.begin() : 0, -1, r, true);
for (auto c : r) {
InfoCompetitor iR(c->getId());
iR.synchronize(false, *c);
iR.serialize(out, false);
}
}
if (out.size() > 0) {
xmlparser mem;
mem.openMemoryOutput(false);
mem.startTag("MOPComplete", "xmlns", "http://www.melin.nu/mop");
out.commit(mem, 100000);
mem.endTag();
mem.getMemoryOutput(answer);
}
else {
answer = "Error (MeOS): Unknown command '" + what + "'";
}
}
void RestServer::getSelection(const string &param, set<int> &sel) {
vector<string> sw;
split(param, ";,", sw);
for (auto &s : sw) {
int id = atoi(s.c_str());
if (id > 0)
sel.insert(id);
}
}
shared_ptr<RestServer::EventRequest> RestServer::getRequest() {
shared_ptr<EventRequest> res;
if (hasAnyRequest) {
lock_guard<mutex> lg(lock);
if (!requests.empty()) {
res = requests.front();
requests.pop_front();
}
if (requests.empty())
hasAnyRequest = false;
}
return res;
}
shared_ptr<RestServer::EventRequest> RestServer::addRequest(multimap<string, string> &param) {
auto rq = make_shared<EventRequest>();
rq->parameters.swap(param);
lock_guard<mutex> lg(lock);
requests.push_back(rq);
hasAnyRequest = true;
return rq;
}
void RestServer::getStatistics(Statistics &s) {
lock_guard<mutex> lg(lock);
s.numRequests = responseTimes.size();
s.maxResponseTime = 0;
s.averageResponseTime = 0;
for (int t : responseTimes) {
s.maxResponseTime = max(s.maxResponseTime, t);
s.averageResponseTime += t;
}
if (s.numRequests > 0) {
s.averageResponseTime /= s.numRequests;
}
}

99
code/restserver.h Normal file
View File

@ -0,0 +1,99 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2017 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
/** Class for providing a MeOS REST service */
#include <memory>
#include <thread>
#include <atomic>
#include <mutex>
#include <deque>
#include <condition_variable>
namespace restbed {
class Service;
class Session;
};
class RestServer {
private:
struct EventRequest {
EventRequest() : state(false) {}
multimap<string, string> parameters;
string answer;
atomic_bool state; //false - asked, true - answerd
bool isCompleted() {
return state;
}
};
mutex lock;
atomic_bool hasAnyRequest;
shared_ptr<thread> service;
shared_ptr<restbed::Service> restService;
condition_variable waitForCompletion;
deque<shared_ptr<EventRequest>> requests;
void getData(oEvent &ref, const string &what, const multimap<string, string> &param, string &answer);
void compute(oEvent &ref);
void startThread(int port);
static void getSelection(const string &param, set<int> &sel);
void handleRequest(const shared_ptr<restbed::Session> &session);
friend void method_handler(const shared_ptr< restbed::Session > session);
shared_ptr<EventRequest> addRequest(multimap<string, string> &param);
shared_ptr<EventRequest> getRequest();
vector<int> responseTimes;
RestServer();
static vector< shared_ptr<RestServer> > startedServers;
RestServer(const RestServer &);
RestServer & operator=(const RestServer &) const;
public:
~RestServer();
void startService(int port);
void stop();
static shared_ptr<RestServer> construct();
static void remove(shared_ptr<RestServer> server);
static void computeRequested(oEvent &ref);
struct Statistics {
int numRequests;
int averageResponseTime;
int maxResponseTime;
};
void getStatistics(Statistics &s);
};

View File

@ -380,7 +380,7 @@ void SpeakerMonitor::splitAnalysis(gdioutput &gdi, int xp, int yp, pRunner r) {
else else
first = false; first = false;
timeloss += pc->getControlOrdinal(j) + L". " + formatTimeW(delta[j]); timeloss += pc->getControlOrdinal(j) + L". " + formatTime(delta[j]);
} }
if (timeloss.length() > charlimit || (!timeloss.empty() && !first && j+1 == delta.size())) { if (timeloss.length() > charlimit || (!timeloss.empty() && !first && j+1 == delta.size())) {
gdi.addStringUT(yp, xp, 0, timeloss).setColor(colorDarkRed); gdi.addStringUT(yp, xp, 0, timeloss).setColor(colorDarkRed);
@ -405,7 +405,7 @@ wstring getTimeDesc(int t1, int t2) {
else if (tb <= 60) else if (tb <= 60)
stime = itow(tb) + lang.tl(L" sekunder"); stime = itow(tb) + lang.tl(L" sekunder");
else else
stime = formatTimeW(tb); stime = formatTime(tb);
return stime; return stime;
} }
@ -504,7 +504,7 @@ void SpeakerMonitor::getMessage(const oEvent::ResultEvent &res,
deltaTime = after - prevAfter; // Positive -> more after. deltaTime = after - prevAfter; // Positive -> more after.
} }
wstring timeS = formatTimeW(res.runTime); wstring timeS = formatTime(res.runTime);
wstring detail; wstring detail;
const wstring *cname = 0; const wstring *cname = 0;

View File

@ -1865,7 +1865,7 @@ Byt till rätt klass (behåll eventuell starttid) = Byt till rätt klass (behål
Byt till vakansplats i rätt klass (om möjligt) = Byt till vakansplats i rätt klass (om möjligt) Byt till vakansplats i rätt klass (om möjligt) = Byt till vakansplats i rätt klass (om möjligt)
Tillåt ny klass, behåll resultat från annan klass = Tillåt ny klass, behåll resultat från annan klass Tillåt ny klass, behåll resultat från annan klass = Tillåt ny klass, behåll resultat från annan klass
Tillåt ny klass, inget totalresultat = Tillåt ny klass, inget totalresultat Tillåt ny klass, inget totalresultat = Tillåt ny klass, inget totalresultat
tooltip_explain_status = - = Okänd status\nOK = Godkänt resultat\nEj start = Startade inte\nFelst. = Felstämplat\nUtgått = Måltid saknas\nDisk. = Diskvalificerad\nDeltar ej = Springer inte tävlingen tooltip_explain_status = - = Okänd status\nOK = Godkänt resultat\nEj start = Startade inte\nÅterbud = Kommer ej att starta, visas i startlistan.\nFelst. = Felstämplat\nUtgått = Måltid saknas\nDisk. = Diskvalificerad\nDeltar ej = Springer inte tävlingen
Placering = Placering Placering = Placering
Resultat från tidigare etapper = Resultat från tidigare etapper Resultat från tidigare etapper = Resultat från tidigare etapper
Input Results = Ingångsresultat Input Results = Ingångsresultat
@ -2252,3 +2252,30 @@ Spara fönster- och speakerinställningar på datorn = Spara fönster- och speak
ask:loadspeaker = Vill du ladda tidigare sparade klass- och fönsterinställningar? ask:loadspeaker = Vill du ladda tidigare sparade klass- och fönsterinställningar?
Återskapa = Återskapa Återskapa = Återskapa
Återskapa tidigare sparade fönster- och speakerinställningar = Återskapa tidigare sparade fönster- och speakerinställningar Återskapa tidigare sparade fönster- och speakerinställningar = Återskapa tidigare sparade fönster- och speakerinställningar
Inkludera resultat från tidigare etapper = Inkludera resultat från tidigare etapper
Animation = Animation
Bakgrund = Bakgrund
Bakgrundsfärg = Bakgrundsfärg
Fullskärm (rullande) = Fullskärm (rullande)
Fullskärm (sidvis) = Fullskärm (sidvis)
Fönster = Fönster
Fönster (rullande) = Fönster (rullande)
Justera visningsinställningar = Justera visningsinställningar
Marginal = Marginal
Sidor per skärm = Sidor per skärm
Textfärg = Textfärg
Utseende = Utseende
Visningsinställningar för 'X' = Visningsinställningar för 'X'
Visningstid = Visningstid
Visning = Visning
ask:hasVacant = Tävlingen innehåller fortfarande vakanser.\n\nVill du ta bort samtliga vakanser innan resultaten exporteras?
warn:missingResult = X deltagare saknar fortfarande resultat, och tas därför inte med.\n\nDu bör använda kvar-i-skogen för att tilldela återstående deltagare status <Ej Start>.
Återställ <Ej Start> till <Status Okänd> = Återställ <Ej Start> till <Status Okänd>
Återbud[status] = Återbud
Lås gafflingar = Lås gafflingar
Markera för att förhindra oavsiktlig ändring av gafflingsnycklar = Markera för att förhindra oavsiktlig ändring av gafflingsnycklar
Tillåt gafflingsändringar = Tillåt gafflingsändringar
ask:updatetimes = Vill du behålla nuvarande starttider, om möjligt? Svara nej för att förskjuta tävlingen.
X har en tid (Y) som inte är kompatibel med förändringen = X har en tid (Y) som inte är kompatibel med förändringen
warn:latestarttime = Att använda starttider mer än X timmar efter nolltiden rekommenderas inte eftersom äldre SI brickor endast har en 12-timmarsklocka.\n\nVill du ändå använda starttiden?
Anm. tid = Anm. tid

View File

@ -172,7 +172,7 @@ void TestMeOS::runProtected(bool protect) const {
gdi_main->isTestMode = false; gdi_main->isTestMode = false;
subWindows.clear(); subWindows.clear();
//oe_main->setProperty("PayModes", pmOrig); //oe_main->setProperty("PayModes", pmOrig);
message = ex.what(); message = gdi_main->widen(ex.what());
if (!protect) if (!protect)
throw; throw;
} }
@ -184,7 +184,7 @@ void TestMeOS::runProtected(bool protect) const {
gdi_main->isTestMode = false; gdi_main->isTestMode = false;
subWindows.clear(); subWindows.clear();
//oe_main->setProperty("PayModes", pmOrig); //oe_main->setProperty("PayModes", pmOrig);
message = "Unknown Exception"; message = L"Unknown Exception";
cleanup(); cleanup();
if (!protect) if (!protect)
throw; throw;
@ -274,7 +274,7 @@ string TestMeOS::selectString(const char *id, const char *data) const {
string TestMeOS::select(const char *id, size_t data) const { string TestMeOS::select(const char *id, size_t data) const {
string res = gdi_main->dbSelect(id, data); string res = gdi_main->dbSelect(id, data);
mainMessageLoop(0, 50); mainMessageLoop(0, 100);
return res; return res;
} }
@ -323,6 +323,13 @@ void TestMeOS::assertEquals(const string &expected,
throw meosAssertionFailure("Expected " + expected + " but got " + value); throw meosAssertionFailure("Expected " + expected + " but got " + value);
} }
void TestMeOS::assertEquals(const wstring &expected,
const wstring &value) const {
if (expected != value)
throw meosAssertionFailure(L"Expected " + expected + L" but got " + value);
}
void TestMeOS::assertEquals(int expected, int value) const { void TestMeOS::assertEquals(int expected, int value) const {
assertEquals(itos(expected), itos(value)); assertEquals(itos(expected), itos(value));
} }
@ -344,6 +351,13 @@ void TestMeOS::assertEquals(const char *message,
assertEquals(string(message), string(expected), value); assertEquals(string(message), string(expected), value);
} }
void TestMeOS::assertEquals(const wstring &message,
const wstring &expected,
const wstring &value) const {
if (expected != value)
throw meosAssertionFailure(message + L": Expected " + expected + L" but got " + value);
}
void TestMeOS::checkString(const char *str, int count) const { void TestMeOS::checkString(const char *str, int count) const {
int c = gdi_main->dbGetStringCount(str, false); int c = gdi_main->dbGetStringCount(str, false);
assertEquals("String " + string(str) + " not found", itos(count), itos(c)); assertEquals("String " + string(str) + " not found", itos(count), itos(c));

View File

@ -41,9 +41,10 @@ enum TestStatus {
}; };
struct meosAssertionFailure { struct meosAssertionFailure {
meosAssertionFailure() {message = "MeOS assertion failure";}; meosAssertionFailure() {message = L"MeOS assertion failure";};
meosAssertionFailure(const string &err) : message(err) {} meosAssertionFailure(const string &err) : message(err.begin(), err.end()) {}
string message; meosAssertionFailure(const wstring &err) : message(err) {}
wstring message;
}; };
class TestMeOS : public SubCommand { class TestMeOS : public SubCommand {
@ -57,7 +58,7 @@ private:
mutable vector<wstring> tmpFiles; mutable vector<wstring> tmpFiles;
mutable TestStatus status; mutable TestStatus status;
mutable string message; mutable wstring message;
int testId; int testId;
int *testIdMain; // Pointer to main test id int *testIdMain; // Pointer to main test id
@ -81,6 +82,10 @@ protected:
void assertEquals(const char *message, const char *expected, const string &value) const; void assertEquals(const char *message, const char *expected, const string &value) const;
void assertEquals(const string &message, const string &expected, const string &value) const; void assertEquals(const string &message, const string &expected, const string &value) const;
void assertEquals(const wstring &expected, const wstring &value) const;
void assertEquals(const wstring &message, const wstring &expected, const wstring &value) const;
void assertTrue(const char *message, bool condition) const; void assertTrue(const char *message, bool condition) const;
int getResultModuleIndex(const char *tag) const; int getResultModuleIndex(const char *tag) const;

View File

@ -158,7 +158,7 @@ void Toolbar::createToolbar(const string &id, const wstring &title)
} }
wstring t = lang.tl(title); wstring t = lang.tl(title);
HWND hParent = gdi.getHWND(); HWND hParent = gdi.getHWNDTarget();
RECT rc; RECT rc;
GetWindowRect(hParent, &rc); GetWindowRect(hParent, &rc);
if (hwndFloater == 0) { if (hwndFloater == 0) {
@ -281,7 +281,7 @@ LRESULT CALLBACK ToolProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Toolbar *tb = (Toolbar *)GetWindowLongPtr(hWnd, GWL_USERDATA); Toolbar *tb = (Toolbar *)GetWindowLongPtr(hWnd, GWL_USERDATA);
if (tb) { if (tb) {
//DefWindowProc(tb->gdi.getHWND(), message, wParam, lParam); //DefWindowProc(tb->gdi.getHWND(), message, wParam, lParam);
SendMessage(tb->gdi.getMain(), message, wParam, lParam); SendMessage(tb->gdi.getHWNDMain(), message, wParam, lParam);
} }
return DefWindowProc(hWnd, message, wParam, lParam); return DefWindowProc(hWnd, message, wParam, lParam);
} }

View File

@ -392,7 +392,7 @@ void xmlparser::openOutputT(const wchar_t *file, bool useCutMode, const string &
toString = false; toString = false;
cutMode = useCutMode; cutMode = useCutMode;
foutFile.open(file); foutFile.open(file);
checkWriteAccess(file);
tagStackPointer=0; tagStackPointer=0;
if (foutFile.bad()) if (foutFile.bad())

View File

@ -220,6 +220,18 @@ public:
return 0; return 0;
} }
bool got(const char *pname) const {
xmlobject x(getObject(pname));
if (x)
return true;
else {
xmlattrib xa(getAttrib(pname));
if (xa)
return true;
}
return false;
}
bool getObjectBool(const char *pname) const; bool getObjectBool(const char *pname) const;
string &getObjectString(const char *pname, string &out) const; string &getObjectString(const char *pname, string &out) const;