MeOS version 3.6.1086
This commit is contained in:
parent
55d526c3e4
commit
a4e2689418
@ -135,9 +135,9 @@ void SportIdent::setCRC(BYTE *bf)
|
||||
bf[len+3]=LOBYTE(crc);
|
||||
}
|
||||
|
||||
bool SportIdent::checkCRC(BYTE *bf)
|
||||
bool SportIdent::checkCRC(BYTE *bf, DWORD maxLen)
|
||||
{
|
||||
DWORD len=bf[1];
|
||||
DWORD len=min(DWORD(bf[1]), maxLen);
|
||||
WORD crc=calcCRC(bf, len+2);
|
||||
|
||||
return bf[len+2]==HIBYTE(crc) && bf[len+3]==LOBYTE(crc);
|
||||
@ -167,7 +167,7 @@ bool SportIdent::readSystemData(SI_StationInfo *si, int retry)
|
||||
if (buff[0] == 0xFF && buff[1] == STX)
|
||||
offset++;
|
||||
if (1){
|
||||
if (checkCRC(LPBYTE(buff+1 + offset))){
|
||||
if (checkCRC(LPBYTE(buff+1 + offset), 100)){
|
||||
si->data.resize(1);
|
||||
SI_StationData &da = si->data[0];
|
||||
da.stationNumber=511 & MAKEWORD(buff[4 + offset], buff[3 + offset]);
|
||||
@ -245,7 +245,7 @@ bool SportIdent::readSystemDataV2(SI_StationInfo &si)
|
||||
int SportIdent::analyzeStation(BYTE *db, SI_StationData &si) {
|
||||
DWORD size = 0;
|
||||
DWORD addr = 0x70;
|
||||
if (checkCRC(LPBYTE(db+1))) {
|
||||
if (checkCRC(LPBYTE(db+1), 256)) {
|
||||
size = DWORD(db[2]) + 6;
|
||||
|
||||
bool dongle = db[0x11] == 0x6f && db[0x12] == 0x21;
|
||||
@ -384,7 +384,11 @@ bool SportIdent::openCom(const wchar_t *com)
|
||||
}
|
||||
|
||||
si->data.clear();
|
||||
|
||||
|
||||
if (si->ComPort == L"TEST") {
|
||||
return true;
|
||||
}
|
||||
|
||||
wstring comfile=wstring(L"//./")+com;
|
||||
si->hComm = CreateFile( comfile.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
@ -510,6 +514,13 @@ bool SportIdent::openCom(const wchar_t *com)
|
||||
|
||||
SI_StationInfo *SportIdent::findStation(const wstring &com)
|
||||
{
|
||||
if (com == L"TEST" && n_SI_Info < 30) {
|
||||
if (n_SI_Info == 0 || SI_Info[n_SI_Info - 1].ComPort != com) {
|
||||
SI_Info[n_SI_Info].ComPort = com;
|
||||
n_SI_Info++;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<n_SI_Info; i++)
|
||||
if (com == SI_Info[i].ComPort)
|
||||
return &SI_Info[i];
|
||||
@ -583,7 +594,7 @@ int SportIdent::readByte(BYTE &byte, HANDLE hComm)
|
||||
#ifdef DEBUG_SI2
|
||||
char t[64];
|
||||
sprintf_s(t, 64, "read=%02X\n", (int)byte);
|
||||
OutputDebugString(t);
|
||||
debugLog(t);
|
||||
#endif
|
||||
if (dwRead)
|
||||
return 1;
|
||||
@ -636,12 +647,12 @@ int SportIdent::readBytes_delay(BYTE *byte, DWORD buffSize, DWORD len, HANDLE h
|
||||
#ifdef DEBUG_SI2
|
||||
char t[64];
|
||||
sprintf_s(t, 64, "retry=%d\n", d);
|
||||
OutputDebugString(t);
|
||||
debugLog(t);
|
||||
|
||||
for (int k = 0; k < read; k++) {
|
||||
char t[64];
|
||||
sprintf_s(t, 64, "mreadd=%02X\n", (int)byte[k]);
|
||||
OutputDebugString(t);
|
||||
debugLog(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -661,7 +672,7 @@ int SportIdent::readBytes(BYTE *byte, DWORD len, HANDLE hComm)
|
||||
for (int k = 0; k < dwRead; k++) {
|
||||
char t[64];
|
||||
sprintf_s(t, 64, "mread=%02X\n", (int)byte[k]);
|
||||
OutputDebugString(t);
|
||||
debugLog(t);
|
||||
}
|
||||
#endif
|
||||
return dwRead;
|
||||
@ -693,7 +704,7 @@ int SportIdent::readBytesDLE_delay(BYTE *byte, DWORD buffSize, DWORD len, HANDL
|
||||
#ifdef DEBUG_SI2
|
||||
char t[64];
|
||||
sprintf_s(t, 64, "retry=%d\n", d);
|
||||
OutputDebugString(t);
|
||||
debugLog(t);
|
||||
#endif
|
||||
|
||||
return read;
|
||||
@ -909,6 +920,45 @@ int SportIdent::MonitorTCPSI(WORD port, int localZeroTime)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool SportIdent::MonitorTEST(SI_StationInfo &si)
|
||||
{
|
||||
int longSleepIter = 0;
|
||||
|
||||
while (true) {
|
||||
if (testCards.empty())
|
||||
return true;
|
||||
TestCard tc = *testCards.begin();
|
||||
testCards.erase(testCards.begin());
|
||||
|
||||
|
||||
SICard card(ConvertedTimeStatus::Hour12);
|
||||
card.StartPunch.Code = 1;
|
||||
int t = card.StartPunch.Time = 3600*8 + rand()%1000;
|
||||
|
||||
card.FinishPunch.Code = 2;
|
||||
card.FinishPunch.Time = card.StartPunch.Time + 1800 + rand() % 3600;
|
||||
card.CardNumber = tc.cardNo;
|
||||
|
||||
for (size_t k = 0; k < tc.punches.size(); k++) {
|
||||
card.Punch[k].Code = tc.punches[k];
|
||||
int w = max<int>(1, tc.punches.size() - k - rand()%3);
|
||||
t = card.Punch[k].Time = (card.FinishPunch.Time + t*w)/(w+1);
|
||||
card.nPunch++;
|
||||
}
|
||||
addCard(card);
|
||||
|
||||
//Sleep(300 + rand()%600);
|
||||
Sleep(0);
|
||||
if (++longSleepIter > 20) {
|
||||
Sleep(100 + rand() % 600);
|
||||
longSleepIter = 0;
|
||||
OutputDebugString(L"Long sleep\n");
|
||||
}
|
||||
}
|
||||
|
||||
OutputDebugString(L"--- Test Finished \n");
|
||||
}
|
||||
|
||||
bool SportIdent::MonitorSI(SI_StationInfo &si)
|
||||
{
|
||||
HANDLE hComm=si.hComm;
|
||||
@ -942,7 +992,7 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
||||
BYTE bf[32];
|
||||
bf[0]=chRead;
|
||||
readBytes(bf+1, 17, hComm);
|
||||
if (checkCRC(LPBYTE(bf)))
|
||||
if (checkCRC(LPBYTE(bf), 32))
|
||||
{
|
||||
WORD Station=MAKEWORD(bf[3], bf[2]);
|
||||
|
||||
@ -1014,7 +1064,7 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
||||
readBytes(bf+1, 10, hComm);
|
||||
|
||||
//ReadByte(chRead); //ETX!
|
||||
if (checkCRC(LPBYTE(bf)))
|
||||
if (checkCRC(LPBYTE(bf), 32))
|
||||
getSI6DataExt(hComm);
|
||||
|
||||
break;
|
||||
@ -1024,7 +1074,7 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
||||
bf[0]=0xE5;
|
||||
readBytes(bf+1, 10, hComm);
|
||||
|
||||
if (checkCRC(LPBYTE(bf)))
|
||||
if (checkCRC(LPBYTE(bf), 32))
|
||||
getSI5DataExt(hComm);
|
||||
|
||||
break;
|
||||
@ -1067,7 +1117,7 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
||||
readBytes(bf+1, 10, hComm);
|
||||
|
||||
//ReadByte(chRead); //ETX!
|
||||
if (checkCRC(LPBYTE(bf)))
|
||||
if (checkCRC(LPBYTE(bf), 32))
|
||||
getSI9DataExt(hComm);
|
||||
|
||||
break;
|
||||
@ -1163,7 +1213,7 @@ void SportIdent::getSI5DataExt(HANDLE hComm)
|
||||
|
||||
if (bf[0]==STX && bf[1]==0xB1)
|
||||
{
|
||||
if (checkCRC(bf+1))
|
||||
if (checkCRC(bf+1, 254))
|
||||
{
|
||||
c[0]=ACK;
|
||||
WriteFile(hComm, c, 1, &written, NULL);
|
||||
@ -1186,7 +1236,7 @@ void SportIdent::getSI6DataExt(HANDLE hComm)
|
||||
BYTE c[16];
|
||||
// STX, 0xE1, 0x01, BN, CRC1,
|
||||
//CRC0, ETX
|
||||
OutputDebugString(L"STARTREAD EXT-");
|
||||
debugLog(L"STARTREAD EXT-");
|
||||
|
||||
int blocks[7]={0,6,7,2,3,4,5};
|
||||
DWORD written=0;
|
||||
@ -1211,13 +1261,13 @@ void SportIdent::getSI6DataExt(HANDLE hComm)
|
||||
int read=readBytes(bf, 128+9, hComm);
|
||||
|
||||
if (read==0) {
|
||||
OutputDebugString(L"TIMING");
|
||||
debugLog(L"TIMING");
|
||||
Sleep(300);
|
||||
read = readBytes(bf, 128+9, hComm);
|
||||
}
|
||||
|
||||
if (bf[0]==STX && bf[1]==0xE1) {
|
||||
if (checkCRC(bf+1)) {
|
||||
if (checkCRC(bf+1, 250)) {
|
||||
memcpy(b+k*128, bf+6, 128);
|
||||
|
||||
LPDWORD ptr = LPDWORD(bf + 6);
|
||||
@ -1225,12 +1275,12 @@ void SportIdent::getSI6DataExt(HANDLE hComm)
|
||||
break; //No need to read more
|
||||
}
|
||||
else {
|
||||
OutputDebugString(L"-FAIL-");
|
||||
debugLog(L"-FAIL-");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
OutputDebugString(L"-FAIL-");
|
||||
debugLog(L"-FAIL-");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1239,7 +1289,7 @@ void SportIdent::getSI6DataExt(HANDLE hComm)
|
||||
c[0]=ACK;
|
||||
WriteFile(hComm, c, 1, &written, NULL);
|
||||
|
||||
OutputDebugString(L"-ACK-");
|
||||
debugLog(L"-ACK-");
|
||||
|
||||
SICard card(ConvertedTimeStatus::Hour24);
|
||||
getCard6Data(b, card);
|
||||
@ -1253,7 +1303,7 @@ void SportIdent::getSI9DataExt(HANDLE hComm)
|
||||
BYTE c[16];
|
||||
// STX, 0xE1, 0x01, BN, CRC1,
|
||||
//CRC0, ETX
|
||||
OutputDebugString(L"STARTREAD9 EXT-");
|
||||
debugLog(L"STARTREAD9 EXT-");
|
||||
|
||||
int blocks_8_9_p_t[2]={0,1};
|
||||
int blocks_10_11_SIAC[5]={0,4,5,6,7};
|
||||
@ -1281,13 +1331,13 @@ void SportIdent::getSI9DataExt(HANDLE hComm)
|
||||
int read=readBytes(bf, 128+9, hComm);
|
||||
|
||||
if (read==0) {
|
||||
OutputDebugString(L"TIMING");
|
||||
debugLog(L"TIMING");
|
||||
Sleep(300);
|
||||
read = readBytes(bf, 128+9, hComm);
|
||||
}
|
||||
|
||||
if (bf[0]==STX && bf[1]==0xEf) {
|
||||
if (checkCRC(bf+1)) {
|
||||
if (checkCRC(bf+1, 200)) {
|
||||
memcpy(b+k*128, bf+6, 128);
|
||||
|
||||
if (k == 0) {
|
||||
@ -1304,12 +1354,12 @@ void SportIdent::getSI9DataExt(HANDLE hComm)
|
||||
|
||||
}
|
||||
else {
|
||||
OutputDebugString(L"-FAIL-");
|
||||
debugLog(L"-FAIL-");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
OutputDebugString(L"-FAIL-");
|
||||
debugLog(L"-FAIL-");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1318,7 +1368,7 @@ void SportIdent::getSI9DataExt(HANDLE hComm)
|
||||
c[0]=ACK;
|
||||
WriteFile(hComm, c, 1, &written, NULL);
|
||||
|
||||
OutputDebugString(L"-ACK-");
|
||||
debugLog(L"-ACK-");
|
||||
|
||||
SICard card(ConvertedTimeStatus::Hour24);
|
||||
if (getCard9Data(b, card))
|
||||
@ -1333,7 +1383,7 @@ bool SportIdent::readSI6Block(HANDLE hComm, BYTE *data)
|
||||
int read=readBytesDLE(bf, 4, hComm);
|
||||
|
||||
if (read==0){
|
||||
OutputDebugString(L"TIMING");
|
||||
debugLog(L"TIMING");
|
||||
Sleep(1000);
|
||||
read=readBytesDLE(bf, 4, hComm);
|
||||
}
|
||||
@ -1369,7 +1419,7 @@ void SportIdent::getSI6Data(HANDLE hComm)
|
||||
BYTE c[16];
|
||||
// STX, 0xE1, 0x01, BN, CRC1,
|
||||
//CRC0, ETX
|
||||
OutputDebugString(L"STARTREAD-");
|
||||
debugLog(L"STARTREAD-");
|
||||
|
||||
//int blocks[3]={0,6,7};
|
||||
DWORD written=0;
|
||||
@ -1390,7 +1440,7 @@ void SportIdent::getSI6Data(HANDLE hComm)
|
||||
|
||||
if (!readSI6Block(hComm, b+k*128)) {
|
||||
if (k<=2) {
|
||||
OutputDebugString(L"-FAIL-");
|
||||
debugLog(L"-FAIL-");
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -1418,7 +1468,7 @@ void SportIdent::getSI6Data(HANDLE hComm)
|
||||
c[0]=ACK;
|
||||
WriteFile(hComm, c, 1, &written, NULL);
|
||||
|
||||
OutputDebugString(L"-ACK-");
|
||||
debugLog(L"-ACK-");
|
||||
SICard card(ConvertedTimeStatus::Hour24);
|
||||
getCard6Data(b, card);
|
||||
|
||||
@ -1688,7 +1738,8 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
|
||||
}
|
||||
|
||||
string2Wide(lastNameByte, lastName);
|
||||
wcsncpy_s(card.lastName, lastName.c_str(), 20);
|
||||
wcsncpy(card.lastName, lastName.c_str(), 20);
|
||||
card.lastName[20] = 0;
|
||||
|
||||
memcpy(firstNameByte, data+32+20, 20);
|
||||
firstNameByte[20] = 0;
|
||||
@ -1698,7 +1749,8 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
|
||||
}
|
||||
|
||||
string2Wide(firstNameByte, firstName);
|
||||
wcsncpy_s(card.firstName, firstName.c_str(), 20);
|
||||
wcsncpy(card.firstName, firstName.c_str(), 20);
|
||||
card.firstName[20] = 0;
|
||||
|
||||
data+=128-16;
|
||||
|
||||
@ -1974,12 +2026,21 @@ void start_si_thread(void *ptr)
|
||||
si->Current_SI_Info=0;
|
||||
LeaveCriticalSection(&si->SyncObj);
|
||||
|
||||
if (si_info.ComPort==L"TCP") {
|
||||
si->MonitorTCPSI(si_info.tcpPort, si_info.localZeroTime);
|
||||
try {
|
||||
if (si_info.ComPort == L"TCP") {
|
||||
si->MonitorTCPSI(si_info.tcpPort, si_info.localZeroTime);
|
||||
}
|
||||
else if (si_info.ComPort == L"TEST") {
|
||||
si->MonitorTEST(si_info);
|
||||
}
|
||||
else {
|
||||
if (!si_info.hComm) MessageBox(NULL, L"ERROR", 0, MB_OK);
|
||||
si->MonitorSI(si_info);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!si_info.hComm) MessageBox(NULL, L"ERROR", 0, MB_OK);
|
||||
si->MonitorSI(si_info);
|
||||
catch (...) {
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1987,7 +2048,7 @@ void SportIdent::startMonitorThread(const wchar_t *com)
|
||||
{
|
||||
SI_StationInfo *si = findStation(com);
|
||||
|
||||
if (si && (si->hComm || si->ComPort==L"TCP"))
|
||||
if (si && (si->hComm || si->ComPort==L"TCP" || si->ComPort == L"TEST"))
|
||||
{
|
||||
if (si->ComPort==L"TCP")
|
||||
tcpPortOpen=0;
|
||||
@ -2366,3 +2427,11 @@ void SICard::deserializePunches(const string &arg) {
|
||||
if (out.size() == 1)
|
||||
punchOnly = true;
|
||||
}
|
||||
|
||||
void SportIdent::addTestCard(int cardNo, const vector<int> &punches) {
|
||||
testCards.emplace(cardNo, punches);
|
||||
}
|
||||
|
||||
void SportIdent::debugLog(const wchar_t *msg) {
|
||||
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include <set>
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2019 Melin Software HB
|
||||
@ -176,7 +178,7 @@ protected:
|
||||
SI_StationInfo *Current_SI_Info; //Current SI_Info in use (for thread startup);
|
||||
|
||||
WORD calcCRC(BYTE *data, DWORD length);
|
||||
bool checkCRC(BYTE *bf);
|
||||
bool checkCRC(BYTE *bf, DWORD maxLen);
|
||||
void setCRC(BYTE *bf);
|
||||
|
||||
bool getCard5Data(BYTE *data, SICard &card);
|
||||
@ -204,12 +206,31 @@ protected:
|
||||
volatile int tcpPortOpen;
|
||||
volatile unsigned int serverSocket;
|
||||
|
||||
bool MonitorTEST(SI_StationInfo &si);
|
||||
bool MonitorSI(SI_StationInfo &si);
|
||||
int MonitorTCPSI(WORD port, int localZeroTime);
|
||||
|
||||
struct TestCard {
|
||||
int cardNo;
|
||||
vector<int> punches;
|
||||
|
||||
bool operator<(const TestCard &c) const {
|
||||
return cardNo < c.cardNo;
|
||||
}
|
||||
|
||||
TestCard(int cardNo, const vector<int> &punches) : cardNo(cardNo),
|
||||
punches(punches) {
|
||||
}
|
||||
};
|
||||
|
||||
set<TestCard> testCards;
|
||||
|
||||
public:
|
||||
SI_StationInfo *findStation(const wstring &com);
|
||||
|
||||
/** Log debug data. */
|
||||
void debugLog(const wchar_t *ptr);
|
||||
|
||||
void getInfoString(const wstring &com, vector<wstring> &info);
|
||||
bool isPortOpen(const wstring &com);
|
||||
bool autoDetect(list<int> &ComPorts);
|
||||
@ -220,6 +241,7 @@ public:
|
||||
void addCard(const SICard &sic);
|
||||
void addPunch(DWORD Time, int Station, int Card, int Mode=0);
|
||||
|
||||
void addTestCard(int cardNo, const vector<int> &punches);
|
||||
|
||||
void EnumrateSerialPorts(list<int> &ports);
|
||||
|
||||
|
||||
@ -406,7 +406,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
||||
throw std::exception("Klassen finns ej.");
|
||||
|
||||
int total, finished, dns;
|
||||
oe->getNumClassRunners(pc->getId(), 0, total, finished, dns);
|
||||
pc->getNumResults(0, total, finished, dns);
|
||||
|
||||
oEvent::PredefinedTypes newType = oEvent::PredefinedTypes(gdi.getSelectedItem("Predefined").first);
|
||||
int nstages = gdi.getTextNo("NStage");
|
||||
@ -1865,14 +1865,14 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.addString("", boldLarge, L"Dela klass: X#" + pc->getName());
|
||||
gdi.dropLine();
|
||||
int tot, fin, dns;
|
||||
oe->getNumClassRunners(pc->getId(), 0, tot, fin, dns);
|
||||
pc->getNumResults(0, tot, fin, dns);
|
||||
if (pc->isQualificationFinalBaseClass()) {
|
||||
set<int> base;
|
||||
pc->getQualificationFinal()->getBaseClassInstances(base);
|
||||
for (int i : base) {
|
||||
if (pc->getVirtualClass(i)) {
|
||||
int tot2 = 0;
|
||||
oe->getNumClassRunners(pc->getVirtualClass(i)->getId(), 0, tot2, fin, dns);
|
||||
pc->getVirtualClass(i)->getNumResults(0, tot2, fin, dns);
|
||||
tot += tot2;
|
||||
}
|
||||
}
|
||||
@ -2849,10 +2849,10 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
|
||||
}
|
||||
if (hasRelay) {
|
||||
headXPos[5]=gdi.getCX();
|
||||
gdi.addInput(string("RestartRope")+legno, L"", 5, MultiCB);
|
||||
gdi.addInput(string("RestartRope")+legno, L"", 7, MultiCB);
|
||||
|
||||
headXPos[6]=gdi.getCX();
|
||||
gdi.addInput(string("Restart")+legno, L"", 5, MultiCB);
|
||||
gdi.addInput(string("Restart")+legno, L"", 7, MultiCB);
|
||||
}
|
||||
|
||||
gdi.dropLine(-0.1);
|
||||
|
||||
@ -2390,15 +2390,16 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
|
||||
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2019 Melin Software HB"));
|
||||
gdi.dropLine();
|
||||
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
|
||||
"(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB,"
|
||||
"\nand (c) 2004-2007 by Educational Technology Resources, Inc.\n"
|
||||
"The database used is MySQL, Copyright (c) 2008-2017 Oracle, Inc."
|
||||
"\n\nGerman Translation by Erik Nilsson-Simkovics"
|
||||
"\n\nDanish Translation by Michael Leth Jess and Chris Bagge"
|
||||
"\n\nRussian Translation by Paul A. Kazakov and Albert Salihov"
|
||||
"\n\nOriginal French Translation by Jerome Monclard"
|
||||
"\n\nAdaption to French conditions and extended translation by Pierre Gaufillet"
|
||||
"\n\nCzech Translation by Marek Kustka");
|
||||
"(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB,"
|
||||
"\nand (c) 2004-2007 by Educational Technology Resources, Inc.\n"
|
||||
"The database used is MySQL, Copyright (c) 2008-2017 Oracle, Inc."
|
||||
"\n\nGerman Translation by Erik Nilsson-Simkovics"
|
||||
"\n\nDanish Translation by Michael Leth Jess and Chris Bagge"
|
||||
"\n\nRussian Translation by Paul A. Kazakov and Albert Salihov"
|
||||
"\n\nOriginal French Translation by Jerome Monclard"
|
||||
"\n\nAdaption to French conditions and extended translation by Pierre Gaufillet"
|
||||
"\n\nCzech Translation by Marek Kustka"
|
||||
"\n\nHelp with English documentation: Torbjörn Wikström");
|
||||
|
||||
gdi.dropLine();
|
||||
gdi.addString("", 0, "Det här programmet levereras utan någon som helst garanti. Programmet är ");
|
||||
|
||||
@ -939,7 +939,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.registerEvent("DataUpdate", ListsEventCB);
|
||||
gdi.setData("DataSync", 1);
|
||||
gdi.registerEvent(bi.id, ListsCB);
|
||||
|
||||
currentList.getParam().pageBreak = true;
|
||||
oe->generateMinuteStartlist(gdi);
|
||||
baseButtons(gdi, 0);
|
||||
gdi.refresh();
|
||||
|
||||
@ -1568,13 +1568,15 @@ void TabRunner::showRunnerReport(gdioutput &gdi) {
|
||||
}
|
||||
|
||||
void TabRunner::generateRunnerReport(oEvent &oe, gdioutput &gdi, vector<pair<int, bool>> &runnersToReport) {
|
||||
|
||||
oe.synchronizeList({ oListId::oLRunnerId, oListId::oLTeamId, oListId::oLPunchId });
|
||||
gdi.fillDown();
|
||||
|
||||
cTeam t = 0;
|
||||
set<int> clsSet;
|
||||
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
||||
pRunner r = oe.getRunner(runnersToReport[k].first, 0);
|
||||
if (!r)
|
||||
continue;
|
||||
clsSet.insert(r->getClassId(true));
|
||||
if (r && r->getTeam()) {
|
||||
pClass cls = r->getClassRef(true);
|
||||
@ -1676,7 +1678,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
||||
|
||||
if (r->statusOK()) {
|
||||
int total, finished, dns;
|
||||
oe.getNumClassRunners(r->getClassId(true), r->getLegNumber(), total, finished, dns);
|
||||
r->getClassRef(true)->getNumResults(r->getLegNumber(), total, finished, dns);
|
||||
|
||||
if (r->getTeam() == 0) {
|
||||
gdi.addString("", fontMediumPlus, L"Tid: X, nuvarande placering Y/Z.#" + str + L"#" + r->getPlaceS() + L"#" + itow(finished));
|
||||
|
||||
@ -48,6 +48,8 @@
|
||||
#include "recorder.h"
|
||||
#include "autocomplete.h"
|
||||
|
||||
constexpr bool addTestPort = false;
|
||||
|
||||
TabSI::TabSI(oEvent *poe):TabBase(poe), activeSIC(ConvertedTimeStatus::Unknown) {
|
||||
editCardData.tabSI = this;
|
||||
directEntryGUI.tabSI = this;
|
||||
@ -184,6 +186,8 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
if (lbi.text.substr(0, 3) == L"TCP")
|
||||
port = L"TCP";
|
||||
else if (lbi.text == L"TEST")
|
||||
port = L"TEST";
|
||||
|
||||
if (gSI->isPortOpen(port)) {
|
||||
gSI->closeCom(port.c_str());
|
||||
@ -211,6 +215,20 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.refresh();
|
||||
return 0;
|
||||
}
|
||||
else if (port == L"TEST") {
|
||||
vector<pRunner> runners;
|
||||
oe->getRunners(0, 0, runners, false);
|
||||
for (pRunner r : runners) {
|
||||
if (r->getCard() || r->getCardNo() == 0)
|
||||
continue;
|
||||
vector<int> pl;
|
||||
auto c = r->getCourse(true);
|
||||
if (c) {
|
||||
pl = c->getControlNumbers();
|
||||
gSI->addTestCard(r->getCardNo(), pl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gdi.addStringUT(0, lang.tl(L"Startar SI på ") + port + L"...");
|
||||
gdi.refresh();
|
||||
@ -1567,6 +1585,9 @@ void TabSI::refillComPorts(gdioutput &gdi)
|
||||
else
|
||||
gdi.addItem("ComPort", L"TCP");
|
||||
|
||||
if (addTestPort)
|
||||
gdi.addItem("ComPort", L"TEST");
|
||||
|
||||
if (active){
|
||||
gdi.selectItemByData("ComPort", active);
|
||||
gdi.setText("StartSI", lang.tl("Koppla ifrån"));
|
||||
|
||||
@ -83,17 +83,21 @@ int TimeStamp::getAge() const
|
||||
return CTime-Time;
|
||||
}
|
||||
|
||||
string TimeStamp::getStamp() const
|
||||
const string &TimeStamp::getStamp() const
|
||||
{
|
||||
if (stampCodeTime == Time)
|
||||
return stampCode;
|
||||
|
||||
stampCodeTime = Time;
|
||||
__int64 ft64=(__int64(Time)+minYearConstant*365*24*3600)*10000000;
|
||||
FILETIME &ft=*(FILETIME*)&ft64;
|
||||
SYSTEMTIME st;
|
||||
FileTimeToSystemTime(&ft, &st);
|
||||
char bf[64];
|
||||
sprintf_s(bf, 32, "%d%02d%02d%02d%02d%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
||||
stampCode = bf;
|
||||
|
||||
char bf[32];
|
||||
sprintf_s(bf, "%d%02d%02d%02d%02d%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
||||
|
||||
return bf;
|
||||
return stampCode;
|
||||
}
|
||||
|
||||
wstring TimeStamp::getStampString() const
|
||||
@ -109,7 +113,7 @@ wstring TimeStamp::getStampString() const
|
||||
return bf;
|
||||
}
|
||||
|
||||
void TimeStamp::setStamp(string s)
|
||||
void TimeStamp::setStamp(const string &s)
|
||||
{
|
||||
if (s.size()<14)
|
||||
return;
|
||||
|
||||
@ -30,12 +30,14 @@
|
||||
|
||||
************************************************************************/
|
||||
|
||||
class TimeStamp
|
||||
{
|
||||
class TimeStamp {
|
||||
unsigned int Time;
|
||||
mutable string stampCode;
|
||||
mutable int stampCodeTime = 0;
|
||||
public:
|
||||
void setStamp(string s);
|
||||
string getStamp() const;
|
||||
void setStamp(const string &s);
|
||||
const string &getStamp() const;
|
||||
|
||||
wstring getStampString() const;
|
||||
int getAge() const;
|
||||
unsigned int getModificationTime() const {return Time;}
|
||||
|
||||
@ -723,13 +723,13 @@ int csvparser::selectPunchIndex(const wstring &competitionDate, const vector<wst
|
||||
for (size_t k = 0; k < sp.size(); k++) {
|
||||
processGeneralTime(sp[k], pt, date);
|
||||
if (!pt.empty()) {
|
||||
if (ti == -1) {
|
||||
//if (ti == -1) {
|
||||
ti = k;
|
||||
pt.swap(processedTime);
|
||||
}
|
||||
else {
|
||||
return -1; // Not a unique time
|
||||
}
|
||||
// }
|
||||
// else {
|
||||
// return -1; // Not a unique time
|
||||
// }
|
||||
if (!date.empty()) {
|
||||
date.swap(processedDate);
|
||||
di = k;
|
||||
@ -913,13 +913,13 @@ const wchar_t *csvparser::getSIC(SIConfigFields sic, const vector<wstring> &sp)
|
||||
bool csvparser::checkSIConfigLine(const oEvent &oe, const vector<wstring> &sp, SICard &card) {
|
||||
if (siconfigmap.empty())
|
||||
return false;
|
||||
|
||||
|
||||
int startIx = siconfigmap[sicRecordStart];
|
||||
if (startIx == 0)
|
||||
return false;
|
||||
|
||||
int cardNo = wtoi(getSIC(sicSIID, sp));
|
||||
|
||||
|
||||
if (cardNo < 1000 || cardNo > 99999999)
|
||||
return false;
|
||||
bool is12Hour = false;
|
||||
@ -934,14 +934,14 @@ bool csvparser::checkSIConfigLine(const oEvent &oe, const vector<wstring> &sp, S
|
||||
|
||||
vector< pair<int, int> > punches;
|
||||
int np = wtoi(getSIC(sicNumPunch, sp));
|
||||
|
||||
|
||||
for (int k=0; k < np; k++) {
|
||||
size_t ix = startIx + k*3;
|
||||
if (ix+2 >= sp.size())
|
||||
|
||||
for (int k = 0; k < np; k++) {
|
||||
size_t ix = startIx + k * 3;
|
||||
if (ix + 2 >= sp.size())
|
||||
return false;
|
||||
int code = wtoi(sp[ix]);
|
||||
int time = analyseSITime(sp[ix+1].c_str(), sp[ix+2].c_str(), is12Hour);
|
||||
int time = analyseSITime(sp[ix + 1].c_str(), sp[ix + 2].c_str(), is12Hour);
|
||||
if (code > 0) {
|
||||
punches.push_back(make_pair(code, time));
|
||||
}
|
||||
@ -949,7 +949,7 @@ bool csvparser::checkSIConfigLine(const oEvent &oe, const vector<wstring> &sp, S
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( (finish > 0 && finish != NOTIME) || punches.size() > 2) {
|
||||
card.clear(0);
|
||||
card.CardNumber = cardNo;
|
||||
|
||||
@ -2428,3 +2428,7 @@ Lagändringblankett = Team Change Form
|
||||
Mappa rootadresssen (http:///localhost:port/) till funktion = Map root address (http:///localhost:port/) to function
|
||||
ClassAvailableMaps = Available maps for class
|
||||
ClassTotalMaps = Total number of maps for class
|
||||
Kunde inte öppna databasen (X) = Could not connect to database (X)
|
||||
Kunde inte ladda upp löpardatabasen (X) = Could not upload runner database (X)
|
||||
Runner check time = Runner check time
|
||||
ClassNumEntries = Number of entries in class
|
||||
|
||||
507
code/french.lng
507
code/french.lng
File diff suppressed because it is too large
Load Diff
@ -59,6 +59,7 @@ const int timeSeconds = 1<<14;
|
||||
const int timerIgnoreSign = 1<<15;
|
||||
const int Capitalize = 1<<16;
|
||||
const int absolutePosition = 1 << 17;
|
||||
const int skipBoundingBox = 1 << 18;
|
||||
|
||||
enum GDICOLOR {colorBlack = RGB(0,0,0),
|
||||
colorRed = RGB(128,0,0),
|
||||
|
||||
@ -311,6 +311,7 @@ void gdioutput::initCommon(double _scale, const wstring &font)
|
||||
|
||||
Background=CreateSolidBrush(GetSysColor(COLOR_WINDOW));
|
||||
|
||||
fontHeightCache.clear();
|
||||
fonts[currentFont].init(scale, currentFont, L"");
|
||||
}
|
||||
|
||||
@ -846,10 +847,37 @@ TextInfo &gdioutput::addStringUT(int yp, int xp, int format, const string &text,
|
||||
return addStringUT(yp, xp, format, widen(text), xlimit, cb, fontFace);
|
||||
}
|
||||
|
||||
int gdioutput::getFontHeight(int format, const wstring &fontFace) const {
|
||||
format = format & 0xFF;
|
||||
auto res = fontHeightCache.find(make_pair(format, fontFace));
|
||||
|
||||
if (res != fontHeightCache.end())
|
||||
return res->second;
|
||||
|
||||
TextInfo TI;
|
||||
TI.format = format;
|
||||
TI.xp = 0;
|
||||
TI.yp = 0;
|
||||
TI.text = L"M1y|";
|
||||
TI.xlimit = 100;
|
||||
TI.callBack = 0;
|
||||
TI.font = fontFace;
|
||||
calcStringSize(TI);
|
||||
int h = TI.textRect.bottom - TI.textRect.top;
|
||||
fontHeightCache.emplace(make_pair(format, fontFace), h);
|
||||
return h;
|
||||
}
|
||||
|
||||
TextInfo &gdioutput::addStringUT(int yp, int xp, int format, const wstring &text,
|
||||
int xlimit, GUICALLBACK cb, const wchar_t *fontFace)
|
||||
{
|
||||
TextInfo TI;
|
||||
bool skipBBCalc = (format & skipBoundingBox) == skipBoundingBox;
|
||||
format &= ~skipBoundingBox;
|
||||
|
||||
TL.emplace_back();
|
||||
TextInfo &TI = TL.back();
|
||||
itTL = TL.begin();
|
||||
|
||||
TI.format=format;
|
||||
TI.xp=xp;
|
||||
TI.yp=yp;
|
||||
@ -859,24 +887,38 @@ TextInfo &gdioutput::addStringUT(int yp, int xp, int format, const wstring &text
|
||||
if (fontFace)
|
||||
TI.font = fontFace;
|
||||
if (!skipTextRender(format)) {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
|
||||
if (skipBBCalc) {
|
||||
assert(xlimit > 0);
|
||||
int h = getFontHeight(format, fontFace);
|
||||
TI.textRect.left = xp;
|
||||
TI.textRect.top = yp;
|
||||
TI.textRect.right = xp + xlimit;
|
||||
TI.textRect.bottom = yp + h;
|
||||
TI.realWidth = xlimit;
|
||||
|
||||
if (hWndTarget && !manualUpdate)
|
||||
RenderString(TI, hDC);
|
||||
else
|
||||
calcStringSize(TI, hDC);
|
||||
|
||||
if (xlimit == 0 || (format & (textRight|textCenter)) == 0) {
|
||||
updatePos(TI.textRect.right+OffsetX, TI.yp, scaleLength(10),
|
||||
TI.textRect.bottom - TI.textRect.top + scaleLength(2));
|
||||
updatePos(TI.textRect.right + OffsetX, TI.yp, scaleLength(10),
|
||||
TI.textRect.bottom - TI.textRect.top + scaleLength(2));
|
||||
}
|
||||
else {
|
||||
updatePos(TI.xp, TI.yp, TI.realWidth + scaleLength(10),
|
||||
TI.textRect.bottom - TI.textRect.top + scaleLength(2));
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
|
||||
if (hWndTarget && !manualUpdate)
|
||||
RenderString(TI, hDC);
|
||||
else
|
||||
calcStringSize(TI, hDC);
|
||||
|
||||
if (xlimit == 0 || (format & (textRight | textCenter)) == 0) {
|
||||
updatePos(TI.textRect.right + OffsetX, TI.yp, scaleLength(10),
|
||||
TI.textRect.bottom - TI.textRect.top + scaleLength(2));
|
||||
}
|
||||
else {
|
||||
updatePos(TI.xp, TI.yp, TI.realWidth + scaleLength(10),
|
||||
TI.textRect.bottom - TI.textRect.top + scaleLength(2));
|
||||
}
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
}
|
||||
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
|
||||
|
||||
if (renderOptimize && !TL.empty()) {
|
||||
if (TL.back().yp > TI.yp)
|
||||
renderOptimize=false;
|
||||
@ -889,9 +931,6 @@ TextInfo &gdioutput::addStringUT(int yp, int xp, int format, const wstring &text
|
||||
TI.textRect.top = yp;
|
||||
}
|
||||
|
||||
TL.push_back(TI);
|
||||
itTL=TL.begin();
|
||||
|
||||
return TL.back();
|
||||
}
|
||||
|
||||
@ -6076,15 +6115,13 @@ void gdioutput::liftCommandLock() const {
|
||||
}
|
||||
|
||||
int gdioutput::getLineHeight(gdiFonts font, const wchar_t *face) const {
|
||||
TextInfo ti;
|
||||
ti.xp = 0;
|
||||
ti.yp = 0;
|
||||
ti.format = font;
|
||||
ti.text = L"&abc_M|!I";
|
||||
if (face)
|
||||
ti.font = face;
|
||||
calcStringSize(ti);
|
||||
return (11*(ti.textRect.bottom - ti.textRect.top))/10;
|
||||
int h;
|
||||
if (face == nullptr)
|
||||
h = getFontHeight(font, _EmptyWString);
|
||||
else
|
||||
h = getFontHeight(font, face);
|
||||
|
||||
return (11*h)/10;
|
||||
}
|
||||
|
||||
GDIImplFontSet::GDIImplFontSet() {
|
||||
|
||||
@ -184,6 +184,8 @@ protected:
|
||||
|
||||
HBRUSH Background;
|
||||
|
||||
mutable map<pair<int, wstring>, int> fontHeightCache;
|
||||
|
||||
map<wstring, GDIImplFontSet> fonts;
|
||||
const GDIImplFontSet &getCurrentFont() const;
|
||||
const GDIImplFontSet &getFont(const wstring &font) const;
|
||||
@ -596,9 +598,7 @@ public:
|
||||
bool clearList(const string &id);
|
||||
|
||||
bool hasField(const string &id) const;
|
||||
/*const wstring &getText(const wchar_t *id, bool acceptMissing = false) const {
|
||||
return getText(toNarrow(id).c_str(), acceptMissing);
|
||||
}*/
|
||||
|
||||
const wstring &getText(const char *id, bool acceptMissing = false) const;
|
||||
|
||||
BaseInfo &getBaseInfo(const char *id) const;
|
||||
@ -616,6 +616,8 @@ public:
|
||||
// Insert text and notify "focusList"
|
||||
bool insertText(const string &id, const wstring &text);
|
||||
|
||||
int getFontHeight(int format, const wstring &fontFace) const;
|
||||
|
||||
// The html version should be UTF-8.
|
||||
void copyToClipboard(const string &html,
|
||||
const wstring &txt) const;
|
||||
|
||||
@ -963,6 +963,7 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
|
||||
parser.declareSymbol("LegPlace", "Place on course leg", true);
|
||||
parser.declareSymbol("Leg", "Leg number in team, zero indexed", false);
|
||||
parser.declareSymbol("BirthYear", "Year of birth", false);
|
||||
parser.declareSymbol("CheckTime", "Runner check time", false);
|
||||
}
|
||||
else {
|
||||
parser.declareSymbol("RunnerStatus", "Status for each team member", true);
|
||||
@ -1276,6 +1277,7 @@ void DynamicResult::prepareCalculations(oRunner &runner) const {
|
||||
parser.addSymbol("LegPlace", place);
|
||||
parser.addSymbol("Leg", runner.getLegNumber());
|
||||
parser.addSymbol("BirthYear", runner.getBirthYear());
|
||||
parser.addSymbol("CheckTime", runner.getCheckTime());
|
||||
}
|
||||
|
||||
void DynamicResult::storeOutput(vector<int> ×, vector<int> &numbers) const {
|
||||
|
||||
@ -812,6 +812,7 @@ void xmlbuffer::startXML(xmlparser &xml, const wstring &dest) {
|
||||
}
|
||||
|
||||
bool xmlbuffer::commit(xmlparser &xml, int count) {
|
||||
vector<wstring> p2;
|
||||
while (count>0 && !blocks.empty()) {
|
||||
block &block = blocks.front();
|
||||
|
||||
@ -819,12 +820,20 @@ bool xmlbuffer::commit(xmlparser &xml, int count) {
|
||||
xml.write(block.tag.c_str(), block.prop, block.value);
|
||||
}
|
||||
else {
|
||||
vector<wstring> p2;
|
||||
for (size_t k = 0; k< block.prop.size(); k++) {
|
||||
p2.push_back(gdi_main->widen(block.prop[k].first));
|
||||
p2.push_back(block.prop[k].second);
|
||||
if (block.prop.size() > 1) {
|
||||
p2.resize(block.prop.size() * 2);
|
||||
for (size_t k = 0; k < block.prop.size(); k++) {
|
||||
p2[k * 2] = gdi_main->widen(block.prop[k].first);
|
||||
p2[k * 2 + 1] = std::move(block.prop[k].second);
|
||||
}
|
||||
xml.startTag(block.tag.c_str(), p2);
|
||||
}
|
||||
else if (block.prop.size() == 1) {
|
||||
xml.startTag(block.tag.c_str(), block.prop[0].first.c_str(), block.prop[0].second);
|
||||
}
|
||||
else if (block.prop.empty()) {
|
||||
xml.startTag(block.tag.c_str());
|
||||
}
|
||||
xml.startTag(block.tag.c_str(), p2);
|
||||
|
||||
for (size_t k = 0; k < block.subValues.size(); k++)
|
||||
block.subValues[k].commit(xml, numeric_limits<int>::max());
|
||||
|
||||
@ -106,6 +106,13 @@ void IOF30Interface::readCourseData(gdioutput &gdi, const xmlobject &xo, bool up
|
||||
failed++;
|
||||
}
|
||||
|
||||
vector<pCourse> allC;
|
||||
oe.getCourses(allC);
|
||||
for (pCourse pc : allC) {
|
||||
if (!courses.count(pc->getName()))
|
||||
courses[pc->getName()] = pc;
|
||||
}
|
||||
|
||||
if (!updateClass)
|
||||
return;
|
||||
|
||||
@ -399,6 +406,13 @@ void IOF30Interface::teamCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
||||
if (!bib.empty()) {
|
||||
teamText = bib;
|
||||
t = bib2Team[bib];
|
||||
if (t == nullptr) {
|
||||
int ibib = _wtoi(bib.c_str());
|
||||
if (ibib > 0) {
|
||||
wstring bib2 = itow(ibib);
|
||||
t = bib2Team[bib2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (t == 0) {
|
||||
@ -2534,9 +2548,9 @@ void IOF30Interface::getLocalDateTime(const string &date, const string &time,
|
||||
SystemTimeToTzSpecificLocalTime(0, &st, &localTime);
|
||||
|
||||
char bf[64];
|
||||
sprintf(bf, "%02d:%02d:%02d", localTime.wHour, localTime.wMinute, localTime.wSecond);
|
||||
sprintf_s(bf, "%02d:%02d:%02d", localTime.wHour, localTime.wMinute, localTime.wSecond);
|
||||
timeOut = bf;
|
||||
sprintf(bf, "%d-%02d-%02d", localTime.wYear, localTime.wMonth, localTime.wDay);
|
||||
sprintf_s(bf, "%d-%02d-%02d", localTime.wYear, localTime.wMonth, localTime.wDay);
|
||||
dateOut = bf;
|
||||
}
|
||||
else {
|
||||
@ -3529,7 +3543,8 @@ bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void IOF30Interface::writeXMLCompetitorDB(xmlparser &xml, const RunnerWDBEntry &rde) const {
|
||||
void IOF30Interface::writeXMLCompetitorDB(xmlparser &xml, const RunnerDB &db,
|
||||
const RunnerWDBEntry &rde) const {
|
||||
wstring s = rde.getSex();
|
||||
|
||||
xml.startTag("Competitor");
|
||||
@ -3566,9 +3581,18 @@ void IOF30Interface::writeXMLCompetitorDB(xmlparser &xml, const RunnerWDBEntry &
|
||||
|
||||
|
||||
if (rde.dbe().clubNo > 0) {
|
||||
xml.startTag("Organisation");
|
||||
xml.write("Id", rde.dbe().clubNo);
|
||||
xml.endTag();
|
||||
pClub clb = db.getClub(rde.dbe().clubNo);
|
||||
if (clb) {
|
||||
uint64_t extId = clb->getExtIdentifier();
|
||||
if (extId != 0) {
|
||||
xml.startTag("Organisation");
|
||||
xml.write("Id", int(extId));
|
||||
xml.endTag();
|
||||
}
|
||||
else {
|
||||
writeClub(xml, *clb, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml.endTag(); // Competitor
|
||||
@ -3926,7 +3950,7 @@ void IOF30Interface::writeRunnerDB(const RunnerDB &db, xmlparser &xml) const {
|
||||
const vector<RunnerWDBEntry> &rdb = db.getRunnerDB();
|
||||
for (size_t k = 0; k < rdb.size(); k++) {
|
||||
if (!rdb[k].isRemoved())
|
||||
writeXMLCompetitorDB(xml, rdb[k]);
|
||||
writeXMLCompetitorDB(xml, db, rdb[k]);
|
||||
}
|
||||
|
||||
xml.endTag();
|
||||
|
||||
@ -232,7 +232,7 @@ class IOF30Interface {
|
||||
int getStageNumber();
|
||||
|
||||
bool readXMLCompetitorDB(const xmlobject &xCompetitor);
|
||||
void writeXMLCompetitorDB(xmlparser &xml, const RunnerWDBEntry &rde) const;
|
||||
void writeXMLCompetitorDB(xmlparser &xml, const RunnerDB &db, const RunnerWDBEntry &rde) const;
|
||||
|
||||
int getStartIndex(const wstring &startId);
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
//V35: abcdef
|
||||
//V36: abcdef
|
||||
int getMeosBuild() {
|
||||
string revision("$Rev: 895 $");
|
||||
string revision("$Rev: 912 $");
|
||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||
}
|
||||
|
||||
@ -42,12 +42,12 @@ int getMeosBuild() {
|
||||
//V33: abcdefghij
|
||||
//V34: abcdfge
|
||||
wstring getMeosDate() {
|
||||
wstring date(L"$Date: 2019-05-11 07:26:35 +0200 (lö, 11 maj 2019) $");
|
||||
wstring date(L"$Date: 2019-06-16 10:37:59 +0200 (sö, 16 jun 2019) $");
|
||||
return date.substr(7,10);
|
||||
}
|
||||
|
||||
wstring getBuildType() {
|
||||
return L""; // No parantheses (...)
|
||||
return L"Update 1"; // No parantheses (...)
|
||||
}
|
||||
|
||||
wstring getMajorVersion() {
|
||||
@ -130,5 +130,8 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
||||
supp.emplace_back(L"IP Skogen Göteborg");
|
||||
supp.emplace_back(L"Smedjebackens Orientering");
|
||||
supp.emplace_back(L"Gudhems IF");
|
||||
supp.emplace_back(L"Kexholm SK");
|
||||
supp.emplace_back(L"Utby IK");
|
||||
supp.emplace_back(L"JWOC 2019");
|
||||
reverse(supp.begin(), supp.end());
|
||||
}
|
||||
|
||||
@ -549,6 +549,8 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
oPrintPost *last = 0;
|
||||
oPrintPost *base = 0;
|
||||
|
||||
auto indexPosToWidthSrc = indexPosToWidth;
|
||||
|
||||
int totalWidth = pos.getWidth();
|
||||
for (map<pair<int, int>, int>::iterator it = linePostCount.begin(); it != linePostCount.end(); ++it) {
|
||||
if (it->second == 1) {
|
||||
@ -606,7 +608,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
|
||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||
setFixedWidth(added, indexPosToWidth, MLHead, j, k);
|
||||
|
||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLHead, j, k)];
|
||||
added.color = mp.color;
|
||||
if (!mp.mergeWithPrevious)
|
||||
base = &added;
|
||||
@ -657,7 +659,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
|
||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||
setFixedWidth(added, indexPosToWidth, MLSubHead, j, k);
|
||||
|
||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLSubHead, j, k)];
|
||||
added.color = mp.color;
|
||||
if (!mp.mergeWithPrevious)
|
||||
base = &added;
|
||||
@ -703,6 +705,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
|
||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||
setFixedWidth(added, indexPosToWidth, MLList, j, k);
|
||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLList, j, k)];
|
||||
|
||||
added.color = mp.color;
|
||||
if (!mp.mergeWithPrevious)
|
||||
@ -756,6 +759,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
|
||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||
setFixedWidth(added, indexPosToWidth, MLSubList, j, k);
|
||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLSubList, j, k)];
|
||||
|
||||
if (last && mp.mergeWithPrevious) {
|
||||
last->doMergeNext = true;
|
||||
@ -1656,6 +1660,7 @@ void MetaList::initSymbols() {
|
||||
typeToSymbol[lClassResultFraction] = L"ClassResultFraction";
|
||||
typeToSymbol[lClassAvailableMaps] = L"ClassAvailableMaps";
|
||||
typeToSymbol[lClassTotalMaps] = L"ClassTotalMaps";
|
||||
typeToSymbol[lClassNumEntries] = L"ClassNumEntries";
|
||||
typeToSymbol[lCourseLength] = L"CourseLength";
|
||||
typeToSymbol[lCourseName] = L"CourseName";
|
||||
typeToSymbol[lCourseClimb] = L"CourseClimb";
|
||||
|
||||
@ -65,7 +65,6 @@ oCard::~oCard()
|
||||
bool oCard::Write(xmlparser &xml)
|
||||
{
|
||||
if (Removed) return true;
|
||||
|
||||
xml.startTag("Card");
|
||||
xml.write("CardNo", cardNo);
|
||||
xml.write("Punches", getPunchString());
|
||||
@ -137,17 +136,13 @@ void oCard::addPunch(int type, int time, int matchControlId)
|
||||
updateChanged();
|
||||
}
|
||||
|
||||
string oCard::getPunchString()
|
||||
{
|
||||
oPunchList::iterator it;
|
||||
|
||||
string pstring;
|
||||
|
||||
for(it=punches.begin(); it != punches.end(); ++it){
|
||||
pstring += it->codeString();
|
||||
const string &oCard::getPunchString() const {
|
||||
punchString.clear();
|
||||
punchString.reserve(punches.size() * 16);
|
||||
for(auto &p : punches) {
|
||||
p.appendCodeString(punchString);
|
||||
}
|
||||
|
||||
return pstring;
|
||||
return punchString;
|
||||
}
|
||||
|
||||
void oCard::importPunches(const string &s) {
|
||||
|
||||
@ -69,6 +69,8 @@ protected:
|
||||
|
||||
void changedObject();
|
||||
|
||||
mutable string punchString;
|
||||
|
||||
public:
|
||||
|
||||
// Returns true if the card was constructed from punches.
|
||||
@ -126,7 +128,7 @@ public:
|
||||
const wstring &getCardNoString() const;
|
||||
void setCardNo(int c);
|
||||
void importPunches(const string &s);
|
||||
string getPunchString();
|
||||
const string &getPunchString() const;
|
||||
|
||||
void Set(const xmlobject &xo);
|
||||
bool Write(xmlparser &xml);
|
||||
|
||||
234
code/oClass.cpp
234
code/oClass.cpp
@ -103,7 +103,6 @@ oClass::~oClass()
|
||||
bool oClass::Write(xmlparser &xml)
|
||||
{
|
||||
if (Removed) return true;
|
||||
|
||||
xml.startTag("Class");
|
||||
|
||||
xml.write("Id", Id);
|
||||
@ -359,26 +358,145 @@ void oClass::importLegMethod(const string &legMethods)
|
||||
apply();
|
||||
}
|
||||
|
||||
int oClass::getNumRunners(bool checkFirstLeg, bool noCountVacant, bool noCountNotCompeting) const {
|
||||
int nRunners=0;
|
||||
oRunnerList::iterator it;
|
||||
|
||||
for (it=oe->Runners.begin(); it != oe->Runners.end(); ++it) {
|
||||
if (it->getClassId(true)==Id) {
|
||||
if (it->skip())
|
||||
continue;
|
||||
if (checkFirstLeg && it->tLeg > 0)
|
||||
continue;
|
||||
if (noCountVacant && it->isVacant())
|
||||
continue;
|
||||
if (noCountNotCompeting && it->getStatus() == StatusNotCompetiting)
|
||||
continue;
|
||||
nRunners++;
|
||||
}
|
||||
}
|
||||
return nRunners;
|
||||
string oClass::getCountTypeKey(int leg, CountKeyType type, bool countVacant) {
|
||||
return itos(leg) + ":" + itos(type) + (countVacant ? "V" : "");
|
||||
}
|
||||
|
||||
int oClass::getNumRunners(bool checkFirstLeg, bool noCountVacant, bool noCountNotCompeting) const {
|
||||
if (tTypeKeyToRunnerCount.first != oe->dataRevision) {
|
||||
for (auto &c : oe->Classes) {
|
||||
c.tTypeKeyToRunnerCount.second.clear();
|
||||
c.tTypeKeyToRunnerCount.first = oe->dataRevision;
|
||||
}
|
||||
}
|
||||
string key = getCountTypeKey(checkFirstLeg ? 0 : -1,
|
||||
noCountNotCompeting ? CountKeyType::All : CountKeyType::IncludeNotCompeting,
|
||||
!noCountVacant);
|
||||
|
||||
auto res = tTypeKeyToRunnerCount.second.find(key);
|
||||
if (res != tTypeKeyToRunnerCount.second.end())
|
||||
return res->second;
|
||||
|
||||
unordered_map<int, int> nRunners;
|
||||
for (auto &r : oe->Runners) {
|
||||
if (r.isRemoved() || !r.Class)
|
||||
continue;
|
||||
if (checkFirstLeg && (r.tLeg > 0 && !r.Class->isQualificationFinalBaseClass()))
|
||||
continue;
|
||||
if (noCountVacant && r.isVacant())
|
||||
continue;
|
||||
if (noCountNotCompeting && r.getStatus() == StatusNotCompetiting)
|
||||
continue;
|
||||
|
||||
int id = r.getClassId(true);
|
||||
++nRunners[id];
|
||||
}
|
||||
|
||||
for (auto &c : oe->Classes) {
|
||||
if (!c.isRemoved())
|
||||
c.tTypeKeyToRunnerCount.second[key] = nRunners[c.Id];
|
||||
}
|
||||
return nRunners[Id];
|
||||
}
|
||||
|
||||
void oClass::getNumResults(int leg, int &total, int &finished, int &dns) const {
|
||||
if (tTypeKeyToRunnerCount.first != oe->dataRevision) {
|
||||
for (auto &c : oe->Classes) {
|
||||
c.tTypeKeyToRunnerCount.second.clear();
|
||||
c.tTypeKeyToRunnerCount.first = oe->dataRevision;
|
||||
}
|
||||
}
|
||||
string keyTot = getCountTypeKey(leg, CountKeyType::ExpectedStarting, false);
|
||||
string keyFinished = getCountTypeKey(leg, CountKeyType::Finished, false);
|
||||
string keyDNS = getCountTypeKey(leg, CountKeyType::DNS, false);
|
||||
|
||||
auto rTot = tTypeKeyToRunnerCount.second.find(keyTot);
|
||||
auto rFinished = tTypeKeyToRunnerCount.second.find(keyFinished);
|
||||
auto rDNS = tTypeKeyToRunnerCount.second.find(keyDNS);
|
||||
|
||||
if (rTot != tTypeKeyToRunnerCount.second.end() &&
|
||||
rFinished != tTypeKeyToRunnerCount.second.end() &&
|
||||
rDNS != tTypeKeyToRunnerCount.second.end()) {
|
||||
total = rTot->second;
|
||||
finished = rFinished->second;
|
||||
dns = rDNS->second;
|
||||
return;
|
||||
}
|
||||
|
||||
struct Cnt {
|
||||
bool team = false;
|
||||
bool singleClass = false;
|
||||
int maxleg = 0;
|
||||
int total = 0;
|
||||
int finished = 0;
|
||||
int dns = 0;
|
||||
};
|
||||
|
||||
//Search runners
|
||||
unordered_map<int, Cnt> cnt;
|
||||
|
||||
for (auto &c : oe->Classes) {
|
||||
if (c.isRemoved())
|
||||
continue;
|
||||
|
||||
ClassType ct = c.getClassType();
|
||||
auto &cc = cnt[c.Id];
|
||||
cc.maxleg = c.getLastStageIndex();
|
||||
if (ct == oClassKnockout)
|
||||
cc.singleClass = true || cc.maxleg == 1;
|
||||
|
||||
if (!(ct == oClassIndividual || ct == oClassIndividRelay || ct == oClassKnockout))
|
||||
cnt[c.Id].team = true;
|
||||
}
|
||||
|
||||
for (auto &r : oe->Runners) {
|
||||
if (r.isRemoved() || !r.Class || r.tStatus == StatusNotCompetiting || r.tStatus == StatusCANCEL)
|
||||
continue;
|
||||
|
||||
auto &c = cnt[r.getClassId(true)];
|
||||
if (c.team)
|
||||
continue;
|
||||
|
||||
int tleg = leg > 0 ? leg : c.maxleg;
|
||||
|
||||
if (r.tLeg == tleg || c.singleClass) {
|
||||
c.total++;
|
||||
|
||||
if (r.tStatus != StatusUnknown)
|
||||
c.finished++;
|
||||
|
||||
if (r.tStatus == StatusDNS)
|
||||
c.dns++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &t : oe->Teams) {
|
||||
if (t.isRemoved() || !t.Class || t.tStatus == StatusNotCompetiting || t.tStatus == StatusCANCEL)
|
||||
continue;
|
||||
|
||||
auto &c = cnt[t.getClassId(true)];
|
||||
if (!c.team)
|
||||
continue;
|
||||
|
||||
c.total++;
|
||||
|
||||
if (t.tStatus != StatusUnknown || t.getLegStatus(leg, false) != StatusUnknown)
|
||||
c.finished++;
|
||||
}
|
||||
|
||||
for (auto &c : oe->Classes) {
|
||||
auto &cc = cnt[c.Id];
|
||||
|
||||
c.tTypeKeyToRunnerCount.second[keyDNS] = cc.dns;
|
||||
c.tTypeKeyToRunnerCount.second[keyFinished] = cc.finished;
|
||||
c.tTypeKeyToRunnerCount.second[keyTot] = cc.total;
|
||||
}
|
||||
auto &cc = cnt[Id];
|
||||
|
||||
dns = cc.dns;
|
||||
total = cc.total;
|
||||
finished = cc.finished;
|
||||
}
|
||||
|
||||
void oClass::setCourse(pCourse c)
|
||||
{
|
||||
@ -1532,62 +1650,6 @@ ClassType oClass::getClassType() const
|
||||
return oClassIndividual;
|
||||
}
|
||||
|
||||
void oEvent::getNumClassRunners(int id, int leg, int &total, int &finished, int &dns) const
|
||||
{
|
||||
total=0;
|
||||
finished=0;
|
||||
dns = 0;
|
||||
//Search runners
|
||||
|
||||
const oClass *pc = getClass(id);
|
||||
|
||||
if (!pc)
|
||||
return;
|
||||
|
||||
ClassType ct=pc->getClassType();
|
||||
if (ct == oClassIndividual || ct == oClassIndividRelay || ct == oClassKnockout) {
|
||||
oRunnerList::const_iterator it;
|
||||
int maxleg = pc->getLastStageIndex();
|
||||
|
||||
for (it = Runners.begin(); it != Runners.end(); ++it) {
|
||||
if (!it->skip() && it->getClassId(true) == id && it->getStatus() != StatusNotCompetiting) {
|
||||
if (leg == 0) {
|
||||
total++;
|
||||
|
||||
if (it->tStatus != StatusUnknown)
|
||||
finished++;
|
||||
else if (it->tStatus == StatusDNS || it->tStatus == StatusCANCEL)
|
||||
dns++;
|
||||
}
|
||||
else {
|
||||
int tleg = leg > 0 ? leg : maxleg;
|
||||
const pRunner r = it->getMultiRunner(tleg);
|
||||
if (r) {
|
||||
total++;
|
||||
if (r->tStatus != StatusUnknown)
|
||||
finished++;
|
||||
else if (it->tStatus == StatusDNS || it->tStatus == StatusCANCEL)
|
||||
dns++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
oTeamList::const_iterator it;
|
||||
|
||||
for (it=Teams.begin(); it != Teams.end(); ++it) {
|
||||
if (it->getClassId(true)==id) {
|
||||
total++;
|
||||
|
||||
if (it->tStatus!=StatusUnknown ||
|
||||
it->getLegStatus(leg, false)!=StatusUnknown)
|
||||
finished++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int oClass::getNumMultiRunners(int leg) const
|
||||
{
|
||||
int ndup=0;
|
||||
@ -3130,6 +3192,20 @@ void oClass::calculateSplits() {
|
||||
|
||||
LegResult legRes;
|
||||
LegResult legBestTime;
|
||||
vector<pRunner> rCls;
|
||||
|
||||
if (isQualificationFinalBaseClass() || isQualificationFinalBaseClass()) {
|
||||
for (auto &r : oe->Runners) {
|
||||
if (!r.isRemoved() && r.getClassRef(true) == this)
|
||||
rCls.push_back(&r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (auto &r : oe->Runners) {
|
||||
if (!r.isRemoved() && r.Class == this)
|
||||
rCls.push_back(&r);
|
||||
}
|
||||
}
|
||||
|
||||
for (set<pCourse>::iterator cit = cSet.begin(); cit!= cSet.end(); ++cit) {
|
||||
pCourse pc = *cit;
|
||||
@ -3142,9 +3218,7 @@ void oClass::calculateSplits() {
|
||||
vector< vector<int> > splitsAcc(nc+1);
|
||||
vector<bool> acceptMissingPunch(nc+1, true);
|
||||
|
||||
for (oRunnerList::iterator it = oe->Runners.begin(); it != oe->Runners.end(); ++it) {
|
||||
if (it->isRemoved() || it->getClassRef(true) != this)
|
||||
continue;
|
||||
for (pRunner it : rCls) {
|
||||
pCourse tpc = it->getCourse(false);
|
||||
if (tpc != pc || tpc == 0)
|
||||
continue;
|
||||
@ -3161,10 +3235,8 @@ void oClass::calculateSplits() {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (oRunnerList::iterator it = oe->Runners.begin(); it != oe->Runners.end(); ++it) {
|
||||
if (it->isRemoved() || it->getClassRef(true) != this)
|
||||
continue;
|
||||
|
||||
for (pRunner it : rCls) {
|
||||
pCourse tpc = it->getCourse(false);
|
||||
|
||||
if (tpc != pc)
|
||||
|
||||
@ -284,6 +284,19 @@ protected:
|
||||
mutable int tMapsUsed;
|
||||
mutable int tMapsUsedNoVacant;
|
||||
|
||||
// First is data revision, second is key
|
||||
mutable pair<int, map<string, int>> tTypeKeyToRunnerCount;
|
||||
|
||||
enum CountKeyType {
|
||||
All,
|
||||
Finished,
|
||||
ExpectedStarting,
|
||||
DNS,
|
||||
IncludeNotCompeting
|
||||
};
|
||||
|
||||
static string getCountTypeKey(int leg, CountKeyType type, bool countVacant);
|
||||
|
||||
void configureInstance(int instance, bool allowCreation) const;
|
||||
public:
|
||||
|
||||
@ -543,6 +556,7 @@ public:
|
||||
// Get total number of runners running this class.
|
||||
// Use checkFirstLeg to only check the number of runners running leg 1.
|
||||
int getNumRunners(bool checkFirstLeg, bool noCountVacant, bool noCountNotCompeting) const;
|
||||
void getNumResults(int leg, int &total, int &finished, int &dns) const;
|
||||
|
||||
//Get remaining maps for class (or int::minvalue)
|
||||
int getNumRemainingMaps(bool forceRecalculate) const;
|
||||
|
||||
@ -97,7 +97,7 @@ int oControl::getCourseControlIdFromIdIndex(int controlId, int index) {
|
||||
bool oControl::write(xmlparser &xml)
|
||||
{
|
||||
if (Removed) return true;
|
||||
|
||||
|
||||
xml.startTag("Control");
|
||||
|
||||
xml.write("Id", Id);
|
||||
|
||||
@ -79,7 +79,7 @@ wstring oCourse::getInfo() const
|
||||
bool oCourse::Write(xmlparser &xml)
|
||||
{
|
||||
if (Removed) return true;
|
||||
|
||||
|
||||
xml.startTag("Course");
|
||||
|
||||
xml.write("Id", Id);
|
||||
@ -415,8 +415,7 @@ bool oCourse::fillCourse(gdioutput &gdi, const string &name)
|
||||
return true;
|
||||
}
|
||||
|
||||
void oCourse::getControls(vector<pControl> &pc)
|
||||
{
|
||||
void oCourse::getControls(vector<pControl> &pc) const {
|
||||
pc.clear();
|
||||
pc.reserve(nControls);
|
||||
for(int k=0;k<nControls;k++){
|
||||
@ -424,6 +423,14 @@ void oCourse::getControls(vector<pControl> &pc)
|
||||
}
|
||||
}
|
||||
|
||||
vector<int> oCourse::getControlNumbers() const {
|
||||
vector<int> ret;
|
||||
for (int k = 0; k<nControls; k++) {
|
||||
ret.push_back(Controls[k]->getFirstNumber());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int oCourse::distance(const SICard &card)
|
||||
{
|
||||
int matches=0;
|
||||
|
||||
@ -211,7 +211,9 @@ public:
|
||||
pControl addControl(int Id);
|
||||
void Set(const xmlobject *xo);
|
||||
|
||||
void getControls(vector<pControl> &pc);
|
||||
void getControls(vector<pControl> &pc) const;
|
||||
vector<int> getControlNumbers() const;
|
||||
|
||||
string getControls() const;
|
||||
string getLegLengths() const;
|
||||
|
||||
|
||||
@ -1134,11 +1134,19 @@ bool oEvent::open(const xmlparser &xml) {
|
||||
ZeroTime = 0;
|
||||
|
||||
xo = xml.getObject("Date");
|
||||
if (xo) Date=xo.getw();
|
||||
|
||||
if (xo) {
|
||||
wstring fDate = xo.getw();
|
||||
if (convertDateYMS(fDate, true) > 0)
|
||||
Date = fDate;
|
||||
}
|
||||
Name.clear();
|
||||
xo = xml.getObject("Name");
|
||||
if (xo) Name=xo.getw();
|
||||
|
||||
if (Name.empty()) {
|
||||
Name = lang.tl("Ny tävling");
|
||||
}
|
||||
|
||||
xo = xml.getObject("Annotation");
|
||||
if (xo) Annotation = xo.getw();
|
||||
|
||||
@ -1719,9 +1727,10 @@ pRunner oEvent::addRunner(const oRunner &r, bool updateStartNo) {
|
||||
Runners.push_back(r);
|
||||
pRunner pr=&Runners.back();
|
||||
|
||||
//cardToRunnerHash.reset();
|
||||
if (cardToRunnerHash && r.getCardNo() != 0) {
|
||||
cardToRunnerHash->emplace(r.getCardNo(), pr);
|
||||
}
|
||||
}
|
||||
|
||||
if (pr->StartNo == 0 && updateStartNo) {
|
||||
pr->StartNo = ++nextFreeStartNo; // Need not be unique
|
||||
@ -2637,13 +2646,12 @@ void oEvent::removeRunner(const vector<int> &ids)
|
||||
continue; //Already found.
|
||||
|
||||
//Remove a singe runner team
|
||||
autoRemoveTeam(r);
|
||||
|
||||
for (size_t k=0;k<r->multiRunner.size();k++)
|
||||
for (size_t k = 0; k < r->multiRunner.size(); k++) {
|
||||
if (r->multiRunner[k])
|
||||
toRemove.insert(r->multiRunner[k]->getId());
|
||||
|
||||
toRemove.insert(Id);
|
||||
}
|
||||
autoRemoveTeam(r);
|
||||
toRemove.insert(r->Id);
|
||||
}
|
||||
|
||||
if (toRemove.empty())
|
||||
@ -4797,8 +4805,7 @@ wstring oEvent::getPropertyStringDecrypt(const char *name, const string &def)
|
||||
return prop2;
|
||||
}
|
||||
|
||||
void oEvent::setPropertyEncrypt(const char *name, const string &prop)
|
||||
{
|
||||
void oEvent::setPropertyEncrypt(const char *name, const string &prop) {
|
||||
wchar_t bf[MAX_COMPUTERNAME_LENGTH + 1];
|
||||
DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
|
||||
GetComputerName(bf, &len);
|
||||
@ -4822,18 +4829,11 @@ void oEvent::setPropertyEncrypt(const char *name, const string &prop)
|
||||
setProperty(name, gdibase.widen(prop2));
|
||||
}
|
||||
|
||||
void oEvent::setProperty(const char *name, int prop)
|
||||
{
|
||||
void oEvent::setProperty(const char *name, int prop) {
|
||||
eventProperties[name]=itow(prop);
|
||||
}
|
||||
/*
|
||||
void oEvent::setProperty(const char *name, const string &prop)
|
||||
{
|
||||
eventProperties[name]=gdibase.toWide(prop);
|
||||
}*/
|
||||
|
||||
void oEvent::setProperty(const char *name, const wstring &prop)
|
||||
{
|
||||
void oEvent::setProperty(const char *name, const wstring &prop) {
|
||||
eventProperties[name] = prop;
|
||||
}
|
||||
|
||||
@ -5762,10 +5762,11 @@ void oEvent::sanityCheck(gdioutput &gdi, bool expectResult, int onlyThisClass) {
|
||||
|
||||
if (!it->tInTeam) {
|
||||
ClassType type = it->Class->getClassType();
|
||||
int cid = it->Class->getId();
|
||||
if (type == oClassIndividRelay) {
|
||||
it->setClassId(0, true);
|
||||
it->setClassId(it->Class->getId(), true);
|
||||
it->synchronize();
|
||||
it->setClassId(cid, true);
|
||||
it->synchronizeAll();
|
||||
}
|
||||
else if (type == oClassRelay) {
|
||||
if (!warnNoTeam) {
|
||||
|
||||
@ -650,9 +650,7 @@ public:
|
||||
|
||||
|
||||
void calculateSplitResults(int controlIdFrom, int controlIdTo);
|
||||
// Get total number of completed runner for given class and leg.
|
||||
void getNumClassRunners(int id, int leg, int &total, int &finished, int &dns) const;
|
||||
|
||||
|
||||
pTeam findTeam(const wstring &s, int lastId, unordered_set<int> &filter) const;
|
||||
pRunner findRunner(const wstring &s, int lastId, const unordered_set<int> &inputFilter, unordered_set<int> &filter) const;
|
||||
|
||||
@ -826,7 +824,7 @@ protected:
|
||||
mutable multimap<int, oAbstractRunner*> bibStartNoToRunnerTeam;
|
||||
|
||||
mutable shared_ptr<unordered_multimap<int, pRunner>> cardToRunnerHash;
|
||||
unordered_multimap<int, pRunner> &getCardToRunner() const;
|
||||
vector<pRunner> getCardToRunner(int cardNo) const;
|
||||
|
||||
mutable set<int> hiredCardHash;
|
||||
mutable int tHiredCardHashDataRevision = -1;
|
||||
|
||||
@ -61,7 +61,6 @@ oFreePunch::~oFreePunch(void)
|
||||
bool oFreePunch::Write(xmlparser &xml)
|
||||
{
|
||||
if (Removed) return true;
|
||||
|
||||
xml.startTag("Punch");
|
||||
xml.write("CardNo", CardNo);
|
||||
xml.write("Time", Time);
|
||||
|
||||
@ -2255,7 +2255,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
xml.startTag("ResultList");
|
||||
|
||||
xml.write("IOFVersion", "version", L"2.0.3");
|
||||
|
||||
wstring hhmmss = L"HH:MM:SS";
|
||||
exportIOFEvent(xml);
|
||||
|
||||
bool ClassStarted=false;
|
||||
@ -2304,13 +2304,13 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
|
||||
xml.startTag("Result");
|
||||
xml.startTag("StartTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(it->getStartTime(), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(it->getStartTime(), ZeroTime));
|
||||
xml.endTag();
|
||||
xml.startTag("FinishTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(it->getLegFinishTime(-1), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(it->getLegFinishTime(-1), ZeroTime));
|
||||
xml.endTag();
|
||||
|
||||
xml.write("Time", "timeFormat", L"HH:MM:SS", formatTimeIOF(it->getLegRunningTime(-1, false), 0));
|
||||
xml.write("Time", "timeFormat", hhmmss, formatTimeIOF(it->getLegRunningTime(-1, false), 0));
|
||||
xml.write("ResultPosition", it->getLegPlaceS(-1, false));
|
||||
|
||||
xml.write("CompetitorStatus", "value", it->Runners[0]->getIOFStatusS());
|
||||
@ -2333,7 +2333,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
xml.startTag("SplitTime", "sequence", itos(no++));
|
||||
xml.write("ControlCode", pcourse->Controls[k]->getFirstNumber());
|
||||
if (unsigned(k)<sp.size() && sp[k].time>0)
|
||||
xml.write("Time", "timeFormat", L"HH:MM:SS", formatTimeIOF(sp[k].time-it->tStartTime, 0));
|
||||
xml.write("Time", "timeFormat", hhmmss, formatTimeIOF(sp[k].time-it->tStartTime, 0));
|
||||
else
|
||||
xml.write("Time", L"--:--:--");
|
||||
|
||||
@ -2410,13 +2410,13 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
xml.write("CCardId", it->getCardNo());
|
||||
xml.endTag();
|
||||
xml.startTag("StartTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(it->getStartTime(), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(it->getStartTime(), ZeroTime));
|
||||
xml.endTag();
|
||||
xml.startTag("FinishTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(it->getFinishTimeAdjusted(), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(it->getFinishTimeAdjusted(), ZeroTime));
|
||||
xml.endTag();
|
||||
|
||||
xml.write("Time", "timeFormat", L"HH:MM:SS", formatTimeIOF(it->getRunningTime(),0));
|
||||
xml.write("Time", "timeFormat", hhmmss, formatTimeIOF(it->getRunningTime(),0));
|
||||
xml.write("ResultPosition", it->getPlaceS());
|
||||
|
||||
xml.write("CompetitorStatus", "value", it->getIOFStatusS());
|
||||
@ -2438,7 +2438,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
xml.startTag("SplitTime", "sequence", itos(no++));
|
||||
xml.write("ControlCode", pcourse->Controls[k]->getFirstNumber());
|
||||
if (unsigned(k)<sp.size() && sp[k].time>0)
|
||||
xml.write("Time", "timeFormat", L"HH:MM:SS", formatTimeIOF(sp[k].time - it->tStartTime, 0));
|
||||
xml.write("Time", "timeFormat", hhmmss, formatTimeIOF(sp[k].time - it->tStartTime, 0));
|
||||
else
|
||||
xml.write("Time", L"--:--:--");
|
||||
|
||||
@ -2459,6 +2459,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set<int>
|
||||
|
||||
void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldStylePatrol)
|
||||
{
|
||||
wstring hhmmss = L"HH:MM:SS";
|
||||
vector<SplitData> dummy;
|
||||
bool ClassStarted=false;
|
||||
int Id=-1;
|
||||
@ -2531,13 +2532,13 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldS
|
||||
xml.write("BibNumber", it->getStartNo());
|
||||
|
||||
xml.startTag("StartTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(it->getStartTime(), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(it->getStartTime(), ZeroTime));
|
||||
xml.endTag();
|
||||
xml.startTag("FinishTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(it->getFinishTimeAdjusted(), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(it->getFinishTimeAdjusted(), ZeroTime));
|
||||
xml.endTag();
|
||||
|
||||
xml.write("Time", "timeFormat", L"HH:MM:SS", formatTimeIOF(it->getRunningTime(), 0));
|
||||
xml.write("Time", "timeFormat", hhmmss, formatTimeIOF(it->getRunningTime(), 0));
|
||||
xml.write("ResultPosition", it->getPlaceS());
|
||||
xml.write("TeamStatus", "value", it->getIOFStatusS());
|
||||
|
||||
@ -2556,13 +2557,13 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldS
|
||||
xml.startTag("Result"); {
|
||||
xml.write("TeamSequence", k+1);
|
||||
xml.startTag("StartTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(r->getStartTime(), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(r->getStartTime(), ZeroTime));
|
||||
xml.endTag();
|
||||
xml.startTag("FinishTime");
|
||||
xml.write("Clock", "clockFormat", L"HH:MM:SS", formatTimeIOF(r->getFinishTimeAdjusted(), ZeroTime));
|
||||
xml.write("Clock", "clockFormat", hhmmss, formatTimeIOF(r->getFinishTimeAdjusted(), ZeroTime));
|
||||
xml.endTag();
|
||||
|
||||
xml.write("Time", "timeFormat", L"HH:MM:SS", formatTimeIOF(r->getRunningTime(), 0));
|
||||
xml.write("Time", "timeFormat", hhmmss, formatTimeIOF(r->getRunningTime(), 0));
|
||||
xml.write("ResultPosition", r->getPlaceS());
|
||||
|
||||
xml.write("CompetitorStatus", "value", r->getIOFStatusS());
|
||||
@ -2590,7 +2591,7 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set<int> &classes, bool oldS
|
||||
xml.startTag("SplitTime", "sequence", itos(no++));
|
||||
xml.write("ControlCode", pcourse->Controls[k]->getFirstNumber());
|
||||
if (unsigned(k)<sp.size() && sp[k].time>0)
|
||||
xml.write("Time", "timeFormat", L"HH:MM:SS", formatTimeIOF(sp[k].time - it->tStartTime, 0));
|
||||
xml.write("Time", "timeFormat", hhmmss, formatTimeIOF(sp[k].time - it->tStartTime, 0));
|
||||
else
|
||||
xml.write("Time", L"--:--:--");
|
||||
|
||||
|
||||
@ -284,7 +284,7 @@ int oListInfo::getMaxCharWidth(const oEvent *oe,
|
||||
const vector< pair<EPostType, wstring> > &typeFormats,
|
||||
gdiFonts font,
|
||||
const wchar_t *fontFace,
|
||||
bool large, int minSize) {
|
||||
bool large, int minSize) const {
|
||||
vector<oPrintPost> pps;
|
||||
for (size_t k = 0; k < typeFormats.size(); k++) {
|
||||
pps.push_back(oPrintPost());
|
||||
@ -1057,7 +1057,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
||||
case lClassResultFraction:
|
||||
if (pc && !invalidClass) {
|
||||
int total, finished, dns;
|
||||
oe->getNumClassRunners(pc->getId(), par.getLegNumber(pc), total, finished, dns);
|
||||
pc->getNumResults(par.getLegNumber(pc), total, finished, dns);
|
||||
swprintf_s(wbf, L"(%d / %d)", finished, total);
|
||||
}
|
||||
break;
|
||||
@ -1091,6 +1091,13 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
||||
}
|
||||
break;
|
||||
|
||||
case lClassNumEntries:
|
||||
if (pc) {
|
||||
int n = pc->getNumRunners(true, true, true);
|
||||
wsptr = &itow(n);
|
||||
}
|
||||
break;
|
||||
|
||||
case lCourseClimb:
|
||||
if (r) {
|
||||
pCourse crs = r->getCourse(false);
|
||||
@ -1658,7 +1665,7 @@ const wstring &oEvent::formatListStringAux(const oPrintPost &pp, const oListPara
|
||||
case lRunnerUMMasterPoint:
|
||||
if (r) {
|
||||
int total, finished, dns;
|
||||
oe->getNumClassRunners(pc->getId(), par.getLegNumber(pc), total, finished, dns);
|
||||
pc->getNumResults(par.getLegNumber(pc), total, finished, dns);
|
||||
int percent = int(floor(0.5+double((100*(total-dns-r->getPlace()))/double(total-dns))));
|
||||
if (r->getStatus()==StatusOK)
|
||||
swprintf_s(wbf, L"%d", percent);
|
||||
@ -2296,7 +2303,7 @@ bool oEvent::formatPrintPost(const list<oPrintPost> &ppli, PrintPostInfo &ppi,
|
||||
continue;
|
||||
}
|
||||
|
||||
int limit = 0;
|
||||
int limit = ppit->xlimit;
|
||||
|
||||
bool keepNext = false;
|
||||
//Skip merged entities
|
||||
@ -2337,20 +2344,20 @@ bool oEvent::formatPrintPost(const list<oPrintPost> &ppli, PrintPostInfo &ppi,
|
||||
if ((pp.type == lRunnerName || pp.type == lRunnerCompleteName ||
|
||||
pp.type == lRunnerFamilyName || pp.type == lRunnerGivenName ||
|
||||
pp.type == lTeamRunner || (pp.type == lPatrolNameNames && !t)) && rr) {
|
||||
ti = &ppi.gdi.addStringUT(y + pdy, x + pdx, pp.format, text,
|
||||
ti = &ppi.gdi.addStringUT(y + pdy, x + pdx, pp.format | skipBoundingBox, text,
|
||||
ppi.gdi.scaleLength(limit), ppi.par.cb, pp.fontFace.c_str());
|
||||
ti->setExtra(rr->getId());
|
||||
ti->id = "R";
|
||||
}
|
||||
else if ((pp.type == lTeamName || pp.type == lPatrolNameNames) && t) {
|
||||
ti = &ppi.gdi.addStringUT(y + pdy, x + pdx, pp.format, text,
|
||||
ti = &ppi.gdi.addStringUT(y + pdy, x + pdx, pp.format | skipBoundingBox, text,
|
||||
ppi.gdi.scaleLength(limit), ppi.par.cb, pp.fontFace.c_str());
|
||||
ti->setExtra(t->getId());
|
||||
ti->id = "T";
|
||||
}
|
||||
else {
|
||||
ti = &ppi.gdi.addStringUT(y + pdy, x + pdx,
|
||||
pp.format, text, ppi.gdi.scaleLength(limit), 0, pp.fontFace.c_str());
|
||||
pp.format | skipBoundingBox, text, ppi.gdi.scaleLength(limit), 0, pp.fontFace.c_str());
|
||||
}
|
||||
if (ti && ppi.keepToghether)
|
||||
ti->lineBreakPrioity = -1;
|
||||
@ -2733,11 +2740,26 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
PrintPostInfo printPostInfo(gdi, li.lp);
|
||||
//oCounter counter;
|
||||
//Render header
|
||||
vector< pair<EPostType, wstring> > v;
|
||||
for (auto &listPostList : { &li.Head, &li.subHead, &li.listPost, &li.subListPost }) {
|
||||
for (auto &lp : *listPostList) {
|
||||
if (lp.xlimit == 0) {
|
||||
v.clear();
|
||||
v.emplace_back(lp.type, lp.text);
|
||||
gdiFonts font = lp.getFont();
|
||||
lp.xlimit = li.getMaxCharWidth(this, gdi, li.getParam().selection, v, font, lp.fontFace.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (formatHead && li.getParam().showHeader) {
|
||||
for (auto &h : li.Head) {
|
||||
if (h.type == lCmpName || h.type == lString) {
|
||||
v.clear();
|
||||
const_cast<wstring&>(h.text) = li.lp.getCustomTitle(h.text);
|
||||
v.emplace_back(h.type, h.text);
|
||||
gdiFonts font = h.getFont();
|
||||
h.xlimit = li.getMaxCharWidth(this, gdi, li.getParam().selection, v, font, h.fontFace.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2748,7 +2770,7 @@ void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool form
|
||||
generateFixedList(gdi, li);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Apply for all teams (calculate start times etc.)
|
||||
for (oTeamList::iterator it = Teams.begin(); it != Teams.end(); ++it) {
|
||||
if (it->isRemoved() || it->tStatus == StatusNotCompetiting)
|
||||
|
||||
@ -53,6 +53,7 @@ enum EPostType
|
||||
lClassResultFraction,
|
||||
lClassAvailableMaps,
|
||||
lClassTotalMaps,
|
||||
lClassNumEntries,
|
||||
lCourseLength,
|
||||
lCourseName,
|
||||
lCourseClimb,
|
||||
@ -297,6 +298,7 @@ struct oPrintPost {
|
||||
GDICOLOR color;
|
||||
int dx;
|
||||
int dy;
|
||||
mutable int xlimit = 0;
|
||||
int legIndex;
|
||||
bool linearLegIndex;
|
||||
gdiFonts getFont() const {return gdiFonts(format & 0xFF);}
|
||||
@ -573,7 +575,7 @@ public:
|
||||
gdiFonts font,
|
||||
const wchar_t *fontFace = 0,
|
||||
bool large = false,
|
||||
int minSize = 0);
|
||||
int minSize = 0) const;
|
||||
|
||||
|
||||
int getMaxCharWidth(const oEvent *oe,
|
||||
@ -583,7 +585,7 @@ public:
|
||||
gdiFonts font,
|
||||
const wchar_t *fontFace = 0,
|
||||
bool large = false,
|
||||
int minSize = 0) {
|
||||
int minSize = 0) const {
|
||||
vector< pair<EPostType, wstring> > typeFormats(1, make_pair(type, formats));
|
||||
return getMaxCharWidth(oe, oe->gdiBase(), clsSel, typeFormats, font, fontFace, largeSize, minSize);
|
||||
}
|
||||
|
||||
@ -63,6 +63,12 @@ string oPunch::codeString() const
|
||||
return bf;
|
||||
}
|
||||
|
||||
void oPunch::appendCodeString(string &dst) const {
|
||||
char bf[32];
|
||||
sprintf_s(bf, 32, "%d-%d;", Type, Time);
|
||||
dst.append(bf);
|
||||
}
|
||||
|
||||
void oPunch::decodeString(const string &s)
|
||||
{
|
||||
Type=atoi(s.c_str());
|
||||
|
||||
@ -97,6 +97,8 @@ public:
|
||||
enum SpecialPunch {PunchStart=1, PunchFinish=2, PunchCheck=3, HiredCard=11111};
|
||||
void decodeString(const string &s);
|
||||
string codeString() const;
|
||||
void appendCodeString(string &dst) const;
|
||||
|
||||
oPunch(oEvent *poe);
|
||||
virtual ~oPunch();
|
||||
|
||||
|
||||
@ -215,7 +215,7 @@ oRunner::~oRunner()
|
||||
bool oRunner::Write(xmlparser &xml)
|
||||
{
|
||||
if (Removed) return true;
|
||||
|
||||
|
||||
xml.startTag("Runner");
|
||||
xml.write("Id", Id);
|
||||
xml.write("Updated", Modified.getStamp());
|
||||
@ -1916,6 +1916,12 @@ bool oRunner::operator<(const oRunner &c) const {
|
||||
return true;
|
||||
else if (tStartTime > c.tStartTime)
|
||||
return false;
|
||||
|
||||
const wstring &b1 = getBib();
|
||||
const wstring &b2 = c.getBib();
|
||||
if (b1 != b2) {
|
||||
return compareBib(b1, b2);
|
||||
}
|
||||
}
|
||||
else if (oe->CurrentSortOrder == SortByStartTimeClass) {
|
||||
if (tStartTime < c.tStartTime)
|
||||
@ -2558,7 +2564,7 @@ pRunner oRunner::nextNeedReadout() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unordered_multimap<int, pRunner> &oEvent::getCardToRunner() const {
|
||||
vector<pRunner> oEvent::getCardToRunner(int cardNo) const {
|
||||
if (!cardToRunnerHash || cardToRunnerHash->size() > Runners.size() * 2) {
|
||||
cardToRunnerHash = make_shared<unordered_multimap<int, pRunner>>();
|
||||
for (auto &rc : Runners) {
|
||||
@ -2570,16 +2576,33 @@ unordered_multimap<int, pRunner> &oEvent::getCardToRunner() const {
|
||||
cardToRunnerHash->emplace(cno, r); // The cache is "to large" -> filter is needed when looking into it.
|
||||
}
|
||||
}
|
||||
return *cardToRunnerHash;
|
||||
vector<pRunner> res;
|
||||
set<int> ids;
|
||||
auto rng = cardToRunnerHash->equal_range(cardNo);
|
||||
for (auto it = rng.first; it != rng.second; ++it) {
|
||||
pRunner r = it->second;
|
||||
if (!r->isRemoved() && r->getCardNo() == cardNo) {
|
||||
if (ids.insert(r->getId()).second)
|
||||
res.push_back(r);
|
||||
|
||||
for (pRunner r2 : r->multiRunner) {
|
||||
if (r2 && r2->getCardNo() == cardNo) {
|
||||
if (ids.insert(r2->getId()).second)
|
||||
res.push_back(r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
pRunner oEvent::getRunnerByCardNo(int cardNo, int time, CardLookupProperty prop) const {
|
||||
auto range = getCardToRunner().equal_range(cardNo);
|
||||
auto range = getCardToRunner(cardNo);
|
||||
bool skipDNS = (prop == CardLookupProperty::SkipNoStart || prop == CardLookupProperty::CardInUse);
|
||||
|
||||
if (range.first != range.second && std::distance(range.first, range.second) == 1) {
|
||||
if (range.size() == 1) {
|
||||
// Single hit
|
||||
pRunner r = range.first->second;
|
||||
pRunner r = range[0];
|
||||
if (r->isRemoved() || r->getCardNo() != cardNo)
|
||||
return nullptr;
|
||||
if (skipDNS && (r->getStatus() == StatusDNS || r->getStatus() == StatusCANCEL))
|
||||
@ -2594,11 +2617,7 @@ pRunner oEvent::getRunnerByCardNo(int cardNo, int time, CardLookupProperty prop)
|
||||
vector<pRunner> cand;
|
||||
bool forceRet = false;
|
||||
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
pRunner r = it->second;
|
||||
if (r->isRemoved() || r->getCardNo() != cardNo)
|
||||
continue;
|
||||
|
||||
for (auto r : range) {
|
||||
if (skipDNS && (r->getStatus() == StatusDNS || r->getStatus() == StatusCANCEL))
|
||||
continue;
|
||||
|
||||
@ -2700,11 +2719,8 @@ void oEvent::getRunnersByCardNo(int cardNo, bool sortUpdate, CardLookupProperty
|
||||
const_cast<oEvent *>(this)->synchronizeList(oListId::oLRunnerId);
|
||||
|
||||
if (cardNo != 0) {
|
||||
auto range = getCardToRunner().equal_range(cardNo);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
pRunner r = it->second;
|
||||
if (r->isRemoved() || r->getCardNo() != cardNo)
|
||||
continue;
|
||||
auto range = getCardToRunner(cardNo);
|
||||
for (auto r : range) {
|
||||
if (skipDNS && (r->getStatus() == StatusDNS || r->getStatus() == StatusCANCEL))
|
||||
continue;
|
||||
if (prop == CardLookupProperty::OnlyMainInstance && r->getRaceNo() != 0)
|
||||
@ -4657,6 +4673,7 @@ bool oRunner::matchName(const wstring &pname) const
|
||||
|
||||
split(tRealName, L" ", myNames);
|
||||
split(pname, L" ", inNames);
|
||||
int numInNames = inNames.size();
|
||||
|
||||
for (size_t k = 0; k < myNames.size(); k++)
|
||||
myNames[k] = canonizeName(myNames[k].c_str());
|
||||
@ -4677,7 +4694,7 @@ bool oRunner::matchName(const wstring &pname) const
|
||||
}
|
||||
}
|
||||
|
||||
return nMatched >= min<int>(myNames.size(), 2);
|
||||
return nMatched >= min<int>(max<int>(numInNames, myNames.size()), 2);
|
||||
}
|
||||
|
||||
oRunner::BibAssignResult oRunner::autoAssignBib() {
|
||||
@ -5998,4 +6015,18 @@ void oAbstractRunner::preventRestart(bool state) {
|
||||
getDI().setInt("NoRestart", state);
|
||||
tPreventRestartCache.first = state;
|
||||
tPreventRestartCache.second = oe->dataRevision;
|
||||
}
|
||||
}
|
||||
|
||||
int oRunner::getCheckTime() const {
|
||||
oPunch *p = nullptr;
|
||||
if (Card) {
|
||||
p = Card->getPunchByType(oPunch::PunchCheck);
|
||||
}
|
||||
else {
|
||||
p = oe->getPunch(Id, oPunch::PunchCheck, getCardNo());
|
||||
}
|
||||
if (p && p->Time > 0)
|
||||
return p->Time;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -567,6 +567,9 @@ public:
|
||||
// Returns true if there are radio control results, provided result calculation oEvent::ResultType::PreliminarySplitResults was invoked.
|
||||
bool hasOnCourseResult() const { return !tOnCourseResults.empty() || getFinishTime() > 0 || getStatus() != RunnerStatus::StatusUnknown; }
|
||||
|
||||
/** Returns a check time (or zero for no time). */
|
||||
int getCheckTime() const;
|
||||
|
||||
/** Get a runner reference (drawing) */
|
||||
pRunner getReference() const;
|
||||
|
||||
|
||||
@ -65,7 +65,7 @@ void oTeam::prepareRemove()
|
||||
bool oTeam::write(xmlparser &xml)
|
||||
{
|
||||
if (Removed) return true;
|
||||
|
||||
|
||||
xml.startTag("Team");
|
||||
xml.write("Id", Id);
|
||||
xml.write("StartNo", StartNo);
|
||||
|
||||
@ -205,21 +205,23 @@ void pdfwriter::generatePDF(const gdioutput &gdi,
|
||||
maxX *= scaleXFactor;
|
||||
float w = HPDF_Page_GetWidth(page);
|
||||
float h = HPDF_Page_GetHeight(page);
|
||||
float scale = (w / maxX) * 0.85f;
|
||||
float scale = (w / maxX) * 0.95f;
|
||||
float fontScale = 1.5f;
|
||||
|
||||
vector<RenderedPage> pages;
|
||||
PageInfo pageInfo;
|
||||
pageInfo.topMargin = h * 0.05f;
|
||||
pageInfo.topMargin = h * 0.03f;
|
||||
pageInfo.scaleX = scale * scaleXFactor;
|
||||
pageInfo.scaleY = scale;
|
||||
pageInfo.leftMargin = w * 0.07f;
|
||||
pageInfo.scaleY = scale * 1.1f;
|
||||
pageInfo.leftMargin = w * 0.03f;
|
||||
pageInfo.bottomMargin = pageInfo.topMargin * 1.0f;
|
||||
pageInfo.pageY = h;
|
||||
pageInfo.printHeader = true;
|
||||
pageInfo.yMM2PrintC = pageInfo.xMM2PrintC = 1199.551f / 420.f;
|
||||
pageInfo.yMM2PrintC *= fontScale;
|
||||
pageInfo.xMM2PrintK = 0;
|
||||
pageInfo.yMM2PrintK = 0;
|
||||
|
||||
|
||||
list<RectangleInfo> rectangles;
|
||||
pageInfo.renderPages(tl, rectangles, true, respectPageBreak, pages);
|
||||
for (size_t j = 0; j< pages.size(); j++) {
|
||||
@ -227,9 +229,11 @@ void pdfwriter::generatePDF(const gdioutput &gdi,
|
||||
if (!pinfo.empty()) {
|
||||
selectFont(page, fs, fontSmall, scale);
|
||||
HPDF_Page_BeginText (page);
|
||||
float df = min(w, h) * 0.02f;
|
||||
float df = min(w, h) * 0.04f;
|
||||
float sw = HPDF_Page_TextWidth(page, gdi.toUTF8(pinfo).c_str());
|
||||
HPDF_Page_TextOut (page, w - sw - df , h - df * 2.5f, gdi.toUTF8(pinfo).c_str());
|
||||
float sy = HPDF_Page_TextWidth(page, "MMM");
|
||||
|
||||
HPDF_Page_TextOut (page, w - sw - df , h - sy, gdi.toUTF8(pinfo).c_str());
|
||||
HPDF_Page_EndText(page);
|
||||
}
|
||||
|
||||
@ -269,7 +273,7 @@ void pdfwriter::generatePDF(const gdioutput &gdi,
|
||||
}
|
||||
}
|
||||
|
||||
selectFont(page, fonts[info[k].ti.font], info[k].ti.format, scale);
|
||||
selectFont(page, fonts[info[k].ti.font], info[k].ti.format, scale*fontScale);
|
||||
HPDF_Page_BeginText (page);
|
||||
float r = GetRValue(info[k].ti.color);
|
||||
float g = GetGValue(info[k].ti.color);
|
||||
@ -278,14 +282,14 @@ void pdfwriter::generatePDF(const gdioutput &gdi,
|
||||
string nt = gdi.toUTF8(info[k].ti.text);
|
||||
|
||||
if (info[k].ti.format & textRight) {
|
||||
float w = float(info[k].ti.xlimit) * scale;
|
||||
float w = float(info[k].ti.xlimit) * scale*fontScale;
|
||||
float sw = HPDF_Page_TextWidth(page, nt.c_str());
|
||||
float space = info[k].ti.xlimit > 0 ? 2 * HPDF_Page_GetCharSpace(page) : 0;
|
||||
HPDF_Page_TextOut (page, info[k].xp + w - sw - space, h - info[k].yp,
|
||||
nt.c_str());
|
||||
}
|
||||
else if (info[k].ti.format & textCenter) {
|
||||
float w = float(info[k].ti.xlimit) * scale;
|
||||
float w = float(info[k].ti.xlimit) * scale*fontScale;
|
||||
float sw = HPDF_Page_TextWidth(page, nt.c_str());
|
||||
HPDF_Page_TextOut (page, info[k].xp + w - sw/2, h - info[k].yp,
|
||||
nt.c_str());
|
||||
|
||||
@ -2436,3 +2436,7 @@ Patrol score, rogaining = Patrullpoäng, rogaining
|
||||
Rogaining points before automatic reduction = Rogainingpoäng före automatisk reduktion
|
||||
Runner's course id = Deltagares banans id
|
||||
Status code for cancelled entry = Statuskod för återbud
|
||||
Kunde inte öppna databasen (X) = Kunde inte öppna databasen (X)
|
||||
Kunde inte ladda upp löpardatabasen (X) = Kunde inte ladda upp löpardatabasen (X)
|
||||
Runner check time = Checktid
|
||||
ClassNumEntries = Antal anmälda i klassen
|
||||
|
||||
@ -98,9 +98,20 @@ const string &xmlparser::encodeXML(const string &input) {
|
||||
void xmlparser::write(const char *tag, const wstring &Value)
|
||||
{
|
||||
if (!cutMode || !Value.empty()) {
|
||||
fOut() << "<" << tag << ">"
|
||||
auto &valEnc = encodeXML(Value);
|
||||
if (valEnc.length() > 400) {
|
||||
fOut() << "<" << tag << ">"
|
||||
<< valEnc
|
||||
<< "</" << tag << ">" << endl;
|
||||
}
|
||||
else {
|
||||
char bf[512];
|
||||
sprintf_s(bf, "<%s>%s</%s>\n", tag, valEnc.c_str(), tag);
|
||||
fOut() << bf;
|
||||
}
|
||||
/*fOut() << "<" << tag << ">"
|
||||
<< encodeXML(Value)
|
||||
<< "</" << tag << ">" << endl;
|
||||
<< "</" << tag << ">" << endl;*/
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -109,17 +120,49 @@ void xmlparser::write(const char *tag, const wstring &Value)
|
||||
void xmlparser::write(const char *tag, const string &Value)
|
||||
{
|
||||
if (!cutMode || Value!="") {
|
||||
fOut() << "<" << tag << ">"
|
||||
<< encodeXML(Value)
|
||||
<< "</" << tag << ">" << endl;
|
||||
auto &valEnc = encodeXML(Value);
|
||||
if (valEnc.length() > 400) {
|
||||
fOut() << "<" << tag << ">"
|
||||
<< valEnc
|
||||
<< "</" << tag << ">" << endl;
|
||||
}
|
||||
else {
|
||||
char bf[512];
|
||||
sprintf_s(bf, "<%s>%s</%s>\n", tag, valEnc.c_str(), tag);
|
||||
fOut() << bf;
|
||||
}
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
}
|
||||
|
||||
void xmlparser::write(const char *tag, const char *Value)
|
||||
{
|
||||
if (!cutMode || Value != "") {
|
||||
auto &valEnc = encodeXML(Value);
|
||||
if (valEnc.length() > 400) {
|
||||
fOut() << "<" << tag << ">"
|
||||
<< valEnc
|
||||
<< "</" << tag << ">" << endl;
|
||||
}
|
||||
else {
|
||||
char bf[512];
|
||||
sprintf_s(bf, "<%s>%s</%s>\n", tag, valEnc.c_str(), tag);
|
||||
fOut() << bf;
|
||||
}
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
}
|
||||
|
||||
|
||||
void xmlparser::write(const char *tag)
|
||||
{
|
||||
fOut() << "<" << tag << "/>" << endl;
|
||||
char bf[128];
|
||||
sprintf_s(bf, "<%s/>\n", tag);
|
||||
fOut() << bf;
|
||||
|
||||
//fOut() << "<" << tag << "/>" << endl;
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
}
|
||||
@ -128,7 +171,7 @@ void xmlparser::write(const char *tag, const char *Property, const string &Value
|
||||
{
|
||||
if (!cutMode || Value!="") {
|
||||
fOut() << "<" << tag << " " << Property << "=\""
|
||||
<< encodeXML(Value) << "\"/>" << endl;
|
||||
<< encodeXML(Value) << "\"/>\n";
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -138,7 +181,7 @@ void xmlparser::write(const char *tag, const char *Property, const wstring &Valu
|
||||
{
|
||||
if (!cutMode || !Value.empty()) {
|
||||
fOut() << "<" << tag << " " << Property << "=\""
|
||||
<< encodeXML(Value) << "\"/>" << endl;
|
||||
<< encodeXML(Value) << "\"/>\n";
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -146,7 +189,8 @@ void xmlparser::write(const char *tag, const char *Property, const wstring &Valu
|
||||
|
||||
void xmlparser::write(const char *tag, const char *prop, const wchar_t *value)
|
||||
{
|
||||
write(tag, prop, wstring(value));
|
||||
encodeString = value;
|
||||
write(tag, prop, encodeString);
|
||||
}
|
||||
|
||||
void xmlparser::writeBool(const char *tag, const char *prop, bool value)
|
||||
@ -173,7 +217,7 @@ void xmlparser::write(const char *tag, const char *Property, const wstring &Prop
|
||||
if (!cutMode || Value != L"" || PropValue != L"") {
|
||||
fOut() << "<" << tag << " " << Property << "=\""
|
||||
<< encodeXML(PropValue) << "\">" << encodeXML(Value)
|
||||
<< "</" << tag << ">" << endl;
|
||||
<< "</" << tag << ">\n";
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -222,10 +266,10 @@ void xmlparser::write(const char *tag, const vector< pair<string, wstring> > &pr
|
||||
}
|
||||
if (!value.empty()) {
|
||||
fOut() << ">" << encodeXML(value)
|
||||
<< "</" << tag << ">" << endl;
|
||||
<< "</" << tag << ">\n";
|
||||
}
|
||||
else
|
||||
fOut() << "/>" << endl;
|
||||
fOut() << "/>\n";
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -239,7 +283,10 @@ void xmlparser::write(const char *tag, const char *prop,
|
||||
|
||||
void xmlparser::writeBool(const char *tag, const char *prop,
|
||||
bool propValue, const wstring &value) {
|
||||
write(tag, prop, propValue ? L"true" : L"false", value);
|
||||
static const wstring wTrue = L"true";
|
||||
static const wstring wFalse = L"false";
|
||||
|
||||
write(tag, prop, propValue ? wTrue : wFalse, value);
|
||||
}
|
||||
/*
|
||||
void xmlparser::write(const char *tag, const char *prop,
|
||||
@ -255,9 +302,12 @@ void xmlparser::write(const char *tag, const char *prop,
|
||||
void xmlparser::write(const char *tag, int Value)
|
||||
{
|
||||
if (!cutMode || Value!=0) {
|
||||
fOut() << "<" << tag << ">"
|
||||
<< Value
|
||||
<< "</" << tag << ">" << endl;
|
||||
char bf[256];
|
||||
sprintf_s(bf, "<%s>%d</%s>\n", tag, Value, tag);
|
||||
fOut() << bf;
|
||||
//fOut() << "<" << tag << ">"
|
||||
// << Value
|
||||
// << "</" << tag << ">" << endl;
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -266,9 +316,16 @@ void xmlparser::write(const char *tag, int Value)
|
||||
void xmlparser::writeBool(const char *tag, bool value)
|
||||
{
|
||||
if (!cutMode || value) {
|
||||
fOut() << "<" << tag << ">"
|
||||
<< (value ? "true" : "false")
|
||||
<< "</" << tag << ">" << endl;
|
||||
if (value) {
|
||||
char bf[256];
|
||||
sprintf_s(bf, "<%s>true</%s>\n", tag, tag);
|
||||
fOut() << bf;
|
||||
}
|
||||
else {
|
||||
char bf[256];
|
||||
sprintf_s(bf, "<%s>false</%s>\n", tag, tag);
|
||||
fOut() << bf;
|
||||
}
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -280,7 +337,7 @@ void xmlparser::write64(const char *tag, __int64 Value)
|
||||
if (!cutMode || Value!=0) {
|
||||
fOut() << "<" << tag << ">"
|
||||
<< Value
|
||||
<< "</" << tag << ">" << endl;
|
||||
<< "</" << tag << ">\n";
|
||||
}
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -289,7 +346,16 @@ void xmlparser::write64(const char *tag, __int64 Value)
|
||||
void xmlparser::startTag(const char *tag, const char *prop, const wstring &Value)
|
||||
{
|
||||
if (tagStackPointer<32) {
|
||||
fOut() << "<" << tag << " " << prop << "=\"" << encodeXML(Value) << "\">" << endl;
|
||||
const string &valEnc = encodeXML(Value);
|
||||
if (valEnc.length() < 128) {
|
||||
char bf[256];
|
||||
sprintf_s(bf, "<%s %s=\"%s\">\n", tag, prop, valEnc.c_str());
|
||||
fOut() << bf;
|
||||
}
|
||||
else {
|
||||
fOut() << "<" << tag << " " << prop << "=\"" << encodeXML(Value) << "\">" << endl;
|
||||
}
|
||||
|
||||
tagStack[tagStackPointer++]=tag;
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -302,7 +368,16 @@ void xmlparser::startTag(const char *tag, const char *prop, const wstring &Value
|
||||
void xmlparser::startTag(const char *tag, const char *prop, const string &Value)
|
||||
{
|
||||
if (tagStackPointer<32) {
|
||||
fOut() << "<" << tag << " " << prop << "=\"" << encodeXML(Value) << "\">" << endl;
|
||||
const string &valEnc = encodeXML(Value);
|
||||
if (valEnc.length() < 128) {
|
||||
char bf[256];
|
||||
sprintf_s(bf, "<%s %s=\"%s\">\n", tag, prop, valEnc.c_str());
|
||||
fOut() << bf;
|
||||
}
|
||||
else {
|
||||
fOut() << "<" << tag << " " << prop << "=\"" << encodeXML(Value) << "\">" << endl;
|
||||
}
|
||||
|
||||
tagStack[tagStackPointer++]=tag;
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -318,7 +393,7 @@ void xmlparser::startTag(const char *tag, const vector<string> &propvalue)
|
||||
for (size_t k=0;k<propvalue.size(); k+=2) {
|
||||
fOut() << propvalue[k] << "=\"" << encodeXML(propvalue[k+1]) << "\" ";
|
||||
}
|
||||
fOut() << ">" << endl;
|
||||
fOut() << ">\n";
|
||||
tagStack[tagStackPointer++]=tag;
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -330,11 +405,11 @@ void xmlparser::startTag(const char *tag, const vector<string> &propvalue)
|
||||
void xmlparser::startTag(const char *tag, const vector<wstring> &propvalue)
|
||||
{
|
||||
if (tagStackPointer<32) {
|
||||
fOut() << "<" << tag << " ";
|
||||
fOut() << "<" << tag ;
|
||||
for (size_t k=0;k<propvalue.size(); k+=2) {
|
||||
fOut() << encodeXML(propvalue[k]) << "=\"" << encodeXML(propvalue[k+1]) << "\" ";
|
||||
fOut() << " " << encodeXML(propvalue[k]) << "=\"" << encodeXML(propvalue[k+1]) << "\"";
|
||||
}
|
||||
fOut() << ">" << endl;
|
||||
fOut() << ">\n";
|
||||
tagStack[tagStackPointer++]=tag;
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -346,7 +421,9 @@ void xmlparser::startTag(const char *tag, const vector<wstring> &propvalue)
|
||||
void xmlparser::startTag(const char *tag)
|
||||
{
|
||||
if (tagStackPointer<32) {
|
||||
fOut() << "<" << tag << ">" << endl;
|
||||
char bf[128];
|
||||
sprintf_s(bf, "<%s>\n", tag);
|
||||
fOut() << bf;
|
||||
tagStack[tagStackPointer++]=tag;
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
@ -358,7 +435,11 @@ void xmlparser::startTag(const char *tag)
|
||||
void xmlparser::endTag()
|
||||
{
|
||||
if (tagStackPointer>0) {
|
||||
fOut() << "</" << tagStack[--tagStackPointer] << ">" << endl;
|
||||
char bf[128];
|
||||
const char *tag = tagStack[--tagStackPointer].c_str();
|
||||
sprintf_s(bf, "</%s>\n", tag);
|
||||
fOut() << bf;
|
||||
|
||||
if (!fOut().good())
|
||||
throw meosException("Writing to XML file failed.");
|
||||
}
|
||||
|
||||
@ -115,6 +115,7 @@ protected:
|
||||
|
||||
gdioutput *utfConverter;
|
||||
|
||||
mutable wstring encodeString;
|
||||
public:
|
||||
void access(int index);
|
||||
|
||||
@ -158,6 +159,8 @@ public:
|
||||
void write(const char *tag, const vector< pair<string, wstring> > &propValue, const wstring &value);
|
||||
|
||||
void write(const char *tag, const string &value);
|
||||
void write(const char *tag, const char *value);
|
||||
|
||||
void write(const char *tag, const wstring &value);
|
||||
|
||||
void write(const char *tag, int value);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user