From a4e26894188a66d03264e757a3a4560fd2f87ea5 Mon Sep 17 00:00:00 2001 From: Erik Melin <31467290+erikmelin@users.noreply.github.com> Date: Tue, 18 Jun 2019 22:30:29 +0200 Subject: [PATCH] MeOS version 3.6.1086 --- code/SportIdent.cpp | 147 ++++++++---- code/SportIdent.h | 24 +- code/TabClass.cpp | 10 +- code/TabCompetition.cpp | 19 +- code/TabList.cpp | 2 +- code/TabRunner.cpp | 6 +- code/TabSI.cpp | 21 ++ code/TimeStamp.cpp | 16 +- code/TimeStamp.h | 10 +- code/csvparser.cpp | 26 +-- code/english.lng | 4 + code/french.lng | 507 +++++++++++++++++++++++++++------------- code/gdifonts.h | 1 + code/gdioutput.cpp | 91 +++++--- code/gdioutput.h | 8 +- code/generalresult.cpp | 2 + code/infoserver.cpp | 19 +- code/iof30interface.cpp | 38 ++- code/iof30interface.h | 2 +- code/meosversion.cpp | 9 +- code/metalist.cpp | 9 +- code/oCard.cpp | 17 +- code/oCard.h | 4 +- code/oClass.cpp | 234 ++++++++++++------- code/oClass.h | 14 ++ code/oControl.cpp | 2 +- code/oCourse.cpp | 13 +- code/oCourse.h | 4 +- code/oEvent.cpp | 43 ++-- code/oEvent.h | 6 +- code/oFreePunch.cpp | 1 - code/oImportExport.cpp | 33 +-- code/oListInfo.cpp | 38 ++- code/oListInfo.h | 6 +- code/oPunch.cpp | 6 + code/oPunch.h | 2 + code/oRunner.cpp | 67 ++++-- code/oRunner.h | 3 + code/oTeam.cpp | 2 +- code/pdfwriter.cpp | 24 +- code/swedish.lng | 4 + code/xmlparser.cpp | 137 ++++++++--- code/xmlparser.h | 3 + 43 files changed, 1142 insertions(+), 492 deletions(-) diff --git a/code/SportIdent.cpp b/code/SportIdent.cpp index 0bc0b51..0e31efc 100644 --- a/code/SportIdent.cpp +++ b/code/SportIdent.cpp @@ -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(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 &punches) { + testCards.emplace(cardNo, punches); +} + +void SportIdent::debugLog(const wchar_t *msg) { + +} diff --git a/code/SportIdent.h b/code/SportIdent.h index ef3819d..fd0369d 100644 --- a/code/SportIdent.h +++ b/code/SportIdent.h @@ -9,6 +9,8 @@ #pragma once #endif // _MSC_VER > 1000 +#include + /************************************************************************ 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 punches; + + bool operator<(const TestCard &c) const { + return cardNo < c.cardNo; + } + + TestCard(int cardNo, const vector &punches) : cardNo(cardNo), + punches(punches) { + } + }; + + set testCards; + public: SI_StationInfo *findStation(const wstring &com); + /** Log debug data. */ + void debugLog(const wchar_t *ptr); + void getInfoString(const wstring &com, vector &info); bool isPortOpen(const wstring &com); bool autoDetect(list &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 &punches); void EnumrateSerialPorts(list &ports); diff --git a/code/TabClass.cpp b/code/TabClass.cpp index 598949a..80e6176 100644 --- a/code/TabClass.cpp +++ b/code/TabClass.cpp @@ -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 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); diff --git a/code/TabCompetition.cpp b/code/TabCompetition.cpp index d452cd2..2c9fd32 100644 --- a/code/TabCompetition.cpp +++ b/code/TabCompetition.cpp @@ -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 "); diff --git a/code/TabList.cpp b/code/TabList.cpp index dc96e05..b7f678f 100644 --- a/code/TabList.cpp +++ b/code/TabList.cpp @@ -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(); diff --git a/code/TabRunner.cpp b/code/TabRunner.cpp index ae74a0e..9ede707 100644 --- a/code/TabRunner.cpp +++ b/code/TabRunner.cpp @@ -1568,13 +1568,15 @@ void TabRunner::showRunnerReport(gdioutput &gdi) { } void TabRunner::generateRunnerReport(oEvent &oe, gdioutput &gdi, vector> &runnersToReport) { - + oe.synchronizeList({ oListId::oLRunnerId, oListId::oLTeamId, oListId::oLPunchId }); gdi.fillDown(); cTeam t = 0; set 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)); diff --git a/code/TabSI.cpp b/code/TabSI.cpp index 487e5d3..68288de 100644 --- a/code/TabSI.cpp +++ b/code/TabSI.cpp @@ -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 runners; + oe->getRunners(0, 0, runners, false); + for (pRunner r : runners) { + if (r->getCard() || r->getCardNo() == 0) + continue; + vector 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")); diff --git a/code/TimeStamp.cpp b/code/TimeStamp.cpp index 029cd12..2a0caf7 100644 --- a/code/TimeStamp.cpp +++ b/code/TimeStamp.cpp @@ -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; diff --git a/code/TimeStamp.h b/code/TimeStamp.h index 9889e2b..2586287 100644 --- a/code/TimeStamp.h +++ b/code/TimeStamp.h @@ -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;} diff --git a/code/csvparser.cpp b/code/csvparser.cpp index 619ede0..09c9d3b 100644 --- a/code/csvparser.cpp +++ b/code/csvparser.cpp @@ -723,13 +723,13 @@ int csvparser::selectPunchIndex(const wstring &competitionDate, const vector &sp) bool csvparser::checkSIConfigLine(const oEvent &oe, const vector &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 &sp, S vector< pair > 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 &sp, S return false; } } - + if ( (finish > 0 && finish != NOTIME) || punches.size() > 2) { card.clear(0); card.CardNumber = cardNo; diff --git a/code/english.lng b/code/english.lng index 7f6b52b..32797a3 100644 --- a/code/english.lng +++ b/code/english.lng @@ -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 diff --git a/code/french.lng b/code/french.lng index e02ebdf..88e00cd 100644 --- a/code/french.lng +++ b/code/french.lng @@ -1,4 +1,4 @@ -encoding = ANSI +encoding = ANSI %s m = %s m %s meter = %s mètres %s, block: %d = %s, bloc: %d @@ -18,7 +18,7 @@ Alla = Tous Alla banfiler = Tous les fichiers de circuit -oli Alla deltagare måste ha ett namn = Tous les concurrents doivent avoir un nom Alla fakturor = Toutes les factures -Alla händelser = Tous les evenements +Alla händelser = Tous les évènements Alla lag måste ha ett namn = Toutes les équipes doivent avoir un nom Alla listor = Toutes les listes Alla lopp = Toutes les courses @@ -31,7 +31,7 @@ Ange om kontrollen fungerar och hur den ska användas = Indiquez si le boîtier Ange startintervall för minutstart = Entrez l'intervalle de départ pour le départ Ange tiden relativt klassens första start = Entrez l'écart en temps par rapport au premier départ de la catégorie. Anm. avg. = Tarifs d'inscription -Anm. avgift = Tarif d'incription +Anm. avgift = Tarif d'inscription Anm. datum = Date d'inscription Anmäl = Entrer Anmäl X = Entrer X pour la compétition @@ -56,7 +56,7 @@ Antal kartor = Nombre de cartes Antal klasser = Nombre de catégorie Antal löpare = Nombre de coureurs Antal löpare på vanligaste banan X = Nombre de coureurs sur le circuit le plus utilisé: X -Antal misslyckade: X = Nombre d'inscriptions =erronnées: X +Antal misslyckade: X = Nombre d'inscriptions Antal startande per block = Nombre de départ par bloc Antal startande per intervall (inklusive redan lottade) = Nombre de départs par intervalle (y compris ceux déjà affectés) Antal sträckor = Nombre de branches @@ -96,7 +96,7 @@ Avgörande händelser = Evènement décisif Avgörs X = Prêt à X Avgörs kl = Prêt à Avläsning/radiotider = Lecture des puces/radio -Avmarkera allt = Tout déselectionner +Avmarkera allt = Tout désélectionner Avrundad tävlingsavgift = Droits d'inscriptions, arrondis Avsluta = Quitter Bad file format = Mauvais format @@ -139,7 +139,7 @@ BoldLarge = Gras, grand BoldSmall = Gras, petit Bommade kontroller = Erreurs de poste Bomtid = Temps perdu -Bomtid (max) = Temsp perdu (max) +Bomtid (max) = Temps perdu (max) Bomtid (medel) = Temps perdu (moyenne) Bomtid (median) = Temps perdu (médiane) Bomtid: X = Temps perdu: X @@ -168,7 +168,7 @@ ClubName = Nom du club ClubRunner = Club / Coureur CmpDate = Date de la compétition CmpName = Nom de la compétition -CourseClimb = Dénivellée circuit +CourseClimb = Dénivelée circuit CourseLength = Longueur circuit CourseName = Nom du circuit CourseResult = Résultat du circuit @@ -178,12 +178,12 @@ Databasvarning: X = Base de donnée, warning : X Datorröst som läser upp förvarningar = Annonce vocales des coureurs Datum = Date Decimalseparator = Séparateur décimal -DefaultFont = Formattage standard -Dela = temps intermédiaires -Dela efter ranking = Temps intermédiaire par classement -Dela klass: X = Temps intermédiaires catégorie: X -Dela klassen = Temps intermédiaires par catégorie -Dela klubbvis = Temps intermédiaire par club +DefaultFont = Formatage standard +Dela = Scinder +Dela efter ranking = Scinder par classement +Dela klass: X = Scinder la catégorie: X +Dela klassen = Scinder la catégorie +Dela klubbvis = Scinder par club Deltagare = Coureurs Deltagare %d = Coureur %d Deltagaren 'X' deltar i patrullklassen 'Y' men saknar patrull. Klassens start- och resultatlistor kan därmed bli felaktiga = Le coureur 'X' est dans la catégorie d'équipe 'Y', mais n'a pas d'équipe. Les résultats dans cette catégorie pourraient être faussés. @@ -194,7 +194,7 @@ Denna etapps nummer = Numéro d'étape Destinationskatalog = répertoire de destination Det går endast att sätta in vakanser på sträcka 1 = Vous pouvez ajouter des places vacantes seulement sur le premier partiel Det här programmet levereras utan någon som helst garanti. Programmet är = Ce programme est fourni tel quel, sans aucune garantie. Ce programme est -Direktanmälan = Saisie rapide +Direktanmälan = Inscription rapide Disk. = Disq. Distriktskod = Code de la Ligue Don't know how to align with 'X' = Impossible d'aligner avec 'X' @@ -223,7 +223,7 @@ Ej tidtagning = non chronométré Ekonomisk sammanställning = Synthèse financière Elektronisk = Electronique Elektronisk godkänd = Accepté électroniquement -Elit = Elite +Elit = Élite Elitavgift = Frais d'inscription pour les Elites Elitklasser = Catégorie Elite En gafflad sträcka = Un embranchement @@ -237,7 +237,7 @@ Etappresultat = Résultats des étapes Eventorkoppling = Connexion à Eventor Export av resultat/sträcktider = Export résultats / temps intermédiaires Exportera = Exporter -Exportera / Säkerhetskopiera = Export / Backup +Exportera / Säkerhetskopiera = Export / Sauvegarde Exportera alla till HTML = Exporter tout en HTML Exportera datafil = Export des données Exportera elektroniska fakturor = Exporter les factures électroniques @@ -245,7 +245,7 @@ Exportera inställningar och löpardatabaser = Export de la configuration et des Exportera löpardatabas = Export de la base des coureurs Exportera nu = Exporter maintenant Exportera på fil = Exporter dans un fichier -Exportera resultat på fil = Exporter les resultats dans un fichier +Exportera resultat på fil = Exporter les résultats dans un fichier Exportera startlista på fil = Exporter les listes de départ dans un fichier Exportera sträcktider = Export des temps intermédiaires Exportera tävlingsdata = Export des données @@ -273,7 +273,7 @@ Felst. = PM Fil att exportera till = Fichier à exporter vers Fil: X = Nom de fichier: X Filnamn = Nom de fichier -Filnamn (OCAD banfil) = Nom de fichier (circuitx OCAD) +Filnamn (OCAD banfil) = Nom de fichier (circuit OCAD) Filnamn IOF (xml) med klubbar = Nom de fichier IOF (xml) avec clubs Filnamn IOF (xml) med löpare = Nom de fichier IOF (xml) avec coureurs Filnamnet får inte vara tomt = Le nom de fichier ne peut être vide @@ -294,7 +294,7 @@ Flytta höger = Vers la droite Flytta vänster = Vers la gauche Format = Format Formaterat webbdokument (html) = Document web (html) -Formateringsregler = Règles de formattage +Formateringsregler = Règles de formatage Formulärläge = Mode formulaire Fortsätt = Continue Fri anmälningsimport = Inscriptions en format libre @@ -309,7 +309,7 @@ Följande deltagare har bytt klass = Les coureurs suivants ont changé de catég Följande deltagare har bytt klass (inget totalresultat) = Les coureurs suivants ont changé de catégorie (pas de résultat total) Följande deltagare har tilldelats en vakant plats = Les coureurs suivants ont pris une place vacante Följande deltagare är anmälda till nästa etapp men inte denna = Les coureurs suivants sont enregistrés pour l'étape suivante mais pas celle-ci -Följande deltagare är nyanmälda = Les coureurs suivants générès de nouvelles inscriptions +Följande deltagare är nyanmälda = Les coureurs suivants générés de nouvelles inscriptions Följande deltagare överfördes ej = Les coureurs suivant ont été ignorés För att ändra måltiden måste löparens målstämplingstid ändras = Pour modifier le temps de course, l'heure de poinçonnage de l'arrivée doit être changée För muspekaren över en markering för att få mer information = Survoler avec le pointeur de la souris une zone pour obtenir plus d'information @@ -418,9 +418,9 @@ Index = Index Individuell = par catégorie Individuell resultatlista, alla lopp = liste de résultat par nom, toute les courses Individuell resultatlista, sammanställning av flera lopp = liste de résultat par nom, résumé -Individuell resultatlista, visst lopp = liste de résultat par nom, specifique -Individuell resultatlista, visst lopp (STOR) = liste de résultat par nom, specifique (GRAND) -Individuell startlista, visst lopp = Liste de départ par nom, spécifi +Individuell resultatlista, visst lopp = liste de résultat par nom, spécifique +Individuell resultatlista, visst lopp (STOR) = liste de résultat par nom, spécifique (GRAND) +Individuell startlista, visst lopp = Liste de départ par nom, spécifique Individuella deltagare = Coureurs individuels Individuella slutresultat = Résultats finaux individuels Individuella totalresultat = Résultats totaux individuels @@ -460,7 +460,7 @@ Klart. X deltagare importerade = Terminé. X coureurs importés Klart. X lag importerade = Terminé. X équipes importées Klart. X patruller importerade = Terminé. X patrouille importées Klart: alla klasser lottade = Tirage de toutes les catégories terminé -Klart: inga klasser behövde lottas = Terminé:aucune catégorie ne necessite un nouveau tirage +Klart: inga klasser behövde lottas = Terminé : aucune catégorie ne nécessite un nouveau tirage Klass = Catégorie Klass %d = Catégorie %d Klass saknad = Catégorie absente @@ -474,7 +474,7 @@ Klassen måste ha ett namn = La catégorie doit avoir un nom Klassens bana = Circuit de la catégorie Klasser = Catégories Klasser (IOF, xml) = Catégories (IOF, xml) -Klasser där nyanmälningar ska överföras = Catégories dans laquelle les nouvelles inscriptions vont être transferrées +Klasser där nyanmälningar ska överföras = Catégories dans laquelle les nouvelles inscriptions vont être transférées Klassinställningar = Configuration des catégories Klassnamn = Nom de la catégorie Klasstyp = Type de la catégorie @@ -484,7 +484,7 @@ Klistra in data från urklipp (X) = Coller depuis le presse papier (X) Klocktid: X = Heure courante: X Klubb = Club Klubb att ta bort = Club à supprimer -Klubb: X = Club: X +Klubb: X = Club : X KlubbId = Id du Club Klubbar = Clubs Klubbar (IOF, xml) = Clubs (IOF, xml) @@ -530,13 +530,13 @@ Källkatalog = Répertoire source Kön = Sexe Kör kontroll inför tävlingen = Vérification de la compétition Ladda upp öppnad tävling på server = Upload de la compétition sur le serveur -Lag = Equipe -Lag %d = Equipe %d -Lag(flera) = Equipes +Lag = Équipe +Lag %d = Équipe %d +Lag(flera) = Équipes Laget 'X' saknar klass = L'équipe 'X' n'a pas de catégorie -Laget hittades inte = Equipe non trouvée +Laget hittades inte = Équipe non trouvée Lagnamn = Nom de l'équipe -Lagrade säkerhetskopior = Copies sauvergardées +Lagrade säkerhetskopior = Copies sauvegardées Land = Pays LargeFont = Texte en grand Latitud = Latitude @@ -586,7 +586,7 @@ Lägger till klubbar = Ajout de club Lägger till löpare = Ajout de participants Längd (m) = Distance (m) Länk till resultatlistan = Lien vers les résultats -Länk till startlistan = Lien vers les listes de départr +Länk till startlistan = Lien vers les listes de départ Läs brickor = Lecture de puce Läser klubbar = Lecture de clubs Läser löpare = Lecture de coureurs @@ -653,7 +653,7 @@ Namn = Nom Nationalitet = Nationalité Nollställ avgifter = RAZ des frais d'inscription Nollställ databaser = RAZ base de données -Nollställde avgift för X deltagare = Effacement des droits d'inscription pour X competiteur(s) +Nollställde avgift för X deltagare = Effacement des droits d'inscription pour X coureur(s) Nolltid = Heure zéro None = Aucun Normal = Normal @@ -700,7 +700,7 @@ Omstart = Redémarrage Omstart i stafettklasser = Redémarrage du relais Omstartstid = Heure de redémarrage Omvänd jaktstart = Chasse inversée -Oparad = Non apairés +Oparad = Non appairés Operationen misslyckades = Echec de l'opération Operationen stöds ej = Opération non supportée Optimerar startfördelning = Optimisation de la distribution des horaires de départ @@ -708,9 +708,9 @@ Ordinarie anmälningsdatum = Date de dernière inscription Ordinarie avgift = Frais d'inscription normaux Organisation = Organisation Oväntad kontroll 'X' i bana Y = Poste 'X' non prévu dans le circuit Y -Packar upp löpardatabas = Expension de la base des coureurs +Packar upp löpardatabas = Extension de la base des coureurs Par- eller singelklass = Catégorie pour patrouille ou individuel -Para ihop = Apairage +Para ihop = Appairage Para ihop bricka X med en deltagare = Association de la puce X avec un coureur Parallell = Parallèle PatrolClubNameNames = Clubs des coureurs (ou de la patrouille) @@ -757,7 +757,7 @@ Ranking (IOF, xml, csv) = Classement (IOF, xml, csv) Rapport inför = Rapport pour Rapporter = Rapports Rapportläge = Mode rapport -Red. avg. efteranm = Retardat. réduit +Red. avg. efteranm = Retardat. Réduit Red. avgift = Réduit Redigera deltagaren = Editer le coureur Redigera lista = Editer la liste @@ -780,6 +780,7 @@ Resultat - X = Résultats - X Resultat banvis per klass = Résultat circuit-wise par catégorie Resultat efter klass och bana - X = Résultats par catégorie et circuit - X Resultat efter sträcka %d = Résultats après le relayeur %d +Resultat efter sträcka X = Résultats après le partiel X Resultat efter sträckan = Résultats après le relayeur Resultat för ett visst lopp = Résultats pour une course donnée Resultat lopp X - Y = Résultats pour la course X - Y @@ -795,11 +796,11 @@ Resultatlistor = Résultats Resultatutskrift = Imprimer les résultats Resultatutskrift / export = Imprimer / Exporter les résultats Rogaining = Course au score -Rogaining, individuell = Course au score indivduelle +Rogaining, individuell = Course au score individuelle Rogaining-poäng = Points (course au score) RogainingPunch = Poinçon (course au score) Rubrik = Titre -Rulla upp och ner automatiskt = Défillement vertical automatique +Rulla upp och ner automatiskt = Défilement vertical automatique Runner = Coureur RunnerBib = Dossard du coureur RunnerCard = Puce du coureur @@ -821,7 +822,7 @@ RunnerRogainingPoint = Points de la course au score RunnerStart = Heure de départ du coureur RunnerStartNo = Numéro de départ du coureur RunnerTempTimeAfter = Temps du coureur après le poste sélectionné -RunnerTempTimeStatus =Temps/statut du coureur au poste sélectionné +RunnerTempTimeStatus = Temps/statut du coureur au poste sélectionné RunnerTime = Temps du coureur RunnerTimeAfter = Retard du coureur RunnerTimeAfterDiff = Différence de retard du coureur @@ -833,7 +834,7 @@ RunnerTotalTime = Temps consolidé du coureur RunnerTotalTimeAfter = Retard consolidé du coureur RunnerTotalTimeStatus = Temps / statut consolidé du coureur RunnerUMMasterPoint = Master points Uppsala möte -SI X inläst. Brickan tillhör Y som saknar klass = La puce X a été lue. La puce appartientt à Y, qui n'a pas de catégorie +SI X inläst. Brickan tillhör Y som saknar klass = La puce X a été lue. La puce appartient à Y, qui n'a pas de catégorie SI X inläst. Brickan är inte knuten till någon löpare (i skogen) = La puce X a été lue. La puce est associé à aucun coureur (en forêt) SI X är redan inläst. Använd interaktiv inläsning om du vill läsa brickan igen = La puce X a déjà été lue. Utiliser la lecture interactive pour la relire. SI X är redan inläst. Ska den läsas in igen? = La puce X a déjà été lue. La relire ? @@ -841,7 +842,7 @@ SI på = SI en marche SI-dubbletter: %d = SI dupliqué: %d SOFT-avgift = Frais d'inscription SOFT [SOFT fee] SOFT-lottning = Méthode de tirage suédoise -Saknad starttid = Heurede départ manquante +Saknad starttid = Heure de départ manquante Sammanställning = Résumé Sammanställning, ekonomi = Résumé financier Sammanställning, klasser = Résumé des catégories @@ -871,7 +872,7 @@ Skapa generell lista = Créer la liste générale Skapa listan = Créer la liste Skapa ny klass = Créer une nouvelle catégorie Skapad av = Créé par -Skapade en bana för klassen %s med %d kontroller från brickdata (SI-%d) = Un circuit pour la catégorie %s avec %d poste dans la puce %d aété créée. +Skapade en bana för klassen %s med %d kontroller från brickdata (SI-%d) = Un circuit pour la catégorie %s avec %d poste dans la puce %d a été créée. Skapade en lokal kopia av tävlingen = Copie locale de la compétition créée Skapar ny etapp = Créer une nouvelle étape Skapar ny tävling = Création d'une nouvelle compétition @@ -932,10 +933,10 @@ Stafett - sammanställning = Relais - résumé Stafett - sträcka = Relais - relayeur Stafett - total = Relais - total Stafettklasser = Catégories pour le relais -Stafettresultat, delsträckor = Résulats du relais, detail relayeurs -Stafettresultat, lag = Résulats du relais, équipe -Stafettresultat, sträcka = Résulats du relais, par relayeur -Stafettresultat, sträcka (STOR) = Résulats du relais, par relayeur (GRAND) +Stafettresultat, delsträckor = Résultats du relais, détail relayeurs +Stafettresultat, lag = Résultats du relais, équipe +Stafettresultat, sträcka = Résultats du relais, par relayeur +Stafettresultat, sträcka (STOR) = Résultats du relais, par relayeur (GRAND) Start = Départ Start nr = Départ no. StartTime = Neure de départ, nom @@ -1018,7 +1019,7 @@ Synkronisera med Eventor = Synchroniser avec Eventor Säkerhetskopiera = Sauvegarder/Enregistrer sous Sätt okända löpare utan registrering till = Définir le statut pour les coureurs non enregistrés Sätt som oparad = Non appairé -Sätter reptid (X) och omstartstid (Y) för = Appliquer le temps de corde [Applying rope time] (X) et l'heure de redémarrage (Y) pour +Sätter reptid (X) och omstartstid (Y) för = Temps de corde (X) et heure de redémarrage (Y) appliqués pour Sök = Rechercher Sök (X) = Rechercher (X) Sök deltagare = Rechercher un coureur @@ -1035,7 +1036,7 @@ Ta bort stämpling = Supprimer le poinçon Ta bort valda rader från tabellen (X) = Supprimer les lignes sélectionnées de la table (X) Tabell = Table Tabelläge = Mode table -Team = Equipe +Team = Équipe TeamBib = Dossard de l'équipe TeamClub = Club de l'équipe TeamLegTimeAfter = Retard de l'équipe au relayeur @@ -1083,7 +1084,7 @@ Tilldelning av hyrbrickor = Affecter les puces louées Tillgängliga automater = Services disponibles Tillsatte vakans = Vacants utilisés Tillsätt vakans = Remplir les vacants -Tillämpa parstart = Démarrer l'apairage +Tillämpa parstart = Démarrer l'appairage Tillåt decimaler = Autoriser les décimales Tillåt direktanmälan = Autoriser la saisie rapide Tillåt valutauttryck med decimaler = Autoriser les expressions monétaires avec décimales @@ -1157,7 +1158,7 @@ Vakanser och efteranmälda = Vacants et retardataires Vakanser stöds ej i stafett = Les vacants ne sont pas supporté en relais Vakant = Vacant Val av export = Choisir Export -Valbar = Optionel +Valbar = Optionnel Vald bricka = Puce choisie Valuta = Devise Valutakod = Code devise @@ -1188,7 +1189,7 @@ Vill du skapa en ny klass? = Voulez-vous créer une nouvelle catégorie ? Vill du spara ändringar? = Voulez-vous enregistrer les changements ? Vill du verkligen radera alla starttider i X? = Voulez-vous vraiment effacer les horaires de départ dans X? Vill du verkligen radera starttider i X klasser? = Voulez-vous vraiment effacer les horaires de départ de la catégorie X ? -Vill du verkligen radera tävlingen? = Sohaitez-vous supprimer la compétition ? +Vill du verkligen radera tävlingen? = Souhaitez-vous supprimer la compétition ? Vill du verkligen stänga MeOS? = Souhaitez-vous fermer MeOS ? Vill du verkligen ta bort laget? = Souhaitez-vous supprimer l'équipe ? Vill du verkligen ta bort löparen? = Souhaitez-vous supprimer le coureur ? @@ -1210,13 +1211,13 @@ Visualisera startfältet = Visualisation des champs de départ Vuxen = Adulte Vuxenklasser = Catégories adultes Vuxna = Adultes -Välj Spara för att lagra brickorna. Interaktiv inläsning är INTE aktiverad = Clicker sur pour enregistrer la puce. La lecture interactive n'est pas activée -Välj Spara för att lagra brickorna. Interaktiv inläsning är aktiverad = Clicker sur pour enregistrer les puces. La lecture interactive est activée +Välj Spara för att lagra brickorna. Interaktiv inläsning är INTE aktiverad = Cliquer sur pour enregistrer la puce. La lecture interactive n'est pas activée +Välj Spara för att lagra brickorna. Interaktiv inläsning är aktiverad = clinker sur pour enregistrer les puces. La lecture interactive est activée Välj alla = Sélectionner tout Välj alla klasser = Sélectionner toutes les catégories Välj allt = Sélectionner tout Välj automatiskt = Sélection automatique -Välj den etapp som föregår denna tävling = Sélectionner l'étape précdente +Välj den etapp som föregår denna tävling = Sélectionner l'étape précédente Välj den etapp som kommer efter denna tävling = Sélectionner l'étape suivante Välj en vakant plats nedan = Choisissez une place vacante ci-dessous Välj ingen = Désélectionner @@ -1238,7 +1239,7 @@ Välj skrivare = Choisir une imprimante Välj tävling = Choisir une compétition Välj vilka klasser och kontroller du vill bevaka = Choisir les catégories et les postes que vous souhaitez observer Välj vilka klasser och kontroller som bevakas = Sélectionner les catégories et les postes à observer -Välj vilka kolumner du vill visa = Choisr les colonnes à afficher +Välj vilka kolumner du vill visa = Choisir les colonnes à afficher Välj vy = Choisir la vue Välkommen till MeOS = Bienvenue dans MeOS Vänligen betala senast = Merci de régler au plus tard le @@ -1271,7 +1272,7 @@ ask:addpunches = Aucune puce n'a été lue pour ce coureur. Voulez-vous ajouter ask:changedclassfee = Le tarif a été modifié pour certaines catégories. Voulez-vous appliquer les nouveaux tarifs aux coureurs déjà présents dans ces catégories ?\n\nAttention: les frais d'inscription affectés manuellement seront écrasés. ask:changedcmpfee = Les tarifs ont été modifiés. Voulez-vous appliquer les nouveaux tarifs aux coureurs et classes existantes ?\n\nAttention les frais d'inscription affectés manuellement seront écrasés. ask:firstasstart = Il existe des coureurs ayant des résultats pour ce circuit. Si vous utilisez le premier poste comme départ, les heures de départ seront écrasées.\n\nSouhaitez-vous continuer ? -ask:kiosk = Quand vous démarrez le kiosque de résultats, vous mettez MeOS dans un mode où il est uniquement possible d'afficher les résultats. Aucune autre opération n'est autorisée jusqu'à ce que le programme soir redémarré. S'il y a un boîtier SI actif raccordé à l'ordinateur, MeOS affichera automatiquement les résultats pour la dernière puce lue.\n\nVous devriez penser à protéger la base de donnée avec un mot de passe, si la diffusion est rendue publique.\n\nVoulez-vous démarrer la difusion des résultats ? +ask:kiosk = Quand vous démarrez le kiosque de résultats, vous mettez MeOS dans un mode où il est uniquement possible d'afficher les résultats. Aucune autre opération n'est autorisée jusqu'à ce que le programme soir redémarré. S'il y a un boîtier SI actif raccordé à l'ordinateur, MeOS affichera automatiquement les résultats pour la dernière puce lue.\n\nVous devriez penser à protéger la base de donnée avec un mot de passe, si la diffusion est rendue publique.\n\nVoulez-vous démarrer la diffusion des résultats ? ask:missingcourse = Des catégories (X) n'ont pas de circuit.\n\nMeOS utilise les circuits lors du tirage pour éviter que les coureurs ayant le même premier poste ne partent en même temps.\n\nVoulez-vous continuer tout de même ? ask:overwrite_server = La compétition est déjà sur le serveur. Voulez-vous écraser la compétition présente sur le serveur ? ask:overwriteconfirm = Vous avez choisi d'écraser la compétition. Vérifiez que personne d'autre n'est connecté.\n\nSouhaitez vous continuer ? @@ -1292,13 +1293,14 @@ fritt att använda och du är välkommen att distribuera det under vissa villkor fyra = quatrième går i mål på X plats med tiden Y = termine X en Y går i mål på X plats, efter Y, på tiden Z = termine X, derrière Y, en Z -går upp i delad ledning med tiden X = partage la tête de la course avec un temps de X +går i mål på delad X plats med tiden Y = finit ex-aequo en Xème place, en Y +går upp i delad ledning med tiden X = partage la tête de la course en X handskakning = authentification har startat = a démarré help:10000 = Un service dans MeOS est un petit programme qui, de temps à autre ou lorsque les données de la compétition changent, fait des choses automatiquement. -help:12138 = Choisr une catégorie à fusionner avec la catégorie choisie. Si le tirage des catégories a été effectué, vous devez refaire un tirage, car les coureurs conservent leur horaire de départ. -help:12290 = La compétition a été créée avec une autre version de MeOS et ne peut pas être ouverte depuis le serveur. Vous pouvez toutefois la compétition depuis un fichier. -help:12352 = Cette opération supprime le club que vous avez choisi (%s, id=%d) et déplace tous les coureurs de ce club vers le club que vous choisissez ci-dessous. L'opération ne peut être annulée. +help:12138 = Choisir une catégorie à fusionner avec la catégorie choisie. Si le tirage des catégories a été effectué, vous devez refaire un tirage, car les coureurs conservent leur horaire de départ. +help:12290 = La compétition a été créée avec une autre version de MeOS et ne peut pas être ouverte depuis le serveur. Vous pouvez toutefois importer la compétition depuis un fichier. +help:12352 = Cette opération supprime le club que vous avez choisi (%s, id help:12662 = Ajoutez des postes en ajoutant une séquence de numéros de postes. Vous ne devez pas préciser l'arrivée. Exemple: 31, 50, 36, 50, 37, 100. help:14070 = Le port TCP est utilisé pour recevoir les poinçons par TCP depuis d'autres machines. Précisez le port utilisé. L'instant initial du protocole est 00:00:00. help:14343 = Une liste avec la puce lue est affichée. Pour affecter un coureur à une autre puce, double cliquez sur la puce ou le coureur que vous souhaitez déplacer. @@ -1311,46 +1313,46 @@ help:26963 = Un ensemble de circuits est utilisé pour définir un ensemble de p help:29191 = Vous pouvez installer les configurations, clubs et base de données des coureurs à partir d'un répertoire source spécifié. Vos configurations locales sont écrasées. MeOS devrait être redémarré après l'installation.\n\nLe bouton vous conduit à une page où vous pouvez exporter votre configuration courante. help:29758 = Ici vous gérez les clubs et l'impression des factures. Vous pouvez définir un tarif prenant en compte le type de catégorie et la date d'inscription. Les clubs en double (mal orthographiés) peuvent être regroupés dans le club correct. Vous pouvez également mettre à jour les adresses de clubs à partir du tableau de comptes. help:30750 = Vous pouvez créer un grand nombre de listes et rapports différents. Ceux-ci peuvent être visualisés à l'écran, imprimés, ou sauvés dans un format web. La liste est automatiquement mise à jour lorsque des données liées à la compétition changent. L'impression automatique des résultats s'obtient à partir de la page Services. Pour exporter les données de la compétition, par exemple les temps intermédiaires, aller à la page Compétition. -help:31661 = Un nouveau départ (en masse) est défini par une barrière horaire et une heure de reprise. A la barrière horaire les passages de relais sont terminés et aucun compétiteur n'est autorisé à partir en forêt. Les concurrents restants partent à l'heure de la barrière horaire. Il est possible de spécifier différents horaires pour des partiels précis, mais en utilisant cett efonction vous pouvez rapidement prendre en charge des catégories entières. +help:31661 = Un nouveau départ (en masse) est défini par une barrière horaire et une heure de reprise. A la barrière horaire les passages de relais sont terminés et aucun compétiteur n'est autorisé à partir en forêt. Les concurrents restants partent à l'heure de la barrière horaire. Il est possible de spécifier différents horaires pour des partiels précis, mais en utilisant cette fonction vous pouvez rapidement prendre en charge des catégories entières.\n\nSi des équipes refusent le départ en masse des attardés (possible aux CFC par exemple), il suffit de cocher dans la page Équipes la case 'Empêcher le redémarrage' des équipes concernées. help:33940 = Importer les inscriptions en format texte libre. Spécifier le nom, le club, la catégorie et le numéro de puce (éventuellement l'heure de départ), de préférence séparés par des virgules, une personne (équipe) par ligne. Il est également possible de spécifier plusieurs compétiteurs dans le même club / catégorie en laissant partiellement vides ces champs. Il est également possible d'importer des données formatées par d'autres moyens. -help:41072 = Sélectionner un poinçon dans la liste pour le modifier ou le supprimer. Vous pouvez ajouter des poinçons manquants à partir du modèle de course. Si l'heure d'arrivée est manquante, le coureur obtient le statut . Si un poinçon est manquant, le statut est . Il est impossible d'assigner un statut incompatible avec les poinçons. S'il y a un poinçon d'arrivée, vous devez le modifier pour pouvoir définir manuellement l'heure d'arrivée. Le même principe s'applique au poinçon de départ. -help:41641 = Entrez un premier horaire de départ et un intervalle. Tirage Aléatoire affecte un ordre de départ totalement aléatoire. La Méthode de Tirage Suédoie utilise des règles spéciales pour répartir les coureurs d'un même club. Départ groupé signifie que la catégorie complète part par petits groupes pendant la durée spécifiée (Départ en masse étendu). Dans le champ Partiel vous pouvez spécifier quel partiel doit être tiré au hasard si la catégorie en a plusieurs. -help:425188 = Vous pouvez gérer automatiquement les compétiteurs qui ne sont pas partis en lisant les boîtiers SI (clear/check/start/controls) dans SIConfig. Sauvegarder les données lues en tant que fichier texte dont les colonnes sont séparées par des points-virgules, et importez ce fichier dans MeOS. Les compétiteurs figurant dans cet import reçoivent un enregistrement. Vous pouvez alors donner le statut DNS à tous les compétiteurs n'ayant pas d'enregistrement. Si ultérieurement vous importez d'autres coureurs, vous pouvez réinitialiser le statut (de DNS à Inconnu) sur les compétiteurs alors importés. +help:41072 = Sélectionner un poinçon dans la liste pour le modifier ou le supprimer. Vous pouvez ajouter des poinçons manquants à partir du modèle de course. Si l'heure d'arrivée est manquante, le coureur obtient le statut . Si un poinçon est manquant, le statut est . Il est impossible d'assigner un statut incompatible avec les poinçons. S'il y a un poinçon d'arrivée, vous devez le modifier pour pouvoir définir manuellement l'heure d'arrivée. Le même principe s'applique au poinçon de départ. +help:41641 = Entrez un premier horaire de départ et un intervalle. Tirage Aléatoire affecte un ordre de départ totalement aléatoire. La Méthode de Tirage Suédoise utilise des règles spéciales pour répartir les coureurs d'un même club. Départ groupé signifie que la catégorie complète part par petits groupes pendant la durée spécifiée (Départ en masse étendu). Dans le champ Partiel vous pouvez spécifier quel partiel doit être tiré au hasard si la catégorie en a plusieurs. +help:425188 = Vous pouvez gérer automatiquement les compétiteurs qui ne sont pas partis en lisant les boîtiers SI (clear/check/start/control) dans SI Config. Sauvegarder les données lues en tant que fichier texte dont les colonnes sont séparées par des points-virgules, et importez ce fichier dans MeOS. Les compétiteurs figurant dans cet import reçoivent un enregistrement. Vous pouvez alors donner le statut Non partant à tous les compétiteurs n'ayant pas d'enregistrement. Si ultérieurement vous importez d'autres coureurs, vous pouvez réinitialiser le statut (de Non partant à Inconnu) sur les compétiteurs alors importés. help:471101 = Activez le boîtier SI en sélectionnant son port COM ou en recherchant les boîtiers SI installés. Appuyez sur Information pour obtenir le statut du port sélectionné.\n\nLecture Interactive vous permet de gérer directement les problèmes tels qu'un numéro de puce erroné. N'utilisez pas cette possibilité quand les compétiteurs ayant des problèmes sont pris en charge séparément.\n\nLa base de données des compétiteurs est utilisée si vous voulez ajouter automatiquement de nouveaux compétiteurs. Les poinçons sont utilisés pour trouver (détecter) la bonne catégorie. help:50431 = Vous êtes désormais connecté à un serveur. Pour ouvrir une compétition sur le serveur, sélectionnez le dans la liste et cliquer Ouvrir. Ajoutez une compétition au serveur, ouvrez la compétition en local et sélectionnez Télécharger. Quand vous aurez ouvert une compétition sur le serveur, vous pourrez voir tous les autres clients MeOS connectés. -help:52726 = Connectez vous à un serveur ci-dessous.\n\nInstallation\nTélécharger et installer MySQL 5 (Community Edition) depuis www.mysql.com. Vous pouvez utiliser la configuration par défaut. Il est uniquement nécessaire d'installer MySQL sur l'ordinateur servant de serveur. Quand MySQL est installé, démarrer MySQL Command Line Client et créez un compte utilisateur pour MeOS. Ecrire quelque chose du genre :\n\n> CREATE USER meos;\nGRANT ALL ON *.* TO meos;\n\nVous avez maintenant un utilisateur meos sans mot de passe. Entrez le nom du serveur ci-dessous (vous pouvez avoir à configurer les pare-feu pour laisser passer le traffic).\n\nComme alternative vous pouvez utiliser le compte root d'origine de MySQL. Le nom d'utilisateur est 'root' et le mot de passe est celui donné lors de l'installation de MySQL. +help:52726 = Connectez vous à un serveur ci-dessous.\n\nInstallation\nTélécharger et installer MySQL 5 (Community Edition) depuis www.mysql.com. Vous pouvez utiliser la configuration par défaut. Il est uniquement nécessaire d'installer MySQL sur l'ordinateur servant de serveur. Quand MySQL est installé, démarrer MySQL Command Line Client et créez un compte utilisateur pour MeOS. Ecrire quelque chose du genre :\n\n> CREATE USER MeOS;\nGRANT ALL ON *.* TO MeOS;\n\nVous avez maintenant un utilisateur MeOS sans mot de passe. Entrez le nom du serveur ci-dessous (vous pouvez avoir à configurer les pare-feu pour laisser passer le traffic).\n\nComme alternative vous pouvez utiliser le compte root d'origine de MySQL. Le nom d'utilisateur est 'root' et le mot de passe est celui donné lors de l'installation de MySQL. help:5422 = Pas de boîtier SI trouvé. Sont-ils connectés et démarrés ? help:59395 = Dans ce formulaire, vous pouvez rapidement effectuer des réglages de base en une seule opération pour plusieurs catégories.\n\nDépart est le nom du départ tel qu'il apparaît sur les liste d'horaire de départ.\n\nUn Bloc est un nombre entre 0 et 100 qui peut fournir une distribution des compétiteurs encore plus fine. Les catégories dans le même bloc seront imprimées dans la même minute sur les horaires de départ. \n\nIndex est une clé de tri. Les catégories sont triées à l'aide de cette clé dans toutes les listes.\n\nLe circuit peut être défini pour les catégories ayant exactement un circuit; s'il y a plusieurs circuits possibles vous devez utiliser le formulaire standard de catégorie.\n\nSaisie rapide détermine si la catégorie accepte les inscriptions rapides. -help:59395_more = The class fees, which shows if you have activated Economy features, are used for new entries. If you change a fee, MeOS will ask if you wish to apply the change to existing competitors.\n\nFor bibs you have the options None, Consecutive and Manual. You can also type the first bib in the class, for example A100, or 50. Consecutive means that the last number of the preceeding class is used to define the first number in this class. Reserved bib numbers gives a gap (of the specified width) in the numbering between classes.\n\nMeOS updates bibs when you draw start times or change the settings. Manual means that MeOS will never automatically update bibs.\n\nFor classes with teams the setting Team member controls the relation between the team number and the bibs. It can be the same, increasing (100, 101, 102), leg dependent (100-1, 100-2, etc.) or completely independent. +help:59395_more = Les tarifs par catégories sont appliqués aux nouvelles inscriptions, si vous avez activé Gestion et frais d'inscriptions. Si vous modifiez un tarif, MeOS vous demandera si vous voulez appliquer ce nouveau tarifs aux coureurs déjà inscrits. \n\nPour les dossards, vous avez le chois entre Aucun, Consécutif et Manuel. Vous pouvez aussi spécifier le premier dossard de la catégorie, par exemple A100, ou 50. Consécutif signifie que le dernier dossard d'une catégorie est utilisé pour définir le premier de la suivante. Des dossards réservés permettent de garder un écart de numérotation entre les catégories, dont vous choisissez la valeur. \n\nMeOS met à jour les dossards si vous modifiez l'architecture ou les horaires des listes de départ. Manuel signifie que MeOS ne mettra jamais à jour automatiquement les dossards.\n\nPour les catégories comportant des équipes, le paramètre équipe contrôle le rapport entre la place dans l'équipe et le dossard. Il peut être Identique (même dossard pour toute l'équipe), Croissant (100, 101, 102), par Relayeur (100-1, 100-2, etc.) ou complètement indépendant. help:7618 = Le nombre de compétiteurs dans l'équipe est défini dans la page Catégories. help:7620 = Intervalle (secondes). Laisser le champ vide pour qu'il soit mis à jour quand la compétition évolue. help:89064 = Pour chaque poste, vous devez spécifier un ou plusieurs numéro de code (codes SI). Dans un circuit, vous faites référence à un poste par son identifiant (ID). Habituellement vous n'avez pas besoin d'ajouter des postes manuellement puisque MeOS ajoute automatiquement tous les postes nécessaires.\n\nL'utilisation de plus d'un code SI est utile lorsque l'on veut remplacer un boîtier défectueux ou pour créer des fourches simples. Pour un poste ordinaire, il est exigé que le compétiteur poinçonne un des postes spécifiés. Si le statut du poste est , tous les postes spécifiés doivent être poinçonnés (dans un ordre quelconque). Si le statut est , le boîtier est ignoré.\n\nSi vous spécifiez un nom de poste, il est possible d'imprimer les résultats avec les temps intermédiaires aux postes nommés.\n\nUn réajustement de l'heure du poste peut être effectué s'il apparaît que le boîtier n'était pas à l'heure. Le format de l'heure est +/-MM:SS ou +/-HH:MM:SS.\n\nLe temps de partiel le plus court définit le temps le plus court possible sur ce partiel. Aucun concurrent n'aura un temps plus court pour aller à ce poste, aussi rapide soit-il. Cela peut être utilisé, par exemple, si une route dangereuse doit être traversée.\n\nLe statut signifie que le temps pour aller au poste est ignoré; le temps total sera le même quel que soit le temps réellement mis pour se rendre au poste. help:9373 = Donnez un ou plusieurs numéro de postes (codes SI) utilisés pour ce poste.\nExemple: 31, 32, 33. help:9615 = Aucune réponse reçue. Voulez-vous ouvrir le port en mode passif ? MeOS doit-il être à l'écoute de poinçons à venir ? -help:assignfee = MeOS va prendre en charge automatiquement pour vous les droits d'inscription dans la plupart des cas. Le tarif est basé sur l'âge et la date d'inscrition des compétiteurs (vous pouvez définir les limites dans Configuration de la compétition). Chaque catégorie définit un tarif. Vous fournissez une valeur par défaut pour différentes catégories dans Configuration de la Compétition, mais vous pouvez également reconfigurer la catégorie en utilisant Configuration Rapide pour cette catégorie.\n\nCette page vous permet d'utiliser différentes limites en âges et date limites d'inscription pour différents tarifs. Sur la page des Compétiteurs, vous pouvez ajuster manuellement le tarif pour chaque compétiteur en cas de besoin. +help:assignfee = MeOS va prendre en charge automatiquement pour vous les droits d'inscription dans la plupart des cas. Le tarif est basé sur l'âge et la date d'inscription des compétiteurs (vous pouvez définir les limites dans Configuration de la compétition). Chaque catégorie définit un tarif. Vous fournissez une valeur par défaut pour différentes catégories dans Configuration de la Compétition, mais vous pouvez également reconfigurer la catégorie en utilisant Configuration Rapide pour cette catégorie.\n\nCette page vous permet d'utiliser différentes limites en âges et date limites d'inscription pour différents tarifs. Sur la page des Compétiteurs, vous pouvez ajuster manuellement le tarif pour chaque compétiteur en cas de besoin. help:baudrate = Vitesse de transmission (baudrate) : utilisez 4800 ou 38400. help:computer_voice = Un poinçon arrivant est mis en correspondance avec un numéro de départ et joue le fichier où N est le numéro de départ. Les fichiers sont situés dans le répertoire ci-dessous. Si le compétiteur/équipe a une nationalité NAT d'affectée, MeOS essaie en priorité de jouer le fichier , qui se doit de contenir le nombre dans la version de langue appropriée. -help:dbage = La base de donnée des compétiteurs dat ede plus de deux mois. Souhaitez vous télécharger une nouvelle base à partir d'Eventor ? +help:dbage = La base de donnée des compétiteurs date de plus de deux mois. Souhaitez vous télécharger une nouvelle base à partir d'Eventor ? help:duplicate = Faire une copie locale de cette compétition. help:eventorkey = Entrez la clef Eventor de votre club (spécial Suède). Vous pouvez obtenir la clef auprès de l'administrateur Eventor de votre club. help:fullscreen = Vous pouvez ajuster la vitesse de défilement en utilisant Ctrl+M (augmente) et Ctrl+N (diminue). Pour sortir du mode plein écran, appuyez sur Esc. help:import_entry_data = Vous pouvez importer des compétiteurs, des catégories, des clubs et des inscriptions à partir de divers formats texte et XML. Il n'est pas nécessaire de fournir tous les fichiers ci-dessous. Par exemple, un fichier CSV de OE avec les inscriptions contient les clubs et les catégories, aussi dans ce cas ces champs devraient-ils être laissés vides.\n\nSi le même compétiteur est importé plusieurs fois vous n'obtiendrez pas plusieurs copies de ce compétiteur, mais son inscription sera modifiée. Cela signifie qu'il est sans danger de ré-importer ou d'importer un fichier d'inscription qui a été étendu. help:importcourse = Vous pouvez importer des circuits et des catégories à partir (par exemple) d'exports OCAD ou Condes. help:ocad13091 = Si vous avez accès aux circuits (par exemple à partir d'OCAD ou Condes) vous pouvez fournir les fichiers contenant les circuits ici. Autrement, vous pourrez ajouter les circuits ultérieurement. -help:relaysetup = Utilisez le guide ci-dessous pour choisir parmis les formulaires de compétitions prédéfinis. Après avoir appliqué la configuration, il est possible d'adapter manuellement la configuration pour chaque partiel et configurer les circuits.\n\nQuelques explications :\n- Relais est utilisé pour différent type de relais.\n- Relais par paire signifie que deux compétiteurs forme une équipe et courent à tour de rôle.\n- Un relais en Co-compétition est parfois utilisé dans les catégories jeunes et permet d'avoir plus d'un compétiteur sur certains partiels. (le premier compétiteur change d'une fois à l'autre).\n- Une patrouille peut s'effectuer avec une ou deux puces.\n- Prologue et poursuite est une compétition individuelle mais constitué de deux courses.\n- Un pool de circuit signifie qu'il y a plusieurs variantes, mais qu'il n'est pas décidé à l'avance qui court sur quelle variante; la décision est prise automatiquement lorsque le coureur a terminé. +help:relaysetup = Utilisez le guide ci-dessous pour choisir parmi les formulaires de compétitions prédéfinis. Après avoir appliqué la configuration, il est possible d'adapter manuellement la configuration pour chaque partiel et configurer les circuits.\n\nQuelques explications :\n- Relais est utilisé pour différent type de relais.\n- Relais par paire signifie que deux compétiteurs forme une équipe et courent à tour de rôle.\n- Un relais en Co-compétition est parfois utilisé dans les catégories jeunes et permet d'avoir plus d'un compétiteur sur certains partiels. (le premier compétiteur change d'une fois à l'autre).\n- Une patrouille peut s'effectuer avec une ou deux puces.\n- Prologue et poursuite est une compétition individuelle mais constitué de deux courses.\n- Un pool de circuit signifie qu'il y a plusieurs variantes, mais qu'il n'est pas décidé à l'avance qui court sur quelle variante; la décision est prise automatiquement lorsque le coureur a terminé. help:restore_backup = Choisissez une sauvegarde à restaurer en cliquant la date à laquelle la sauvegarde a été faite. help:runnerdatabase = En important une base de donnée de clubs et de coureurs, MeOS reconnaitra automatiquement les coureurs inconnus (par leur numéro de puce), et vous aurez les adresses et numéros de téléphone du club. help:save = MeOS sauve automatiquement toutes les configurations lorsque c'est nécessaire. help:speaker_setup = Choisissez les catégories et circuits que vous voulez surveiller. help:speakerprio = Cochez les coureurs/équipes que vous souhaitez surveiller dès le départ et tant que tout va bien. Mettre deux coches pour surveiller même si le résultat n'est plus très bon. Aucune coche signifie que la surveillance n'est activée que si le coureur/l'équipe a de bons résultats (donc pas forcément depuis le départ). help:splitexport = Décidez si vous voulez exporter les résultats individuellement ou globalement pour chaque course. Si vous choisissez d'exporter toutes les courses, des fichiers numérotés seront créés. -help:startmethod = MeOS utilisera automatiquement la méthode de départ choisie. Quoi que vous choisissiez ici, vous pourez dans tous les cas changer la méthode de départ ou refaire le tirage plus tard. -help:winsplits_auto = Ce service sauvegarde les temps intermédiaires dans un fichier IOF (xml) à intervalles réguliers. Si vous ouvrez ce fichier dans WinSplits, les temps intermédiaires seront mis à jour en temps réel. +help:startmethod = MeOS utilisera automatiquement la méthode de départ choisie. Quoi que vous choisissiez ici, vous pourrez dans tous les cas changer la méthode de départ ou refaire le tirage plus tard. +help:winsplits_auto = Ce service sauvegarde les temps intermédiaires dans un fichier IOF (xml) à intervalles réguliers. Si vous ouvrez ce fichier dans Winslet, les temps intermédiaires seront mis à jour en temps réel. help:zero_time = Définissez l'heure zéro à une heure avant le premier départ prévu. help:long_times = La date de compétition est la date à laquelle toutes les catégories commencent. L'heure zéro est à minuit. -help_autodraw = Fournit une première heure de départ (ordinaire), un intervalle minimal (pour une catégorie) et le pourcentage de vacants. Vous pouvez également choisir la méthode utilisée pour le tirage au sort et si les personnes inscrites tardivement doivent partir avant ou après les autres coureurs. Le premier horaire de départ doit être postérieur l'heure zéro de la compétition.\n\nSi vous cliquez sur , MeOS vérifie toutes les catégories. Si la catégorie n'a pas eu de tirage celui-ci est effectué. S'il y a des personnes inscrites tardivement sans horaires de départ dans une catégorie, leur horaire de départ sera tiré au sort.\n\nMeOS garantit que les coureurs ayant des circuits similaires ne partent pas simultanément, et de la place est réservée pour permettre l'accueil de coureurs inscrits tardivement dans les même conditions.\n\nSi au contraire vous cliquez sur vous pouvez contrôler exactement quelle catégories sont tirées au sort et avec quels paramètres. -help_draw = Le tirage au sort des horaire de départ se fait en deux temps. Premièrement vous choisissez les catégories et entrz quelques paramètres. Quand vous appuyez sur MeOS utilise vos paramètres pour attribuer les plages d'horaires entre les catégories. MeOS garantit que les catégories ayant des circuits similaires ne partent pas ne même temps en prenant en compte toutes les catégories ayant déjà eu un tirage. L'objectif est une répartition uniforme des partants.\n\nLa répartition calculée se présente sous la forme d'une table dans laquelle vous pouvez effectuer vos propres modifications, ou laisser MeOS mettre à jour sa répartition en prenant en compte vos modifications. Lorsque vous êtes satisfaits avec la répartition, vous laisser MeOS faire le tirage au sort des catégories sélectionnées.\n\nLes paramétrages que vous devez effectuer consistent à fournir l'heure du premier départ possible, et le plus petit intervalle de temps entre coureur autorisé. Le nombre maximal de départ en parallèle détermine combien de coureurs peuvent prendre le départ en même temps. Une valeur plus importante conduit à une durée de départ plus faible.\n\nLe pourcentage de vacants détermine le nombre d'horaires laissés disponibles. Si vous n'en voulez aucune, entrez 0%. Le nombre prévu de retardataires réserve de la place pour ces derniers dans la liste de départ, avec la garantie qu'aucun coureur prenant le départ au même moment n'aura un circuit identique. -info:multieventnetwork = Pour prendre en charge plus d'une étape vous devez travailler localement. Faite une copie de sauvergarde de la compétition, ouvrez-la en local et transferrez les résultats à l'étape suivante. Enfin, remontez l'étape suivante sur le serveur. +help_autodraw = Fournit une première heure de départ (ordinaire), un intervalle minimal (pour une catégorie) et le pourcentage de vacants. Vous pouvez également choisir la méthode utilisée pour le tirage au sort et si les personnes inscrites tardivement doivent partir avant ou après les autres coureurs. Le premier horaire de départ doit être supérieur à l'heure zéro de la compétition.\n\nSi vous cliquez sur , MeOS vérifie toutes les catégories. Si la catégorie n'a pas eu de tirage celui-ci est effectué. S'il y a des personnes inscrites tardivement sans horaires de départ dans une catégorie, leur horaire de départ sera tiré au sort.\n\nMeOS garantit que les coureurs ayant des circuits similaires ne partent pas simultanément, et de la place est réservée pour permettre l'accueil de coureurs inscrits tardivement dans les même conditions.\n\nSi au contraire vous cliquez sur vous pouvez contrôler exactement quelle catégories sont tirées au sort et avec quels paramètres. +help_draw = Le tirage au sort des horaire de départ se fait en deux temps. Premièrement vous choisissez les catégories et entrez quelques paramètres. Quand vous appuyez sur MeOS utilise vos paramètres pour attribuer les plages d'horaires entre les catégories. MeOS garantit que les catégories ayant des circuits similaires ne partent pas ne même temps en prenant en compte toutes les catégories ayant déjà eu un tirage. L'objectif est une répartition uniforme des partants.\n\nLa répartition calculée se présente sous la forme d'une table dans laquelle vous pouvez effectuer vos propres modifications, ou laisser MeOS mettre à jour sa répartition en prenant en compte vos modifications. Lorsque vous êtes satisfaits avec la répartition, vous laisser MeOS faire le tirage au sort des catégories sélectionnées.\n\nLes paramétrages que vous devez effectuer consistent à fournir l'heure du premier départ possible, et le plus petit intervalle de temps entre coureur autorisé. Le nombre maximal de départ en parallèle détermine combien de coureurs peuvent prendre le départ en même temps. Une valeur plus importante conduit à une durée de départ plus faible.\n\nLe pourcentage de vacants détermine le nombre d'horaires laissés disponibles. Si vous n'en voulez aucune, entrez 0%. Le nombre prévu de retardataires réserve de la place pour ces derniers dans la liste de départ, avec la garantie qu'aucun coureur prenant le départ au même moment n'aura un circuit identique. +info:multieventnetwork = Pour prendre en charge plus d'une étape vous devez travailler localement. Faite une copie de sauvegarde de la compétition, ouvrez-la en local et transférez les résultats à l'étape suivante. Enfin, remontez l'étape suivante sur le serveur. info:readout_action = X: Puce no. Y lue.\nDes actions manuelles sont requises. info:readout_queue = X: Puce no. Y lue.\nLa puce a été mise en file d'attente. inforestwarning = Aucun concurrent ne semble être encore en forêt. Comme les données qui ont servi à émettre cette conclusion peuvent être erronées, vous devez vérifier qu'aucun concurrent n'est encore en forêt par d'autres moyens. @@ -1373,10 +1375,10 @@ sexa = sixième sjua = septième sjunde = septième sjätte = sixième -skicka stämplar = envoyer le spoinçons +skicka stämplar = envoyer les poinçons sortering: X, antal rader: Y = ordre de tri: X, nombre de lignes: Y starten (X) = le départ (X) -sträcka %d = variation %d +sträcka X = Partiel X stämplade vid = a poinçonné stämplar vid X som Y, på tiden Z = poinçonne à X en tant que Y, en Z tar ledningen med tiden X = prend la tête en X @@ -1406,8 +1408,8 @@ warn:changedtimezero = Changer l'heure zéro d'une compétition ayant des résul warn:olddbversion = La base de donnée est utilisée par une version postérieure de MeOS. Une mise à jour est recommandée. warning:dbproblem = ATTENTION. Problèmes rencontrés avec la connexion à la base: 'X'. La connexion sera automatiquement restaurée. Vous pouvez continuer à travailler normalement. warning:drawresult = La catégorie a déjà des résultats, les heures de départ seront écrasées. Voulez-vous continuer ? -warning:has_entries = La catégorie a déjà des coureurs . Changer la réparition des variations à ce stade peut entraîner un eperte de données.\n\nVoulez-vous continuer ? -warning:has_results = La catégorie a déjà des résultats. Changer la réparition des variations à ce stade est inhabituel.\n\nVoulez-vous continuer ? +warning:has_entries = La catégorie a déjà des coureurs . Changer la répartition des variations à ce stade peut entraîner une perte de données.\n\nVoulez-vous continuer ? +warning:has_results = La catégorie a déjà des résultats. Changer la répartition des variations à ce stade est inhabituel.\n\nVoulez-vous continuer ? xml-data = données xml Äldre protokoll = Protocole périmé Ändra = Modifier @@ -1428,7 +1430,7 @@ xml-data = données xml Återgå = Retour Återställ = Restaurer Återställ / uppdatera klasstillhörighet = Réinitialiser / modifier la catégorie du coureur -Återställ löpare med registrering till = Passer le statut à pour les coureurs inscrits +Återställ löpare med registrering till = Passer le statut à pour les coureurs inscrits Återställ säkerhetskopia = Restaurer la sauvegarde Återställ tabeldesignen och visa allt = Restaurer la présentation de la table ÅÅÅÅ-MM-DD = AAAA-MM-JJ @@ -1442,12 +1444,12 @@ xml-data = données xml Öppna i ett nytt fönster = Ouvrir dans une nouvelle fenêtre Öppna klasser, ungdom = Ouvrir les catégories jeunes Öppna klasser, vuxna = Ouvrir les catégories adultes -Öppna nästa = Ouvrir le sivant +Öppna nästa = Ouvrir le suivant Öppna nästa etapp = Ouvrir l'étape suivante Öppna tävling = Ouvrir la compétition Öppna vald tävling = Ouvrir la compétition sélectionnée Öppnad tävling = Compétition ouverte -Överför anmälda = [Transfer entires] +Överför anmälda = [Transfert soumis] Överför nya deltagare i ej valda klasser med status "deltar ej" = Transférer les nouveaux coureurs dans les catégories non sélectionnées avec le statut "Ne participe pas" Överför resultat = Transférer les résultats Överför resultat till X = Transfert des résultats à X @@ -1465,7 +1467,7 @@ xml-data = données xml åttonde = huitième Kopia (X) = Copier (X) Tillåt samma bana inom basintervall = Autoriser le même circuit dans l'intervalle de base ($1467) -Välj X = Selectionner X +Välj X = Sélectionner X Ett startblock spänner över flera starter: X/Y = Un bloc de départ couvre plus d'un départ: X/Y Bricka X = Puce X RunnerTimePerKM = Allure min/km @@ -1519,7 +1521,7 @@ Nej = Non På banan = Sur le circuit Stämpelkod = Code du poste Tidpunkt = Temps -Antal deltagare = Competiteurs +Antal deltagare = Compétiteurs Förekomst = Occurrence Exporterar om = Export dans Exportformat = Format d'export @@ -1538,6 +1540,7 @@ URL = URL URL måste anges = URL manquant Tidsintervall (sekunder) = Intervalle de temps (secondes) Antal skickade uppdateringar X (Y kb) = Nombre de mise à jour X (Y kb) +Filename OE (csv) with runners and clubs = Nom de fichier OE (csv) avec coureurs et clubs Filen finns redan: X = La destination existe déjà: X Misslyckades med att ladda upp onlineresultat = Echec lors de la monté des résultats sur Internet Onlineservern svarade felaktigt = Le serveur distant a fourni une réponse inattendue (Configuration incorrecte ?) @@ -1545,7 +1548,7 @@ Onlineservern svarade: ZIP stöds ej = Réponse du serveur distant : ZIP non sup Onlineservern svarade: Serverfel = Réponse du serveur distant: Erreur du serveur Onlineservern svarade: Felaktigt lösenord = Réponse du serveur distant : Mot de passe incorrect Onlineservern svarade: Felaktigt tävlings-id = Réponse du serveur distant : Identifiant de compétition incorrect -Online Results Error X = Erreur dans les résulatts en ligne X +Online Results Error X = Erreur dans les résultats en ligne X PDF = PDF ClassTeamLeg = Catégorie, équipe, relayeur Okänd = Inconnu @@ -1602,7 +1605,7 @@ Skriver sträcktider när tävlingsdata ändras = Ecriture du fichier quand les Bana med slingor = Circuits avec boucles En bana med slingor tillåter deltagaren att ta slingorna i valfri ordning = Un circuit avec des boucles autorise le coureur à effectuer les boucles dans n'importe quel ordre. Varvningskontroll = Poste commun -warn:notextended = INFO: Programmez les boîtiers en protocole étendu avec SI.Config pour accélérer la lecture de puce. +warn:notextended = INFO: Programmez les boîtiers en protocole étendu avec SI. Config pour accélérer la lecture de puce. help:DirectResult = - S'il n'y a pas de circuit, le statut est mis à OK sur le poinçon d'arrivé.\n\n- S'il y a des circuits, les poinçons radio sont utilisés comme postes. Aucune lecture de puce n'est nécessaire. Resultat vid målstämpling = Résultat sur le poinçon d'arrivée Stämpling = Poinçon @@ -1625,7 +1628,7 @@ Brickan används av X = La puce est utilisée par X DATABASE ERROR = ERREUR DE BASE DE DONNEE Lyssnar på X = Ecoute de X vid kontroll X = au poste X -info:runnerdbonline = Comme vous êtes connecté à un serveur, il n'est pas possible d'étiter les bases de données club et compétiteurs manuellement. Effectuez les changements avant d'uploader la compétition sur un serveur. Il est également possible de remplacer la base de données existante sur le serveur en important une nouvelle base (à partir de IOF XML). +info:runnerdbonline = Comme vous êtes connecté à un serveur, il n'est pas possible d'éditer les bases de données club et compétiteurs manuellement. Effectuez les changements avant d'uploader la compétition sur un serveur. Il est également possible de remplacer la base de données existante sur le serveur en important une nouvelle base (à partir de IOF XML). ask:cleardb = Voulez-vous effacer les données club et compétiteurs ? Banan saknar rogainingkontroller = La compétition n'a pas de poste de type course au score Banans kontroller ger för få poäng för att täcka poängkravet = Les postes de type course au score n'attribuent pas assez de points @@ -1648,7 +1651,7 @@ Standard = Standard TeamRogainingPointTotal = Total des points de l'équipe The forking is fair = Les variations sont équitables Underfilter = Sous filtre -Ogiltigt lag på rad X = Equipe invalide ligne X +Ogiltigt lag på rad X = Équipe invalide ligne X Okänd klass på rad X = Catégorie inconnue ligne X Klassen X är individuell = La catégorie X est individuelle Använd befintliga deltagare = Utiliser les compétiteurs déjà inscrits @@ -1660,18 +1663,18 @@ Club and runner database = Base de donnée des clubs et compétiteurs Clubs = Clubs Economy and fees = Gestion et frais d'inscription Forked individual courses = Circuit individuel avec variations -General = General +General = Général Manual point reductions and adjustments = Réduction des points et ajustements Manual time penalties and adjustments = Pénalités en temps et ajustements MeOS Features = Fonctionnalités de MeOS MeOS – Funktioner = MeOS – Fonctionnalités -Patrols = Equipe -Prepare start lists = Preparation des listes de départ +Patrols = Équipe +Prepare start lists = Préparation des listes de départ Relays = Relais Several MeOS Clients in a network = Plusieurs clients MeOS en réseau Several races for a runner = Plusieurs compétitions pour un concurrent -Spara laguppställningar = Enregistrer la constitution de l'équipe [Save Team Line-Ups] -Teams and forking = Equipes et variations +Spara laguppställningar = Enregistrer la constitution de l'équipe [Save Team Line-UPS] +Teams and forking = Équipes et variations Track runners in forest = Suivi des coureurs en forêt Vacancies and entry cancellations = Places disponibles et annulation des inscriptions Banan saknas = Circuit manquant @@ -1687,17 +1690,17 @@ The forking is not fair = Les variations ne sont pas équitables Unfair control legs = Branche non équitable Växel = Passage help:teamlineup = Ici vous pouvez importer un alignement d'équipe à partir d'un fichier texte structuré qu'il est facile de produire manuellement à partir d'un tableur. Le fichier doit avoir le format suivant :\n\nCatégorie;Nom de l'équipe;[Club]\nCompétiteur 1;[No de puce];[Club];[Circuit];[Catégorie du compétiteur]\nCompétiteur 2;[No de puce];[Club];[Circuit];[Catégorie du compétiteur]\n...\nCatégorie;Nom de l'équipe;[Club]\n...\n\nLes champs marqués entre crochets [] sont optionnels. Notez que les catégories et circuits utilisées doivent exister, et que le nombre de branches dans la catégorie doit correspondre au nombre de ligne définissant les compétiteurs après la catégorie. Des lignes vides peuvent être utilisées s'il n'y a pas de compétiteur. L'option signifie que seulement les compétiteurs déjà inscrits à la compétition sont ajoutés à l'équipe; les autres compétiteurs spécifiés sont ignorés. -Poängjustering = Point d'ajustment +Poängjustering = Point d'ajustement Use initials in names = Utiliser les initiales comme noms Exportera klubbar (IOF-XML) = Export des clubs (IOF-XML) Exportera personer (IOF-XML) = Export des personnes (IOF-XML) Töm databasen = Effacement des données Several stages = Plusieurs étapes Assign courses and apply forking to X = Assigner un circuit et appliquer la variation à X -Assign selected courses to selected legs = Assigner les circuits sélectionnés aux branches sélectioonnées +Assign selected courses to selected legs = Assigner les circuits sélectionnés aux branches sélectionnées Calculate and apply forking = Calculer et utiliser les variations Clear selections = Effacer les sélections -Define forking = Definir les variations +Define forking = Définir les variations Forking setup = Configuration des variations Leg X: Do not modify = Branche X: Ne pas modifier Legs = Branches @@ -1706,7 +1709,7 @@ Leg X = Branche X Leg X: Use Y = La branche X: utilise Y Created X distinct forkings using Y courses = X variations distinctes ont été créées à partir de Y circuits Clear Memory = Effacement de la mémoire -Create Competition = Creation de la compétition +Create Competition = Création de la compétition Print Card Data = Imprimer les données de la puce Print card data = Imprimer les données de la puce help:analyzecard = Cette fonction vous permet d'imprimer les données de la puce sans utiliser une quelconque compétition, comme le ferait une borne d'impression autonome. Sélectionner 'Imprimer les temps intermédiaires' pour choisir et configurer l'imprimante.\n\nLes puces sont également conservées en mémoire (mais pas dans la compétition). Vous pouvez éditer le nom et le club pour une puce en cliquant le nom (ou 'inconnu'). Vous pouvez également enregistrer les puces dans un fichier (Enregistrer) ou créer une nouvelle compétition à partir des données des puces. Notez que si une compétition est ouverte, vous devez la fermer pour rendre cette option disponible. @@ -1723,7 +1726,7 @@ Första tillåtna starttid = Heure du premier départ possible Importera anmälda = Importer les inscriptions Individuell tävling = Compétition individuelle Namn och tidpunkt = Nom et heure -Skapar tävling = Creation de la compétition +Skapar tävling = Création de la compétition Tävling med lag = Compétition en équipe Tävlingen måste avgöras mellan X och Y = La compétition doit se dérouler entre X et Y Tävlingens namn = Nom de la compétition @@ -1731,7 +1734,7 @@ Välj från lista = Sélection détaillée Välj vilka funktioner du vill använda = Sélectionnez les fonctionnalités de MeOS dont vous avez besoin pour cette compétition Individuellt, gafflat = Individuel, avec variations Skapa tävlingen = Créer la compétition -newcmp:featuredesc = Selectionnez les fonctionnalités de MeOS dont vous avez besoin pour cette compétition. Vous pouvez ajouter ou supprimer des fonctionnalités à tout moment en sélectionnant sur la page Compétition. +newcmp:featuredesc = Sélectionnez les fonctionnalités de MeOS dont vous avez besoin pour cette compétition. Vous pouvez ajouter ou supprimer des fonctionnalités à tout moment en sélectionnant sur la page Compétition. Exportera till fil = Exporter dans un fichier FilterPrelResult = Résultats prél. FinishTimeReverse = Temps inversés (le dernier en premier) @@ -1742,8 +1745,8 @@ Result score calculation for runner = Détermination du score pour un compétite Result score calculation for team = Détermination du score pour une équipe ResultDescription = Nom du type de résultat Skapa = Créer -Status calculation for runner = Détermination du status pour un compétiteur -Status calculation for team = Détermination du status pour une équipe +Status calculation for runner = Détermination du statut pour un compétiteur +Status calculation for team = Détermination du statut pour une équipe Support time from control = Temps depuis le poste [Support time from control] Support time to control = Temps vers le poste [Support time to control] Time calculation for runner = Calcul du temps pour un compétiteur @@ -1800,28 +1803,28 @@ Runner/team finish time = Heure d'arrivée compétiteur/équipe Runner/team input place = Place initiale compétiteur/équipe Runner/team input points = Points initiaux compétiteur/équipe Runner/team input running time = Temps de course initial compétiteur/équipe -Runner/team input status = Status initial compétiteur/équipe +Runner/team input status = Statut initial compétiteur/équipe Runner/team place = Place compétiteur/équipe Runner/team rogaining overtime = Dépassement du temps pour compétiteur/équipe (course au score) Runner/team rogaining points = Point compétiteur/équipe (course au score) Runner/team rogaining points adjustment = Ajustement des points compétiteur/équipe (course au score) Runner/team running time = Temps de course compétiteur/équipe Runner/team start time = Heure de départ compétiteur/équipe -Runner/team status = Status compétiteur/équipe +Runner/team status = Statut compétiteur/équipe Runner/team time adjustment = Ajustement du temps compétiteur/équipe Runner/team total place = Place finale compétiteur/équipe Runner/team total running time = Temps total de course compétiteur/équipe -Runner/team total status = Status final compétiteur/équipe +Runner/team total status = Statut final compétiteur/équipe Shortest time in class = Meilleur temps de la catégorie -Status as computed by your status method = Status tel que calculé par votre méthode -Status code for a missing punch = Code de status pour un poinçon manquant -Status code for a time over the maximum = Code de status en cas de dépassement du temps -Status code for a valid result = Code de status pour un résultat valide -Status code for an unknown result = Code de status pour un résultat inconnu -Status code for disqualification = Code de status pour une disqualification -Status code for not competing = Code de status en cas d'absence -Status code for not finishing = Code de status en cas d'abandon -Status code for not starting = Code de status en cas de non prise de départ +Status as computed by your status method = Statut tel que calculé par votre méthode +Status code for a missing punch = Code de statut pour un poinçon manquant +Status code for a time over the maximum = Code de statut en cas de dépassement du temps +Status code for a valid result = Code de statut pour un résultat valide +Status code for an unknown result = Code de statut pour un résultat inconnu +Status code for disqualification = Code de statut pour une disqualification +Status code for not competing = Code de statut en cas d'absence +Status code for not finishing = Code de statut en cas d'abandon +Status code for not starting = Code de statut en cas de non prise de départ Points as computed by your point method = Points tels que calculés par votre méthode Time as computed by your time method = Temps tel que calculé par votre méthode Time after leg winner = Temps après le vainqueur du partiel @@ -1835,7 +1838,7 @@ Runner's method output numbers = Méthode de génération de nombre pour les com Runner's method output times = Méthode de génération des temps pour les compétiteurs [Runner's method output times] Running time for each team member = Temps de course pour chaque équipier Start time for each team member = Heure de départ pour chaque équipier -Status for each team member = Status de cahque équipier +Status for each team member = Statut de chaque équipier Check: X = Vérification : X Debug = Debug Debug Output = Sortie de debug @@ -1850,26 +1853,26 @@ Symboler = Symboles TeamPointAdjustment = Ajustement des points de l'équipe TeamTimeAdjustment = Ajustement du temps de l'équipe Variabler = Variables -Check: X = Véfification : X +Check: X = Vérification : X Choose result module = Choisir le module de résultat Result Modules = Modules de résultat Error in result module X, method Y (Z) = Erreur dans le module de résultat 'X', méthode 'Y'\n\nZ Invalid operator X = Opérateur invalide X Unknown symbol X = Symbole inconnu X -RunnerGlobal = Competiteur (catégories regroupées) -TeamGlobal = Equipe (catégories regroupées) +RunnerGlobal = Compétiteur (catégories regroupées) +TeamGlobal = Équipe (catégories regroupées) List Error: X = Erreur de liste : X Rader markerade med (*) kommer från en lista i tävlingen = Les lignes avec une (*) proviennent d'une liste de la compétition Resultatmodulen används i X = Le module de résultat est utilisé dans X Valfri = Optionnel -Vill du sätta resultatet från tidigare etapper till ? = Voulez-vous modifier le résultat des étapes précédentes en (Not taking part = absent)? +Vill du sätta resultatet från tidigare etapper till ? = Voulez-vous modifier le résultat des étapes précédentes en ? Hantera deltagare som bytt klass = Traitement des compétiteurs qui ont changé de catégorie Välj klasser med nya anmälningar = Spécifiez les catégories pour lesquelles de nouvelles inscriptions sont autorisées Byt till rätt klass (behåll eventuell starttid) = Basculer vers la bonne catégorie (conserver l'heure de départ) -Byt till vakansplats i rätt klass (om möjligt) = Déplacer vers un horaire vacant dans la bonne catagorie (si possible) +Byt till vakansplats i rätt klass (om möjligt) = Déplacer vers un horaire vacant dans la bonne catégorie (si possible) Tillåt ny klass, behåll resultat från annan klass = Autoriser de nouvelles catégories et conserver les résultats des autres catégories -Tillåt ny klass, inget totalresultat = Autoriser de nouvelels catégories mais sans résultat global -tooltip_explain_status = - = Status inconnu (pas encore de résultat)\nOK = Résultat valide\nDNS = Did Not Start (non parti)\nMP = Missing Punch (poiçon manquant)\nDNF = Did Not Finish (abandon)\nDISQ = Disqualifié\nOMT = Over Maximum Time (dépassement du temps maxi)\nNTP = Not Taking Part (absent) +Tillåt ny klass, inget totalresultat = Autoriser de nouvelles catégories mais sans résultat global +tooltip_explain_status = - Placering = Place Resultat från tidigare etapper = Résultats des étapes précédentes Input Results = Saisir les résultats [Input Results] @@ -1915,7 +1918,7 @@ Ultra Long = Ultra Longue Tillgängliga filer installerades. Starta om MeOS. = Les configurations ont été installées. Redémarrez MeOS S.V.P. edit_in_forest = Gérer\nCompétiteurs en forêt Latest Results = Résultats récents -warning:direct_result = Notez que l'utilisation de nécessite que tous les poinçons de tous les postes du circuit aient été transmis comme poste radio, ou que MeOS soit utilisé pour chronométrer uniquement sans tenir compte du circuit.\n\nUtiliser les résultats sur poinçon d'arrivée ? +warning:direct_result = Notez que l'utilisation de nécessite que tous les poinçons de tous les postes du circuit aient été transmis comme poste radio, ou que MeOS soit utilisé pour chronométrer uniquement sans tenir compte du circuit.\n\nUtiliser les résultats sur poinçon d'arrivée ? Inställningar startbevis = Configuration de l'impression des tickets de départ Skrivarinställningar = Configuration de l'impression Skrivarinställningar för sträcktider och startbevis = Configuration de l'impression des tickets de temps intermédiaires et de départ @@ -1938,7 +1941,7 @@ info_shortening = Sélectionnez un circuit existant qui raccourcit le circuit s Tilldela starttider = Attribuer des heures de départ Avkortar: X = Raccourcit: X Vill du nollställa alla manuellt tilldelade banor? = Voulez-vous effacer tous les circuits manuellement attribués ? -Ange löpande numrering eller första nummer i klassen = Spécifier une numérotatin consécutive entre catégories ou le premier numéro de la catégorie +Ange löpande numrering eller första nummer i klassen = Spécifier une numérotation consécutive entre catégories ou le premier numéro de la catégorie Ange relation mellan lagets och deltagarnas nummerlappar = Spécifier la relation entre le dossard de l'équipe et les dossards des coureurs de l'équipe Lagmedlem = Membre de l'équipe Löpande = Consécutif @@ -1966,7 +1969,7 @@ Laguppställningen hade fel, som har rättats = La constitution de l'équipe a ControlClasses = Catégories du poste ControlCodes = Numéros du poste ControlCourses = Circuits du poste -ControlMaxLostTime = Potse, temps perdu, maximum +ControlMaxLostTime = Poste, temps perdu, maximum ControlMedianLostTime = Poste, temps perdu, médian ControlMistakeQuotient = Poste, pourcentage de coureurs avec perte de temps ControlName = Nom du poste @@ -1981,7 +1984,7 @@ Control = Poste Control Statistics = Statistiques du poste Control Statistics - X = Statistiques du poste - X Course = Course -FilterSameParallel = Collect parallel legs ($1984) +FilterSameParallel = Variations identiques Kontrollrapport - X = Rapport du poste - X Maxbom = Erreur maximale Control Overview = Aperçut général du poste @@ -1994,7 +1997,7 @@ Tillsätt tillfälliga anonyma lagmedlemmar = Ajouter des membres d'équipe anon Tillsätt = Nommer help:anonymous_team = Créer et nommer des membres (temporaires) d'équipe pour toutes les équipes, auxquels vous pouvez assigner une puce, un circuit, etc. Anonymt namn = Nom anonyme -Med anmälningsavgift (lagets klubb) = Avec les frais d'insciption (pour le club de l'équipe) +Med anmälningsavgift (lagets klubb) = Avec les frais d'inscription (pour le club de l'équipe) Tar bort X = Retrait de X Källa = Source Ta bort eventuella avanmälda deltagare = Supprimer les inscriptions annulées si nécessaire @@ -2002,15 +2005,15 @@ Verktyg = Outils Automatisk = Automatique Avstånd = Distance Extra avstånd ovanför textblock = Distance additionnelle -FilterSameParallelNotFirst = Recueillir les variations parallèles, ignorer la première ($2005) +FilterSameParallelNotFirst = Variations identiques sauf la première RunnerLeg = Concurrent (variation spécifique) Texten ska innehålla tecknet X, som byts ut mot tävlingsspecifik data = Le texte doit inclure le symbole X, qui est remplacé par les données spécifiques à la compétition Tabellverktyg = Outils table Antal reserverade nummerlappsnummer mellan klasser = Nombre de dossards réservés entre les catégories -help:bibs = Vous pouvez gérer les dossards manuellement ou automatiquement. Ici vous pouvez assigner les dossards manuellement pour une certaine catégorie en spécifiant la méthode Manuelle et en fournissant le premier numéro pour cette catégorie.\n\nLa méthode automatique fonctionne de la même façon, avec la différence que MeOS mettra à jour les dossards de toutes les catégories d'un coup. Bien qu'il soit possible de faire ce paramétrage ici, il est préférable d'utiliser le Paramétrage rapide pour les catégories afin d'avoir une vue d'ensemble de toutes les catégories.\n\nUtiliser la méthode Automatique avec les méthodes Aucun ou Consécutifs, qui indique que le dernier numéro de la catégorie précédente est utilisé comme premier numéro. Le nombre de dossards réservés définit le saut de numérotation entre catégories.\n\nPour les catégories d'équipes vous pouvez spécifier la relation existant entre les numéros de dossard des équipiers et celui de l'équipe. Il peut être Identique, Indépendant, Croissant (Equipe 1: 101, 102, 103, 104, Equipe 2: 111, 112, 113, 114 etc.) ou par Combinaison (100-1, 100-2, 100-3 etc). +help:bibs = Vous pouvez gérer les dossards manuellement ou automatiquement. Ici vous pouvez assigner les dossards manuellement pour une certaine catégorie en spécifiant la méthode Manuelle et en fournissant le premier numéro pour cette catégorie.\n\nLa méthode automatique fonctionne de la même façon, avec la différence que MeOS mettra à jour les dossards de toutes les catégories d'un coup. Bien qu'il soit possible de faire ce paramétrage ici, il est préférable d'utiliser le Paramétrage rapide pour les catégories afin d'avoir une vue d'ensemble de toutes les catégories.\n\nUtiliser la méthode Automatique avec les méthodes Aucun ou Consécutifs, qui indique que le dernier numéro de la catégorie précédente est utilisé comme premier numéro. Le nombre de dossards réservés définit le saut de numérotation entre catégories.\n\nPour les catégories d'équipes vous pouvez spécifier la relation existant entre les numéros de dossard des équipiers et celui de l'équipe. Il peut être Identique, Indépendant, Croissant (Équipe 1: 101, 102, 103, 104, Équipe 2: 111, 112, 113, 114 etc.) ou par Combinaison (100-1, 100-2, 100-3 etc). RunnerGeneralPlace = Classement individuel ou par équipe du concurrent ($2011) RunnerGeneralTimeAfter = Retard individuel ou par équipe du concurrent ($2012) -RunnerGeneralTimeStatus = Temps / status individuel ou de l'équipe du concurrent ($2013) +RunnerGeneralTimeStatus = Temps / statut individuel ou de l'équipe du concurrent ($2013) open_error = Impossible d'ouvrir X.\n\nY. open_error_locked = Cette compétition est déjà ouverte dans MeOS.\n\nVous devez utiliser une base de données pour ouvrir plus d'un exemplaire d'une compétition. Ogiltigt bricknummer = Numéro de puce invalide @@ -2029,18 +2032,18 @@ Vill du att X tar sträckan istället för Y? = Voulez-vous que X coure cette va Ändra lagets gaffling = Changer les variations de l'équipe Deltagarens klass styrs av laget = La catégorie est définie par l'équipe För att delta i en lagklass måste deltagaren ingå i ett lag = Pour participer à une catégorie d'équipe vous devez assigner une équipe au compétiteur -Dela upp = Temps intermédiaires +Dela upp = Scinder Alla sträckor = Toutes les variantes Liveresultat, deltagare = Résultats en direct, individuels Använd enhets-id istället för tävlings-id = Utiliser l'identifiant de l'appareil au lieu de l'identifiant de la compétition ($2035) Enhetens ID-nummer (MAC) = Identifiant de l'appareil (MAC) Antal deltagare: X = Nombre de compétiteurs : X -Dela efter placering = Temps intermédiaires par résultat ($2038) -Dela efter tid = Temps intermédiaires par temps ($2039) -Dela slumpmässigt = Temps intermédiaire par aléatoire -Jämna klasser (placering) = Make equal classes (result) ($2041) -Jämna klasser (ranking) = Make equal classes (ranking) ($2042) -Jämna klasser (tid) = Make equal classes (time) ($2043) +Dela efter placering = Scinder par résultat +Dela efter tid = scinder par temps +Dela slumpmässigt = Scinder aléatoirement +Jämna klasser (placering) = Faire des catégories égales (résultats) +Jämna klasser (ranking) = Faire des catégories égales (classement) +Jämna klasser (tid) = Faire des catégories égales (Temps) Klass X = Catégorie X Not yet implemented = Non encore implémenté Tidstillägg = Pénalité (M:S) @@ -2048,7 +2051,7 @@ help:seeding_info = L'allocation ensemencée des heures de départ signifie qu'u Ange en gruppstorlek (som repeteras) eller flera kommaseparerade gruppstorlekar = Fournir une taille de groupe (qui sera répétée) ou plusieurs tailles séparées par des virgules Hindra att deltagare från samma klubb startar på angränsande tider = Empêcher que des coureurs du même club partent à des horaires consécutifs. Låt de bästa start först = Faire ne sorte que le mieux classé parte en premier -Seedningsgrupper = Groupes ensemensés +Seedningsgrupper = Groupes ensemencés Seedningskälla = Données d'ensemencement error:invalidmethod = La méthode sélectionnée ne génère pas de distribution. Les données d'ensemencement sont insuffisantes. Ogiltig storlek på seedningsgrupper X = Taille des groupes d'ensemencement invalide : X @@ -2062,7 +2065,7 @@ Kopiera = Copier Kopiera till urklipp = Copier dans le presse papier RunnerStartCond = Heure de départ du concurrent (si individuel) StartTimeForClassRange = Plage d'heure de départ de la catégorie -TeamStartCond = Heure de départde l'équipe (si individuel) +TeamStartCond = Heure de départ de l'équipe (si individuel) Liveresultat = Résultats en direct Visa rullande tider mellan kontroller i helskärmsläge = Afficher les temps s'écoulant entre deux postes en mode plein écran help:liveresultat = Cette méthode démarre un chronomètre en mode plein écran quand un compétiteur d'une catégorie sélectionnée poinçonne le poste , et mesure le temps jusqu'à ce que le poste soit atteint. Sinon la liste des meilleurs temps est affichée. Les deux postes doivent bien sûr être des postes radio et si vous utilisez un réseau, vérifiez bien que vous avez activé pour obtenir rapidement des temps les plus précis possibles. @@ -2090,7 +2093,7 @@ prefsEMail = Courriel prefsEliteFee = Tarif par défaut pour les élites prefsEntryFee = Tarif par défaut prefsEventorBase = URL d'Eventor -prefsFirstInvoice = Premier numéro de fature +prefsFirstInvoice = Premier numéro de facture prefsFirstTime = Premier départ prefsHomepage = Site web prefsInteractive = Gestion interactive des puces @@ -2153,10 +2156,10 @@ Ej startstämpling = Ignorer le poinçon de départ Extraplatser = Places supplémentaires Fritt = Libre Från lag = De l'équipe -Lag + sträcka = Equipe + variation +Lag + sträcka = Équipe + variation Nummerlappshantering = Gestion des dossards Oordnade parallella = Unordered parallel ($2158) -Spara starttider = Enregistrer les heuresde départ +Spara starttider = Enregistrer les heures de départ X platser. Startar Y = X places. Départ de Y övriga = autre RunnerStartZero = Heure de départ relative du coureur (heure zéro) @@ -2166,7 +2169,7 @@ Inget filter = Pas de filtre Inlästa stämplar = Lire les poinçons Löpare saknas = Aucun coureur Klasserna X och Y har samma externa id. Använd tabelläget för att ändra id = Les catégories X et Y ont le même identifiant externe. Utiliser le mode table pour corriger l'identifiant. -Vill du koppla isär X från inläst bricka Y? = Would you like to disconnect X from the read out card Y ? ($2169) +Vill du koppla isär X från inläst bricka Y? = Voulez-vous délier X de na puce numéro Y ? RunnerRogainingPointGross = Points avant pénalités Samlade poäng = Points acquis Tidsavdrag = Pénalités @@ -2212,30 +2215,220 @@ leder med X = est en tête avec X delar placering med X = est à égalité avec X sekund = seconde skickar ut X = envoyer X -Import names as "surname, first name" = Importer les noms sous la forme "nom de famille, prénoms" -Use French Federation of Orienteering mapping = Utiliser le format de la Fédération Française de CO Export language = Langue -Export Split Times = Exporter les temps intermédiaires -Filename OE (csv) with runners and clubs = Nom de fichier OE (csv) avec coureurs et clubs +Use French Federation of Orienteering mapping = Utiliser le format de la Fédération Française de CO +Export split times = Exporter les temps intermédiaires Climb (m) = Dénivelée (m) Utrymme: X = Taille : X [Radera] = [Supprimer] +prefsNumSplitsOnePage = Nombre de puces par page +prefsPayModes = Modes de paiement +prefsSplitPrintMaxWait = Temps d'attente maximum lors de l'impression des temps intermédiaires +prefsWideSplitFormat = Imprimer les temps intermédiaires en grand format ClassTeamLegResult = Résultat par catégorie et relayeur +SortLastNameOnly = Nom de famille Databaskälla = Base de donnée source -Export split times = Exporter les temps intermédiaires Filnamn IOF (xml) eller OE (csv) med löpare = Fichier IOF (xml) ou OE (csv) avec coureurs Importinställning = Préférences d'importation -Längsta tid i sekunder att vänta med utskrift = Délai maximum d'attente de l'impression en seconde -Max antal brickor per sida = Nombre maximum de puces par page -Resultat efter sträcka X = Résultats après le partiel X -SortLastNameOnly = Nom de famille -Sträcktider i kolumner (f?r standardpapper) = Temps en colonnes (papier standard) prefsExportCSVSplits = Inclure les temps intermédiaires dans l'export csv prefsExportFormat = Format d'exportation par défaut prefsImportOptions = Options d'importation par défaut -prefsNumSplitsOnePage = Nombre de puces par page -prefsPayModes = Modes de paiement prefsSplitLateFees = Séparer les frais d'inscription en frais standards et frais d'inscription tardive pour l'exportation IOF XML -prefsSplitPrintMaxWait = Temps d'attente maximum lors de l'impression des temps intermédiaires -prefsWideSplitFormat = Imprimer les temps intermédiaires en grand format -sträcka X = Partiel X +Längsta tid i sekunder att vänta med utskrift = Délai maximum d'attente de l'impression en seconde +Max antal brickor per sida = Nombre maximum de puces par page +Sträcktider i kolumner (för standardpapper) = Temps en colonnes (pour imprimante A4) +Spara inmatade tider i tävlingen utan att tilldela starttider = Enregistrer les paramètres et les heures de départ de chaque catégorie pour y revenir plus tard +SRR Dongle = Dongle SRR +red channel = Chaine rouge +blue channel = Chaine bleue +Printing failed (X: Y) Z = Port par défaut +prefsNameMode = Format du nom : X +Kommunikationen med en SI-enhet avbröts = Connection perdue à la base SI-master +Varning: avgiften kan ej faktureras = Attention : impossible de générer de facture pour ce montant +Gamla brickor utan stöd för långa tider = Puces anciennes ne prenant pas en charge les longues courses +ask:convert_to_patrol = Certaines catégories contiennent des requêtes pour que certains coureurs aient la même heure de départ. Voulez-vous convertir ces catégories en catégories pour co-compétiteurs (type raid) ? +Antal som inte importerades: X = Nombre d'inscriptions sautées : X +Det finns anmälningsdata för flera etapper = Il y a des données pour plusieurs étapes +Välj etapp att importera = Sélectionner l'étape à importer +ask:savespeaker = Voulez-vous sauvegarder les paramètres d'affichage et de catégorie sur cet ordinateur ? +Spara fönster- och speakerinställningar på datorn = Enregistrer la fenêtre et les paramètres sur cet ordinateur +ask:loadspeaker = Voulez-vous recréer des fenêtres sauvegardées précédemment sur cet ordinateur ? +Återskapa = Régénérer +Återskapa tidigare sparade fönster- och speakerinställningar = Régénérer les fenêtres et paramètres enregistrés précédemment +Inkludera resultat från tidigare etapper = Inclure les résultats de toutes les étapes +Animation = Animation +Bakgrund = Arrière plan +Bakgrundsfärg = Couleur de fond +Fullskärm (rullande) = Plein écran (déroulant) +Fullskärm (sidvis) = Plein écran (page par page) +Fönster = Fenêtre +Fönster (rullande) = Fenêtre (déroulant) +Justera visningsinställningar = Ajuster les paramètres de visualisation +Marginal = Marge +Sidor per skärm = Pages par écran +Textfärg = Couleur du texte +Utseende = Apparence +Visningsinställningar för 'X' = Paramètres d'affichage pour 'X' +Visningstid = Afficher le temps +Visning = Mode d'affichage +ask:hasVacant = Il y a toujours des vacants.\n\nVoulez-vous retirer tous les vacants avant d'exporter les résultats ? +warn:missingResult = X coureurs ne sont toujours pas rentrés et ne sont donc pas classés.\n\nVous pouvez aller dans l'onglet 'Coureurs restants' et les passer en statut +Återställ till = Remettre en +Återbud[status] = Annulé +Lås gafflingar = Verrouiller les variations +Markera för att förhindra oavsiktlig ändring av gafflingsnycklar = Vérifier pour empêcher toute erreur dans la répartition des variations +Tillåt gafflingsändringar = Déverrouiller les variations +ask:updatetimes = Voulez-vous conserver autant que possible les horaires de départ déjà assignés ? Répondez Non pour décaler la compétition dans le temps +X har en tid (Y) som inte är kompatibel med förändringen = X a une heure de départ (Y) ce qui n'est pas compatible avec ce changement +warn:latestarttime = Utiliser des heures de départ plus de X heures après l'heure zéro n'est pas conseillé +Anm. tid = Heure d'inscription +RunnerEntryDate = Date d'inscription +RunnerEntryTime = Heure d'inscription +RunnerPaid = Payé +RunnerPayMethod = Méthode de payement +EntryTime = Heure d'inscription +Ekonomihantering, X = Gestion financière, X +Manuellt gjorda justeringar = Ajustements manuels +Antal förfrågningar: X = Nombre de requêtes +Genomsnittlig svarstid: X ms = Temps moyen de réponse : X +Informationsserver = Informations serveur +Längsta svarstid: X ms = Temps de réponse maximal : X +MeOS Informationsserver REST-API = MeOS Information Server REST-API +Testa servern = Tester le serveur +help:rest = MeOS REST API vous permet d'accéder à la compétition via le web. Vous pouvez afficher les résultats directement sur un navigateur, mais aussi exporter les données de la course en XML pour les envoyer vers d'autres applications et programmes. +Server startad på X = Serveur sur le port X +Inconsistent qualification rule, X = Règle de qualification incohérente, X +help:LockStartList = MeOS ne va mas modifier les heures de départ d'une catégorie verrouillée, même si les résultats des qualifications sont modifiées +Kval/final-schema = Schéma de qualifications/finale +Lås startlista = Verrouiller la liste de départ +FilterNoCancel = Pas annulés +CourseStartTime = Circuit, heure de départ +Startlista, banvis = Liste de départ par circuit +Stämplingsintervall, rogaining-patrull = Intervalle de poinçonnage dans la patrouille +Patrullresultat (STOR) = Résultats de la patrouille (GRAND) +Patrol Team Rogaining = Course au score en patrouille +Rogaining results for a patrol = Résultats de course au score pour binôme (ou plus) +Exportera ett kalkylblad med lottningsinställningar som du kan redigera och sedan läsa in igen = 0 +Kalkylblad/csv = Tableur/csv +Importerar lottningsinställningar = Importer les paramètres des listes de départ +help:exportdraw = Vous pouvez exporter un tableur en CSV avec les catégories, le nombre d'inscrits et les paramètres des listes de départ par catégories. Il est ensuite possible d'éditer ces données et de les ré-importer dans MeOS pour créer les listes de départ. +prefsDrawInterlace = Entrelacer catégorie/circuits dans la liste de départ +prefsServicePort = Port par défaut X +Ingen nummerlapp = Num de dossard +Rogaining results for a team, where each team member collects points individually = Résultats de course au score pour binôme où chaque membre collecte des points de façon individuelle +prefsCodePage = Code table pour l'import/export en 8 bits +Inga klasser tillåter direktanmälan. På sidan klasser kan du ändra denna egenskap. = Aucune catégorie n'autorise les inscriptions rapides.\n\nVous pouvez modifier ce paramètre à la page 'Catégories'. +Database is used and cannot be deleted = La base de donnée est utilisée et ne peut être supprimée +Classes together = Catégories regroupées +Finish order = Ordre d'arrivée +First to finish = Premier qui a fini +Individual result by finish time = Résultat individuel sur l'heure d'arrivée +Endast tidtagning = Chronométrage seul +AllPunches = Tous les poinçons +CoursePunches = Poinçons (sur le circuit) +FilterNamedControl = Postes nommés +FilterNotFinish = Uniquement les arrivés +LineBreak = Saut de ligne +PunchAbsTime = Poinçon, heure réelle +PunchTimeSinceLast = Temps entre les postes +PunchTotalTime = Temps au poste +PunchName = Poinçon, code du poste +PunchNamedSplit = Temps depuis le dernier poste nommé +PunchSplitTime = Temps depuis le dernier poste (temps intermédiaire) +ClassLiveResult = Live results (temps radios), par catégorie +Felaktigt datum 'X' (Använd YYYY-MM-DD) = Date incorrecte (Mettre AAAA-MM-JJ) +FilterAnyResult = Avec temps radios/résultats +Liveresultat, radiotider = Résultats en direct avec radios +PunchTotalTimeAfter = Temps passé au poste +RunnerCheck = Heure de contrôle +RunnerId = Licence/ID +StartTimeClass = Heure de départ, catégorie +ask:outofmaps = Plus de cartes disponibles. Voulez-vous tout de même inscrire ce coureur ? +Varning: Kartorna är slut = Attention : plus de cartes disponibles +X går vidare, klass enligt ranking = X qualifiés, catégorie par le ranking +Vill du ta bort schemat? = Voulez-vous supprimer le schéma ? +ask:removescheme = Si vous retirez le schéma de qualification, les résultats seront perdus. Voulez-vous continuer ? +ClassKnockoutTotalResult = Class, knock-out total result +Support intermediate legs = Supporter les variations spécifiques en relais +help:custom_text_lines = Vous pouvez insérer du texte spécifique en ajoutant en dessous [DonnéeSpécifique]. Les infos disponibles sont visibles dans le tableau déroulant à droite.\n\nPar exemple : Bravo [RunnerName] ! +Importerar ranking = Importer le ranking +Klart. X värden tilldelade = Terminé. X valeurs assignées +Felaktigt rankingformat i X. Förväntat: Y = Format de classement incorrect pour X.\nY attendu +Importerar RAID patrull csv-fil = Importer les données RAID en csv +Varning: Följande deltagare har ett osäkert resultat = Attention : les informations sur ce coureur ne sont pas claires +Direkt tidtagning = Chronométrage en direct +Klassval för 'X' = Sélection de la catégorie pour 'X' +Endast tidtagning (utan banor) = Chronométrage seul (pas de circuits) +Knockout total = Résumé des éliminations +Varvräkning = Compter les tours +Varvräkning med mellantid = Compter les tours en temps supplémentaire +Without courses = Sans circuit +Timekeeping = Chronométrage +Endast grundläggande (enklast möjligt) = Fonctionnalités de base +Endast tidtagning (utan banor), stafett = Chronométrage seul (pas de circuits), relais +Individuellt = Individuel +Lag och stafett = Équipe et relais +Övrigt = Divers +htmlhelp = Le HTML peut être exporté comme un tableur structuré ou comme un document formaté librement +HTML Export = Export HTML +HTML Export för 'X' = Export HTML pour 'X' +Lagra inställningar = Enregistrer les paramètres +Kolumner = Colonnes +Rader = Lignes +HTML formaterad genom listinställningar = HTML formaté par les paramètres de la liste +Begränsa antal rader per sida = Nombre max de lignes par page +Färre slingor = Moins de boucles +RunnerGrossTime = Temps avant modifications +TeamGrossTime = Temps de l'équipe avant modification +Visa detaljerad rapport för viss deltagare = Afficher le rapport détaillé pour un coureur spécifique +Förhindra att laget deltar i någon omstart = Permet à l'équipe de ne pas prendre part au départ en masse des attardés +Förhindra omstart = Empêcher le redémarrage +Ej omstart = Pas de redémarrage +Visa rubrik mellan listorna = Afficher le titre entre les listes +Slå ihop med befintlig lista = Fusionner avec une liste existante +Från löpardatabasen = De la base de donnée coureurs +Från löpardatabasen i befintliga klubbar = De la base de donnée coureurs dan les clubs existants +Med direktanmälan = Avec inscription directe +Tillåt anmälan = Autoriser les inscriptions +Anyone = N'importe qui +Bricknummer = Numéro de puce +Anmäl andra = Nouvelle inscription +Anmälan mottagen = Inscription acceptée +Automatisk omladdning = Mise à jour automatique +Till vilka klasser = Pour quelles catégories +Vem får anmäla sig = Qui peut s'inscrire +Anmälan måste hanteras manuellt = Votre inscription nécessite un traitement manuel +EFilterAPIEntry = Inscriptions via API +Visa rubrik = Afficher le titre +Rad X är ogiltig = La ligne X est invalide +Klassen X är listad flera gånger = La catégorie X est listée plusieurs fois +Ogiltig starttid X = Heure de départ invalide : X +Ogiltigt startintervall X = Intervalle de départ invalide : X +Hittar inte klass X = Impossible de trouver la catégorie X +MeOS utvecklinsstöd = Aide au développement de MeOS +info:pageswithcolumns = Montrer la liste page par page, avec un nombre spécifié de colonnes. Les infos sont mises à jour à chaque bouclage. +Pages with columns = Pages avec colonnes +Pages with columns, no header = Pages avec colonnes, sans titre +Externa adresser = Liens externes +info:advanceinfo = Le service de transfert instantané des résultats a planté. Les résultats seront reçus avec quelques secondes de délais. C'est ce qui risque d'arriver si plus d'un service est lancé depuis cet ordinateur. +Klassen är full = La catégorie est déjà complète +Flytta upp = Monter +Flytta ner = Descendre +EFilterWrongFee = Frais d'inscription inattendu +RunnerExpectedFee = Tarif d'inscription attendu +Unexpected Fee = Tarifs d'inscription inattendus +Anmälningsdatum = Date d'inscription +Förväntad = Attendu +Registrera hyrbrickor = Pré-inscrire les puces louées +Vill du sätta hyrbricka på befintliga löpare med dessa brickor? = Voulez-vous distribuer les puces comptées comme louées à des coureurs déjà inscrits ? +Vill du ta bort brickan från hyrbrickslistan? = Voulez-vous retirer la puce de la liste des puces à louer ? +Vill du tömma listan med hyrbrickor? = Voulez-vous supprimer la liste des puces à louer ? +prefsLastExportTarget = Cible du dernier export +prefsServiceRootMap = Fonctions standard pour la source du serveur Web +prefsshowheader = Afficher les titres +help:registerhiredcards = Pré-inscrivez des puces comme puces louées pour assigner automatiquement le statut et le tarif correspondant quand cette puce est assignée. +Lagändringblankett = Modifications d'équipes +Mappa rootadresssen (http:///localhost:port/) till funktion = Map root address (http:///localhost:port/) to function ($2428) +ClassAvailableMaps = Cartes disponibles pour la catégorie +ClassTotalMaps = Nombre total de cartes pour la catégorie +Export split times = Exporter les temps intermédiaires diff --git a/code/gdifonts.h b/code/gdifonts.h index 4954057..1d8fc02 100644 --- a/code/gdifonts.h +++ b/code/gdifonts.h @@ -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), diff --git a/code/gdioutput.cpp b/code/gdioutput.cpp index 60c49a0..a45b3b6 100644 --- a/code/gdioutput.cpp +++ b/code/gdioutput.cpp @@ -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() { diff --git a/code/gdioutput.h b/code/gdioutput.h index 9700a64..ee8f4fb 100644 --- a/code/gdioutput.h +++ b/code/gdioutput.h @@ -184,6 +184,8 @@ protected: HBRUSH Background; + mutable map, int> fontHeightCache; + map 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; diff --git a/code/generalresult.cpp b/code/generalresult.cpp index a5ba25c..bfc727c 100644 --- a/code/generalresult.cpp +++ b/code/generalresult.cpp @@ -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 ×, vector &numbers) const { diff --git a/code/infoserver.cpp b/code/infoserver.cpp index 3f82969..1d41f41 100644 --- a/code/infoserver.cpp +++ b/code/infoserver.cpp @@ -812,6 +812,7 @@ void xmlbuffer::startXML(xmlparser &xml, const wstring &dest) { } bool xmlbuffer::commit(xmlparser &xml, int count) { + vector 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 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::max()); diff --git a/code/iof30interface.cpp b/code/iof30interface.cpp index d5fef11..be54c42 100644 --- a/code/iof30interface.cpp +++ b/code/iof30interface.cpp @@ -106,6 +106,13 @@ void IOF30Interface::readCourseData(gdioutput &gdi, const xmlobject &xo, bool up failed++; } + vector 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 &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(); diff --git a/code/iof30interface.h b/code/iof30interface.h index 288a5d4..637785e 100644 --- a/code/iof30interface.h +++ b/code/iof30interface.h @@ -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); diff --git a/code/meosversion.cpp b/code/meosversion.cpp index 90c2659..fe62d77 100644 --- a/code/meosversion.cpp +++ b/code/meosversion.cpp @@ -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 &supp, vector &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()); } diff --git a/code/metalist.cpp b/code/metalist.cpp index 8f8fef0..e68efd2 100644 --- a/code/metalist.cpp +++ b/code/metalist.cpp @@ -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, 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(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(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(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(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"; diff --git a/code/oCard.cpp b/code/oCard.cpp index 0c1c7b1..dc0742e 100644 --- a/code/oCard.cpp +++ b/code/oCard.cpp @@ -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) { diff --git a/code/oCard.h b/code/oCard.h index d5e57dd..bcc44d9 100644 --- a/code/oCard.h +++ b/code/oCard.h @@ -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); diff --git a/code/oClass.cpp b/code/oClass.cpp index 3685af7..6b27774 100644 --- a/code/oClass.cpp +++ b/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 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 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 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::iterator cit = cSet.begin(); cit!= cSet.end(); ++cit) { pCourse pc = *cit; @@ -3142,9 +3218,7 @@ void oClass::calculateSplits() { vector< vector > splitsAcc(nc+1); vector 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) diff --git a/code/oClass.h b/code/oClass.h index 7321032..f2c153a 100644 --- a/code/oClass.h +++ b/code/oClass.h @@ -284,6 +284,19 @@ protected: mutable int tMapsUsed; mutable int tMapsUsedNoVacant; + // First is data revision, second is key + mutable pair> 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; diff --git a/code/oControl.cpp b/code/oControl.cpp index 04a619a..8a34360 100644 --- a/code/oControl.cpp +++ b/code/oControl.cpp @@ -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); diff --git a/code/oCourse.cpp b/code/oCourse.cpp index b5fb4c1..fb53c3b 100644 --- a/code/oCourse.cpp +++ b/code/oCourse.cpp @@ -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 &pc) -{ +void oCourse::getControls(vector &pc) const { pc.clear(); pc.reserve(nControls); for(int k=0;k &pc) } } +vector oCourse::getControlNumbers() const { + vector ret; + for (int k = 0; kgetFirstNumber()); + } + return ret; +} + int oCourse::distance(const SICard &card) { int matches=0; diff --git a/code/oCourse.h b/code/oCourse.h index 58f3177..6f4066e 100644 --- a/code/oCourse.h +++ b/code/oCourse.h @@ -211,7 +211,9 @@ public: pControl addControl(int Id); void Set(const xmlobject *xo); - void getControls(vector &pc); + void getControls(vector &pc) const; + vector getControlNumbers() const; + string getControls() const; string getLegLengths() const; diff --git a/code/oEvent.cpp b/code/oEvent.cpp index 89286cc..052b7b1 100644 --- a/code/oEvent.cpp +++ b/code/oEvent.cpp @@ -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 &ids) continue; //Already found. //Remove a singe runner team - autoRemoveTeam(r); - - for (size_t k=0;kmultiRunner.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) { diff --git a/code/oEvent.h b/code/oEvent.h index d888791..35b6d3d 100644 --- a/code/oEvent.h +++ b/code/oEvent.h @@ -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 &filter) const; pRunner findRunner(const wstring &s, int lastId, const unordered_set &inputFilter, unordered_set &filter) const; @@ -826,7 +824,7 @@ protected: mutable multimap bibStartNoToRunnerTeam; mutable shared_ptr> cardToRunnerHash; - unordered_multimap &getCardToRunner() const; + vector getCardToRunner(int cardNo) const; mutable set hiredCardHash; mutable int tHiredCardHashDataRevision = -1; diff --git a/code/oFreePunch.cpp b/code/oFreePunch.cpp index a4440a9..5f336ed 100644 --- a/code/oFreePunch.cpp +++ b/code/oFreePunch.cpp @@ -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); diff --git a/code/oImportExport.cpp b/code/oImportExport.cpp index 45aecde..107beec 100644 --- a/code/oImportExport.cpp +++ b/code/oImportExport.cpp @@ -2255,7 +2255,7 @@ void oEvent::exportIOFResults(xmlparser &xml, bool selfContained, const set 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 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 xml.startTag("SplitTime", "sequence", itos(no++)); xml.write("ControlCode", pcourse->Controls[k]->getFirstNumber()); if (unsigned(k)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 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 xml.startTag("SplitTime", "sequence", itos(no++)); xml.write("ControlCode", pcourse->Controls[k]->getFirstNumber()); if (unsigned(k)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 void oEvent::exportTeamSplits(xmlparser &xml, const set &classes, bool oldStylePatrol) { + wstring hhmmss = L"HH:MM:SS"; vector dummy; bool ClassStarted=false; int Id=-1; @@ -2531,13 +2532,13 @@ void oEvent::exportTeamSplits(xmlparser &xml, const set &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 &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 &classes, bool oldS xml.startTag("SplitTime", "sequence", itos(no++)); xml.write("ControlCode", pcourse->Controls[k]->getFirstNumber()); if (unsigned(k)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"--:--:--"); diff --git a/code/oListInfo.cpp b/code/oListInfo.cpp index 6ca1b07..8819608 100644 --- a/code/oListInfo.cpp +++ b/code/oListInfo.cpp @@ -284,7 +284,7 @@ int oListInfo::getMaxCharWidth(const oEvent *oe, const vector< pair > &typeFormats, gdiFonts font, const wchar_t *fontFace, - bool large, int minSize) { + bool large, int minSize) const { vector 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 &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 &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 > 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(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) diff --git a/code/oListInfo.h b/code/oListInfo.h index 52c26a6..23d3dcc 100644 --- a/code/oListInfo.h +++ b/code/oListInfo.h @@ -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 > typeFormats(1, make_pair(type, formats)); return getMaxCharWidth(oe, oe->gdiBase(), clsSel, typeFormats, font, fontFace, largeSize, minSize); } diff --git a/code/oPunch.cpp b/code/oPunch.cpp index abca535..2afcf89 100644 --- a/code/oPunch.cpp +++ b/code/oPunch.cpp @@ -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()); diff --git a/code/oPunch.h b/code/oPunch.h index b80a291..ed954da 100644 --- a/code/oPunch.h +++ b/code/oPunch.h @@ -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(); diff --git a/code/oRunner.cpp b/code/oRunner.cpp index d0daf16..765838c 100644 --- a/code/oRunner.cpp +++ b/code/oRunner.cpp @@ -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 &oEvent::getCardToRunner() const { +vector oEvent::getCardToRunner(int cardNo) const { if (!cardToRunnerHash || cardToRunnerHash->size() > Runners.size() * 2) { cardToRunnerHash = make_shared>(); for (auto &rc : Runners) { @@ -2570,16 +2576,33 @@ unordered_multimap &oEvent::getCardToRunner() const { cardToRunnerHash->emplace(cno, r); // The cache is "to large" -> filter is needed when looking into it. } } - return *cardToRunnerHash; + vector res; + set 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 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(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(myNames.size(), 2); + return nMatched >= min(max(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; -} \ No newline at end of file +} + +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; +} diff --git a/code/oRunner.h b/code/oRunner.h index 4d06901..038b62b 100644 --- a/code/oRunner.h +++ b/code/oRunner.h @@ -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; diff --git a/code/oTeam.cpp b/code/oTeam.cpp index 124f812..008c367 100644 --- a/code/oTeam.cpp +++ b/code/oTeam.cpp @@ -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); diff --git a/code/pdfwriter.cpp b/code/pdfwriter.cpp index 752f7c8..49c0fe1 100644 --- a/code/pdfwriter.cpp +++ b/code/pdfwriter.cpp @@ -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 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 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()); diff --git a/code/swedish.lng b/code/swedish.lng index 2a64b5f..27650eb 100644 --- a/code/swedish.lng +++ b/code/swedish.lng @@ -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 diff --git a/code/xmlparser.cpp b/code/xmlparser.cpp index c85cc83..294ac0e 100644 --- a/code/xmlparser.cpp +++ b/code/xmlparser.cpp @@ -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 + << "" << endl; + } + else { + char bf[512]; + sprintf_s(bf, "<%s>%s\n", tag, valEnc.c_str(), tag); + fOut() << bf; + } + /*fOut() << "<" << tag << ">" << encodeXML(Value) - << "" << endl; + << "" << 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) - << "" << endl; + auto &valEnc = encodeXML(Value); + if (valEnc.length() > 400) { + fOut() << "<" << tag << ">" + << valEnc + << "" << endl; + } + else { + char bf[512]; + sprintf_s(bf, "<%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 + << "" << endl; + } + else { + char bf[512]; + sprintf_s(bf, "<%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) - << "" << endl; + << "\n"; } if (!fOut().good()) throw meosException("Writing to XML file failed."); @@ -222,10 +266,10 @@ void xmlparser::write(const char *tag, const vector< pair > &pr } if (!value.empty()) { fOut() << ">" << encodeXML(value) - << "" << endl; + << "\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 - << "" << endl; + char bf[256]; + sprintf_s(bf, "<%s>%d\n", tag, Value, tag); + fOut() << bf; + //fOut() << "<" << tag << ">" + // << Value + // << "" << 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") - << "" << endl; + if (value) { + char bf[256]; + sprintf_s(bf, "<%s>true\n", tag, tag); + fOut() << bf; + } + else { + char bf[256]; + sprintf_s(bf, "<%s>false\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 - << "" << endl; + << "\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 &propvalue) for (size_t k=0;k" << 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 &propvalue) void xmlparser::startTag(const char *tag, const vector &propvalue) { if (tagStackPointer<32) { - fOut() << "<" << tag << " "; + fOut() << "<" << tag ; for (size_t k=0;k" << 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 &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() << "" << endl; + char bf[128]; + const char *tag = tagStack[--tagStackPointer].c_str(); + sprintf_s(bf, "\n", tag); + fOut() << bf; + if (!fOut().good()) throw meosException("Writing to XML file failed."); } diff --git a/code/xmlparser.h b/code/xmlparser.h index 144b54a..b4b24c7 100644 --- a/code/xmlparser.h +++ b/code/xmlparser.h @@ -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 > &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);