311 lines
12 KiB
C++
311 lines
12 KiB
C++
/************************************************************************
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
Melin Software HB - software@melin.nu - www.melin.nu
|
|
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
|
|
|
|
************************************************************************/
|
|
|
|
#pragma once
|
|
#include <map>
|
|
#include <set>
|
|
#include <vector>
|
|
|
|
class oEvent;
|
|
class xmlobject;
|
|
typedef vector<xmlobject> xmlList;
|
|
class xmlparser;
|
|
class gdioutput;
|
|
class oRunner;
|
|
class oClub;
|
|
class oTeam;
|
|
class oCourse;
|
|
class oControl;
|
|
class oClass;
|
|
class oDataInterface;
|
|
class oDataConstInterface;
|
|
class oAbstractRunner;
|
|
struct RunnerWDBEntry;
|
|
class RunnerDB;
|
|
|
|
typedef oRunner * pRunner;
|
|
typedef oClass * pClass;
|
|
typedef oClub * pClub;
|
|
typedef oTeam * pTeam;
|
|
typedef oCourse *pCourse;
|
|
|
|
class IOF30Interface {
|
|
oEvent &oe;
|
|
|
|
int cachedStageNumber;
|
|
int entrySourceId;
|
|
|
|
bool splitLateFee;
|
|
bool useGMT; // Use GMT when exporting
|
|
|
|
// Export teams as individual
|
|
bool teamsAsIndividual;
|
|
// Unroll course loops
|
|
bool unrollLoops;
|
|
// Include data on stage number
|
|
bool includeStageRaceInfo;
|
|
void operator=(const IOF30Interface &);
|
|
|
|
struct LegInfo {
|
|
int maxRunners;
|
|
int minRunners;
|
|
LegInfo() : maxRunners(1), minRunners(1) {}
|
|
void setMinRunners(int nr) {minRunners = max(minRunners, nr); maxRunners = max(maxRunners, nr);}
|
|
void setMaxRunners(int nr) {maxRunners = max(maxRunners, nr);}
|
|
};
|
|
|
|
struct FeeInfo {
|
|
double fee;
|
|
double taxable;
|
|
double percentage; // Eventor / OLA stupidity
|
|
|
|
wstring currency;
|
|
|
|
wstring fromTime;
|
|
wstring toTime;
|
|
|
|
wstring fromBirthDate;
|
|
wstring toBirthDate;
|
|
|
|
bool includes(const FeeInfo &fo) const {
|
|
if (toBirthDate != fo.toBirthDate || fromBirthDate != fo.fromBirthDate)
|
|
return false;
|
|
if (!includeFrom(fromTime, fo.fromTime))
|
|
return false;
|
|
if (!includeTo(toTime, fo.toTime))
|
|
return false;
|
|
/*if (!includeFrom(fromBirthDate, fo.fromBirthDate))
|
|
return false;
|
|
if (!includeTo(toBirthDate, fo.toBirthDate))
|
|
return false;*/
|
|
return true;
|
|
}
|
|
|
|
void add(FeeInfo &fi);
|
|
|
|
wstring getDateKey() const {return fromTime + L" - " + toTime;}
|
|
FeeInfo() : fee(0), taxable(0), percentage(0) {}
|
|
|
|
const bool operator<(const FeeInfo &fi) const {
|
|
return fee < fi.fee || (fee == fi.fee && taxable < fi.taxable);
|
|
}
|
|
private:
|
|
bool includeFrom(const wstring &a, const wstring &b) const {
|
|
if ( a > b || (b.empty() && !a.empty()) )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool includeTo(const wstring &a, const wstring &b) const {
|
|
if ( (!a.empty() && a < b) || (b.empty() && !a.empty()) )
|
|
return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
struct FeeStatistics {
|
|
double fee;
|
|
double lateFactor;
|
|
};
|
|
|
|
vector<FeeStatistics> feeStatistics;
|
|
|
|
static void getAgeLevels(const vector<FeeInfo> &fees, const vector<int> &ix,
|
|
int &normalIx, int &redIx, wstring &youthLimit, wstring &seniorLimit);
|
|
|
|
bool matchStageFilter(const set<int> &stageFilter, const xmlList &races);
|
|
|
|
set<string> idProviders;
|
|
string preferredIdProvider;
|
|
|
|
void readEvent(gdioutput &gdi, const xmlobject &xo,
|
|
map<int, vector<LegInfo> > &teamClassConfig);
|
|
pRunner readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam team,
|
|
const map<int, vector<LegInfo> > &teamClassConfig,
|
|
const set<int> &stageFilter,
|
|
map<int, vector< pair<int, int> > > &personId2TeamLeg);
|
|
pRunner readPerson(gdioutput &gdi, const xmlobject &xo);
|
|
pClub readOrganization(gdioutput &gdi, const xmlobject &xo, bool saveToDB);
|
|
pClass readClass(const xmlobject &xo,
|
|
map<int, vector<LegInfo> > &teamClassConfig);
|
|
|
|
pTeam readTeamEntry(gdioutput &gdi, xmlobject &xTeam,
|
|
const set<int> &stageFilter,
|
|
map<int, pair<wstring, int> > &bibPatterns,
|
|
const map<int, vector<LegInfo> > &teamClassConfig,
|
|
map<int, vector< pair<int, int> > > &personId2TeamLeg);
|
|
|
|
pRunner readPersonStart(gdioutput &gdi, pClass pc, xmlobject &xo, pTeam team,
|
|
const map<int, vector<LegInfo> > &teamClassConfig);
|
|
|
|
pTeam readTeamStart(gdioutput &gdi, pClass pc, xmlobject &xTeam,
|
|
map<int, pair<wstring, int> > &bibPatterns,
|
|
const map<int, vector<LegInfo> > &teamClassConfig);
|
|
|
|
pTeam getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, bool &newTeam);
|
|
|
|
static int getIndexFromLegPos(int leg, int legorder, const vector<LegInfo> &setup);
|
|
|
|
void prescanEntry(xmlobject & xo, set<int>& stages);
|
|
void setupClassConfig(int classId, const xmlobject &xTeam, map<int, vector<LegInfo> > &teamClassConfig);
|
|
|
|
void setupRelayClasses(const map<int, vector<LegInfo> > &teamClassConfig);
|
|
void setupRelayClass(pClass pc, const vector<LegInfo> &teamClassConfig);
|
|
|
|
int parseISO8601Time(const xmlobject &xo);
|
|
wstring getCurrentTime() const;
|
|
|
|
static void getNationality(const xmlobject &xCountry, oDataInterface &di);
|
|
|
|
static void getAmount(const xmlobject &xAmount, double &amount, wstring ¤cy);
|
|
static void getAssignedFee(const xmlobject &xFee, double &fee, double &paid, double &taxable, double &percentage, wstring ¤cy);
|
|
static void getFee(const xmlobject &xFee, FeeInfo &fee);
|
|
static void getFeeAmounts(const xmlobject &xFee, double &fee, double &taxable, double &percentage, wstring ¤cy);
|
|
|
|
void writeFees(xmlparser &xml, const oRunner &r) const;
|
|
|
|
void writeAmount(xmlparser &xml, const char *tag, int amount) const;
|
|
void writeAssignedFee(xmlparser &xml, const oAbstractRunner &tr, int paidForCard) const;
|
|
void writeRentalCardService(xmlparser &xml, int cardFee, bool paid) const;
|
|
|
|
void getProps(vector<wstring> &props) const;
|
|
|
|
void writeClassResult(xmlparser &xml, const oClass &c, const vector<pRunner> &r,
|
|
const vector<pTeam> &t);
|
|
|
|
void writeClass(xmlparser &xml, const oClass &c);
|
|
void writeCourse(xmlparser &xml, const oCourse &c);
|
|
void writePersonResult(xmlparser &xml, const oRunner &r, bool includeCourse,
|
|
bool teamMember, bool hasInputTime);
|
|
|
|
|
|
void writeTeamResult(xmlparser &xml, const oTeam &t, bool hasInputTime);
|
|
|
|
void writeResult(xmlparser &xml, const oRunner &rPerson, const oRunner &rResultCarrier,
|
|
bool includeCourse, bool includeRaceNumber, bool teamMember, bool hasInputTime);
|
|
|
|
void writePerson(xmlparser &xml, const oRunner &r);
|
|
void writeClub(xmlparser &xml, const oClub &c, bool writeExtended) const;
|
|
|
|
|
|
void getRunnersToUse(const pClass cls, vector<pRunner> &rToUse,
|
|
vector<pTeam> &tToUse, int leg, bool includeUnknown) const;
|
|
|
|
void writeClassStartList(xmlparser &xml, const oClass &c, const vector<pRunner> &r,
|
|
const vector<pTeam> &t);
|
|
|
|
void writePersonStart(xmlparser &xml, const oRunner &r, bool includeCourse, bool teamMember);
|
|
|
|
void writeTeamNoPersonStart(xmlparser &xml, const oTeam &t, int leg, bool includeRaceNumber);
|
|
|
|
void writeTeamStart(xmlparser &xml, const oTeam &t);
|
|
|
|
void writeStart(xmlparser &xml, const oRunner &r, bool includeCourse,
|
|
bool includeRaceNumber, bool teamMember);
|
|
|
|
|
|
pCourse haveSameCourse(const vector<pRunner> &r) const;
|
|
void writeLegOrder(xmlparser &xml, const oClass *pc, int legNo) const;
|
|
|
|
// Returns zero if no stage number
|
|
int getStageNumber();
|
|
|
|
bool readXMLCompetitorDB(const xmlobject &xCompetitor);
|
|
void writeXMLCompetitorDB(xmlparser &xml, const RunnerWDBEntry &rde) const;
|
|
|
|
int getStartIndex(const wstring &startId);
|
|
|
|
bool readControl(const xmlobject &xControl);
|
|
pCourse readCourse(const xmlobject &xcrs);
|
|
|
|
void readCourseGroups(xmlobject xClassCourse, vector< vector<pCourse> > &crs);
|
|
void bindClassCourse(oClass &pc, const vector< vector<pCourse> > &crs);
|
|
|
|
static wstring constructCourseName(const xmlobject &xcrs);
|
|
static wstring constructCourseName(const wstring &family, const wstring &name);
|
|
|
|
void classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignment, const map<wstring, pCourse> &courses,
|
|
const map<wstring, vector<pCourse> > &coursesFamilies);
|
|
void classCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
|
const map<wstring, pCourse> &courses,
|
|
const map<wstring, vector<pCourse> > &coursesFamilies);
|
|
void personCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
|
const map<wstring, pCourse> &courses);
|
|
void teamCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
|
const map<wstring, pCourse> &courses);
|
|
|
|
void assignTeamCourse(gdioutput &gdi, oTeam &t, xmlList &xAssignment,
|
|
const map<wstring, pCourse> &courses);
|
|
|
|
pCourse findCourse(gdioutput &gdi, const map<wstring, pCourse> &courses,
|
|
xmlobject &xPAssignment);
|
|
|
|
wstring writeControl(xmlparser &xml, const oControl &c, set<wstring> &writtenId);
|
|
|
|
void writeCourseInfo(xmlparser &xml, const oCourse &c);
|
|
|
|
void writeFullCourse(xmlparser &xml, const oCourse &c,
|
|
const map<int, wstring> &ctrlId2ExportId);
|
|
|
|
void readId(const xmlobject &person, int &pid, __int64 &extId) const;
|
|
|
|
public:
|
|
IOF30Interface(oEvent *oe, bool forceSplitFee);
|
|
virtual ~IOF30Interface() {}
|
|
|
|
void getIdTypes(vector<string> &types);
|
|
void setPreferredIdType(const string &type);
|
|
|
|
void readEventList(gdioutput &gdi, xmlobject &xo);
|
|
|
|
/** Scan the entry list to find specification of stage numbers*/
|
|
void prescanEntryList(xmlobject & xo, set<int>& definedStages);
|
|
|
|
void readEntryList(gdioutput &gdi, xmlobject &xo, bool removeNonexisting,
|
|
const set<int> &stageFilter, int &entRead, int &entFail, int &entRemoved);
|
|
|
|
void readStartList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
|
|
|
void readClassList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
|
|
|
void readCompetitorList(gdioutput &gdi, const xmlobject &xo, int &personCount);
|
|
|
|
void readClubList(gdioutput &gdi, const xmlobject &xo, int &clubCount);
|
|
|
|
void readCourseData(gdioutput &gdi, const xmlobject &xo, bool updateClasses, int &courseCount, int &entFail);
|
|
|
|
void writeResultList(xmlparser &xml, const set<int> &classes, int leg,
|
|
bool useUTC, bool teamsAsIndividual,
|
|
bool unrollLoops, bool includeStageInfo);
|
|
|
|
void writeStartList(xmlparser &xml, const set<int> &classes, bool useUTC,
|
|
bool teamsAsIndividual, bool includeStageInfo);
|
|
|
|
void writeEvent(xmlparser &xml);
|
|
|
|
void writeCourses(xmlparser &xml);
|
|
|
|
void writeRunnerDB(const RunnerDB &db, xmlparser &xml) const;
|
|
|
|
void writeClubDB(const RunnerDB &db, xmlparser &xml) const;
|
|
};
|