// oEvent.h: interface for the oEvent class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_OEVENT_H__CDA15578_CB62_4EAD_96B9_3037355F5D48__INCLUDED_) #define AFX_OEVENT_H__CDA15578_CB62_4EAD_96B9_3037355F5D48__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 /************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2018 Melin Software HB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ #include "oDataContainer.h" #include "oControl.h" #include "oCourse.h" #include "oClass.h" #include "oClub.h" #include "oRunner.h" #include "oCard.h" #include "oFreePunch.h" #include "oTeam.h" #include "intkeymap.hpp" #include #include #ifdef OLD #include #include #define unordered_multimap stdext::hash_multimap #define unordered_map stdext::hash_map #define unordered_set stdext::hash_set #else #include #include #endif #define cVacantId 888888888 #define cNoClubId 999999999 class MeOSFileLock; class RunnerDB; class gdioutput; class oDataContainer; class oListInfo; struct oListParam; struct oPrintPost; enum EStdListType; class oFreeImport; class oWordList; class ClassConfigInfo; enum EPostType; struct SocketPunchInfo; class DirectSocket; template class intkeymap; class MeOSFeatures; class GeneralResult; class DynamicResult; struct SpeakerString; struct ClassDrawSpecification; class ImportFormats; struct oCounter { int level1; int level2; int level3; oCounter() : level1(0), level2(0), level3(0) {} void operator++() {level1++, level2++, level3++;} }; struct GeneralResultCtr { wstring name; string tag; wstring fileSource; bool isDynamic() const; mutable GeneralResult *ptr; GeneralResultCtr(const char *tag, const wstring &name, GeneralResult *ptr); GeneralResultCtr(wstring &file, DynamicResult *ptr); GeneralResultCtr() : ptr(0) {} ~GeneralResultCtr(); GeneralResultCtr(const GeneralResultCtr &ctr); void operator=(const GeneralResultCtr &ctr); }; class oTimeLine { public: enum TimeLineType {TLTStart, TLTFinish, TLTRadio, TLTExpected}; enum Priority {PTop = 6, PHigh = 5, PMedium = 4, PLow = 3}; private: int time; wstring msg; wstring detail; TimeLineType type; Priority priority; pair typeId; //True if teamId, otherwise runnerId int classId; int ID; public: oTimeLine &setMessage(const wstring &msg_) {msg = msg_; return *this;} oTimeLine &setDetail(const wstring &detail_) {detail = detail_; return *this;} const wstring &getMessage() const {return msg;} const wstring &getDetail() const {return detail;} int getTime() const {return time;} TimeLineType getType() const {return type;} Priority getPriority() const {return priority;} int getClassId() const {return classId;} pair getSource() const {return typeId;} oAbstractRunner *getSource(const oEvent &oe) const; __int64 getTag() const; oTimeLine(int time, TimeLineType type, Priority priority, int classId, int id, oAbstractRunner *source); virtual ~oTimeLine(); }; typedef multimap TimeLineMap; typedef TimeLineMap::iterator TimeLineIterator; typedef list oControlList; typedef list oCourseList; typedef list oClassList; typedef list oClubList; typedef list oRunnerList; typedef list oCardList; typedef list oTeamList; typedef list oFreePunchList; typedef int (*GUICALLBACK)(gdioutput *gdi, int type, void *data); struct ClassInfo; struct DrawInfo; struct CompetitionInfo { int Id; wstring Name; wstring Annotation; wstring Date; wstring NameId; wstring FullPath; string Server; string ServerUser; string ServerPassword; string Modified; wstring url; wstring firstStart; wstring account; wstring lastNormalEntryDate; int ServerPort; int numConnected; // Number of connected entities int backupId; // Used to identify backups bool operator<(const CompetitionInfo &ci) { if (Date != ci.Date) return Date TempResultMap; struct TimeRunner; struct PrintPostInfo; enum PropertyType { String, Integer, Boolean }; class oEvent : public oBase { private: oDataDefiner *firstStartDefiner; oDataDefiner *intervalDefiner; protected: // Revision number for data modified on this client. unsigned long dataRevision; // Set to true if a global modification is made that should case all lists etc to regenerate. bool globalModification; gdioutput &gdibase; HMODULE hMod;//meosdb.dll void generateFixedList(gdioutput &gdi, const oListInfo &li); void startReconnectDaemon(); mutable int vacantId; //Cached vacant id mutable int noClubId; //Cached no club id wstring Name; wstring Annotation; wstring Date; DWORD ZeroTime; mutable map date2LocalTZ; const wstring &getTimeZoneString() const; int tCurrencyFactor; wstring tCurrencySymbol; wstring tCurrencySeparator; bool tCurrencyPreSymbol; int tMaxTime; bool writeControls(xmlparser &xml); bool writeCourses(xmlparser &xml); bool writeClasses(xmlparser &xml); bool writeClubs(xmlparser &xml); bool writeRunners(xmlparser &xml, ProgressWindow &pw); //Write free cards not bound to runner bool writeCards(xmlparser &xml); bool writePunches(xmlparser &xml, ProgressWindow &pw); bool writeTeams(xmlparser &xml); oControlList Controls; oCourseList Courses; intkeymap courseIdIndex; oClassList Classes; oClubList Clubs; intkeymap clubIdIndex; oRunnerList Runners; intkeymap runnerById; RunnerDB *runnerDB; MeOSFeatures *meosFeatures; oCardList Cards; oFreePunchList punches; typedef unordered_multimap PunchIndexType; typedef PunchIndexType::iterator PunchIterator; typedef PunchIndexType::const_iterator PunchConstIterator; /** First level maps a constant based on control number and index on course to a second maps, that maps cardNo to punches. */ map punchIndex; oTeamList Teams; intkeymap teamById; oDataContainer *oEventData; oDataContainer *oControlData; oDataContainer *oCourseData; oDataContainer *oClassData; oDataContainer *oClubData; oDataContainer *oRunnerData; oDataContainer *oTeamData; string sqlUpdateRunners; string sqlUpdateClasses; string sqlUpdateCourses; string sqlUpdateControls; string sqlUpdateClubs; string sqlUpdateCards; string sqlUpdatePunches; string sqlUpdateTeams; int sqlCounterRunners; int sqlCounterClasses; int sqlCounterCourses; int sqlCounterControls; int sqlCounterClubs; int sqlCounterCards; int sqlCounterPunches; int sqlCounterTeams; bool sqlChangedRunners; bool sqlChangedClasses; bool sqlChangedCourses; bool sqlChangedControls; bool sqlChangedClubs; bool sqlChangedCards; bool sqlChangedPunches; bool sqlChangedTeams; bool needReEvaluate(); DirectSocket *directSocket; int getFreeRunnerId(); int getFreeClassId(); int getFreeCourseId(); int getFreeControlId(); int getFreeClubId(); int getFreeCardId(); int getFreePunchId(); int getFreeTeamId(); int qFreeRunnerId; int qFreeClassId; int qFreeCourseId; int qFreeControlId; int qFreeClubId; int qFreeCardId; int qFreePunchId; int qFreeTeamId; int nextFreeStartNo; void updateFreeId(); void updateFreeId(oBase *ob); SortOrder CurrentSortOrder; list cinfo; list backupInfo; mutable map classTypeNameToType; MetaListContainer *listContainer; wchar_t CurrentFile[260]; wstring currentNameId; static int dbVersion; string MySQLServer; string MySQLUser; string MySQLPassword; int MySQLPort; string serverName;//Verified (connected) server name. MeOSFileLock *openFileLock; bool HasDBConnection; bool HasPendingDBConnection; bool msSynchronize(oBase *ob); void resetChangeStatus(bool onlyChangable=true); void storeChangeStatus(bool onlyChangable=true); wstring clientName; vector connectedClients; DWORD clientCheckSum() const; //Calculate a check sum for current clients DWORD currentClientCS; //The current, stored check sum. //Protected speaker functions. int computerTime; multimap timeLineEvents; int timeLineRevision; set timelineClasses; set modifiedClasses; static const int dataSize = 1024; int getDISize() const {return dataSize;} BYTE oData[dataSize]; BYTE oDataOld[dataSize]; vector< vector > dynamicData; /** Get internal data buffers for DI */ oDataContainer &getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const; //Precalculated. Used in list processing. vector currentSplitTimes; void initProperties(); map eventProperties; map savedProperties; bool tUseStartSeconds; set< pair > readPunchHash; void insertIntoPunchHash(int card, int code, int time); void removeFromPunchHash(int card, int code, int time); bool isInPunchHash(int card, int code, int time); void generateStatisticsPart(gdioutput &gdi, const vector &type, const set &feeLimit, int actualFee, bool useReducedFee, int baseFee, int &entries_sum, int &started_sum, int &fee_sum) const; void getRunnersPerDistrict(vector &runners) const; void getDistricts(vector &district); void autoAddTeam(pRunner pr); void autoRemoveTeam(pRunner pr); void exportIOFEventList(xmlparser &xml); void exportIOFEvent(xmlparser &xml); void exportIOFClass(xmlparser &xml); void exportIOFStartlist(xmlparser &xml); void exportIOFClublist(xmlparser &xml); void exportIOFResults(xmlparser &xml, bool selfContained, const set &classes, int leg, bool oldStylePatrol); void exportTeamSplits(xmlparser &xml, const set &classes, bool oldStylePatrol); /** Set up transient data in classes */ void reinitializeClasses(); /** Analyze the result status of each class*/ void analyzeClassResultStatus() const; /// Implementation versions int setupTimeLineEvents(int classId, int currentTime); int setupTimeLineEvents(vector &started, const vector< pair > &rc, int currentTime, bool finish); void timeLinePrognose(TempResultMap &result, TimeRunner &tr, int prelT, int radioNumber, const wstring &rname, int radioId); int nextTimeLineEvent; // Time when next known event will occur. // Tables map tables; // Internal list method void generateListInternal(gdioutput &gdi, const oListInfo &li, bool formatHead); /** Format a string for a list. */ const wstring &formatListStringAux(const oPrintPost &pp, const oListParam &par, const pTeam t, const pRunner r, const pClub c, const pClass pc, oCounter &counter) const; /** Format a string that does not depend on team or runner*/ const wstring &formatSpecialStringAux(const oPrintPost &pp, const oListParam &par, const pTeam t, int legIndex, const pCourse pc, const pControl ctrl, oCounter &counter) const; void changedObject(); mutable vector generalResults; // Temporarily disable recaluclate leader times bool disableRecalculate; public: int getVacantClub(bool returnNoClubClub); // Create vacant club if it does not exist int getVacantClubIfExist(bool returnNoClubClub) const; enum NameMode { FirstLast, LastFirst, Raw, }; private: NameMode currentNameMode; public: NameMode getNameMode() const {return currentNameMode;}; NameMode setNameMode(NameMode newNameMode); /// Get new punches since firstTime void getLatestPunches(int firstTime, vector &punches) const; void resetSQLChanged(bool resetAllTeamsRunners, bool cleanClasses); void pushDirectChange(); void getPayModes(vector< pair > &modes); void setPayMode(int id, const wstring &mode); bool hasDirectSocket() const {return directSocket != 0;} DirectSocket &getDirectSocket(); bool advancePunchInformation(const vector &gdi, vector &pi, bool getPunch, bool getFinish); // Sets and returns extra lines (string, style) to be printed on the split print, invoice, ... void setExtraLines(const char *attrib, const vector > &lines); void getExtraLines(const char *attrib, vector > &lines) const; RunnerDB &getRunnerDatabase() const {return *runnerDB;} MeOSFeatures &getMeOSFeatures() const {return *meosFeatures;} void getDBRunnersInEvent(intkeymap &runners) const; MetaListContainer &getListContainer() const; wstring getNameId(int id) const; const wstring &getFileNameFromId(int id) const; // Adjust team size to class size and create multi runners. void adjustTeamMultiRunners(pClass cls); //Get list of runners in a class void getRunners(int classId, int courseId, vector &r, bool sortRunners = true); void getRunnersByCard(int cardNo, vector &r); void getTeams(int classId, vector &t, bool sortTeams = true); bool hasRank() const; bool hasBib(bool runnerBib, bool teamBib) const; bool hasTeam() const; /// Speaker timeline int setupTimeLineEvents(int currentTime); void renderTimeLineEvents(gdioutput &gdi) const; int getTimeLineEvents(const set &classes, vector &events, set<__int64> &stored, int currentTime); /// Notification that a class has been changed. If only a punch changed void classChanged(pClass cls, bool punchOnly); // Rogaining bool hasRogaining() const; // Maximal time wstring getMaximalTimeS() const; int getMaximalTime() const; void setMaximalTime(const wstring &time); void saveProperties(const wchar_t *file); void loadProperties(const wchar_t *file); /** Get number of classes*/ int getNumClasses() const {return Classes.size();} /** Get number of runners */ int getNumRunners() const {return runnerById.size();} // Show an warning dialog if database is not sane void sanityCheck(gdioutput &gdi, bool expectResult, int checkOnlyClass = -1); // Automatic draw of all classes void automaticDrawAll(gdioutput &gdi, const wstring &firstStart, const wstring &minIntervall, const wstring &vacances, bool lateBefore, bool softMethod, int pairSize); // Restore a backup by renamning the file to .meos void restoreBackup(); void generateVacancyList(gdioutput &gdi, GUICALLBACK callBack); // Returns true if there is a multi runner class. bool hasMultiRunner() const; void updateTabs(bool force = false, bool hide = false) const; bool useRunnerDb() const; void useRunnerDb(bool use); int getFirstClassId(bool teamClass) const; void generateCompetitionReport(gdioutput &gdi); // To file if n > 10. enum InvoicePrintType {IPTAllPrint=1, IPTAllHTML=11, IPTNoMailPrint=2, IPTNonAcceptedPrint=3, IPTElectronincHTML=12, IPTAllPDF=13}; void printInvoices(gdioutput &gdi, InvoicePrintType type, const wstring &basePath, bool onlySummary); void selectRunners(const wstring &classType, int lowAge, int highAge, const wstring &firstDate, const wstring &lastDate, bool includeWithFee, vector &output) const; void applyEventFees(bool updateClassFromEvent, bool updateFees, bool updateCardFees, const set &classFilter); void listConnectedClients(gdioutput &gdi); void validateClients(); bool hasClientChanged() const; enum PredefinedTypes {PNoSettings, PPool, PForking, PPoolDrawn, PHunting, PPatrol, PPatrolOptional, PPatrolOneSI, PRelay, PTwinRelay, PYouthRelay, PNoMulti}; void fillPredefinedCmp(gdioutput &gdi, const string &name) const; // Sets up class and ajust multirunner in teams and synchronizes. void setupRelay(oClass &cls, PredefinedTypes type, int nleg, const wstring &start); void setupRelayInfo(PredefinedTypes type, bool &useNLeg, bool &useNStart); void fillLegNumbers(const set &cls, bool isTeamList, bool includeSubLegs, vector< pair > &out); void reCalculateLeaderTimes(int classId); void testFreeImport(gdioutput &gdi); void getFreeImporter(oFreeImport &fi); void init(oFreeImport &fi); 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; static const wstring &formatStatus(RunnerStatus status); inline bool useStartSeconds() const {return tUseStartSeconds;} void calcUseStartSeconds(); void assignCardInteractive(gdioutput &gdi, GUICALLBACK cb); int getPropertyInt(const char *name, int def); const string &getPropertyString(const char *name, const string &def); const wstring &getPropertyString(const char *name, const wstring &def); wstring getPropertyStringDecrypt(const char *name, const string &def); void setProperty(const char *name, int prop); //void setProperty(const char *name, const string &prop); void setProperty(const char *name, const wstring &prop); void setPropertyEncrypt(const char *name, const string &prop); void listProperties(bool userProps, vector< pair > &propNames) const; // Get classes that have not yet been drawn. // someMissing (true = all classes where some runner has no start time) // (false = all classeds where no runner has a start time) void getNotDrawnClasses(set &classes, bool someMissing); void getAllClasses(set &classes); bool deleteCompetition(); void clear(); // Drop the open database. void dropDatabase(); bool connectToMySQL(const string &server, const string &user, const string &pwd, int port); bool connectToServer(); bool reConnect(char *errorMsg256); void closeDBConnection(); const string &getServerName() const; // Upload competition to server bool uploadSynchronize(); // Download competition from server bool readSynchronize(const CompetitionInfo &ci); void playPrewarningSounds(const wstring &basedir, set &controls); void clearPrewarningSounds(); void tryPrewarningSounds(const wstring &basedir, int number); int getFreeStartNo() const; void generatePreReport(gdioutput &gdi); void generateList(gdioutput &gdi, bool reEvaluate, const oListInfo &li, bool updateScrollBars); void generateListInfo(oListParam &par, int lineHeight, oListInfo &li); void generateListInfo(vector &par, int lineHeight, oListInfo &li); void generateListInfo(EStdListType lt, const gdioutput &gdi, int classId, oListInfo &li); void generateListInfoAux(oListParam &par, int lineHeight, oListInfo &li, const wstring &name); /** Format a string for a list. Returns true of output is not empty*/ const wstring &formatListString(const oPrintPost &pp, const oListParam &par, const pTeam t, const pRunner r, const pClub c, const pClass pc, oCounter &counter) const; const wstring &formatSpecialString(const oPrintPost &pp, const oListParam &par, const pTeam t, int legIndex, const pCourse crs, const pControl ctrl, oCounter &counter) const; void calculatePrintPostKey(const list &ppli, gdioutput &gdi, const oListParam &par, const pTeam t, const pRunner r, const pClub c, const pClass pc, oCounter &counter, wstring &key); const wstring &formatListString(EPostType type, const pRunner r) const; const wstring &formatListString(EPostType type, const pRunner r, const wstring &format) const; /** Format a print post. Returns true of output is not empty*/ bool formatPrintPost(const list &ppli, PrintPostInfo &ppi, const pTeam t, const pRunner r, const pClub c, const pClass pc, const pCourse crs, const pControl ctrl, int legIndex); void listGeneratePunches(const list &ppli, gdioutput &gdi, const oListParam &par, pTeam t, pRunner r, pClub club, pClass cls); void getListTypes(map &listMap, int filter); void getListType(EStdListType type, oListInfo &li); void fillListTypes(gdioutput &gdi, const string &name, int filter); void checkOrderIdMultipleCourses(int ClassId); void addBib(int ClassId, int leg, const wstring &firstNumber); void addAutoBib(); //Speaker functions. void speakerList(gdioutput &gdi, int classId, int leg, int controlId, int previousControlId, bool totalResults, bool shortNames); int getComputerTime() const {return (computerTime+500)/1000;} int getComputerTimeMS() const {return computerTime;} void updateComputerTime(); // Get set of controls with registered punches void getFreeControls(set &controlId) const; // Returns the added punch, of null of already added. pFreePunch addFreePunch(int time, int type, int card, bool updateRunner); pFreePunch addFreePunch(oFreePunch &fp); bool useLongTimes() const; void useLongTimes(bool use); /** Use the current computer time to convert the specified time to a long time, if long times are used. */ int convertToFullTime(int inTime); /** Internal version of start order optimizer */ void optimizeStartOrder(vector< vector > > &StartField, DrawInfo &drawInfo, vector &cInfo, int useNControls, int alteration); struct ResultEvent { ResultEvent() {} ResultEvent(pRunner r, int time, int control, RunnerStatus status): r(r), time(time), control(control), status(status), resultScore(0), place(-1), runTime(0), partialCount(0), legNumber(short(r->tLeg)) {} pRunner r; int time; int control; RunnerStatus status; int localIndex; int resultScore; int runTime; unsigned short place; /* By default zero. Used for parallel results etc. -1 : Ignore 1,2,3 (how many runners are missing on the leg) */ short partialCount; short legNumber; inline int classId() const {return r->getClassId(true);} inline int leg() const {return legNumber;} }; void getResultEvents(const set &classFilter, const set &controlFilter, vector &results) const; protected: // Returns hash key for punch based on control id, and leg. Class is marked as changed if oldHashKey != newHashKey. int getControlIdFromPunch(int time, int type, int card, bool markClassChanged, oFreePunch &punch); static void drawSOFTMethod(vector &runners, bool handleBlanks=true); bool enumerateBackups(const wstring &file, const wstring &filetype, int type); unordered_multimap cardHash; mutable multimap bibStartNoToRunnerTeam; int tClubDataRevision; bool readOnly; mutable int tLongTimesCached; mutable map > cachedFirstStart; //First start per classid. map, oFreePunch> advanceInformationPunches; public: void updateStartTimes(int delta); void useDefaultProperties(bool useDefault); bool isReadOnly() const {return readOnly;} void setReadOnly() {readOnly = true;} enum IOFVersion {IOF20, IOF30}; void setCurrency(int factor, const wstring &symbol, const wstring &separator, bool preSymbol); wstring formatCurrency(int c, bool includeSymbol = true) const; int interpretCurrency(const wstring &c) const; int interpretCurrency(double val, const wstring &cur); void setupClubInfoData(); //Precalculate temporary data in club object // Clears map if clear is true. A cleared map is not used. Map must be cleared after use, is not updated. void setupCardHash(bool clear = false); void remove(); bool canRemove() const; /// Return revision number for current data long getRevision() const {return dataRevision;} /// Calculate total missed time and other statistics for each control void setupControlStatistics() const; // Get information on classes void getClassConfigurationInfo(ClassConfigInfo &cnf) const; /** Add numbers to make team names unique */ void makeUniqueTeamNames(); void removeVacanies(int classId); wstring getInfo() const {return Name;} bool verifyConnection(); bool isClient() const {return HasDBConnection;} const wstring &getClientName() const {return clientName;} void setClientName(const wstring &n) {clientName=n;} void removeFreePunch(int id); pFreePunch getPunch(int id) const; pFreePunch getPunch(int runnerId, int courseControlId, int card) const; void getPunchesForRunner(int runnerId, vector &punches) const; //Returns true if data is changed. bool autoSynchronizeLists(bool syncPunches); bool synchronizeList(oListId id, bool preSyncEvent = true, bool postSyncEvent = true); void generateInForestList(gdioutput &gdi, GUICALLBACK cb, GUICALLBACK cb_nostart); pRunner dbLookUpById(__int64 extId) const; pRunner dbLookUpByCard(int CardNo) const; pRunner dbLookUpByName(const wstring &name, int clubId, int classId, int birthYear) const; void updateRunnerDatabase(); void updateRunnerDatabase(pRunner r, map &clubIdMap); /** Returns the first start in a class */ int getFirstStart(int classId = 0) const; void convertTimes(pRunner runner, SICard &sic) const; pCard getCard(int Id) const; pCard getCardByNumber(int cno) const; bool isCardRead(const SICard &card) const; void getCards(vector &cards); /** Try to find the class that best matches the card. Negative return = missing controls Positve return = extra controls Zero = exact match */ int findBestClass(const SICard &card, vector &classes) const; wstring getCurrentTimeS() const; //void reEvaluateClass(const set &classId, bool doSync); void reEvaluateCourse(int courseId, bool doSync); void reEvaluateAll(const set &classId, bool doSync); void reEvaluateChanged(); void exportIOFSplits(IOFVersion version, const wchar_t *file, bool oldStylePatrolExport, bool useUTC, const set &classes, int leg, bool teamsAsIndividual, bool unrollLoops, bool includeStageData, bool forceSplitFee); void exportIOFStartlist(IOFVersion version, const wchar_t *file, bool useUTC, const set &classes, bool teamsAsIndividual, bool includeStageInfo, bool forceSplitFee); bool exportOECSV(const wchar_t *file, int LanguageTypeIndex, bool includeSplits); bool save(); void duplicate(); void newCompetition(const wstring &Name); void clearListedCmp(); bool enumerateCompetitions(const wchar_t *path, const wchar_t *extension); bool fillCompetitions(gdioutput &gdi, const string &name, int type, const wstring &select = L""); bool enumerateBackups(const wstring &path); bool listBackups(gdioutput &gdi, GUICALLBACK cb); const BackupInfo &getBackup(int id) const; void deleteBackups(const BackupInfo &bu); // Check if competition is empty bool empty() const; void generateMinuteStartlist(gdioutput &gdi); bool classHasTeams(int Id) const; bool classHasResults(int Id) const; bool isCourseUsed(int Id) const; bool isClassUsed(int Id) const; bool isControlUsed(int Id) const; bool isRunnerUsed(int Id) const; bool isClubUsed(int Id) const; void removeRunner(const vector &Ids); void removeCourse(int Id); void removeClass(int Id); void removeControl(int Id); void removeTeam(int Id); void removeClub(int Id); void removeCard(int Id); /// Convert a clock time string to time relative zero time int getRelativeTime(const wstring &absoluteTime) const; //int getRelativeTime(const string &absoluteTime) const {return getRelativeTime(toWide(absoluteTime));} /// Convert a clock time string to time relative zero time int getRelativeTime(const string &date, const string &absoluteTime, const string &timeZone) const; // Convert a clock time string (SI5 12 Hour clock) to time relative zero time //int getRelativeTimeFrom12Hour(const wstring &absoluteTime) const; /// Convert c clock time string to absolute time (after 00:00:00) static int convertAbsoluteTime(const string &m); static int convertAbsoluteTime(const wstring &m); /// Get clock time from relative time const wstring &getAbsTime(DWORD relativeTime) const; wstring getAbsDateTimeISO(DWORD relativeTime, bool includeDate, bool useGMT) const; const wstring &getAbsTimeHM(DWORD relativeTime) const; const wstring &getName() const; wstring getTitleName() const; void setName(const wstring &m); const wstring &getAnnotation() const {return Annotation;} void setAnnotation(const wstring &m); const wstring &getDate() const {return Date;} void setDate(const wstring &m); int getZeroTimeNum() const {return ZeroTime;} wstring getZeroTime() const; void setZeroTime(wstring m); /** Get the automatic bib gap between classes. */ int getBibClassGap() const; /** Set the automatic bib gap between classes. */ void setBibClassGap(int numStages); bool openRunnerDatabase(const wchar_t *file); bool saveRunnerDatabase(const wchar_t *file, bool onlyLocal); enum ResultType {RTClassResult, RTTotalResult, RTCourseResult, RTClassCourseResult}; void calculateResults(ResultType result, bool includePreliminary = false); void calculateRogainingResults(const set &classSelection); void calculateResults(list &rl); void calculateTeamResults(bool totalMultiday); bool calculateTeamResults(int leg, bool totalMultiday); // Set results for specified classes to tempResult void calculateTeamResultAtControl(const set &classId, int leg, int controlId, bool totalResults); bool sortRunners(SortOrder so); /** If linear leg is true, leg is interpreted as actual leg numer, otherwise w.r.t to parallel legs. */ bool sortTeams(SortOrder so, int leg, bool linearLeg); pCard allocateCard(pRunner owner); /** Optimize the start order based on drawInfo. Result in cInfo */ void optimizeStartOrder(gdioutput &gdi, DrawInfo &drawInfo, vector &cInfo); void loadDrawSettings(const set &classes, DrawInfo &drawInfo, vector &cInfo) const; enum DrawType { drawAll, remainingBefore, remainingAfter, }; void drawRemaining(bool useSOFTMethod, bool placeAfter); void drawList(const vector &spec, bool useSOFTMethod, int pairSize, DrawType drawType); void drawListClumped(int classID, int firstStart, int interval, int vacances); void drawPersuitList(int classId, int firstTime, int restartTime, int ropeTime, int interval, int pairSize, bool reverse, double scale); wstring getAutoTeamName() const; pTeam addTeam(const oTeam &t, bool autoAssignStartNo); pTeam addTeam(const wstring &pname, int clubId=0, int classId=0); pTeam getTeam(int Id) const; pTeam getTeamByName(const wstring &pname) const; const vector< pair > &fillTeams(vector< pair > &out, int classId=0); const vector< pair > &fillStatus(vector< pair > &out); const vector< pair > &fillControlStatus(vector< pair > &out) const; void fillTeams(gdioutput &gdi, const string &id, int ClassId=0); void fillStatus(gdioutput &gdi, const string &id); void fillControlStatus(gdioutput &gdi, const string &id) const; wstring getAutoRunnerName() const; pRunner addRunner(const wstring &pname, int clubId, int classId, int cardNo, int birthYear, bool autoAdd); pRunner addRunner(const wstring &pname, const wstring &pclub, int classId, int cardNo, int birthYear, bool autoAdd); pRunner addRunnerFromDB(const pRunner db_r, int classId, bool autoAdd); pRunner addRunner(const oRunner &r, bool updateStartNo); pRunner addRunnerVacant(int classId); pRunner getRunner(int Id, int stage) const; /** Get a competitor by cardNo. @param cardNo card number to look for. @param time if non-zero, try to find a runner actually running on the specified time, if there are multiple runners using the same card. @param onlyRunnerWithNoCard returns only a runner that has no card tied. @param ignoreRunnersWithNoStart If true, never return a runner with status NoStart @return runner of null. */ pRunner getRunnerByCardNo(int cardNo, int time, bool onlyRunnerWithNoCard = false, bool ignoreRunnersWithNoStart = false) const; /** Get all competitors for a cardNo. @param cardNo card number to look for. @param ignoreRunnersWithNoStart If true, skip runners with status DNS @param skipDuplicates if true, only return the main instance of each runner (if several races) @param out runners using the card */ void getRunnersByCardNo(int cardNo, bool ignoreRunnersWithNoStart, bool skipDuplicates, vector &out) const; /** Finds a runner by start number (linear search). If several runners has same bib/number try to get the right one: findWithoutCardNo false : find first that has not finished findWithoutCardNo true : find first with no card. */ pRunner getRunnerByBibOrStartNo(const wstring &bib, bool findWithoutCardNo) const; pRunner getRunnerByName(const wstring &pname, const wstring &pclub = L"") const; enum FillRunnerFilter {RunnerFilterShowAll = 1, RunnerFilterOnlyNoResult = 2, RunnerFilterWithResult = 4, RunnerCompactMode = 8}; const vector< pair > &fillRunners(vector< pair > &out, bool longName, int filter, const unordered_set &personFilter); void fillRunners(gdioutput &gdi, const string &id, bool longName = false, int filter = 0); Table *getRunnersTB();//Table mode Table *getClubsTB(); Table *getPunchesTB(); Table *getClassTB(); Table *getControlTB(); Table *getCardsTB(); Table *getTeamsTB(); Table *getCoursesTB(); void generateTableData(const string &tname, Table &table, TableUpdateInfo &ui); void generateControlTableData(Table &table, oControl *addControl); void generateRunnerTableData(Table &table, oRunner *addRunner); void generateClassTableData(Table &table, oClass *addClass); void generateCardTableData(Table &table, oCard *addCard); void generateClubTableData(Table &table, oClub *club); void generatePunchTableData(Table &table, oFreePunch *punch); void generateCourseTableData(Table &table, oCourse *course); void generateTeamTableData(Table &table, oTeam *team); pClub addClub(const wstring &pname, int createId=0); pClub addClub(const oClub &oc); void getClubRunners(int clubId, vector &runners) const; void getClubTeams(int clubId, vector &teams) const; //Get club, first by id then by name, and create if it does not exist pClub getClubCreate(int Id, const wstring &createName); void mergeClub(int clubIdPri, int clubIdSec); pClub getClub(int Id) const; pClub getClub(const wstring &pname) const; const vector< pair > &fillClubs(vector< pair > &out); void fillClubs(gdioutput &gdi, const string &id); void getClubs(vector &c, bool sort); void viewClubMembers(gdioutput &gdi, int clubId); void updateClubsFromDB(); void updateRunnersFromDB(); void fillFees(gdioutput &gdi, const string &name, bool withAuto) const; wstring getAutoClassName() const; pClass addClass(const wstring &pname, int CourseId = 0, int classId = 0); pClass addClass(oClass &c); pClass getClassCreate(int Id, const wstring &createName); pClass getClass(const wstring &name) const; void getClasses(vector &classes, bool sync) const; pClass getBestClassMatch(const wstring &name) const; bool getClassesFromBirthYear(int year, PersonSex sex, vector &classes) const; pClass getClass(int Id) const; void getStartBlocks(vector &blocks, vector &starts) const; enum ClassFilter { filterNone, filterOnlyMulti, filterOnlySingle, filterOnlyDirect, }; enum ClassExtra { extraNone, extraDrawn, extraNumMaps, }; const vector< pair > &fillClasses(vector< pair > &out, ClassExtra extended, ClassFilter filter); void fillClasses(gdioutput &gdi, const string &id, ClassExtra extended, ClassFilter filter); bool fillClassesTB(gdioutput &gdi); const vector< pair > &fillStarts(vector< pair > &out); const vector< pair > &fillClassTypes(vector< pair > &out); void fillStarts(gdioutput &gdi, const string &id); void fillClassTypes(gdioutput &gdi, const string &id); wstring getAutoCourseName() const; pCourse addCourse(const wstring &pname, int plength = 0, int id = 0); pCourse addCourse(const oCourse &oc); pCourse getCourseCreate(int Id); pCourse getCourse(const wstring &name) const; pCourse getCourse(int Id) const; void getCourses(vector &courses) const; /** Get controls. If calculateCourseControls, duplicate numbers are calculated for each control and course. */ void getControls(vector &controls, bool calculateCourseControls) const; void fillCourses(gdioutput &gdi, const string &id, bool simple = false); const vector< pair > &fillCourses(vector< pair > &out, bool simple = false); void calculateNumRemainingMaps(); pControl getControl(int Id) const; pControl getControl(int Id, bool create); enum ControlType {CTAll, CTRealControl, CTCourseControl}; const vector< pair > &fillControls(vector< pair > &out, ControlType type); const vector< pair > &fillControlTypes(vector< pair > &out); bool open(int id); bool open(const wstring &file, bool import=false); bool open(const xmlparser &xml); bool save(const wstring &file); pControl addControl(int id, int number, const wstring &name); pControl addControl(const oControl &oc); int getNextControlNumber() const; pCard addCard(const oCard &oc); /** Import entry data */ void importXML_EntryData(gdioutput &gdi, const wstring &file, bool updateClass, bool removeNonexisting, const set &filter, const string &preferredIdType); protected: pClass getXMLClass(const xmlobject &xentry); pClub getClubCreate(int clubId); bool addXMLCompetitorDB(const xmlobject &xentry, int ClubId); bool addOECSVCompetitorDB(const vector &row); pRunner addXMLPerson(const xmlobject &person); pRunner addXMLStart(const xmlobject &xstart, pClass cls); pRunner addXMLEntry(const xmlobject &xentry, int ClubId, bool setClass); bool addXMLTeamEntry(const xmlobject &xentry, int ClubId); bool addXMLClass(const xmlobject &xclub); bool addXMLClub(const xmlobject &xclub, bool importToDB); // Fill in the output map. Set flag to true if match is made on id, false if on name. enum class RankStatus { IdMatch, NameMatch, Ambivalent }; bool addXMLRank(const xmlobject &xrank, const map<__int64, int> &externIdToRunnerId, map> &output); bool addXMLEvent(const xmlobject &xevent); bool addXMLCourse(const xmlobject &xcourse, bool addClasses); /** type: 0 control, 1 start, 2 finish*/ bool addXMLControl(const xmlobject &xcontrol, int type); public: GeneralResult &getGeneralResult(const string &tag, wstring &sourceFileOut) const; void getGeneralResults(bool onlyEditable, vector< pair > > &tagNameList, bool includeDateInName) const; void loadGeneralResults(bool forceReload) const; void getPredefinedClassTypes(map &types) const; wstring cloneCompetition(bool cloneRunners, bool cloneTimes, bool cloneCourses, bool cloneResult, bool addToDate); enum ChangedClassMethod { ChangeClassVacant, ChangeClass, TransferNoResult, TransferAnyway, }; void transferResult(oEvent &ce, const set &allowNewEntries, ChangedClassMethod changeClassMethod, bool transferAllNoCompete, vector &changedClass, vector &changedClassNoResult, vector &assignedVacant, vector &newEntries, vector ¬Transfered, vector &noAssignmentTarget); void transferResult(oEvent &ce, ChangedClassMethod changeClassMethod, vector &newEntries, vector ¬Transfered, vector &noAssignmentTarget); enum MultiStageType { MultiStageNone = 0, MultiStageSeparateEntry = 1, MultiStageSameEntry = 2, }; MultiStageType getMultiStageType() const; bool hasNextStage() const; bool hasPrevStage() const; int getNumStages() const; void setNumStages(int numStages); int getStageNumber() const; void setStageNumber(int num); /** Check that all necessary features are present, (fix by adding features)*/ void checkNecessaryFeatures(); /** Show dialog and return false if card is not used. */ bool checkCardUsed(gdioutput &gdi, oRunner &runnerToAssignCard, int CardNo); void analyseDNS(vector &unknown_dns, vector &known_dns, vector &known, vector &unknown, bool &hasSetDNS); void importOECSV_Data(const wstring &oecsvfile, bool clear); void importXML_IOF_Data(const wstring &clubfile, const wstring &competitorfile, bool clear); void generateTestCard(SICard &sic) const; pClass generateTestClass(int nlegs, int nrunners, wchar_t *name, const wstring &start); pCourse generateTestCourse(int nCtrl); void generateTestCompetition(int nClasses, int nRunners, bool generateTeams); //Returns number of changed, non-saved elements. int checkChanged(vector &out) const; void checkDB(); //Check database for consistancy... oEvent(gdioutput &gdi); oEvent &operator=(const oEvent &oe); virtual ~oEvent(); friend class oAbstractRunner; friend class oCourse; friend class oClass; friend class oClub; friend class oRunner; friend class oBase; friend class oControl; friend class oTeam; friend class oCard; friend class oFreePunch; friend class oListInfo; friend class MeosSQL; friend class MySQLReconnect; friend class TestMeOS; //const string &toNarrow(const wstring &in) const {return gdibase.toNarrow(in);} //const wstring &toWide(const string &in) const {return gdibase.toWide(in);} const gdioutput &gdiBase() const {return gdibase;} }; #endif // !defined(AFX_OEVENT_H__CDA15578_CB62_4EAD_96B9_3037355F5D48__INCLUDED_)