MeOS version 3.5.826 RC2

This commit is contained in:
Erik Melin 2018-03-25 22:21:24 +02:00
parent cf33e11e22
commit 5327deebbb
33 changed files with 603 additions and 367 deletions

View File

@ -1045,6 +1045,7 @@ void RunnerDB::updateAdd(const oRunner &r, map<int, int> &clubIdMap)
dbe = &dbr;
break;
}
++it;
}
}

View File

@ -34,6 +34,7 @@
#include <winsock2.h>
#include "localizer.h"
#include "meos_util.h"
#include "gdioutput.h"
#include "oPunch.h"
#include <algorithm>
@ -72,7 +73,6 @@ SportIdent::SportIdent(HWND hWnd, DWORD Id)
//ThreadHandle=0;
n_SI_Info=0;
ZeroTime=0;
InitializeCriticalSection(&SyncObj);
tcpPortOpen=0;
@ -859,7 +859,7 @@ int SportIdent::MonitorTCPSI(WORD port, int localZeroTime)
vector<SIPunch> punches(nPunch);
r = recv(client, (char*)&punches[0], 8 * nPunch, 0);
if (r == 8 * nPunch) {
SICard card;
SICard card(ConvertedTimeStatus::Hour24);
card.CheckPunch.Code = -1;
card.StartPunch.Code = -1;
card.FinishPunch.Code = -1;
@ -1169,7 +1169,7 @@ void SportIdent::getSI5DataExt(HANDLE hComm)
WriteFile(hComm, c, 1, &written, NULL);
BYTE *Card5Data=bf+5;
SICard card;
SICard card(ConvertedTimeStatus::Hour12);
getCard5Data(Card5Data, card);
addCard(card);
}
@ -1241,7 +1241,7 @@ void SportIdent::getSI6DataExt(HANDLE hComm)
OutputDebugString(L"-ACK-");
SICard card;
SICard card(ConvertedTimeStatus::Hour24);
getCard6Data(b, card);
addCard(card);
}
@ -1320,7 +1320,7 @@ void SportIdent::getSI9DataExt(HANDLE hComm)
OutputDebugString(L"-ACK-");
SICard card;
SICard card(ConvertedTimeStatus::Hour24);
if (getCard9Data(b, card))
addCard(card);
}
@ -1419,7 +1419,7 @@ void SportIdent::getSI6Data(HANDLE hComm)
WriteFile(hComm, c, 1, &written, NULL);
OutputDebugString(L"-ACK-");
SICard card;
SICard card(ConvertedTimeStatus::Hour24);
getCard6Data(b, card);
addCard(card);
@ -1469,7 +1469,7 @@ void SportIdent::getSI5Data(HANDLE hComm)
WriteFile(hComm, c, 1, &written, NULL);
//BYTE *Card5Data=bf+5;
SICard card;
SICard card(ConvertedTimeStatus::Hour12);
getCard5Data(bf, card);
addCard(card);
@ -1507,7 +1507,7 @@ bool SportIdent::getCard5Data(BYTE *data, SICard &card)
data+=16;
card.convertedTime = ConvertedTimeStatus::Hour12;
analyseSI5Time(data+3, card.StartPunch.Time, card.StartPunch.Code);
analyseSI5Time(data+5, card.FinishPunch.Time, card.FinishPunch.Code);
analyseSI5Time(data+9, card.CheckPunch.Time, card.CheckPunch.Code);
@ -1571,6 +1571,7 @@ bool SportIdent::getCard9Data(BYTE *data, SICard &card)
int series = data[24] & 15;
card.convertedTime = ConvertedTimeStatus::Hour24;
analysePunch(data+12, card.StartPunch.Time, card.StartPunch.Code);
analysePunch(data+16, card.FinishPunch.Time, card.FinishPunch.Code);
analysePunch(data+8, card.CheckPunch.Time, card.CheckPunch.Code);
@ -1670,26 +1671,38 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
// DWORD control;
// DWORD time;
card.convertedTime = ConvertedTimeStatus::Hour24;
analysePunch(data+8, card.StartPunch.Time, card.StartPunch.Code);
analysePunch(data+4, card.FinishPunch.Time, card.FinishPunch.Code);
analysePunch(data+12, card.CheckPunch.Time, card.CheckPunch.Code);
card.nPunch=min(int(data[2]), 192);
int i;
char lastNameByte[21], firstNameByte[21];
wstring lastName, firstName;
memcpy(card.LastName, data+32, 20);
for(i=19;i>0 && card.LastName[i]==0x20;i--)
card.LastName[i]=0;
memcpy(lastNameByte, data+32, 20);
lastNameByte[20] = 0;
for (i = 19; i >= 0 && lastNameByte[i] == 0x20; i--) {
lastNameByte[i] = 0;
}
memcpy(card.FirstName, data+32+20, 20);
for(i=19;i>0 && card.FirstName[i]==0x20;i--)
card.FirstName[i]=0;
string2Wide(lastNameByte, lastName);
wcsncpy(card.lastName, lastName.c_str(), 20);
memcpy(firstNameByte, data+32+20, 20);
firstNameByte[20] = 0;
for (i = 19; i >= 0 && firstNameByte[i] == 0x20; i--) {
firstNameByte[i] = 0;
}
string2Wide(firstNameByte, firstName);
wcsncpy(card.firstName, firstName.c_str(), 20);
data+=128-16;
for(unsigned k=0;k<card.nPunch;k++)
{
for(unsigned k=0;k<card.nPunch;k++) {
analysePunch(data+4*k, card.Punch[k].Time, card.Punch[k].Code);
}
@ -1731,21 +1744,6 @@ void SportIdent::analyseSI5Time(BYTE *data, DWORD &time, DWORD &control)
{
if (*LPWORD(data)!=0xEEEE) {
time=MAKEWORD(data[1], data[0]);
if (ZeroTime<12*3600) {
//Förmiddag
if ( time < ZeroTime )
time+=12*3600; //->Eftermiddag
}
else {
//Eftermiddag
if ( time >= ZeroTime%(12*3600) ) {
//Eftermiddag
time+=12*3600;
}
// else Efter midnatt OK.
}
control=0;
}
else {
@ -1754,6 +1752,36 @@ void SportIdent::analyseSI5Time(BYTE *data, DWORD &time, DWORD &control)
}
}
void SICard::analyseHour12Time(DWORD zeroTime) {
if (convertedTime != ConvertedTimeStatus::Hour12)
return;
StartPunch.analyseHour12Time(zeroTime);
CheckPunch.analyseHour12Time(zeroTime);
FinishPunch.analyseHour12Time(zeroTime);
for (DWORD k = 0; k < nPunch; k++)
Punch[k].analyseHour12Time(zeroTime);
convertedTime = ConvertedTimeStatus::Hour24;
}
void SIPunch::analyseHour12Time(DWORD zeroTime) {
if (Code != -1 && Time>=0 && Time <=12*3600) {
if (zeroTime < 12 * 3600) {
//Förmiddag
if (Time < zeroTime)
Time += 12 * 3600; //->Eftermiddag
}
else {
//Eftermiddag
if (Time >= zeroTime % (12 * 3600)) {
//Eftermiddag
Time += 12 * 3600;
}
// else Efter midnatt OK.
}
}
}
void SportIdent::EnumrateSerialPorts(list<int> &ports)
{
@ -1867,7 +1895,7 @@ void SportIdent::addCard(const SICard &sic)
void SportIdent::addPunch(DWORD Time, int Station, int Card, int Mode)
{
SICard sic;
SICard sic(ConvertedTimeStatus::Hour24);
memset(&sic, 0, sizeof(sic));
sic.CardNumber=Card;
sic.StartPunch.Code = -1;
@ -1912,7 +1940,7 @@ void SportIdent::addPunch(DWORD Time, int Station, int Card, int Mode)
sic.FinishPunch.Code = oPunch::PunchFinish;
}
}
sic.PunchOnly=true;
sic.punchOnly = true;
addCard(sic);
}
@ -2048,14 +2076,6 @@ bool SportIdent::autoDetect(list<int> &ComPorts)
return !ComPorts.empty();
}
void SportIdent::setZeroTime(DWORD zt)
{
EnterCriticalSection(&SyncObj);
ZeroTime=zt%(24*3600);
LeaveCriticalSection(&SyncObj);
}
bool SportIdent::isPortOpen(const wstring &com)
{
SI_StationInfo *si = findStation(com);
@ -2146,8 +2166,7 @@ static string formatTimeN(int t) {
return nt;
}
vector<string> SICard::codeLogData(int row) const
{
vector<string> SICard::codeLogData(gdioutput &gdi, int row) const {
vector<string> log;
log.push_back(itos(row));
@ -2158,14 +2177,10 @@ vector<string> SICard::codeLogData(int row) const
log.push_back(itos(CardNumber));
log.push_back("");
log.push_back("");
wstring fn(FirstName), ln(LastName), cn(Club);
string fnn(fn.begin(), fn.end());
string lnn(ln.begin(), ln.end());
string cnn(cn.begin(), cn.end());
log.push_back(fnn);
log.push_back(lnn);
log.push_back(cnn);
log.push_back(gdi.recodeToNarrow(firstName));
log.push_back(gdi.recodeToNarrow(lastName));
log.push_back(gdi.recodeToNarrow(club));
log.push_back("");
log.push_back("");
log.push_back("");
@ -2179,11 +2194,12 @@ vector<string> SICard::codeLogData(int row) const
log.push_back("");
log.push_back("");
//We set monday on every punch, since this is our way of
//saying that we have 24-h clock.
string indicator24 = convertedTime == ConvertedTimeStatus::Hour12 ? "" : "MO";
//We set monday on every punch for 24-hour clock, since this indicates 24-hour support. Empty for 12-hour punch
if (signed(CheckPunch.Code) >= 0) {
log.push_back(itos(CheckPunch.Code));
log.push_back("MO");
log.push_back(indicator24);
log.push_back(formatTimeN(CheckPunch.Time));
}
else {
@ -2194,7 +2210,7 @@ vector<string> SICard::codeLogData(int row) const
if (signed(StartPunch.Code) >= 0) {
log.push_back(itos(StartPunch.Code));
log.push_back("MO");
log.push_back(indicator24);
log.push_back(formatTimeN(StartPunch.Time));
}
else {
@ -2205,7 +2221,7 @@ vector<string> SICard::codeLogData(int row) const
if (signed(FinishPunch.Code) >= 0) {
log.push_back(itos(FinishPunch.Code));
log.push_back("MO");
log.push_back(indicator24);
log.push_back(formatTimeN(FinishPunch.Time));
}
else {
@ -2219,7 +2235,7 @@ vector<string> SICard::codeLogData(int row) const
if (k<int(nPunch)) {
log.push_back(itos(Punch[k].Code));
if (Punch[k].Time>0) {
log.push_back("MO");
log.push_back(indicator24);
log.push_back(formatTimeN(Punch[k].Time));
}
else {
@ -2316,6 +2332,7 @@ string SICard::serializePunches() const {
}
void SICard::deserializePunches(const string &arg) {
convertedTime = ConvertedTimeStatus::Hour24;
FinishPunch.Code = -1;
StartPunch.Code = -1;
CheckPunch.Code = -1;
@ -2348,5 +2365,5 @@ void SICard::deserializePunches(const string &arg) {
*tp = atoi(mark[1].c_str());
}
if (out.size() == 1)
PunchOnly = true;
punchOnly = true;
}

View File

@ -40,6 +40,8 @@ const BYTE NAK=0x15;
// This is taken from r56 and checked in on r63
#include <vector>
class gdioutput;
struct SICard5Detect
{
BYTE code;//Code;
@ -49,23 +51,34 @@ struct SICard5Detect
WORD crc;
};
struct SIPunch
{
struct SIPunch {
DWORD Code;
DWORD Time;
void analyseHour12Time(DWORD zeroTime);
};
enum class ConvertedTimeStatus {
Unknown = 0,
Hour12,
Hour24,
Done,
};
struct SICard
{
SICard() {
SICard(ConvertedTimeStatus status) {
clear(0);
convertedTime = false;
convertedTime = status;
}
// Clears the card if this == condition or condition is 0
void clear(const SICard *condition) {
if (this==condition || condition==0)
memset(this, 0, sizeof(SICard));
}
void analyseHour12Time(DWORD zeroTime);
bool empty() const {return CardNumber==0;}
DWORD CardNumber;
SIPunch StartPunch;
@ -73,19 +86,19 @@ struct SICard
SIPunch CheckPunch;
DWORD nPunch;
SIPunch Punch[192];
wchar_t FirstName[21];
wchar_t LastName[21];
wchar_t Club[41];
wchar_t firstName[21];
wchar_t lastName[21];
wchar_t club[41];
char readOutTime[32];
bool PunchOnly;
bool convertedTime;
bool punchOnly;
ConvertedTimeStatus convertedTime;
// Used for manual time input
int runnerId;
int relativeFinishTime;
bool statusOK;
bool statusDNF;
vector<string> codeLogData(int row) const;
vector<string> codeLogData(gdioutput &converter, int row) const;
static vector<string> logHeader();
unsigned calculateHash() const;
@ -147,7 +160,6 @@ protected:
bool readSystemDataV2(SI_StationInfo &si);
CRITICAL_SECTION SyncObj;
DWORD ZeroTime; //Used to analyse times. Seconds 0-24h (0-24*3600)
int readByte_delay(BYTE &byte, HANDLE hComm);
int readBytes_delay(BYTE *byte, DWORD buffSize, DWORD len, HANDLE hComm);
int readBytesDLE_delay(BYTE *byte, DWORD buffSize, DWORD len, HANDLE hComm);
@ -200,7 +212,6 @@ public:
void getInfoString(const wstring &com, vector<wstring> &info);
bool isPortOpen(const wstring &com);
void setZeroTime(DWORD zt);
bool autoDetect(list<int> &ComPorts);
void stopMonitorThread();

View File

@ -798,7 +798,7 @@ void PrintResultMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
wstring printError;
lock = true;
try {
gdioutput gdiPrint("print", gdi.getScale(), gdi.getCP());
gdioutput gdiPrint("print", gdi.getScale());
gdiPrint.clearPage(false);
oe->generateList(gdiPrint, true, listInfo, false);
if (doPrint) {
@ -986,7 +986,7 @@ void PunchMachine::status(gdioutput &gdi)
void PunchMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
{
#ifndef MEOSDB
SICard sic;
SICard sic(ConvertedTimeStatus::Hour24);
oe->generateTestCard(sic);
SportIdent &si = TabSI::getSI(gdi);
if (!sic.empty()) {
@ -998,7 +998,7 @@ void PunchMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
pRunner r=oe->getRunnerByCardNo(sic.CardNumber, 0, false);
if (r && r->getCardNo()) {
sic.CardNumber=r->getCardNo();
sic.PunchOnly=true;
sic.punchOnly=true;
sic.nPunch=1;
sic.Punch[0].Code=radio;
si.addCard(sic);

View File

@ -962,7 +962,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
gdi.addSelection("Method", 200, 200, 0, L"Metod:");
gdi.addItem("Method", lang.tl("Lottning"), DMRandom);
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
gdi.selectItemByData("Method", getDefaultMethod(false));
gdi.selectItemByData("Method", getDefaultMethod({ DMRandom, DMSOFT }));
gdi.fillDown();
gdi.addCheckbox("LateBefore", "Efteranmälda före ordinarie");
@ -1566,7 +1566,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
gdi.setRestorePoint("MultiDayDraw");
lastDrawMethod = NOMethod;
drawDialog(gdi, getDefaultMethod(true), *pc);
drawDialog(gdi, getDefaultMethod(getSupportedDrawMethods(multiDay)), *pc);
}
else if (bi.id == "HandleMultiDay") {
ListBoxInfo lbi;
@ -1576,9 +1576,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (!pc)
throw std::exception("Class not found");
if (gdi.isChecked(bi.id) && (lastDrawMethod == DMReversePursuit ||
if (!gdi.isChecked(bi.id) && (lastDrawMethod == DMReversePursuit ||
lastDrawMethod == DMPursuit)) {
drawDialog(gdi, getDefaultMethod(false), *pc);
drawDialog(gdi, DMSOFT, *pc);
}
else
setMultiDayClass(gdi, gdi.isChecked(bi.id), lastDrawMethod);
@ -2253,7 +2253,7 @@ void TabClass::showClassSettings(gdioutput &gdi)
gdi.addItem("Method", lang.tl("Lottning"), DMRandom);
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
gdi.selectItemByData("Method", getDefaultMethod(false));
gdi.selectItemByData("Method", getDefaultMethod({DMRandom, DMSOFT}));
gdi.addSelection("PairSize", 150, 200, 0, L"Tillämpa parstart:");
gdi.addItem("PairSize", getPairOptions());
@ -3250,15 +3250,22 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
if (lastDrawMethod == method)
return;
bool noUpdate = false;
if (lastDrawMethod == DMPursuit && method == DMReversePursuit)
return;
noUpdate = true;
if (lastDrawMethod == DMReversePursuit && method == DMPursuit)
return;
noUpdate = true;
if (lastDrawMethod == DMRandom && method == DMSOFT)
return;
noUpdate = true;
if (lastDrawMethod == DMSOFT && method == DMRandom)
noUpdate = true;
if (noUpdate) {
lastDrawMethod = method;
return;
}
int firstStart = 3600,
interval = 120,
@ -3281,7 +3288,7 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
}
gdi.restore("MultiDayDraw", false);
const bool multiDay = oe->hasPrevStage();
const bool multiDay = oe->hasPrevStage() && gdi.isChecked("HandleMultiDay");
if (method == DMSeeded) {
gdi.addString("", 10, "help:seeding_info");
@ -3352,7 +3359,7 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
gdi.addCheckbox("HandleBibs", "Tilldela nummerlappar:", ClassesCB, lastHandleBibs).setSynchData(&lastHandleBibs);
gdi.dropLine(-0.2);
gdi.addInput("Bib", L"", 10, 0, L"", L"Mata in första nummerlappsnummer, eller blankt för att ta bort nummerlappar");
gdi.disableInput("Bib");
gdi.setInputStatus("Bib", lastHandleBibs);
gdi.fillDown();
gdi.dropLine(2.5);
gdi.popX();
@ -3390,6 +3397,16 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
lastDrawMethod = method;
}
set<DrawMethod> TabClass::getSupportedDrawMethods(bool hasMulti) const {
set<DrawMethod> base = { DMRandom, DMSOFT, DMClumped, DMSimultaneous, DMSeeded };
if (hasMulti) {
base.insert(DMPursuit);
base.insert(DMReversePursuit);
}
return base;
}
void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, DrawMethod defaultMethod) {
gdi.clearList("Method");
@ -3404,12 +3421,14 @@ void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, DrawMethod defaul
gdi.addItem("Method", lang.tl("Omvänd jaktstart"), DMReversePursuit);
}
else if (defaultMethod > 10)
defaultMethod = getDefaultMethod(hasMulti);
defaultMethod = DMSOFT;
gdi.selectItemByData("Method", defaultMethod);
if (gdi.hasField("Vacanses")) {
gdi.setInputStatus("Vacanses", !hasMulti);
}
if (gdi.hasField("HandleBibs")) {
gdi.setInputStatus("HandleBibs", !hasMulti);
if (hasMulti) {
@ -4078,28 +4097,12 @@ void TabClass::updateSplitDistribution(gdioutput &gdi, int num, int tot) const {
gdi.refresh();
}
DrawMethod TabClass::getDefaultMethod(bool allowPursuit) const {
int dm = oe->getPropertyInt("DefaultDrawMethod", DMSOFT);
if (!allowPursuit) {
if (dm == DMRandom)
return DMRandom;
else
return DMSOFT;
}
else {
switch (dm) {
case DMRandom:
return DMRandom;
case DMPursuit:
return DMPursuit;
case DMReversePursuit:
return DMReversePursuit;
case DMSeeded:
return DMSeeded;
default:
return DMSOFT;
}
}
DrawMethod TabClass::getDefaultMethod(const set<DrawMethod> &allowedValues) const {
DrawMethod dm = (DrawMethod)oe->getPropertyInt("DefaultDrawMethod", DMSOFT);
if (allowedValues.count(dm))
return dm;
else
return DMSOFT;
}
vector< pair<wstring, size_t> > TabClass::getPairOptions() {

View File

@ -76,6 +76,8 @@ class TabClass :
DrawInfo drawInfo;
void setMultiDayClass(gdioutput &gdi, bool hasMulti, DrawMethod defaultMethod);
set<DrawMethod> getSupportedDrawMethods(bool multiDay) const;
void drawDialog(gdioutput &gdi, DrawMethod method, const oClass &cls);
void pursuitDialog(gdioutput &gdi);
@ -136,7 +138,7 @@ class TabClass :
void updateSplitDistribution(gdioutput &gdi, int numInClass, int tot) const;
DrawMethod getDefaultMethod(bool allowPursuit) const;
DrawMethod getDefaultMethod(const set<DrawMethod> &allowedValues) const;
void enableLoadSettings(gdioutput &gdi);

View File

@ -134,7 +134,6 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
oe->setZeroTime(zt);
oe->synchronize();
if (gSI) gSI->setZeroTime(oe->getZeroTimeNum());
gdi.setWindowTitle(oe->getTitleName());
gdi.setText("Date", oe->getDate());
@ -159,7 +158,6 @@ bool TabCompetition::importFile(HWND hWnd, gdioutput &gdi)
gdi.setWaitCursor(true);
if (oe->open(fileName, true)) {
if (gSI) gSI->setZeroTime(oe->getZeroTimeNum());
gdi.setWindowTitle(oe->getTitleName());
resetSaveTimer();
return true;
@ -1766,7 +1764,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
oListInfo li;
par.selection = allTransfer;
oe->generateListInfo(par, gdi.getLineHeight(), li);
gdioutput tGdi("temp", gdi.getScale(), gdi.getCP());
gdioutput tGdi("temp", gdi.getScale());
oe->generateList(tGdi, true, li, false);
tGdi.writeTableHTML(save, oe->getName(), 0);
tGdi.openDoc(save.c_str());
@ -1851,7 +1849,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
par.setLegNumberCoded(-1);
oListInfo li;
oe->generateListInfo(par, gdi.getLineHeight(), li);
gdioutput tGdi("temp", gdi.getScale(), gdi.getCP());
gdioutput tGdi("temp", gdi.getScale());
oe->generateList(tGdi, true, li, false);
tGdi.writeTableHTML(save, oe->getName(), 0);
tGdi.openDoc(save.c_str());
@ -2286,7 +2284,6 @@ void TabCompetition::openCompetition(gdioutput &gdi, int id) {
err = ex.wwhat();
}
if (gSI) gSI->setZeroTime(oe->getZeroTimeNum());
resetSaveTimer();
oe->setProperty("LastCompetition", id);
gdi.setWindowTitle(oe->getTitleName());
@ -2308,8 +2305,6 @@ int TabCompetition::restoreCB(gdioutput &gdi, int type, void *data) {
gdi.alert("Kunde inte öppna tävlingen.");
}
else {
if (gSI) gSI->setZeroTime(oe->getZeroTimeNum());
const wstring &name = oe->getName();
if (name.find_last_of(L"}") != name.length()-1)
oe->setName(name + L" {" + lang.tl(L"återställd") + L"}");
@ -3903,8 +3898,7 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
gdi.fillRight();
gdi.pushX();
fields.push_back("MaxTime");
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Rogaining) &&
oe->getMeOSFeatures().hasFeature(MeOSFeatures::Patrol)) {
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Rogaining)) {
fields.push_back("DiffTime");
}
gdi.fillDown();

View File

@ -877,7 +877,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
pRunner r=oe->getRunner(runnerId, 0);
if (!r) return 0;
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
if (bi.getExtraInt() == 0)
r->printSplits(gdiprint);
else
@ -1053,7 +1053,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
auto &db = oe->getRunnerDatabase();
bool show = false;
if (ii.text.length() > 1) {
auto dbClub = extractClub(gdi);
auto dbClub = extractClub(oe, gdi);
auto rw = db.getRunnerSuggestions(ii.text, dbClub ? dbClub->getId() : 0, 10);
if (!rw.empty()) {
auto &ac = gdi.addAutoComplete(ii.id);
@ -3024,7 +3024,7 @@ void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
gdi.TabFocus(1);
}
pClub TabRunner::extractClub(gdioutput &gdi) {
pClub TabRunner::extractClub(oEvent *oe, gdioutput &gdi) {
oClub *dbClub = nullptr;
if (gdi.hasField("Club")) {
auto &db = oe->getRunnerDatabase();

View File

@ -109,8 +109,9 @@ private:
protected:
void clearCompetitionData();
pClub extractClub(gdioutput &gdi);
public:
static pClub extractClub(oEvent *oe, gdioutput &gdi);
void handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) override;
const char * getTypeStr() const {return "TRunnerTab";}

View File

@ -48,12 +48,12 @@
#include "recorder.h"
#include "autocomplete.h"
TabSI::TabSI(oEvent *poe):TabBase(poe) {
TabSI::TabSI(oEvent *poe):TabBase(poe), activeSIC(ConvertedTimeStatus::Unknown) {
editCardData.tabSI = this;
directEntryGUI.tabSI = this;
interactiveReadout=poe->getPropertyInt("Interactive", 1)!=0;
useDatabase=poe->useRunnerDb() && poe->getPropertyInt("Database", 1)!=0;
useDatabase = poe->getPropertyInt("Database", 1)!=0;
printSplits = false;
printStartInfo = false;
savedCardUniqueId = 1;
@ -89,7 +89,7 @@ static void entryTips(gdioutput &gdi) {
}
void TabSI::logCard(const SICard &card)
void TabSI::logCard(gdioutput &gdi, const SICard &card)
{
if (logger == 0) {
logger = new csvparser;
@ -104,7 +104,7 @@ void TabSI::logCard(const SICard &card)
logcounter = 0;
}
vector<string> log = card.codeLogData(++logcounter);
vector<string> log = card.codeLogData(gdi, ++logcounter);
logger->outputRow(log);
}
@ -143,8 +143,8 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
vector<string> head = SICard::logHeader();
saver.outputRow(head);
int count = 0;
for (list< pair<int, SICard> >::const_iterator it = savedCards.begin(); it != savedCards.end(); ++it) {
vector<string> log = it->second.codeLogData(++count);
for (auto it = savedCards.begin(); it != savedCards.end(); ++it) {
vector<string> log = it->second.codeLogData(gdi, ++count);
saver.outputRow(log);
}
}
@ -492,14 +492,16 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
}
}
else if (bi.id=="Save") {
SICard sic;
sic.clear(0);
SICard sic(ConvertedTimeStatus::Hour24);
sic.CheckPunch.Code = -1;
sic.CardNumber=gdi.getTextNo("SI");
int f = convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum());
int s = convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum());
if (f < s) {
f += 24 * 3600;
}
sic.FinishPunch.Time= f % (24*3600);
sic.StartPunch.Time = f % (24*3600);
sic.StartPunch.Time = s % (24*3600);
if (!gdi.isChecked("HasFinish")) {
sic.FinishPunch.Code = -1;
sic.FinishPunch.Time = 0;
@ -521,10 +523,20 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.getRecorder().record("insertCard(" + itos(sic.CardNumber) + ", \"" + sic.serializePunches() + "\"); //Readout card");
if (false) {
sic.convertedTime = ConvertedTimeStatus::Hour12;
sic.StartPunch.Time %= (12 * 3600);
sic.FinishPunch.Time %= (12 * 3600);
sic.CheckPunch.Time %= (12 * 3600);
for (unsigned i = 0; i < sic.nPunch; i++) {
sic.Punch[i].Time %= (12 * 3600);
}
}
gSI->addCard(sic);
}
else if (bi.id=="SaveP") {
SICard sic;
SICard sic(ConvertedTimeStatus::Hour24);
sic.clear(0);
sic.FinishPunch.Code = -1;
sic.CheckPunch.Code = -1;
@ -535,7 +547,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (f > 0) {
sic.FinishPunch.Time = f;
sic.FinishPunch.Code = 1;
sic.PunchOnly = true;
sic.punchOnly = true;
gSI->addCard(sic);
return 0;
}
@ -544,7 +556,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (s > 0) {
sic.StartPunch.Time = s;
sic.StartPunch.Code = 1;
sic.PunchOnly = true;
sic.punchOnly = true;
gSI->addCard(sic);
return 0;
}
@ -552,7 +564,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
sic.Punch[sic.nPunch].Code=gdi.getTextNo("C1");
sic.Punch[sic.nPunch].Time=convertAbsoluteTimeHMS(gdi.getText("C2"), oe->getZeroTimeNum());
sic.nPunch = 1;
sic.PunchOnly = true;
sic.punchOnly = true;
gSI->addCard(sic);
}
else if (bi.id=="Cancel") {
@ -626,7 +638,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.pushX();
SICard si_copy=activeSIC;
gEvent->convertTimes(si_copy);
gEvent->convertTimes(nullptr, si_copy);
//Find matching class...
vector<pClass> classes;
@ -828,6 +840,10 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.getSelectedItem("Class", lbi);
if (signed(lbi.data)<=0) {
if (oe->getNumClasses() > 0) {
gdi.alert(L"Ingen klass vald");
return 0;
}
pClass pc = oe->getClassCreate(0, lang.tl(L"Öppen klass"));
lbi.data = pc->getId();
pc->setAllowQuickEntry(true);
@ -975,7 +991,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.restore("ManualInput", false);
SICard sic;
SICard sic(ConvertedTimeStatus::Hour24);
sic.runnerId = runnerMatchedId;
sic.relativeFinishTime = relTime;
sic.statusOK = ok;
@ -1011,7 +1027,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
}
else if (bi.id == "CCSPrint") {
//gdi.print(oe);
gdioutput gdiPrint("print", gdi.getScale(), gdi.getCP());
gdioutput gdiPrint("print", gdi.getScale());
gdiPrint.clearPage(false);
int tCardPosX = cardPosX;
@ -1135,7 +1151,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if ((gdi.getData("RunnerId", rid) && rid>0) || !gdi.getText("Club", true).empty())
return 0; // Selected from list
if (!bi.text.empty() && useDatabase) {
if (!bi.text.empty() && showDatabase()) {
pRunner db_r = oe->dbLookUpByName(bi.text, 0, 0, 0);
if (!db_r && lastClubId)
db_r = oe->dbLookUpByName(bi.text, lastClubId, 0, 0);
@ -1151,8 +1167,27 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
else if (type == GUI_COMBOCHANGE) {
ListBoxInfo bi=*(ListBoxInfo *)data;
if (bi.id == "Runners") {
inputId++;
gdi.addTimeoutMilli(300, "AddRunnerInteractive", SportIdentCB).setExtra(inputId);
if (!showDatabase()) {
inputId++;
gdi.addTimeoutMilli(300, "AddRunnerInteractive", SportIdentCB).setExtra(inputId);
}
bool show = false;
if (showDatabase() && bi.text.length() > 1) {
auto rw = oe->getRunnerDatabase().getRunnerSuggestions(bi.text, 0, 20);
if (!rw.empty()) {
auto &ac = gdi.addAutoComplete(bi.id);
ac.setAutoCompleteHandler(this);
vector<AutoCompleteRecord> items = getRunnerAutoCompelete(oe->getRunnerDatabase(), rw, 0);
ac.setData(items);
ac.show();
show = true;
}
}
if (!show) {
gdi.clearAutoComplete(bi.id);
}
}
}
else if (type == GUI_EVENT) {
@ -1160,6 +1195,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (ev.id == "AutoComplete") {
pRunner r = oe->getRunner(runnerMatchedId, 0);
if (r) {
gdi.clearAutoComplete("");
gdi.setInputFocus("OK1");
gdi.setText("Runners", r->getName());
gdi.setData("RunnerId", runnerMatchedId);
@ -1325,7 +1361,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.addTimeoutMilli(50, "TieCard", SportIdentCB).setExtra(runnerMatchedId);
}
else if (cardNo>0 && gdi.getText("Name").empty()) {
SICard sic;
SICard sic(ConvertedTimeStatus::Hour24);
sic.clear(0);
sic.CardNumber = cardNo;
@ -1482,7 +1518,6 @@ SportIdent &TabSI::getSI(const gdioutput &gdi) {
if (!gSI) {
HWND hWnd=gdi.getHWNDMain();
gSI = new SportIdent(hWnd, 0);
gSI->setZeroTime(gEvent->getZeroTimeNum());
}
return *gSI;
}
@ -1767,6 +1802,35 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
return;
}
else if (mode == ModeCardData) {
if (sic.convertedTime == ConvertedTimeStatus::Hour12) {
int locTime = getLocalAbsTime();
int st = -1;
if (sic.StartPunch.Code != -1)
st = sic.StartPunch.Time;
else if (sic.nPunch > 0 && sic.Punch[0].Code != -1)
st = sic.Punch[0].Time;
if (st == -1)
st = (locTime + 3600 * 20) % (12 * 3600);
else {
// We got a start time. Calculate running time
if (sic.FinishPunch.Code != -1) {
int rt = (sic.FinishPunch.Time - st + 12 * 3600) % (12 * 3600);
// Adjust to local time at start;
locTime = (locTime - rt + (24 * 3600)) % (24 * 3600);
}
}
int zt1 = (st + 23 * 3600) % (24 * 3600);
int zt2 = st + 11 * 3600;
int d1 = min(abs(locTime - zt1), abs(locTime - zt1 + 3600 * 24));
int d2 = min(abs(locTime - zt2), abs(locTime - zt2 + 3600 * 24));
if (d1 < d2)
sic.analyseHour12Time(zt1);
else
sic.analyseHour12Time(zt2);
}
savedCards.push_back(make_pair(savedCardUniqueId++, sic));
if (printSplits) {
@ -1789,7 +1853,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
gEvent->synchronizeList(oLCardId, true, false);
gEvent->synchronizeList(oLRunnerId, false, true);
if (sic.PunchOnly) {
if (sic.punchOnly) {
processPunchOnly(gdi, sic);
return;
}
@ -1810,7 +1874,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
throw meosException("Internal error");
//SIPage not loaded...
if (!r && useDatabase)
if (!r && showDatabase())
r=autoMatch(sic, 0);
// Assign a class if not already done
@ -1907,7 +1971,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
if (sic.runnerId == 0) {
r = gEvent->getRunnerByCardNo(sic.CardNumber, 0, !readBefore);
if (!r && useDatabase) {
if (!r && showDatabase()) {
//Look up in database.
db_r = gEvent->dbLookUpByCard(sic.CardNumber);
if (db_r)
@ -1964,17 +2028,17 @@ void TabSI::startInteractive(gdioutput &gdi, const SICard &sic, pRunner r, pRunn
gdi.fillRight();
gdi.pushX();
gdi.addCombo("Runners", 200, 300, SportIdentCB, L"Namn:");
gdi.addCombo("Runners", 300, 300, SportIdentCB, L"Namn:");
gEvent->fillRunners(gdi, "Runners", false, oEvent::RunnerFilterOnlyNoResult);
if (db_r){
gdi.setText("Runners", db_r->getName()); //Data from DB
}
else if (sic.FirstName[0] || sic.LastName[0]){ //Data from SI-card
gdi.setText("Runners", wstring(sic.FirstName)+L" "+sic.LastName);
else if (sic.firstName[0] || sic.lastName[0]){ //Data from SI-card
gdi.setText("Runners", wstring(sic.lastName) + L", " + sic.firstName);
}
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
gdi.addCombo("Club", 200, 300, 0, L"Klubb:");
gdi.addCombo("Club", 200, 300, 0, L"Klubb:").setHandler(&directEntryGUI);
gEvent->fillClubs(gdi, "Club");
if (db_r)
@ -2082,10 +2146,10 @@ bool TabSI::processUnmatched(gdioutput &gdi, const SICard &csic, bool silent)
wstring warnings;
// Write read card to log
logCard(sic);
logCard(gdi, sic);
// Convert punch times to relative times.
gEvent->convertTimes(sic);
gEvent->convertTimes(nullptr, sic);
if (sic.CheckPunch.Code!=-1)
card->addPunch(oPunch::PunchCheck, sic.CheckPunch.Time, 0);
@ -2235,10 +2299,10 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
info += runner->getClass(true);
// Write read card to log
logCard(sic);
logCard(gdi, sic);
// Convert punch times to relative times.
oe->convertTimes(sic);
oe->convertTimes(runner, sic);
pCourse prelCourse = runner->getCourse(false);
const int finishPT = prelCourse ? prelCourse->getFinishPunchType() : oPunch::PunchFinish;
bool hasFinish = false;
@ -2395,7 +2459,7 @@ void TabSI::processPunchOnly(gdioutput &gdi, const SICard &csic)
{
SICard sic=csic;
DWORD loaded;
gEvent->convertTimes(sic);
gEvent->convertTimes(nullptr, sic);
oFreePunch *ofp=0;
if (sic.nPunch==1)
@ -2442,7 +2506,7 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
wstring name;
wstring club;
int age = 0;
if (useDatabase) {
if (showDatabase()) {
pRunner db_r=oe->dbLookUpByCard(sic.CardNumber);
if (db_r) {
@ -2453,8 +2517,8 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
}
//Else get name from card
if (name.empty() && (sic.FirstName[0] || sic.LastName[0]))
name=wstring(sic.LastName) + L", " + wstring(sic.FirstName);
if (name.empty() && (sic.firstName[0] || sic.lastName[0]))
name=wstring(sic.lastName) + L", " + wstring(sic.firstName);
gdi.setText("Name", name);
if (gdi.hasField("Club"))
@ -2565,7 +2629,15 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r)
gdi.addInput("Name", storedInfo.storedName, 16, 0, L"Namn:").setHandler(&directEntryGUI);
gdi.addSelection("Class", 150, 200, 0, L"Klass:").setHandler(&directEntryGUI);
oe->fillClasses(gdi, "Class", oEvent::extraNumMaps, oEvent::filterOnlyDirect);
{
vector< pair<wstring, size_t> > d;
oe->fillClasses(d, oEvent::extraNumMaps, oEvent::filterOnlyDirect);
if (d.empty() && oe->getNumClasses() > 0) {
gdi.alert(L"Inga klasser tillåter direktanmälan. På sidan klasser kan du ändra denna egenskap.");
}
gdi.addItem("Class", d);
}
if (storedInfo.storedClassId > 0 && gdi.selectItemByData("Class", storedInfo.storedClassId)) {
}
else if (!gdi.selectItemByData("Class", lastClassId)) {
@ -2703,7 +2775,7 @@ void TabSI::generateSplits(const pRunner r, gdioutput &gdi)
while(checkpPrintQueue(gdi));
}
else {
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
vector<int> mp;
r->evaluateCard(true, mp);
r->printSplits(gdiprint);
@ -2714,7 +2786,7 @@ void TabSI::generateSplits(const pRunner r, gdioutput &gdi)
void TabSI::generateStartInfo(gdioutput &gdi, const oRunner &r) {
if (printStartInfo) {
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
r.printStartInfo(gdiprint);
printProtected(gdi, gdiprint);
//gdiprint.print(splitPrinter, oe, false, true);
@ -2985,9 +3057,9 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
gdi.removeControl("CancelCard");
wstring name, club;
if (card.FirstName[0])
name = wstring(card.FirstName) + (card.LastName[0] ? (L" " + wstring(card.LastName)) : L"");
club = card.Club;
if (card.firstName[0])
name = (card.lastName[0] ? (wstring(card.lastName) + L", ") : L"") + wstring(card.firstName);
club = card.club;
bool noName = name.empty();
bool noClub = club.empty();
if (noName)
@ -3017,9 +3089,9 @@ void TabSI::EditCardData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType ty
wstring club = gdi.getBaseInfo("ClubName").getExtra() ? L"" : gdi.getText("ClubName");
wstring given = getGivenName(name);
wstring familty = getFamilyName(name);
wcsncpy_s(card.FirstName, given.c_str(), 20);
wcsncpy_s(card.LastName, familty.c_str(), 20);
wcsncpy_s(card.Club, club.c_str(), 40);
wcsncpy_s(card.firstName, given.c_str(), 20);
wcsncpy_s(card.lastName, familty.c_str(), 20);
wcsncpy_s(card.club, club.c_str(), 40);
wstring s = name;
if (!club.empty())
@ -3049,9 +3121,9 @@ void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
gdi.pushX();
gdi.fillRight();
wstring name, clubName;
if (c.FirstName[0] != 0) {
name = wstring(c.FirstName) + L" " + c.LastName;
clubName = c.Club;
if (c.firstName[0] != 0) {
name = wstring(c.firstName) + L" " + c.lastName;
clubName = c.club;
}
else {
const RunnerWDBEntry *r = oe->getRunnerDatabase().getRunnerByCard(c.CardNumber);
@ -3060,12 +3132,12 @@ void TabSI::printCard(gdioutput &gdi, int cardId, bool forPrinter) const {
const oClub *club = oe->getRunnerDatabase().getClub(r->dbe().clubNo);
if (club) {
clubName = club->getName();
wcsncpy_s(c.Club, clubName.c_str(), 20);
wcsncpy_s(c.club, clubName.c_str(), 20);
}
wstring given = r->getGivenName();
wstring family = r->getFamilyName();
wcsncpy_s(c.FirstName, given.c_str(), 20);
wcsncpy_s(c.LastName, family.c_str(), 20);
wcsncpy_s(c.firstName, given.c_str(), 20);
wcsncpy_s(c.lastName, family.c_str(), 20);
}
}
@ -3164,7 +3236,7 @@ int TabSI::analyzePunch(SIPunch &p, int &start, int &accTime, int &days) {
}
void TabSI::generateSplits(int cardId, gdioutput &gdi) {
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
printCard(gdiprint, cardId, true);
printProtected(gdi, gdiprint);
}
@ -3266,15 +3338,15 @@ void TabSI::createCompetitionFromCards(gdioutput &gdi) {
if (!cls.empty()) {
wstring name;
if (cards[k].second->FirstName[0])
name = cards[k].second->FirstName;
if (cards[k].second->LastName[0])
name += L" " + wstring(cards[k].second->LastName);
if (cards[k].second->lastName[0])
name = wstring(cards[k].second->lastName) + L", ";
if (cards[k].second->firstName[0])
name += cards[k].second->firstName;
if (name.empty())
name = lang.tl(L"Bricka X#" + itow(cards[k].second->CardNumber));
oe->addRunner(name, wstring(cards[k].second->Club), cls[0]->getId(),
oe->addRunner(name, wstring(cards[k].second->club), cls[0]->getId(),
cards[k].second->CardNumber, 0, true);
processInsertCard(*cards[k].second);
@ -3487,8 +3559,7 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
}
}
else if (cmd == "tickoff") {
SICard sic;
sic.clear(0);
SICard sic(ConvertedTimeStatus::Hour24);
for (map<int, CardNumberFlags>::const_iterator it = checkedCardFlags.begin();
it != checkedCardFlags.end(); ++it) {
int stat = it->second;
@ -3591,7 +3662,7 @@ bool TabSI::checkpPrintQueue(gdioutput &gdi) {
return false; // Wait a little longer
}
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter, gdi.getCP());
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
vector<int> mp;
for (size_t m = 0; m < printLen && !printPunchRunnerIdQueue.empty(); m++) {
int rid = printPunchRunnerIdQueue.front().second;
@ -3720,7 +3791,7 @@ void TabSI::DirectEntryGUI::handle(gdioutput &gdi, BaseInfo &info, GuiEventType
else if (type == GUI_INPUTCHANGE) {
InputInfo &ii = dynamic_cast<InputInfo &>(info);
bool show = false;
if (tabSI->useDatabase && ii.id == "Name") {
if (tabSI->showDatabase() && ii.id == "Name") {
auto &db = tabSI->oe->getRunnerDatabase();
if (ii.text.length() > 1) {
auto dbClub = tabSI->extractClub(gdi);
@ -3801,3 +3872,8 @@ void TabSI::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
gdi.clearAutoComplete("");
gdi.TabFocus(1);
}
bool TabSI::showDatabase() const {
return useDatabase && oe->useRunnerDb();
}

View File

@ -192,6 +192,8 @@ protected:
public:
bool showDatabase() const;
static vector<AutoCompleteRecord> getRunnerAutoCompelete(RunnerDB &db, const vector< pair<RunnerWDBEntry *, int>> &rw, pClub dbClub);
void handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) override;
@ -231,7 +233,7 @@ public:
int siCB(gdioutput &gdi, int type, void *data);
void logCard(const SICard &card);
void logCard(gdioutput &gdi, const SICard &card);
void setCardNumberField(const string &fieldId) {insertCardNumberField=fieldId;}

View File

@ -42,6 +42,7 @@
#include "TabRunner.h"
#include "MeOSFeatures.h"
#include "RunnerDB.h"
#include "autocomplete.h"
#include "TabSI.h"
@ -1058,6 +1059,29 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
gdi.getTextNo("DirCard") > 0);
}
if (oe->useRunnerDb() && ii.id == "DirName") {
auto &db = oe->getRunnerDatabase();
bool show = false;
if (ii.text.length() > 1) {
auto dbClub = TabRunner::extractClub(oe, gdi);
auto rw = db.getRunnerSuggestions(ii.text, dbClub ? dbClub->getId() : 0, 10);
if (dbClub != nullptr && rw.empty()) // Default: Any club
rw = db.getRunnerSuggestions(ii.text, 0, 10);
if (!rw.empty()) {
auto &ac = gdi.addAutoComplete(ii.id);
ac.setAutoCompleteHandler(this);
ac.setData(TabSI::getRunnerAutoCompelete(db, rw, dbClub));
ac.show();
show = true;
}
}
if (!show) {
gdi.clearAutoComplete(ii.id);
}
}
}
else if (type == GUI_INPUT) {
InputInfo &ii=*(InputInfo *)data;
@ -1115,6 +1139,27 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
}
}
else if (type == GUI_COMBOCHANGE) {
ListBoxInfo &combo = *(ListBoxInfo *)(data);
bool show = false;
if (oe->useRunnerDb() && combo.id == "Club" && combo.text.length() > 1) {
auto clubs = oe->getRunnerDatabase().getClubSuggestions(combo.text, 20);
if (!clubs.empty()) {
auto &ac = gdi.addAutoComplete(combo.id);
ac.setAutoCompleteHandler(this);
vector<AutoCompleteRecord> items;
for (auto club : clubs)
items.emplace_back(club->getDisplayName(), club->getName(), club->getId());
ac.setData(items);
ac.show();
show = true;
}
}
if (!show) {
gdi.clearAutoComplete(combo.id);
}
}
else if (type==GUI_CLEAR) {
if (teamId>0)
save(gdi, true);
@ -1322,7 +1367,7 @@ bool TabTeam::loadPage(gdioutput &gdi)
}
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
gdi.addCombo("Club", 180, 300, 0, L"Klubb:");
gdi.addCombo("Club", 180, 300, TeamCB, L"Klubb:");
oe->fillClubs(gdi, "Club");
drop = true;
}
@ -1897,3 +1942,26 @@ bool TabTeam::warnDuplicateCard(gdioutput &gdi, string id, int cno, pRunner r, v
return false;
}
}
void TabTeam::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
auto bi = gdi.setText(info.getTarget(), info.getCurrent().c_str());
if (bi) {
int ix = info.getCurrentInt();
bi->setExtra(ix);
if (info.getTarget() == "Name") {
auto &db = oe->getRunnerDatabase();
auto runner = db.getRunnerByIndex(ix);
if (runner && gdi.hasField("Club") && gdi.getText("Club").empty()) {
pClub club = db.getClub(runner->dbe().clubNo);
if (club)
gdi.setText("Club", club->getName());
}
if (runner && runner->dbe().cardNo > 0 && gdi.hasField("DirCard") && gdi.getText("DirCard").empty()) {
gdi.setText("DirCard", runner->dbe().cardNo);
}
}
}
gdi.clearAutoComplete("");
gdi.TabFocus(1);
}

View File

@ -21,11 +21,12 @@
************************************************************************/
#include "tabbase.h"
#include "autocompletehandler.h"
struct TeamLineup;
class TabTeam :
public TabBase
public TabBase, AutoCompleteHandler
{
private:
bool save(gdioutput &gdi, bool dontReloadTeams);
@ -73,11 +74,11 @@ private:
void switchRunners(pTeam team, int leg, pRunner r, pRunner oldR);
protected:
void clearCompetitionData();
public:
void handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) override;
const char * getTypeStr() const {return "TTeamTab";}
TabType getType() const {return TTeamTab;}

View File

@ -756,7 +756,7 @@ bool Table::keyCommand(gdioutput &gdi, KeyCommandCode code) {
gdi.refresh();
}
else if (code == KC_PRINT) {
gdioutput gdiPrint("temp", gdi.getScale(), gdi.getCP());
gdioutput gdiPrint("temp", gdi.getScale());
gdiPrint.clearPage(false);
gdiPrint.print(getEvent(), this);
}

View File

@ -839,17 +839,11 @@ bool csvparser::importPunches(const oEvent &oe, const wstring &file, vector<Punc
return true;
}
int analyseSITime(const oEvent &oe, const wchar_t *dow, const wchar_t *time)
int analyseSITime(const wchar_t *dow, const wchar_t *time, bool &is12Hour)
{
int t=-1;
if (trim(dow).length()>0)
t = oe.getRelativeTime(time);
else
t = oe.getRelativeTimeFrom12Hour(time);
if (t<0)
t=0;
int t = oEvent::convertAbsoluteTime(time);
if (t >= 0 && trim(dow).empty())
is12Hour = true;
return t;
}
@ -935,10 +929,10 @@ bool csvparser::checkSIConfigLine(const oEvent &oe, const vector<wstring> &sp, S
if (cardNo < 1000 || cardNo > 99999999)
return false;
int check = analyseSITime(oe, getSIC(sicCheckDOW, sp), getSIC(sicCheckTime, sp));
int start = analyseSITime(oe, getSIC(sicStartDOW, sp), getSIC(sicStartTime, sp));
int finish = analyseSITime(oe, getSIC(sicFinishDOW, sp), getSIC(sicFinishTime, sp));
bool is12Hour = false;
int check = analyseSITime(getSIC(sicCheckDOW, sp), getSIC(sicCheckTime, sp), is12Hour);
int start = analyseSITime(getSIC(sicStartDOW, sp), getSIC(sicStartTime, sp), is12Hour);
int finish = analyseSITime(getSIC(sicFinishDOW, sp), getSIC(sicFinishTime, sp), is12Hour);
int startCode = wtoi(getSIC(sicStart, sp));
int finishCode = wtoi(getSIC(sicFinish, sp));
int checkCode = wtoi(getSIC(sicCheck, sp));
@ -954,7 +948,7 @@ bool csvparser::checkSIConfigLine(const oEvent &oe, const vector<wstring> &sp, S
if (ix+2 >= sp.size())
return false;
int code = wtoi(sp[ix]);
int time = analyseSITime(oe, sp[ix+1].c_str(), sp[ix+2].c_str());
int time = analyseSITime(sp[ix+1].c_str(), sp[ix+2].c_str(), is12Hour);
if (code > 0) {
punches.push_back(make_pair(code, time));
}
@ -998,12 +992,12 @@ bool csvparser::checkSIConfigLine(const oEvent &oe, const vector<wstring> &sp, S
card.Punch[k].Time = punches[k].second;
}
wcsncpy_s(card.FirstName, fname.c_str(), 20);
card.FirstName[20] = 0;
wcsncpy_s(card.LastName, lname.c_str(), 20);
card.LastName[20] = 0;
wcsncpy_s(card.firstName, fname.c_str(), 20);
card.firstName[20] = 0;
wcsncpy_s(card.lastName, lname.c_str(), 20);
card.lastName[20] = 0;
card.nPunch = punches.size();
card.convertedTime = true;
card.convertedTime = is12Hour ? ConvertedTimeStatus::Hour12 : ConvertedTimeStatus::Hour24;
return true;
}
@ -1061,7 +1055,7 @@ bool csvparser::checkSimanLine(const oEvent &oe, const vector<wstring> &sp, SICa
card.Punch[k].Time = punches[k].second;
}
card.nPunch = punches.size();
card.convertedTime = false;
card.convertedTime = ConvertedTimeStatus::Hour24; //XXX Not correct in general
return true;
}
@ -1098,7 +1092,7 @@ bool csvparser::importCards(const oEvent &oe, const wstring &file, vector<SICard
//split(bf, sp);
const vector<wstring> &sp = *it;
SICard card;
SICard card(ConvertedTimeStatus::Unknown);
if (checkSimanLine(oe, sp, card)) {
cards.push_back(card);
@ -1111,13 +1105,13 @@ bool csvparser::importCards(const oEvent &oe, const wstring &file, vector<SICard
else if (sp.size()>28) {
int no = wtoi(sp[0]);
card.CardNumber = wtoi(sp[2]);
wcsncpy_s(card.FirstName, sp[5].c_str(), 20);
wcsncpy_s(card.LastName, sp[6].c_str(), 20);
wcsncpy_s(card.Club, sp[7].c_str(), 40);
wcsncpy_s(card.firstName, sp[5].c_str(), 20);
wcsncpy_s(card.lastName, sp[6].c_str(), 20);
wcsncpy_s(card.club, sp[7].c_str(), 40);
bool hour12 = false;
if (trim(sp[21]).length()>1) {
card.CheckPunch.Code = wtoi(sp[19]);
card.CheckPunch.Time = analyseSITime(oe, sp[20].c_str(), sp[21].c_str());
card.CheckPunch.Time = analyseSITime(sp[20].c_str(), sp[21].c_str(), hour12);
}
else {
card.CheckPunch.Code = -1;
@ -1126,7 +1120,7 @@ bool csvparser::importCards(const oEvent &oe, const wstring &file, vector<SICard
if (trim(sp[24]).length()>1) {
card.StartPunch.Code = wtoi(sp[22]);
card.StartPunch.Time = analyseSITime(oe, sp[23].c_str(), sp[24].c_str());
card.StartPunch.Time = analyseSITime(sp[23].c_str(), sp[24].c_str(), hour12);
}
else {
card.StartPunch.Code = -1;
@ -1135,7 +1129,7 @@ bool csvparser::importCards(const oEvent &oe, const wstring &file, vector<SICard
if (trim(sp[27]).length()>1) {
card.FinishPunch.Code = wtoi(sp[25]);
card.FinishPunch.Time = analyseSITime(oe, sp[26].c_str(), sp[27].c_str());
card.FinishPunch.Time = analyseSITime(sp[26].c_str(), sp[27].c_str(), hour12);
}
else {
card.FinishPunch.Code = -1;
@ -1147,11 +1141,11 @@ bool csvparser::importCards(const oEvent &oe, const wstring &file, vector<SICard
if (sp.size()>28+3*card.nPunch) {
for (unsigned k=0;k<card.nPunch;k++) {
card.Punch[k].Code = wtoi(sp[29+k*3]);
card.Punch[k].Time = analyseSITime(oe, sp[30+k*3].c_str(), sp[31+k*3].c_str());
card.Punch[k].Time = analyseSITime(sp[30+k*3].c_str(), sp[31+k*3].c_str(), hour12);
}
card.PunchOnly = false;
card.punchOnly = false;
nimport++;
card.convertedTime = true;
card.convertedTime = hour12 ? ConvertedTimeStatus::Hour12 : ConvertedTimeStatus::Hour24;
cards.push_back(card);
}
}

View File

@ -363,57 +363,58 @@ ControlRunnersLeft = Antal løbere der mangler at stemple post
ControlVisitors = Forventet antal løbere til post
Could not load list 'X' = Kunne ikke indlæse liste 'X'
Country = Land
Course = Bana
CourseClasses = Banas klasser
CourseClimb = Banans stigning
CourseLength = Banlängd, specifik bana
CourseName = Banans namn
CourseResult = Bana, resultat
CourseShortening = Banavkortningar
CourseUsage = Banas antal anmälda
CourseUsageNoVacant = Banas antal anmälda (ej vakanta)
Create Competition = Skapa tävling
Created X distinct forkings using Y courses = Skapade X olika gafflingsalternativ med hjälp av Y banor
CurrentTime = Aktuell tid
Course = Bane
CourseClasses = Banes klasser
CourseClimb = Banens højdemeter
CourseLength = Banelængde, specifik bane
CourseName = Banens navn
CourseResult = Bane, resultater
CourseShortening = Baneafkortninger
CourseStartTime = Bane, starttid
CourseUsage = Banes antal tilmeldte
CourseUsageNoVacant = Banes antal tilmeldte (ej vakante)
Create Competition = Dan løb
Created X distinct forkings using Y courses = Dannede X forskellige gaflingsalternativer ved hjælp af Y baner
CurrentTime = Aktuel tid
CustomSort = Egen sortering
Döp om = Döp om
Döp om X = Döp om X
Data from result module (X) = Data från resultatmodul (X)
Databasanslutning = Databasanslutning
DATABASE ERROR = DATABASFEL
Databaskälla = Databaskälla
Databasvarning: X = Databasvarning: X
Datorröst som läser upp förvarningar = Datorröst som läser upp förvarningar
Datum (för första start) = Datum (för första start)
Datum = Datum
Datumfilter = Datumfilter
Debug = Testkör
Debug Output = Resultat av testkörning
Debug X for Y = Testkör X med Y
Decimalseparator = Decimaltecken
DefaultFont = Standardformatering
Define forking = Definiera gaffling
Definierade mappningar = Definierade mappningar
Dela = Dela
Dela efter placering = Dela efter placering
Dela efter ranking = Dela efter ranking
Dela efter tid = Dela efter tid
Dela klass: X = Dela klass: X
Dela klassen = Dela klassen
Dela klubbvis = Dela klubbvis
Dela slumpmässigt = Dela slumpmässigt
Dela upp = Dela upp
delar placering med X = delar placering med X
Deltagare %d = Deltagare %d
Deltagare (kvarvarande) = Deltagare (tilbage)
Deltagare = Deltagare
Deltagaren 'X' deltar i patrullklassen 'Y' men saknar patrull. Klassens start- och resultatlistor kan därmed bli felaktiga = Deltagaren 'X' deltar i patrullklassen 'Y' men saknar patrull. Klassens start- och resultatlistor kan därmed bli felaktiga
Deltagaren 'X' deltar i stafettklassen 'Y' men saknar lag. Klassens start- och resultatlistor kan därmed bli felaktiga = Deltagaren 'X' deltar i stafettklassen 'Y' men saknar lag. Klassens start- och resultatlistor kan därmed bli felaktiga
Deltagaren 'X' saknar klass = Deltagaren 'X' saknar klass
Deltagarens klass styrs av laget = Deltagarens klass styrs av laget
Deltar ej = Deltar ej
Denna etapps nummer = Denna etapps nummer
Description = Beskrivning
Döp om = Døb om
Döp om X = Døb X om
Data from result module (X) = Data fra resultatmodul (X)
Databasanslutning = Databaseforbindelse
DATABASE ERROR = DATABASEFEJL
Databaskälla = Databaskilde
Databasvarning: X = Database advarsel: X
Datorröst som läser upp förvarningar = Computerstemme der læser forvarslinger op
Datum (för första start) = Dato (for første start)
Datum = Dato
Datumfilter = Datofilter
Debug = Afprøv
Debug Output = Resultat af afprøvning
Debug X for Y = Afprøv X med Y
Decimalseparator = Decimal separator
DefaultFont = Standardtegnsæt
Define forking = Definier gafflinger
Definierade mappningar = Definierede mappningar
Dela = Del
Dela efter placering = Del efter placering
Dela efter ranking = Del efter ranking
Dela efter tid = Del efter tid
Dela klass: X = Del klass: X
Dela klassen = Del klassen
Dela klubbvis = Del klubbvis
Dela slumpmässigt = Del tilfældigt
Dela upp = Del op
delar placering med X = deler placering med X
Deltagare %d = Deltagere %d
Deltagare (kvarvarande) = Deltagere (tilbage)
Deltagare = Deltagere
Deltagaren 'X' deltar i patrullklassen 'Y' men saknar patrull. Klassens start- och resultatlistor kan därmed bli felaktiga = Deltageren 'X' deltager i patruljeklassen 'Y' men savner patrulje. Klassens start- och resultatlister kan derfor blive fejlbehæftede
Deltagaren 'X' deltar i stafettklassen 'Y' men saknar lag. Klassens start- och resultatlistor kan därmed bli felaktiga = Deltageren 'X' deltar i stafettklasse 'Y' men saknar hold. Klassens start- och resultatlister kan derfor blive fejlbehæftede
Deltagaren 'X' saknar klass = Deltagar 'X' savner klasse
Deltagarens klass styrs av laget = Deltagerens klasse styres af holdet
Deltar ej = Deltager ikke
Denna etapps nummer = Denne etappes nummer
Description = Beskrivelse
Destination: X = Destination: X
Destinationskatalog = Mappe at gemme i
Det finns anmälningsdata för flera etapper = Det findes timeldinddata for flere etapper
@ -477,6 +478,7 @@ Endast grundläggande = Grundfunktioner
Endast på obligatoriska sträckor = Håndter kun obligatoriske stræk.
Enhetens ID-nummer (MAC) = Enhedens ID (MAC)
Enhetstyp = Enhedstype
EntryTime = Tilmeldingstidspunkt
Error in result module X, method Y (Z) = Fejl i resultatmodul 'X', metode 'Y'\n\nZ
error:invalidmethod = Den valgte metode gav ikke nogen fordeling. Kildedata utilstrækkelige.
Etapp = Etape
@ -500,6 +502,7 @@ Exportera alla till HTML = Eksporter alle til HTML
Exportera alla till PDF = Exporter alt til PDF
Exportera datafil = Eksporter datafil
Exportera elektroniska fakturor = Eksporter elektroniske fakturaer
Exportera ett kalkylblad med lottningsinställningar som du kan redigera och sedan läsa in igen = Exporter et regneark med lodtrækningsindstillinger som du kan redigere og derefter læse ind igen
Exportera individuella lopp istället för lag = Eksporter individuelle løb istedet for hold
Exportera inställningar och löpardatabaser = Eksporter opsætning og løberdatabaser
Exportera klubbar (IOF-XML) = Eksporter klubber (IOF-XML)
@ -601,6 +604,7 @@ Filnamnet får inte vara tomt = Filnavnet må ikke være tomt
Filnamnsprefix = Prefix for filnavn
Filter = Filter
FilterHasCard = Med brik
FilterNoCancel = Ej afbud
FilterNoCard = Uden brik
FilterNotVacant = Ikke vakant
FilterOnlyVacant = Kun vakant
@ -752,6 +756,7 @@ help:dbage = Løberdatabasen er ældre end 2 måneder. Vil du hente en opdateret
help:DirectResult = - Hvis der ikke er nogen bane sættes status til OK ved målstempling.\n\n- Hvis der er en bane med radioposter over det hele er det ikke nødvendigt at aflæse brikken.
help:duplicate = Lav en lokal kopi af det aktuelle løb.
help:eventorkey = Indtast klubbens API-nøgle for Eventor, den er nødvendig for at kunne tilslutte til Eventor og hente tilmeldinger og løberregister. Nøglen får du af klubbens Eventor-administrator.
help:exportdraw = Du kan exportere et regneark i CSV-format der for hver klasse indeholder, antal tilmeldte og lodtrækningerne. Du kan herefter redigera lodtrækningerne og importere det tillbage til MeOS til lodtrækning.
help:fullscreen = Du kan justere hastigheden med Ctrl+M (hurtigere) respektive Ctrl+N (langsommere) på tastaturet. For at forlade fuldskærm, tryk på Esc.
help:import_entry_data = Du kan importere løbere, klasser, klubber og tilmeldinger i et antal forskellige tekst- og XML-formater. Det er ikke nødvendigt at angive samtlige filer. F.eks. indeholder OE-CSV format for tilmeldinger såvel klasser som klubber. I det tilfælde behøver felterne for klasser og klubber ikke at indlæses separat\n\nHvis information om samme løber importeres flere gange, bliver løberens information opdateret de efterfølgende gange. Der dannes ikke flere kopier af løberen i databasen. Det gør at man kan importere eftertilmeldinger ved at importere en opdateret fil med samtlige tilmeldinger.
help:importcourse = Du kan importere baner og klasser fra (eksempelvis) OCAD's eller Condes i IOF XML format.
@ -816,6 +821,7 @@ Importerar anmälningar (IOF, xml) = Importerer tilmeldinger (IOF, XML)
Importerar banor (IOF, xml) = Importerer baner (IOF, XML)
Importerar klasser (IOF, xml) = Importerer klasser (IOF, XML)
Importerar klubbar (IOF, xml) = Importerer klubber (IOF, XML)
Importerar lottningsinställningar = Importerar lodtrækningsindstilninger
Importerar OCAD csv-fil = Importerer OCAD csv-fil
Importerar OE2003 csv-fil = Importerer OE2003 csv-fil
Importerar OS2003 csv-fil = Importerer OS2003 csv-fil
@ -860,8 +866,9 @@ Ingen klass = Ingen klasse
Ingen klass vald = Ingen klasse valgt
Ingen löpare saknar bricka = Ingen løbere mangler SI-brik
Ingen matchar 'X' = Ingen matcher 'X'
Ingen nummerlapp = Intet brystnummer
Ingen parstart = Individuel start
Ingen rogaining = Ingen pointløb
Ingen rogaining = Intet pointløb
Inget filter = Intet filter
Inget nummer = Intet nummer
Inkludera information om flera lopp per löpare = Inkluder information om flere løb for den enkelte løber
@ -914,6 +921,7 @@ Källa = Kilde(fra)
Källkatalog = Mappe at hente fra
Kön = Køn
Kör kontroll inför tävlingen = Foretag kontrol før løbet
Kalkylblad/csv = Regneark/csv
kartor = kort
klar = færdig
Klart = Færdig
@ -1322,12 +1330,14 @@ Para ihop = Dan par
Para ihop bricka X med en deltagare = Par brik X med en deltager
Parallell = Parallel
Parvis (två och två) = Parvis (to og to)
Patrol Team Rogaining = Rogaining (Hold/Patrulje)
PatrolClubNameNames = Deltagers (eller patruljes) klub(ber)
PatrolNameNames = Deltagers (eller patruljes) navn(e)
Patrols = Patruljer
Patrull = Patrulje
Patrull, 1 SI-pinne = Patrulje, 1 SI-brik
Patrull, 2 SI-pinnar = Patrulje, 2 SI-brikker
Patrullresultat (STOR) = Patruljeresultat (STOR)
PDF = PDF
Personer = Personer
Plac = Plac
@ -1370,7 +1380,8 @@ prefsCurrencySymbol = Valutasymbol
prefsDatabase = Brug løberdatabase
prefsDatabaseUpdate = Seneste opdatering af løberdatabase
prefsDefaultDrawMethod = Foretrukken lodtrækningsmetode
prefsDirectPort = Netværksport for forhåndsinformation om stemplingar
prefsDirectPort = Netværksport for forhåndsinformation om stemplinger
prefsDrawInterlace = Klip klasser/baner ved vid lodtrækning
prefsEliteFee = Standard elite startgebyr
prefsEMail = Arrangør email
prefsEntryFee = Standard startgebyr
@ -1399,6 +1410,7 @@ prefsPort = MySQL netværksport
prefsRentCard = Lej af Si brikker
prefsSeniorAge = Aldergrænse for pensionistgebyr
prefsServer = Forvalgt netværks server
prefsServicePort = Forudvalgt serviceport
prefsSpeakerShortNames = Brug initialer i navn
prefssplitanalysis = Foretag stræktidsanalyse
prefsSplitLateFees = Opdel beløb for for sen tilmelding i normal- og tillægsdel ved IOF XML eksport
@ -1526,6 +1538,8 @@ reused card = genbrugt brik
Rogaining-poäng = Points
Rogaining = Pointløb
Rogaining points for each team member = Pointløbs points for hvert holdmedlem
Rogaining results for a patrol = Pointløbsresultater for en patrulje med to eller flere deltagare.
Rogaining results for a team, where each team member collects points individually = Pointløbsresultater for et hold hvor hver deltager individuelt samler point
Rogaining, individuell = Pointløb, individuelt
RogainingPunch = Stempling, pointløb
Rogainingresultat - %s = Rogaining resultater - %s
@ -1566,6 +1580,8 @@ RunnerClassCourseTimeAfter = Tid efter på bane indenfor klasse
RunnerClub = Løbers klub
RunnerCompleteName = Fulde navn
RunnerCourse = Løbers bane
RunnerEntryDate = Dato for tilmelding
RunnerEntryTime = Tidspunkt for tilmelding
RunnerFamilyName = Efternavn
RunnerFee = Startafgift
RunnerFinish = Løbers måltid
@ -1579,6 +1595,8 @@ RunnerLegNumber = Løbere grupperet efter stræk
RunnerLegNumberAlpha = Formateret turnummer
RunnerName = Løbers navn
RunnerNationality = Løbers nationalitet
RunnerPaid = Betalt beløb
RunnerPayMethod = Betalningsmåde
RunnerPhone = Løbers telefonnummer
RunnerPlace = Løbers placering
RunnerPlaceDiff = Løbers placering, forskel
@ -1776,6 +1794,7 @@ Stämplingar = Stemplinger
Stämplingar saknas: X = Stemplinger mangler: X
Stämplingsautomat = Kontrolenhed
Stämplingsintervall (MM:SS) = Stemplingsinterval (MM:SS)
Stämplingsintervall, rogaining-patrull = Stemplingsintervall for pointløbspatrulje
Stämplingstest [!] = Stemplingstest [!]
Stämplingstest = Stemplingstest
Stämplingstid = Stemplingstid
@ -1822,6 +1841,7 @@ Startlista %%s - sträcka %d = Startliste %%s - tur %d
Startlista = Startliste
Startlista ett visst lopp = Startliste for et bestemt løb
Startlista lopp X - Y = Startliste løb X - Y
Startlista, banvis = Startliste, per bane
Startlista, individuell = Startliste, individuel
Startlista, patrull = Startliste, patruljer
Startlista, stafett (lag) = Startliste, stafet (hold)
@ -2262,7 +2282,7 @@ warn:olddbversion = Databasen bruges af en nyere version af MeOS. Opgradering an
warn:opennewversion = Dette løb er dannet i MeOS X. Du risikerer at tabe data hvis du fortsætter.\n\nVil du fortsætte?
warn:updatelegs = Det kan være nødvendigt at opdatere længden af de enkelte baner.
warning:dbproblem = ADVARSEL. Problemer med databaseforbindelsen: 'X'. Forbindelsen genoprettes automatisk. Fortsæt med at arbejde normalt.
warning:direct_result = OBS. bruf af <Resultat ved målstempling> kræver at alle poster er radioposter eller at MeOS kun bruges til tidtagning uden baner.\n\nSkal resultat ved målstempling aktiveres?
warning:direct_result = OBS. brug af <Resultat ved målstempling> kræver at alle poster er radioposter eller at MeOS kun bruges til tidtagning uden baner.\n\nSkal resultat ved målstempling aktiveres?
warning:drawresult = Klassen har allerede resultater, starttider overskrives. Vil du fortsætte?
warning:has_entries = Klassen har allerede løbere. Hvis du ændrer turfordelingen kan du miste data.\n\nVil du fortsætte?
warning:has_results = Klassen har allerede resultater. Ændring af turfordelingen er usædvanligt.\n\nVil du fortsætte?

View File

@ -12,7 +12,7 @@ ALLA( = All(
API-nyckel = API key
Accepterade elektroniska fakturor = Accepted electronic invoices
Adress = Address
Adress och kontakt = Address and contact
Adress och kontakt = Address and Contact
Aktivera = Activate
Alla = All
Alla banfiler = All course files
@ -127,7 +127,7 @@ Behandlar: X = Processing: X
Bekräfta att %s byter klass till %s = Please confirm that %s changes class to %s
Bekräfta att deltagaren har lämnat återbud = Please confirm drop out of this runner
Betalat = Paid
Betalningsinformation = Payment details
Betalningsinformation = Payment Details
Bevakar händelser i X = Monitoring events in X
Bevakningsprioritering = Select runner to watch
Block = Block
@ -1115,7 +1115,7 @@ Tävlingsinställningar = Competition Settings
Tävlingsinställningar (IOF, xml) = Competition settings (IOF, xml)
Tävlingsnamn = Competition name
Tävlingsrapport = Competition Report
Tävlingsregler = Competition rules
Tävlingsregler = Competition Rules
Tävlingsstatistik = Competition Statistics
Underlag för tävlingsavgift = Data for competition fee
Underlista = Sub list
@ -1422,7 +1422,7 @@ xml-data = xml data
Åldersfilter = Age filter
Åldersgräns ungdom = Age limit, low
Åldersgräns äldre = Age limit, high
Åldersgränser, reducerad anmälningsavgift = Age limits, fee reduction
Åldersgränser, reducerad anmälningsavgift = Age Limits, Fee Reduction
Ångra = Undo
Återansluten mot databasen, tävlingen synkroniserad = Reconnected to database, competition synchronized
Återbud = Drop Out
@ -2249,9 +2249,9 @@ Det finns anmälningsdata för flera etapper = There is entry data for several s
Välj etapp att importera = Select stage to import
ask:savespeaker = Do you wish to save current class and window settings on this computer?
Spara fönster- och speakerinställningar på datorn = Save windows and settings on this computer
ask:loadspeaker = Do you wish to re-create previously saved windows on this computer?
Återskapa = Re-create
Återskapa tidigare sparade fönster- och speakerinställningar = Re-create previously saved windows and settings
ask:loadspeaker = Do you wish to recreate previously saved windows on this computer?
Återskapa = Recreate
Återskapa tidigare sparade fönster- och speakerinställningar = Recreate previously saved windows and settings
Inkludera resultat från tidigare etapper = Include results from all stages
Animation = Animation
Bakgrund = Background
@ -2292,7 +2292,7 @@ Informationsserver = Information server
Längsta svarstid: X ms = Longest response time: X ms
MeOS Informationsserver REST-API = MeOS Information Server REST-API
Testa servern = Test the server
help:rest = MeOS REST API lets you access competition data via a webb connection. You can show result lists directly in a webb browser, but you can also request competition data and results in a XML format, suitble for further processing in third party programs and apps.
help:rest = MeOS REST API lets you access competition data via a web connection. You can show result lists directly in a web browser, but you can also request competition data and results in an XML format, suitable for further processing in third party programs and apps.
Server startad på X = Server running on port X
Inconsistent qualification rule, X = Inconsistent qualification rule, X
help:LockStartList = MeOS will not update assignement to a locked class even if qualification results are altered.
@ -2301,7 +2301,7 @@ Lås startlista = Lock start list
FilterNoCancel = Not cancelled
CourseStartTime = Course, start time
Startlista, banvis = Start list, by course
Stämplingsintervall, rogaining-patrull = Punch interval within Rogaining patrol
Stämplingsintervall, rogaining-patrull = Punch interval within rogaining patrol
Patrullresultat (STOR) = Patrol results (LARGE)
Patrol Team Rogaining = Patrol Team Rogaining
Rogaining results for a patrol = Rogaining results for a patrol of two or more competitors.
@ -2313,3 +2313,5 @@ prefsDrawInterlace = Interlace class/course when drawing start lists
prefsServicePort = Default service port
Ingen nummerlapp = No bib
Rogaining results for a team, where each team member collects points individually = Rogaining results for a team, where each team member collects points individually
prefsCodePage = Code table for 8 bit text on import/export.
Inga klasser tillåter direktanmälan. På sidan klasser kan du ändra denna egenskap. = No class is marked to allow quick entry.\n\nOn the page Classes you can change this property.

View File

@ -78,6 +78,7 @@ extern Image image;
static int debugDrawColor = 0;
#endif
extern int defaultCodePage;
GuiHandler &BaseInfo::getHandler() const {
if (handler == 0)
@ -106,9 +107,8 @@ bool gdioutput::skipTextRender(int format) {
#ifndef MEOSDB
gdioutput::gdioutput(const string &_tag, double _scale, int defaultCodePage) :
recorder((Recorder *)0, false),
defaultCodePage(defaultCodePage) {
gdioutput::gdioutput(const string &_tag, double _scale) :
recorder((Recorder *)0, false) {
tag = _tag;
po_default = new PrinterObject();
tabs = 0;
@ -118,8 +118,8 @@ gdioutput::gdioutput(const string &_tag, double _scale, int defaultCodePage) :
isTestMode = false;
}
gdioutput::gdioutput(double _scale, HWND hWnd, const PrinterObject &prndef, int defaultCodePage) :
recorder((Recorder *)0, false), defaultCodePage(defaultCodePage) {
gdioutput::gdioutput(double _scale, HWND hWnd, const PrinterObject &prndef) :
recorder((Recorder *)0, false) {
hasAnyTimer = false;
po_default = new PrinterObject(prndef);
tabs = 0;
@ -6378,9 +6378,9 @@ const wstring &gdioutput::widen(const string &input) {
return output;
}
const wstring &gdioutput::recodeToWide(const string &input) const {
const wstring &gdioutput::recodeToWide(const string &input) {
wstring &output = StringCache::getInstance().wget();
int cp = 1252;
int cp = defaultCodePage;
// if (defaultCodePage > 0)
// cp = defaultCodePage;
@ -6406,9 +6406,9 @@ const wstring &gdioutput::recodeToWide(const string &input) const {
return output;
}
const string &gdioutput::recodeToNarrow(const wstring &input) const {
const string &gdioutput::recodeToNarrow(const wstring &input) {
string &output = StringCache::getInstance().get();
int cp = 1252;
int cp = defaultCodePage;
// if (defaultCodePage > 0)
// cp = defaultCodePage;
@ -6428,10 +6428,12 @@ const string &gdioutput::recodeToNarrow(const wstring &input) const {
output = "";
return output;
}
output.reserve(input.size()+1);
int res = input.size() * 3 + 2;
output.reserve(res);
output.resize(input.size(), 0);
BOOL usedDef = false;
WideCharToMultiByte(cp, MB_PRECOMPOSED, input.c_str(), input.size(), &output[0], output.size(), "?", &usedDef);
int ok = WideCharToMultiByte(cp, 0, input.c_str(), input.size(), &output[0], res, "?", &usedDef);
return output;
}
/*

View File

@ -283,7 +283,6 @@ protected:
shared_ptr<AnimationData> animationData;
shared_ptr<AutoCompleteInfo> autoCompleteInfo;
int defaultCodePage;
public:
AutoCompleteInfo &addAutoComplete(const string &key);
@ -324,8 +323,8 @@ public:
bool isTest() const {return isTestMode;}
const string &getTag() const {return tag;}
bool hasTag(const string &t) const {return tag == t;}
const wstring &recodeToWide(const string &input) const;
const string &recodeToNarrow(const wstring &input) const;
static const wstring &recodeToWide(const string &input);
static const string &recodeToNarrow(const wstring &input);
static const wstring &widen(const string &input);
static const string &narrow(const wstring &input);
@ -752,13 +751,12 @@ public:
void closeWindow();
void setDBErrorState(bool state);
int getCP() const {return defaultCodePage;}
friend int TablesCB(gdioutput *gdi, int type, void *data);
friend class Table;
friend gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x, int max_y);
gdioutput(const string &tag, double _scale, int defaultCodePage);
gdioutput(double _scale, HWND hWndTarget, const PrinterObject &defprn, int defaultCodePage);
gdioutput(const string &tag, double _scale);
gdioutput(double _scale, HWND hWndTarget, const PrinterObject &defprn);
virtual ~gdioutput();
};

View File

@ -408,13 +408,18 @@ void InfoCompetition::serialize(xmlbuffer &xml, bool diffOnly) const {
void InfoBaseCompetitor::serialize(xmlbuffer &xml, bool diffOnly, int course) const {
vector< pair<string, wstring> > prop;
prop.push_back(make_pair("org", itow(organizationId)));
prop.push_back(make_pair("cls", itow(classId)));
prop.push_back(make_pair("stat", itow(status)));
prop.push_back(make_pair("st", itow(startTime)));
prop.push_back(make_pair("rt", itow(runningTime)));
prop.reserve(10);
prop.emplace_back("org", itow(organizationId));
prop.emplace_back("cls", itow(classId));
prop.emplace_back("stat", itow(status));
prop.emplace_back("st", itow(startTime));
prop.emplace_back("rt", itow(runningTime));
if (course != 0)
prop.push_back(make_pair("crs", itow(course)));
prop.emplace_back("crs", itow(course));
if (!bib.empty()) {
prop.emplace_back("bib", bib);
}
xml.write("base", prop, name);
}
@ -459,6 +464,13 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
runningTime = rt;
ch = true;
}
wstring newBib = bc.getBib();
if (bib != newBib) {
bib = newBib;
ch = true;
}
return ch;
}

View File

@ -156,6 +156,7 @@ class InfoBaseCompetitor : public InfoBase {
int status;
int startTime;
int runningTime;
wstring bib;
void serialize(xmlbuffer &xml, bool diffOnly, int course) const;
bool synchronizeBase(oAbstractRunner &bc);
public:

View File

@ -67,6 +67,7 @@
#include "autocomplete.h"
#include "image.h"
int defaultCodePage = 1252;
Image image;
gdioutput *gdi_main=0;
@ -207,9 +208,13 @@ int APIENTRY WinMain(HINSTANCE hInstance,
enableTests = true;
}
HWND hSplash = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_SPLASH), nullptr, splashDialogProc);
ShowWindow(hSplash, SW_SHOW);
UpdateWindow(hSplash);
HWND hSplash = nullptr;
if (strstr(lpCmdLine, "-nosplash") == 0) {
hSplash = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_SPLASH), nullptr, splashDialogProc);
ShowWindow(hSplash, SW_SHOW);
UpdateWindow(hSplash);
}
DWORD splashStart = GetTickCount();
for (int k = 0; k < 100; k++) {
@ -253,7 +258,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
HACCEL hAccelTable;
gdi_main = new gdioutput("main", 1.0, 0);
gdi_main = new gdioutput("main", 1.0);
gdi_extra.push_back(gdi_main);
try {
@ -297,6 +302,8 @@ int APIENTRY WinMain(HINSTANCE hInstance,
wstring defLang = gEvent->getPropertyString("Language", L"Svenska");
defaultCodePage = gEvent->getPropertyInt("CodePage", 1252);
// Backward compatibility
if (defLang==L"103")
defLang = L"Svenska";
@ -399,8 +406,10 @@ int APIENTRY WinMain(HINSTANCE hInstance,
gdi_main->setFont(gEvent->getPropertyInt("TextSize", 0),
gEvent->getPropertyString("TextFont", L"Arial"));
DWORD startupToc = GetTickCount() - splashStart;
Sleep(min<int>(1000, max<int>(0,700 - startupToc)));
if (hSplash != nullptr) {
DWORD startupToc = GetTickCount() - splashStart;
Sleep(min<int>(1000, max<int>(0, 700 - startupToc)));
}
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow)) {
@ -424,8 +433,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
(HINSTANCE) NULL, GetCurrentThreadId());
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MEOS);
DestroyWindow(hSplash);
initMySQLCriticalSection(true);
@ -852,7 +860,7 @@ gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x,
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
gdioutput *gdi = new gdioutput(tag, 1.0, 0);
gdioutput *gdi = new gdioutput(tag, 1.0);
gdi->setFont(gEvent->getPropertyInt("TextSize", 0),
gEvent->getPropertyString("TextFont", L"Arial"));
@ -1160,7 +1168,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
//The card has been read and posted to a synchronized
//queue by different thread. Read and process this card.
{
SICard sic;
SICard sic(ConvertedTimeStatus::Unknown);
while (gSI && gSI->getCard(sic))
InsertSICard(*gdi_main, sic);
break;

View File

@ -38,7 +38,7 @@ namespace MeOSUtil {
string convertSystemTimeN(const SYSTEMTIME &st);
string convertSystemDateN(const SYSTEMTIME &st);
string convertSystemTimeOnlyN(const SYSTEMTIME &st);
extern int defaultCodePage;
DWORD mainThreadId = -1;
StringCache &StringCache::getInstance() {
@ -180,7 +180,7 @@ SYSTEMTIME Int64SecondToSystemTime(__int64 time) {
//2014-11-03 07:02:00
string convertSystemTimeN(const SYSTEMTIME &st)
{
char bf[32];
char bf[64];
sprintf_s(bf, "%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond);
@ -190,7 +190,7 @@ string convertSystemTimeN(const SYSTEMTIME &st)
//2014-11-03 07:02:00
wstring convertSystemTime(const SYSTEMTIME &st)
{
wchar_t bf[32];
wchar_t bf[64];
swprintf_s(bf, L"%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond);
@ -2167,7 +2167,7 @@ void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &
}
void string2Wide(const string &in, wstring &out) {
int cp = 1252;
int cp = defaultCodePage;
if (in.empty()) {
out = L"";
return;

View File

@ -29,7 +29,7 @@
//V33: abcde
//V35: abcde
int getMeosBuild() {
string revision("$Rev: 652 $");
string revision("$Rev: 669 $");
return 174 + atoi(revision.substr(5, string::npos).c_str());
}
@ -39,14 +39,14 @@ int getMeosBuild() {
//V31: abcde
//V32: abcdefgh
//V33: abcdefghij
//V34: abcdfg
//V34: abcdfge
wstring getMeosDate() {
wstring date(L"$Date: 2018-03-04 09:44:43 +0100 (sö, 04 mar 2018) $");
wstring date(L"$Date: 2018-03-25 07:29:55 +0200 (sö, 25 mar 2018) $");
return date.substr(7,10);
}
wstring getBuildType() {
return L"RC1"; // No parantheses (...)
return L"RC2"; // No parantheses (...)
}
wstring getMajorVersion() {
@ -185,4 +185,7 @@ void getSupporters(vector<wstring> &supp)
supp.push_back(L"O-Ringen AB");
supp.push_back(L"Hans Carlstedt, Sävedalens AIK");
supp.push_back(L"Attunda OK");
supp.push_back(L"Siguldas Takas, Latvia");
supp.push_back(L"Eric Teutsch, Ottawa Orienteering Club, Canada");
supp.push_back(L"Silkeborg OK, Denmark");
}

View File

@ -463,6 +463,7 @@ bool oCard::isCardRead(const SICard &card) const
void oCard::getSICard(SICard &card) const {
card.clear(0);
card.CardNumber = cardNo;
card.convertedTime = ConvertedTimeStatus::Done;
oPunchList::const_iterator it;
for (it = punches.begin(); it != punches.end(); ++it) {
if (it->Type>30)

View File

@ -1688,7 +1688,7 @@ void oClass::updateChangedCoursePool() {
}
}
SICard card;
SICard card(ConvertedTimeStatus::Unknown);
oRunnerList::iterator it;
for (it = oe->Runners.begin(); it != oe->Runners.end(); ++it) {
if (it->isRemoved() || it->Class != this)
@ -4284,6 +4284,17 @@ void oClass::loadQualificationFinalScheme(const wstring &fileName) {
inst->synchronize();
}
synchronize();
for (oRunner &r : oe->Runners) {
if (r.getClassRef(false) == this) {
pTeam t = r.getTeam();
if (t == 0) {
t = oe->addTeam(r.getName(), r.getClubId(), getId());
t->setStartNo(r.getStartNo(), false);
t->setRunner(0, &r, true);
}
r.synchronizeAll();
}
}
}
void oClass::updateFinalClasses(oRunner *causingResult, bool updateStartNumbers) {

View File

@ -579,6 +579,7 @@ void oEvent::listProperties(bool userProps, vector< pair<string, PropertyType> >
i.insert("addressxpos");
i.insert("AutoSaveTimeOut");
i.insert("ServicePort");
i.insert("CodePage");
propNames.clear();
for(map<string, wstring>::const_iterator it = eventProperties.begin();
@ -924,7 +925,7 @@ bool oEvent::save(const wstring &fileIn) {
xml.startTag("meosdata", "version", getMajorVersion());
xml.write("Name", Name);
xml.write("Date", Date);
xml.write("ZeroTime", ZeroTime);
xml.write("ZeroTime", itos(ZeroTime));
xml.write("NameId", currentNameId);
xml.write("Annotation", Annotation);
xml.write("Id", Id);
@ -1119,6 +1120,7 @@ void oEvent::restoreBackup()
bool oEvent::open(const xmlparser &xml) {
xmlobject xo;
ZeroTime = 0;
xo = xml.getObject("Date");
if (xo) Date=xo.getw();
@ -2434,37 +2436,6 @@ int oEvent::getRelativeTime(const wstring &m) const {
else return -1;
}
int oEvent::getRelativeTimeFrom12Hour(const wstring &m) const
{
int atime=convertAbsoluteTime(m);
if (atime>=0 && atime<3600*24) {
int lowBound = ZeroTime;
int highBound = ZeroTime + 3600 * 12;
bool ok = ( atime >= lowBound && atime <= highBound) ||
( (atime+3600*24) >= lowBound && (atime+3600*24) <= highBound);
int rtime = atime - ZeroTime;
if (!ok)
rtime += 12 * 3600;
rtime = (rtime+24*3600)%(24*3600);
//int rtime=atime-(ZeroTime % (3600*12));
/* if (rtime<=0)
rtime+=3600*12;
*/
//Don't allow times just before zero time.
if (rtime>3600*22)
return -1;
return rtime;
}
else return -1;
}
void oEvent::removeRunner(const vector<int> &ids)
{
oRunnerList::iterator it;
@ -4036,12 +4007,47 @@ int oEvent::findBestClass(const SICard &card, vector<pClass> &classes) const
return Distance;
}
void oEvent::convertTimes(SICard &sic) const
void oEvent::convertTimes(pRunner runner, SICard &sic) const
{
if (sic.convertedTime)
assert(sic.convertedTime != ConvertedTimeStatus::Unknown);
if (sic.convertedTime == ConvertedTimeStatus::Done)
return;
sic.convertedTime = true;
if (sic.convertedTime == ConvertedTimeStatus::Hour12) {
int startTime = ZeroTime + 3600; //Add one hour. Subtracted below
if (useLongTimes())
startTime = 5 * 3600; // Avoid midnight as default. Prefer morning
int st = -1;
if (runner) {
st = runner->getStartTime();
if (st > 0) {
startTime = (ZeroTime + st) % (3600 * 24);
}
else {
st = -1;
}
}
if (st <= -1) {
// Fallback for no start time. Take from card. Will be wrong if more than 12 hour after ZeroTime
if (sic.StartPunch.Code != -1) {
st = sic.StartPunch.Time;
}
else if (sic.nPunch > 0 && sic.Punch[0].Time >= 0) {
st = sic.Punch[0].Time;
}
if (st >= 0) { // Optimize local zero time w.r.t first punch
int relT12 = (st - ZeroTime + 3600 * 24) % (3600 * 12);
startTime = (ZeroTime + relT12) % (3600 * 24);
}
}
int zt = (startTime + 23 * 3600) % (24 * 3600); // Subtract one hour
sic.analyseHour12Time(zt);
}
sic.convertedTime = ConvertedTimeStatus::Done;
if (sic.CheckPunch.Code!=-1){
if (sic.CheckPunch.Time<ZeroTime)
@ -4819,6 +4825,7 @@ void oEvent::analyzeClassResultStatus() const
void oEvent::generateTestCard(SICard &sic) const
{
sic.clear(0);
sic.convertedTime == ConvertedTimeStatus::Hour24;
if (Runners.empty())
return;

View File

@ -864,7 +864,7 @@ public:
/** Returns the first start in a class */
int getFirstStart(int classId = 0) const;
void convertTimes(SICard &sic) const;
void convertTimes(pRunner runner, SICard &sic) const;
pCard getCard(int Id) const;
pCard getCardByNumber(int cno) const;
@ -941,8 +941,8 @@ public:
/// Convert a clock time string to time relative zero time
int getRelativeTime(const string &date, const string &absoluteTime, const string &timeZone) const;
/// Convert a clock time string (SI5 12 Hour clock) to time relative zero time
int getRelativeTimeFrom12Hour(const wstring &absoluteTime) const;
// Convert a clock time string (SI5 12 Hour clock) to time relative zero time
//int getRelativeTimeFrom12Hour(const wstring &absoluteTime) const;
/// Convert c clock time string to absolute time (after 00:00:00)
static int convertAbsoluteTime(const string &m);

View File

@ -723,7 +723,7 @@ void oRunner::addPunches(pCard card, vector<int> &missingPunches) {
updateChanged();
if (card) {
if (CardNo==0)
if (card->cardNo > 0)
CardNo=card->cardNo;
//315422
assert(card->tOwner==0 || card->tOwner==this);
@ -739,7 +739,7 @@ void oRunner::addPunches(pCard card, vector<int> &missingPunches) {
int numCtrlLong = mainCourse->getNumControls();
int numCtrlShort = shortVersion->getNumControls();
SICard sic;
SICard sic(ConvertedTimeStatus::Unknown);
Card->getSICard(sic);
int level = 0;
while (mainCourse->distance(sic) < 0 && abs(numCtrl-numCtrlShort) < abs(numCtrl-numCtrlLong)) {

View File

@ -368,8 +368,7 @@ void OnlineInput::processPunches(oEvent &oe, list< vector<wstring> > &rocData) {
void OnlineInput::processCards(gdioutput &gdi, oEvent &oe, const xmlList &cards) {
for (size_t k = 0; k < cards.size(); k++) {
SICard sic;
sic.clear(0);
SICard sic(ConvertedTimeStatus::Hour24);
sic.CardNumber = cards[k].getObjectInt("number");
if (cards[k].getObject("finish"))
sic.FinishPunch.Time = cards[k].getObject("finish").getObjectInt("time") / 10;

View File

@ -254,7 +254,7 @@ void RestServer::computeInternal(oEvent &ref, shared_ptr<RestServer::EventReques
auto res = listCache.find(type);
if (res != listCache.end()) {
gdioutput gdiPrint("print", ref.gdiBase().getScale(), ref.gdiBase().getCP());
gdioutput gdiPrint("print", ref.gdiBase().getScale());
gdiPrint.clearPage(false);
if (!res->second.second) {

View File

@ -2298,7 +2298,7 @@ Lås startlista = Lås startlista
FilterNoCancel = Ej återbud
CourseStartTime = Bana, starttid
Startlista, banvis = Startlista, banvis
Stämplingsintervall, rogaining-patrull = Stämplingsintervall inom rogaining-patrull
Stämplingsintervall, rogaining-patrull = Stämplingsintervall inom rogainingpatrull
Patrol Team Rogaining = Rogaining (Lag/Patrull)
Rogaining results for a patrol = Rogainingresultat för en patrull med två eller fler deltagare.
Patrullresultat (STOR) = Patrullresultat (STOR)
@ -2315,3 +2315,5 @@ prefsDrawInterlace = Saxa klasser/banor vid lottning
prefsServicePort = Förvald serviceport
Ingen nummerlapp = Ingen nummerlapp
Rogaining results for a team, where each team member collects points individually = Rogainingresultat för ett lag där varje lagmedlem samlar poäng individuellt
prefsCodePage = Kodtabell för 8-bitars text vid import/export
Inga klasser tillåter direktanmälan. På sidan klasser kan du ändra denna egenskap. = Inga klasser tillåter direktanmälan.\n\nPå sidan klasser kan du ändra denna egenskap.

View File

@ -376,7 +376,7 @@ void TestMeOS::checkStringRes(const char *str, int count) const {
void TestMeOS::insertCard(int cardNo, const char *ser) const {
SICard sic;
SICard sic(ConvertedTimeStatus::Unknown);
sic.CardNumber = cardNo;
sic.deserializePunches(ser);
TabSI::getSI(*gdi_main).addCard(sic);