/********************i**************************************************** MeOS - Orienteering Software Copyright (C) 2009-2017 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 "stdafx.h" #include "oListInfo.h" #include "oEvent.h" #include "gdioutput.h" #include "meos_util.h" #include #include #include "Localizer.h" #include "metalist.h" #include #include "gdifonts.h" #include "generalresult.h" #include "meosexception.h" struct PrintPostInfo { PrintPostInfo(gdioutput &gdi, const oListParam &par) : gdi(gdi), par(par), keepToghether(false) {} gdioutput &gdi; const oListParam ∥ oCounter counter; bool keepToghether; void reset() {keepToghether = false;} private: PrintPostInfo &operator=(const PrintPostInfo &a) {} }; oListInfo::oListInfo() { listType=EBaseTypeRunner; listSubType=EBaseTypeRunner; calcResults=false; calcTotalResults = false; rogainingResults = false; calcCourseClassResults = false; listPostFilter.resize(_EFilterMax+1, 0); listPostSubFilter.resize(_ESubFilterMax+1, 0); fixedType = false; largeSize = false; supportClasses = true; supportLegs = false; supportParameter = false; supportLarge = false; supportTo = false; supportFrom = false; supportCustomTitle = true; resType = Classwise; supportSplitAnalysis = true; supportInterResults = true; supportPageBreak = true; supportClassLimit = true; needPunches = false; } oListInfo::~oListInfo(void) { } oPrintPost::oPrintPost() { dx=0; dy=0; format=0; type=lString; legIndex= - 1; linearLegIndex = true; fixedWidth = 0; mergeWithTmp = 0; doMergeNext = false; color = colorDefault; resultModuleIndex = -1; } oPrintPost::oPrintPost(EPostType type_, const string &text_, int format_, int dx_, int dy_, pair index) { dx=dx_; dy=dy_; text=text_; format=format_; type=type_; legIndex=index.first; linearLegIndex = index.second; fixedWidth = 0; mergeWithTmp = 0; doMergeNext = false; color = colorDefault; resultModuleIndex = -1; } bool oListInfo::needRegenerate(const oEvent &oe) const { for(oClassList::const_iterator it = oe.Classes.begin(); it != oe.Classes.end(); ++it) { if (it->isRemoved()) continue; if (!lp.selection.empty() && lp.selection.count(it->getId()) == 0 ) continue; // Not our class int legToCheck = -1; if (needPunches) { int to = oControl::getIdIndexFromCourseControlId(lp.useControlIdResultTo).first; int from = oControl::getIdIndexFromCourseControlId(lp.useControlIdResultFrom).first; if (it->wasSQLChanged(legToCheck, to) || it->wasSQLChanged(legToCheck, from) ) return true; } else { if (it->wasSQLChanged(legToCheck, -1)) return true; } } return false; } static void generateNBestHead(const oListParam &par, oListInfo &li, int ypos) { if (par.filterMaxPer > 0) li.addHead(oPrintPost(lString, lang.tl("Visar de X bästa#" + itos(par.filterMaxPer)), normalText, 0, ypos)); } static pair getControlName(const oEvent &oe, int courseContolId) { pair idt = oControl::getIdIndexFromCourseControlId(courseContolId); pControl to = oe.getControl(idt.first); string toS; bool name = false; if (to) { if (to->hasName()) { toS = to->getName(); name = true; } else if (to->getFirstNumber()>0) toS = itos(to->getFirstNumber()); else toS = itos(idt.first); if (to->getNumberDuplicates() > 0) toS += "-" + itos(idt.second + 1); } else toS = itos(idt.first); return make_pair(toS, name); } static string getFullControlName(const oEvent &oe, int ctrl) { pair toS = getControlName(oe, ctrl); if (toS.second) return toS.first; else return lang.tl("Kontroll X#" + toS.first); } static void getResultTitle(const oEvent &oe, const oListParam &lp, string &title) { if (lp.useControlIdResultTo <= 0 && lp.useControlIdResultFrom <= 0) title = lang.tl("Resultat - %s"); else if (lp.useControlIdResultTo>0 && lp.useControlIdResultFrom<=0){ pair toS = getControlName(oe, lp.useControlIdResultTo); if (toS.second) title = lang.tl("Resultat - %s") + ", " + toS.first; else title = lang.tl("Resultat - %s") + ", " + lang.tl("vid kontroll X#" + toS.first); } else { string fromS = lang.tl("Start"), toS = lang.tl("Mål"); if (lp.useControlIdResultTo>0) { toS = getControlName(oe, lp.useControlIdResultTo).first; } if (lp.useControlIdResultFrom>0) { fromS = getControlName(oe, lp.useControlIdResultFrom).first; } title = lang.tl("Resultat mellan X och Y#" + fromS + "#" + toS); } } static double adjustmentFactor(double par, double target) { double k = (1.0 - target)/10; double val = max(target, 1.0 - (par * k)); return val; } int oListInfo::getMaxCharWidth(const oEvent *oe, const set &clsSel, const vector< pair > &typeFormats, gdiFonts font, const char *fontFace, bool large, int minSize) { vector pps; for (size_t k = 0; k < typeFormats.size(); k++) { pps.push_back(oPrintPost()); pps.back().text = typeFormats[k].second; pps.back().type = typeFormats[k].first; } oListParam par; par.setLegNumberCoded(0); oCounter c; vector extras(pps.size(), 0); for (size_t k = 0; k < pps.size(); k++) { string extra; switch (pps[k].type) { case lRunnerTotalTimeAfter: case lRunnerClassCourseTimeAfter: case lRunnerTimeAfterDiff: case lRunnerTempTimeAfter: case lRunnerTimeAfter: case lRunnerMissedTime: case lTeamTimeAfter: case lTeamLegTimeAfter: case lTeamTotalTimeAfter: case lTeamTimeAdjustment: case lRunnerTimeAdjustment: case lRunnerGeneralTimeAfter: extra = "+10:00"; break; case lTeamRogainingPointOvertime: case lRunnerRogainingPointOvertime: case lResultModuleTime: case lResultModuleTimeTeam: case lTeamTime: case lTeamTotalTime: case lTeamTotalTimeStatus: case lTeamLegTimeStatus: case lTeamTimeStatus: case lRunnerTempTimeStatus: case lRunnerTotalTimeStatus: case lRunnerTotalTime: case lClassStartTime: case lRunnerFinish: case lRunnerTime: case lRunnerTimeStatus: case lRunnerTimePlaceFixed: extra = "50:50"; break; case lRunnerGeneralTimeStatus: case lClassStartTimeRange: extra = "50:50 (50:50)"; break; case lTeamRogainingPointReduction: case lRunnerRogainingPointReduction: case lTeamPointAdjustment: case lRunnerPointAdjustment: case lRunnerRogainingPointGross: case lRunnerPlace: case lRunnerPlaceDiff: case lTeamPlaceDiff: case lRunnerTotalPlace: case lRunnerClassCoursePlace: case lTeamPlace: case lTeamTotalPlace: case lPunchControlPlace: case lPunchControlPlaceAcc: case lResultModuleNumber: case lResultModuleNumberTeam: extra = "199."; break; case lRunnerGeneralPlace: extra = "199. (99.)"; break; } int width = 0; EPostType type = pps[k].type; if (type == lClubName || type == lRunnerName || type == lTeamName || type == lTeamRunner || type == lTeamClub) width = max(15, width); if (type == lRunnerGivenName || type == lRunnerFamilyName || type == lRunnerNationality) width = max(7, width); if (type == lRunnerCompleteName || type == lPatrolNameNames || type == lPatrolClubNameNames) width = max(20, width); width = max(extra.size(), width); extras[k] = width; } for (size_t k = 0; k < pps.size(); k++) { const oPrintPost &pp = pps[k]; int width = 0; for (oClassList::const_iterator it = oe->Classes.begin(); it != oe->Classes.end(); ++it) { if (it->isRemoved()) continue; if (!clsSel.empty() && clsSel.count(it->getId()) == 0) continue; const string &out = oe->formatListString(pp, par, 0, 0, 0, pClass(&*it), c); width = max(width, int(out.length())); } for (oCourseList::const_iterator it = oe->Courses.begin(); it != oe->Courses.end(); ++it) { if (it->isRemoved()) continue; const string &out = oe->formatSpecialString(pp, par, 0, 0, pCourse(&*it), 0, c); width = max(width, int(out.length())); } for (oControlList::const_iterator it = oe->Controls.begin(); it != oe->Controls.end(); ++it) { if (it->isRemoved()) continue; const string &out = oe->formatSpecialString(pp, par, 0, 0, 0, pControl(&*it), c); width = max(width, int(out.length())); } extras[k] = max(extras[k], width); } int width = minSize; vector row(pps.size(), 0); for (oRunnerList::const_iterator it = oe->Runners.begin(); it != oe->Runners.end(); ++it) { if (it->isRemoved()) continue; // Case when runner/team has different class bool teamOK = it->getTeam() && clsSel.count(it->getTeam()->getClassId()); if (!clsSel.empty() && (!teamOK && clsSel.count(it->getClassId()) == 0)) continue; copy(extras.begin(), extras.end(), row.begin()); for (size_t k = 0; k < pps.size(); k++) { oPrintPost &pp = pps[k]; pp.legIndex = it->tLeg; pp.linearLegIndex = true; int numIter = 1; if (pp.type == lPunchNamedTime || pp.type == lPunchTime) { row[k] = max(row[k], 10); pRunner r = pRunner(&*it); numIter = (r && r->getCard()) ? r->getCard()->getNumPunches() + 1 : 1; } while (numIter-- > 0) { const string &out = oe->formatListString(pp, par, it->tInTeam, pRunner(&*it), it->Club, it->Class, c); row[k] = max(row[k], int(out.length())); if (numIter>0) c.level3++; } } int sum = 0; for (size_t k = 0; k < row.size(); k++) sum += row[k]; width = max(width, sum); } if (width == 0) { for (size_t k = 0; k < row.size(); k++) width += extras[k]; } double w = width; double s = 1.0; s = oe->gdibase.getRelativeFontScale(font, fontFace); if (w > 15) { if (large) w *= adjustmentFactor(w-15, 0.7); else w *= adjustmentFactor(w-15, 0.85); if (w > 40) w *= adjustmentFactor(w-40, 0.85); } w = max(w, minSize); if (width>0 && !large) return int(s*(w*6.0+20.0)); else if (width>0 && large) return int(s*(w*7.0+10.0)); else return 0; } const string & oEvent::formatListString(EPostType type, const pRunner r) const { oPrintPost pp; oCounter ctr; oListParam par; par.setLegNumberCoded(r->tLeg); pp.type = type; return formatListString(pp, par, r->tInTeam, r, r->Club, r->Class, ctr); } const string & oEvent::formatListString(EPostType type, const pRunner r, const string &format) const { oPrintPost pp; oCounter ctr; oListParam par; par.setLegNumberCoded(r->tLeg); pp.type = type; pp.text = format; return formatListString(pp, par, r->tInTeam, r, r->Club, r->Class, ctr); } const string &oEvent::formatListString(const oPrintPost &pp, const oListParam &par, const pTeam t, const pRunner r, const pClub c, const pClass pc, oCounter &counter) const { const oPrintPost *cpp = &pp; const string *tmp = 0; string *out = 0; while (cpp) { if (tmp) { if (!out) { out = &StringCache::getInstance().get(); *out = ""; } out->append(*tmp); } tmp = &formatListStringAux(*cpp, par, t, r, c, pc, counter); cpp = cpp->mergeWithTmp; } if (out) { out->append(*tmp); return *out; } else return *tmp; } const string &oEvent::formatSpecialString(const oPrintPost &pp, const oListParam &par, const pTeam t, int legIndex, const pCourse crs, const pControl ctrl, oCounter &counter) const { const oPrintPost *cpp = &pp; const string *tmp = 0; string *out = 0; while (cpp) { if (tmp) { if (!out) { out = &StringCache::getInstance().get(); *out = ""; } out->append(*tmp); } tmp = &formatSpecialStringAux(*cpp, par, t, legIndex, crs, ctrl, counter); cpp = cpp->mergeWithTmp; } if (out) { out->append(*tmp); return *out; } else return *tmp; } const string &oEvent::formatSpecialStringAux(const oPrintPost &pp, const oListParam &par, const pTeam t, int legIndex, const pCourse pc, const pControl ctrl, oCounter &counter) const { char bf[512]; const string *sptr=0; bf[0]=0; static bool reentrantLock = false; if (reentrantLock == true) { reentrantLock = false; throw meosException("Internal list error"); } switch (pp.type) { case lCourseLength: if (pc) { int len = pc->getLength(); if (len > 0) sprintf_s(bf, "%d", len); } break; case lCourseName: case lRunnerCourse: if (pc) { sptr = &pc->getName(); } break; case lRunnerLegNumberAlpha: if (t && t->getClassRef() && legIndex >= 0) { string legStr = t->getClassRef()->getLegNumber(legIndex); strcpy_s(bf, legStr.c_str()); } break; case lRunnerLegNumber: if (t && t->getClassRef() && legIndex >= 0) { int legNumber, legOrder; t->getClassRef()->splitLegNumberParallel(legIndex, legNumber, legOrder); sptr = &itos(legNumber+1); } break; case lCourseClimb: { int len = pc ? pc->getDCI().getInt("Climb") : 0; if (len > 0) sprintf_s(bf, "%d", len); } break; case lCourseUsage: if (pc) { sptr = &itos(pc->getNumUsedMaps(false)); } break; case lCourseUsageNoVacant: if (pc) { sptr = &itos(pc->getNumUsedMaps(true)); } break; case lCourseClasses: if (pc) { vector cls; pc->getClasses(cls); string tmp; for (size_t k = 0; k < cls.size(); k++) { if (k > 0) tmp += ", "; tmp += cls[k]->getName(); if (tmp.length() > 100) { tmp += ", ..."; break; } } strncpy_s(bf, tmp.c_str(), 256); } break; case lControlName: if (ctrl) strncpy_s(bf, ctrl->getName().c_str(), 128); break; case lControlCourses: if (ctrl) { vector crs; ctrl->getCourses(crs); if (crs.size() == Courses.size()) { sptr = &lang.tl("Alla"); break; } string tmp; for (size_t k = 0; k < crs.size(); k++) { if (k > 0) tmp += ", "; tmp += crs[k]->getName(); if (tmp.length() > 100) { tmp += ", ..."; break; } } strncpy_s(bf, tmp.c_str(), 256); } break; case lControlClasses: if (ctrl) { vector cls; ctrl->getClasses(cls); if (cls.size() == getNumClasses()) { sptr = &lang.tl("Alla"); break; } string tmp; for (size_t k = 0; k < cls.size(); k++) { if (k > 0) tmp += ", "; tmp += cls[k]->getName(); if (tmp.length() > 100) { tmp += ", ..."; break; } } strncpy_s(bf, tmp.c_str(), 256); } break; case lControlVisitors: if (ctrl) sptr = &itos(ctrl->getNumVisitors(false)); break; case lControlPunches: if (ctrl) sptr = &itos(ctrl->getNumVisitors(true)); break; case lControlMedianLostTime: if (ctrl) sptr = &formatTime(ctrl->getMissedTimeMedian()); break; case lControlMaxLostTime: if (ctrl) sptr = &formatTime(ctrl->getMissedTimeMax()); break; case lControlMistakeQuotient: if (ctrl) { string tmp = itos(ctrl->getMistakeQuotient()); tmp += "%"; strncpy_s(bf, tmp.c_str(), 20); } break; case lControlRunnersLeft: if (ctrl) sptr = &itos(ctrl->getNumRunnersRemaining()); break; case lControlCodes: if (ctrl) { vector numbers; ctrl->getNumbers(numbers); string tmp; for (size_t j = 0; j < numbers.size(); j++) { if (j > 0) tmp += ", "; tmp += itos(numbers[j]); } strncpy_s(bf, tmp.c_str(), 256); } break; default: { reentrantLock = true; try { const string &res = formatListStringAux(pp, par, t, t ? t->getRunner(legIndex) : 0, t ? t->getClubRef() : 0, t ? t->getClassRef() : 0, counter); reentrantLock = false; return res; } catch(...) { reentrantLock = false; throw; } } } if (pp.type!=lString && (sptr==0 || sptr->empty()) && bf[0]==0) return _EmptyString; else if (sptr) { if (pp.text.empty()) return *sptr; else { sprintf_s(bf, pp.text.c_str(), sptr->c_str()); string &res = StringCache::getInstance().get(); res = bf; return res; } } else { if (pp.text.empty()) { string &res = StringCache::getInstance().get(); res = bf; return res; } else { char bf2[512]; sprintf_s(bf2, pp.text.c_str(), bf); string &res = StringCache::getInstance().get(); res = bf2; return res; } } } const string &oEvent::formatListStringAux(const oPrintPost &pp, const oListParam &par, const pTeam t, const pRunner r, const pClub c, const pClass pc, oCounter &counter) const { char bf[512]; const string *sptr=0; bf[0]=0; bool invalidClass = pc && pc->getClassStatus() != oClass::Normal; int legIndex = pp.legIndex; if(pc && pp.type != lResultModuleNumber && pp.type != lResultModuleNumberTeam && pp.type != lResultModuleTime && pp.type != lResultModuleTimeTeam) legIndex = pc->getLinearIndex(pp.legIndex, pp.linearLegIndex); switch ( pp.type ) { case lClassName: if (invalidClass) sprintf_s(bf, "%s (%s)", pc->getName().c_str(), lang.tl("Struken").c_str()); else sptr=pc ? &pc->getName() : 0; break; case lResultDescription: { string title; getResultTitle(*this, par, title); strcpy_s(bf, title.c_str()); } break; case lTimingFromName: if (par.useControlIdResultFrom > 0) strcpy_s(bf, getFullControlName(*this, par.useControlIdResultFrom).c_str()); else sptr = &lang.tl("Start"); break; case lTimingToName: if (par.useControlIdResultTo > 0) strcpy_s(bf, getFullControlName(*this, par.useControlIdResultTo).c_str()); else sptr = &lang.tl("Mål"); break; case lClassLength: if (pc) { strcpy_s(bf, pc->getLength(par.relayLegIndex).c_str()); } break; case lClassStartName: if (pc) strcpy_s(bf, pc->getDI().getString("StartName").c_str()); break; case lClassStartTime: case lClassStartTimeRange: if (pc) { int first, last; pc->getStartRange(legIndex, first, last); if (pc->hasFreeStart()) strcpy_s(bf, lang.tl("Fri starttid").c_str()); else if (first > 0 && first == last) { if (oe->useStartSeconds()) strcpy_s(bf, oe->getAbsTime(first).c_str()); else strcpy_s(bf, oe->getAbsTimeHM(first).c_str()); } else if (pp.type == lClassStartTimeRange) { string range = oe->getAbsTimeHM(first) + MakeDash(" - ") + oe->getAbsTimeHM(last); strcpy_s(bf, range.c_str()); } } break; case lClassResultFraction: if (pc && !invalidClass) { int total, finished, dns; oe->getNumClassRunners(pc->getId(), par.getLegNumber(pc), total, finished, dns); sprintf_s(bf, "(%d / %d)", finished, total); } break; case lCourseLength: if (r) { pCourse crs = r->getCourse(false); return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter); } break; case lCourseName: case lRunnerCourse: if (r) { pCourse crs = r->getCourse(false); return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter); } break; case lCourseClimb: if (r) { pCourse crs = r->getCourse(false); return formatSpecialStringAux(pp, par, t, 0, crs, 0, counter); } break; case lCourseShortening: if (r) { int sh = r->getNumShortening(); if (sh > 0) sprintf_s(bf, "%d", sh); } break; case lCmpName: sptr = &getName(); break; case lCmpDate: strcpy_s(bf, this->getDate().c_str()); break; case lCurrentTime: strcpy_s(bf, getCurrentTimeS().c_str()); break; case lRunnerClub: sptr=(r && r->Club) ? &r->Club->getDisplayName() : 0; break; case lRunnerFinish: if (r && !invalidClass) { if (pp.resultModuleIndex == -1) sptr = &r->getFinishTimeS(); else sptr = &r->getTempResult(pp.resultModuleIndex).getFinishTimeS(this); } break; case lRunnerStart: case lRunnerStartCond: case lRunnerStartZero: if (r) { if ((pp.type == lRunnerStartCond || pp.type == lRunnerStartZero) && pc && !pc->hasFreeStart()) { int fs, ls; pc->getStartRange(legIndex, fs, ls); if (fs>0 && fs == ls) { break; // Common start time, skip } } if (r->startTimeAvailable()) { if (pp.type != lRunnerStartZero) sptr = &r->getStartTimeCompact(); else { int st = r->getStartTime(); sptr = &getTimeMS(st-3600); } } else sptr = &MakeDash("-"); } break; case lRunnerName: sptr = r ? &r->getName() : 0; break; case lRunnerGivenName: if (r) strcpy_s(bf, r->getGivenName().c_str()); break; case lRunnerFamilyName: if (r) strcpy_s(bf, r->getFamilyName().c_str()); break; case lRunnerCompleteName: if (r) strcpy_s(bf, r->getCompleteIdentification().c_str()); break; case lPatrolNameNames: if (t) { pRunner r1 = t->getRunner(0); pRunner r2 = t->getRunner(1); if (r1 && r2) { sprintf_s(bf, "%s / %s", r1->getName().c_str(),r2->getName().c_str()); } else if (r1) { sptr = &r1->getName(); } else if (r2) { sptr = &r2->getName(); } } else { sptr = r ? &r->getName() : 0; } break; case lPatrolClubNameNames: if (t) { pRunner r1 = t->getRunner(0); pRunner r2 = t->getRunner(1); pClub c1 = r1 ? r1->Club : 0; pClub c2 = r2 ? r2->Club : 0; if (c1 == c2) c2 = 0; if (c1 && c2) { sprintf_s(bf, "%s / %s", c1->getDisplayName().c_str(),c2->getDisplayName().c_str()); } else if (c1) { sptr = &c1->getDisplayName(); } else if (c2) { sptr = &c2->getDisplayName(); } } else { sptr = r && r->Club ? &r->Club->getDisplayName() : 0; } break; case lRunnerTime: if (r && !invalidClass) { if (pp.resultModuleIndex == -1) sptr = &r->getRunningTimeS(); else sptr = &r->getTempResult(pp.resultModuleIndex).getRunningTimeS(0); if (r->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } case lRunnerTimeStatus: if (r) { if (invalidClass) sptr = &lang.tl("Struken"); else if (pp.resultModuleIndex == -1) { bool ok = r->prelStatusOK(); if (ok && pc && !pc->getNoTiming()) { sptr = &r->getRunningTimeS(); if (r->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } else { if (ok) sptr = &formatStatus(StatusOK); else sptr = &r->getStatusS(); } } else { const oAbstractRunner::TempResult &res = r->getTempResult(pp.resultModuleIndex); if (res.getStatus() == StatusOK && pc && !pc->getNoTiming()) { sptr = &res.getRunningTimeS(0); if (r->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } else sptr = &res.getStatusS(StatusOK); } } break; case lRunnerGeneralTimeStatus: if (r) { if (invalidClass) sptr = &lang.tl("Struken"); else if (pp.resultModuleIndex == -1) { if (r->prelStatusOK() && pc && !pc->getNoTiming()) { string timeStatus = r->getRunningTimeS(); if (r->hasInputData() || (r->getLegNumber() > 0 && !r->isPatrolMember())) { RunnerStatus ts = r->getTotalStatus(); int rt = r->getTotalRunningTime(); if (ts == StatusOK || (ts == StatusUnknown && rt > 0)) { string vts = formatTime(rt) + " (" + timeStatus + ")"; swap(vts, timeStatus); } else { string vts = formatStatus(ts) + " (" + timeStatus + ")"; swap(vts, timeStatus); } } if (r->getNumShortening() > 0) { sprintf_s(bf, "*%s", timeStatus.c_str()); } else { strcpy_s(bf, timeStatus.c_str()); } } else sptr = &r->getStatusS(); } else { const oAbstractRunner::TempResult &res = r->getTempResult(pp.resultModuleIndex); if (res.getStatus() == StatusOK && pc && !pc->getNoTiming()) { sptr = &res.getRunningTimeS(0); if (r->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } else sptr = &res.getStatusS(StatusOK); } } break; break; case lRunnerGeneralTimeAfter: if (r && pc && !invalidClass && !pc->getNoTiming()) { if (pp.resultModuleIndex == -1) { if (r->hasInputData() || (r->getLegNumber() > 0 && !r->isPatrolMember())) { int tleg = r->tLeg >= 0 ? r->tLeg:0; if (r->getTotalStatus()==StatusOK) { if ( (t && t->getNumShortening(tleg) == 0) || (!t && r->getNumShortening() == 0)) { int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true); if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } else { sptr = &MakeDash("-"); } } } else { int tleg=r->tLeg>=0 ? r->tLeg:0; if (r->tStatus==StatusOK && pc && !pc->getNoTiming() ) { if (r->getNumShortening() == 0) { int after = r->getRunningTime() - pc->getBestLegTime(tleg); if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } else { sptr = &MakeDash("-"); } } } } else { int after = r->getTempResult(pp.resultModuleIndex).getTimeAfter(); if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } } break; case lRunnerTimePerKM: if (r && !invalidClass && r->prelStatusOK()) { const pCourse pc = r->getCourse(false); if (pc) { int t = r->getRunningTime(); int len = pc->getLength(); if (len > 0 && t > 0) { int sperkm = (1000 * t) / len; strcpy_s(bf, formatTime(sperkm).c_str()); } } } break; case lRunnerTotalTime: if (r && !invalidClass) { if (pp.resultModuleIndex == -1) sptr = &r->getTotalRunningTimeS(); else sptr = &r->getTempResult(pp.resultModuleIndex).getRunningTimeS(r->getTotalTimeInput()); } break; case lRunnerTotalTimeStatus: if (invalidClass) sptr = &lang.tl("Struken"); else if (r) { if (pp.resultModuleIndex == -1) { if ((r->getTotalStatus()==StatusOK || (r->getTotalStatus()==StatusUnknown && r->prelStatusOK() && r->getInputStatus() == StatusOK) )&& pc && !pc->getNoTiming()) { sptr = &r->getTotalRunningTimeS(); if (r->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } else sptr = &r->getTotalStatusS(); } else { const oAbstractRunner::TempResult &res = r->getTempResult(pp.resultModuleIndex); RunnerStatus input = r->getTotalStatusInput(); if (input == StatusOK && res.getStatus() == StatusOK && pc && !pc->getNoTiming()) { sptr = &res.getRunningTimeS(r->getTotalTimeInput()); if (r->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } else sptr = &res.getStatusS(input); } } break; case lRunnerTempTimeStatus: if (invalidClass) sptr = &lang.tl("Struken"); else if (r) { if (r->tempStatus==StatusOK && pc && !pc->getNoTiming()) strcpy_s(bf, formatTime(r->tempRT).c_str()); else strcpy_s(bf, formatStatus(r->tempStatus).c_str() ); } break; case lRunnerPlace: if (r && !invalidClass && pc && !pc->getNoTiming()) { if (pp.resultModuleIndex == -1) strcpy_s(bf, r->getPrintPlaceS(pp.text.empty()).c_str() ); else sptr = &r->getTempResult(pp.resultModuleIndex).getPrintPlaceS(pp.text.empty()); } break; case lRunnerTotalPlace: if (r && !invalidClass && pc && !pc->getNoTiming()) strcpy_s(bf, r->getPrintTotalPlaceS(pp.text.empty()).c_str() ); break; case lRunnerGeneralPlace: if (r && !invalidClass && pc && !pc->getNoTiming()) { if (pp.resultModuleIndex == -1) { if (r->hasInputData() || (r->getLegNumber() > 0 && !r->isPatrolMember())) { string iPlace; if (pc->getClassType() != oClassPatrol) iPlace = r->getPrintPlaceS(true); string tPlace = r->getPrintTotalPlaceS(true); string v; if (iPlace.empty()) v = tPlace; else { if (tPlace.empty()) tPlace = MakeDash("-"); v = tPlace + " (" + iPlace + ")"; } strcpy_s(bf, v.c_str()); } else strcpy_s(bf, r->getPrintPlaceS(pp.text.empty()).c_str() ); } else sptr = &r->getTempResult(pp.resultModuleIndex).getPrintPlaceS(pp.text.empty()); } break; case lRunnerClassCoursePlace: if (r && !invalidClass && pc && !pc->getNoTiming()) { int p = r->getCoursePlace(); if (p>0 && p<10000) sprintf_s(bf, "%d.", p); } break; case lRunnerPlaceDiff: if (r && !invalidClass && pc && !pc->getNoTiming()) { int p = r->getTotalPlace(); if (r->getTotalStatus() == StatusOK && p > 0 && r->inputPlace>0) { int pd = p - r->inputPlace; if (pd > 0) sprintf_s(bf, "+%d", pd); else if (pd < 0) sprintf_s(bf, "-%d", -pd); } } break; case lRunnerTimeAfterDiff: if (r && pc && !invalidClass) { int tleg = r->tLeg >= 0 ? r->tLeg:0; if (r->getTotalStatus()==StatusOK && pc && !pc->getNoTiming()) { int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true); int afterOld = r->inputTime - pc->getBestInputTime(tleg); int ad = after - afterOld; if (ad > 0) sprintf_s(bf, "+%d:%02d", ad/60, ad%60); if (ad < 0) sprintf_s(bf, "-%d:%02d", (-ad)/60, (-ad)%60); } } break; case lRunnerRogainingPoint: if (r && !invalidClass) { if (pp.resultModuleIndex == -1) sprintf_s(bf, "%d", r->getRogainingPoints(false)); else sprintf_s(bf, "%d", r->getTempResult(pp.resultModuleIndex).getPoints()); } break; case lRunnerRogainingPointTotal: if (r && !invalidClass) { if (pp.resultModuleIndex == -1) sprintf_s(bf, "%d", r->getRogainingPoints(true)); else sprintf_s(bf, "%d", r->getTempResult(pp.resultModuleIndex).getPoints() + r->getInputPoints()); } break; case lRunnerRogainingPointReduction: if (r && !invalidClass) { int red = r->getRogainingReduction(); if (red > 0) sprintf_s(bf, "-%d", red); } break; case lRunnerRogainingPointGross: if (r && !invalidClass) { int p = r->getRogainingPointsGross(); sptr = &itos(p); } break; case lRunnerPointAdjustment: if (r && !invalidClass) { int a = r->getPointAdjustment(); if (a<0) sptr = &itos(a); else if (a>0) sprintf_s(bf, "+%d", a); } break; case lRunnerTimeAdjustment: if (r && !invalidClass) { int a = r->getTimeAdjustment(); if (a != 0) sptr = &getTimeMS(a); } break; case lRunnerRogainingPointOvertime: if (r && !invalidClass) { int over = r->getRogainingOvertime(); if (over > 0) sptr = &formatTime(over); } break; case lRunnerTimeAfter: if (r && pc && !invalidClass && !pc->getNoTiming()) { int after = 0; if (pp.resultModuleIndex == -1) { int tleg=r->tLeg>=0 ? r->tLeg:0; int brt = pc->getBestLegTime(tleg); if (r->prelStatusOK() && brt > 0) { after=r->getRunningTime() - brt; } } else { after = r->getTempResult(pp.resultModuleIndex).getTimeAfter(); } if (r->getNumShortening() == 0) { if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } else { sptr = &MakeDash("-"); } } break; case lRunnerTotalTimeAfter: if (r && pc && !invalidClass) { int tleg = r->tLeg >= 0 ? r->tLeg:0; if (r->getTotalStatus()==StatusOK && pc && !pc->getNoTiming()) { if ( (t && t->getNumShortening(tleg) == 0) || (!t && r->getNumShortening() == 0)) { int after = r->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true); if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } else { sptr = &MakeDash("-"); } } } break; case lRunnerClassCourseTimeAfter: if (r && pc && !invalidClass) { pCourse crs = r->getCourse(false); if (crs && r->tStatus==StatusOK && !pc->getNoTiming()) { int after = r->getRunningTime() - pc->getBestTimeCourse(crs->getId()); if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } } break; case lRunnerTimePlaceFixed: if (r && !invalidClass) { int t = r->getTimeWhenPlaceFixed(); if (t == 0 || (t>0 && t < getComputerTime())) { strcpy_s(bf, lang.tl("klar").c_str()); } else if (t == -1) strcpy_s(bf, "-"); else strcpy_s(bf, oe->getAbsTime(t).c_str()); } break; case lRunnerLegNumberAlpha: case lRunnerLegNumber: if (r) return formatSpecialStringAux(pp, par, t, r->getLegNumber(), 0, 0, counter); else strcpy_s(bf, par.getLegName().c_str()); break; case lRunnerMissedTime: if (r && r->tStatus == StatusOK && pc && !pc->getNoTiming() && !invalidClass) { strcpy_s(bf, r->getMissedTimeS().c_str()); } break; case lRunnerTempTimeAfter: if (r && pc) { if (r->tempStatus==StatusOK && pc && !pc->getNoTiming() && r->tempRT>pc->tLegLeaderTime) { int after=r->tempRT-pc->tLegLeaderTime; sprintf_s(bf, "+%d:%02d", after/60, after%60); } } break; case lRunnerCard: if (r && r->CardNo > 0) sprintf_s(bf, "%d", r->getCardNo()); break; case lRunnerRank: if (r) { int rank=r->getDI().getInt("Rank"); if (rank>0) strcpy_s(bf, FormatRank(rank).c_str()); } break; case lRunnerBib: if (r) { string bib = r->getBib(); if (!bib.empty()) sprintf_s(bf, "%s", bib.c_str()); } break; case lRunnerUMMasterPoint: if (r) { int total, finished, dns; oe->getNumClassRunners(pc->getId(), 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) sprintf_s(bf, "%d", percent); else sprintf_s(bf, "0"); } break; case lRunnerAge: if (r) { int y = r->getBirthAge(); if (y > 0) sprintf_s(bf, "%d", y); } break; case lRunnerBirthYear: if (r) { int y = r->getBirthYear(); if (y > 0) sprintf_s(bf, "%d", y); } break; case lRunnerSex: if (r) { PersonSex s = r->getSex(); if (s == sFemale) sptr = &lang.tl("Kvinna"); else if (s == sMale) sptr = &lang.tl("Man"); } break; case lRunnerPhone: if (r) { string s = r->getDCI().getString("Phone"); strcpy_s(bf, s.c_str()); } break; case lRunnerFee: if (r) { string s = formatCurrency(r->getDCI().getInt("Fee")); strcpy_s(bf, s.c_str()); } break; case lTeamFee: if (t) { string s = formatCurrency(t->getTeamFee()); strcpy_s(bf, s.c_str()); } break; case lRunnerNationality: if (r) { string nat = r->getNationality(); strcpy_s(bf, nat.c_str()); } break; case lTeamName: //sptr = t ? &t->Name : 0; if (t) { strcpy_s(bf, t->getDisplayName().c_str()); } break; case lTeamStart: case lTeamStartCond: case lTeamStartZero: if (t) { if ((pp.type == lTeamStartCond || pp.type == lTeamStartZero) && pc && !pc->hasFreeStart()) { int fs, ls; pc->getStartRange(legIndex, fs, ls); if (fs>0 && fs == ls) { break; // Common start time, skip } } if (unsigned(legIndex)Runners.size() && t->Runners[legIndex] && t->Runners[legIndex]->startTimeAvailable()) { if (pp.type != lTeamStartZero) sptr = &t->Runners[legIndex]->getStartTimeCompact(); else { int st = t->Runners[legIndex]->getStartTime(); sptr = &getTimeMS(st-3600); } } } break; case lTeamStatus: if (t && !invalidClass) { if (pp.resultModuleIndex == -1) sptr = &t->getLegStatusS(legIndex, false); else sptr = &t->getTempResult(pp.resultModuleIndex).getStatusS(StatusOK); } break; case lTeamTime: if (t && !invalidClass) { if (pp.resultModuleIndex == -1) strcpy_s(bf, t->getLegRunningTimeS(legIndex, false).c_str() ); else sptr = &t->getTempResult(pp.resultModuleIndex).getRunningTimeS(0); } break; case lTeamTimeStatus: if (invalidClass) sptr = &lang.tl("Struken"); else if (t) { if (pp.resultModuleIndex == -1) { RunnerStatus st = t->getLegStatus(legIndex, false); if (st==StatusOK || (st==StatusUnknown && t->getLegRunningTime(legIndex, false)>0)) strcpy_s(bf, t->getLegRunningTimeS(legIndex, false).c_str()); else sptr = &t->getLegStatusS(legIndex, false); } else { RunnerStatus st = t->getTempResult(pp.resultModuleIndex).getStatus(); if (st == StatusOK || st == StatusUnknown) { sptr = &t->getTempResult(pp.resultModuleIndex).getRunningTimeS(0); if (t->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } else sptr = &t->getTempResult(pp.resultModuleIndex).getStatusS(StatusOK); } } break; case lTeamRogainingPoint: if (t && !invalidClass) { if (pp.resultModuleIndex == -1) sprintf_s(bf, "%d", t->getRogainingPoints(false)); else sprintf_s(bf, "%d", t->getTempResult(pp.resultModuleIndex).getPoints()); } break; case lTeamRogainingPointTotal: if (t && !invalidClass) { if (pp.resultModuleIndex == -1) sprintf_s(bf, "%d", t->getRogainingPoints(true)); else sprintf_s(bf, "%d", t->getTempResult(pp.resultModuleIndex).getPoints() + t->getInputPoints()); } break; case lTeamRogainingPointReduction: if (t && !invalidClass) { int red = t->getRogainingReduction(); if (red > 0) sprintf_s(bf, "-%d", red); } break; case lTeamRogainingPointOvertime: if (t && !invalidClass) { int over = t->getRogainingOvertime(); if (over > 0) sptr = &formatTime(over); } break; case lTeamPointAdjustment: if (t && !invalidClass) { int a = t->getPointAdjustment(); if (a<0) sptr = &itos(a); else if (a>0) sprintf_s(bf, "+%d", a); } break; case lTeamTimeAdjustment: if (t && !invalidClass) { int a = t->getTimeAdjustment(); if (a != 0) sptr = &getTimeMS(a); } break; case lTeamTimeAfter: if (t && !invalidClass) { if (pp.resultModuleIndex == -1) { if (t->getLegStatus(legIndex, false)==StatusOK) { if (t->getNumShortening(legIndex) == 0) { int ta=t->getTimeAfter(legIndex); if (ta>0) sprintf_s(bf, "+%d:%02d", ta/60, ta%60); } else { sptr = &MakeDash("-"); } } } else { if (t->getTempResult().getStatus() == StatusOK) { int after = t->getTempResult(pp.resultModuleIndex).getTimeAfter(); if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } } } break; case lTeamPlace: if (t && !invalidClass && pc && !pc->getNoTiming()) { if (pp.resultModuleIndex == -1) { strcpy_s(bf, t->getLegPrintPlaceS(legIndex, false, pp.text.empty()).c_str()); } else sptr = &t->getTempResult(pp.resultModuleIndex).getPrintPlaceS(pp.text.empty()); } break; case lTeamLegTimeStatus: if (invalidClass) sptr = &lang.tl("Struken"); else if (t) { int ix = r ? r->getLegNumber() : counter.level3; if (t->getLegStatus(ix, false)==StatusOK) strcpy_s(bf, t->getLegRunningTimeS(ix, false).c_str() ); else strcpy_s(bf, t->getLegStatusS(ix, false).c_str() ); } break; case lTeamLegTimeAfter: if (t) { int ix = r ? r->getLegNumber() : counter.level3; if (t->getLegStatus(ix, false)==StatusOK && !invalidClass) { if (t->getNumShortening(ix) == 0) { int ta=t->getTimeAfter(ix); if (ta>0) sprintf_s(bf, "+%d:%02d", ta/60, ta%60); } else { sptr = &MakeDash("-"); } } } break; case lTeamClub: if (t) { strcpy_s(bf, t->getDisplayClub().c_str()); } break; case lTeamRunner: if (t && unsigned(legIndex)Runners.size() && t->Runners[legIndex]) sptr=&t->Runners[legIndex]->getName(); break; case lTeamRunnerCard: if (t && unsigned(legIndex)Runners.size() && t->Runners[legIndex] && t->Runners[legIndex]->getCardNo()>0) sprintf_s(bf, "%d", t->Runners[legIndex]->getCardNo()); break; case lTeamBib: if (t) { sptr = &t->getBib(); } break; case lTeamTotalTime: if (t && !invalidClass) strcpy_s(bf, t->getLegRunningTimeS(legIndex, true).c_str() ); break; case lTeamTotalTimeStatus: if (invalidClass) sptr = &lang.tl("Struken"); else if (t) { if (pp.resultModuleIndex == -1) { if (t->getLegStatus(legIndex, true)==StatusOK) strcpy_s(bf, t->getLegRunningTimeS(legIndex, true).c_str() ); else strcpy_s(bf, t->getLegStatusS(legIndex, true).c_str() ); } else { RunnerStatus st = t->getTempResult(pp.resultModuleIndex).getStatus(); RunnerStatus inp = t->getInputStatus(); if (st == StatusOK && inp == StatusOK) { sptr = &t->getTempResult(pp.resultModuleIndex).getRunningTimeS(0); if (t->getNumShortening() > 0) { sprintf_s(bf, "*%s", sptr->c_str()); sptr = 0; } } else sptr = &t->getTempResult(pp.resultModuleIndex).getStatusS(StatusOK); } } break; case lTeamPlaceDiff: if (t && !invalidClass) { int p = t->getTotalPlace(); if (t->getTotalStatus() == StatusOK && p > 0 && t->inputPlace>0) { int pd = p - t->inputPlace; if (pd > 0) sprintf_s(bf, "+%d", pd); else if (pd < 0) sprintf_s(bf, "-%d", -pd); } } break; case lTeamTotalPlace: if (t && !invalidClass && pc && !pc->getNoTiming()) strcpy_s(bf, t->getPrintTotalPlaceS(pp.text.empty()).c_str() ); break; break; case lTeamTotalTimeAfter: if (t && pc && !invalidClass) { int tleg = t->getNumRunners() - 1; if (t->getTotalStatus()==StatusOK && pc && !pc->getNoTiming()) { int after = t->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true); if (after > 0) sprintf_s(bf, "+%d:%02d", after/60, after%60); } } break; case lTeamTotalTimeDiff: if (t && pc && !invalidClass) { int tleg = t->getNumRunners() - 1; if (t->getTotalStatus()==StatusOK && pc && !pc->getNoTiming()) { int after = t->getTotalRunningTime() - pc->getTotalLegLeaderTime(tleg, true); int afterOld = t->inputTime - pc->getBestInputTime(tleg); int ad = after - afterOld; if (ad > 0) sprintf_s(bf, "+%d:%02d", ad/60, ad%60); if (ad < 0) sprintf_s(bf, "-%d:%02d", (-ad)/60, (-ad)%60); } } break; case lTeamStartNo: if (t) sprintf_s(bf, "%d", t->getStartNo()); break; case lRunnerStartNo: if (r) sprintf_s(bf, "%d", r->getStartNo()); break; case lNationality: if (r && !(sptr = &r->getDCI().getString("Nationality"))->empty()) break; else if (t && !(sptr = &t->getDCI().getString("Nationality"))->empty()) break; else if (c && !(sptr = &c->getDCI().getString("Nationality"))->empty()) break; break; case lCountry: if (r && !(sptr = &r->getDCI().getString("Country"))->empty()) break; else if (t && !(sptr = &t->getDCI().getString("Country"))->empty()) break; else if (c && !(sptr = &c->getDCI().getString("Country"))->empty()) break; break; case lPunchNamedTime: if (r && r->Card && r->getCourse(true) && !invalidClass) { const pCourse crs = r->getCourse(true); const oControl *ctrl=crs->getControl(counter.level3); if (!ctrl || ctrl->isRogaining(crs->hasRogaining())) break; if (r->getPunchTime(counter.level3, false)>0 && ctrl->hasName()) { sprintf_s(bf, "%s: %s (%s)", ctrl->getName().c_str(), r->getNamedSplitS(counter.level3).c_str(), r->getPunchTimeS(counter.level3, false).c_str()); } } break; case lPunchTime: case lPunchControlNumber: case lPunchControlCode: case lPunchLostTime: case lPunchControlPlace: case lPunchControlPlaceAcc: if (r && r->Card && r->getCourse(true) && !invalidClass) { const pCourse crs=r->getCourse(true); int nCtrl = crs->getNumControls(); if (counter.level3 != nCtrl) { // Always allow finish const oControl *ctrl=crs->getControl(counter.level3); if (!ctrl || ctrl->isRogaining(crs->hasRogaining())) break; } if (pp.type == lPunchTime) { if (r->getPunchTime(counter.level3, false)>0) { sprintf_s(bf, "%s (%s)", r->getSplitTimeS(counter.level3, false).c_str(), r->getPunchTimeS(counter.level3, false).c_str()); } else { strcpy_s(bf, MakeDash("- (-)").c_str()); } } else if (pp.type == lPunchControlNumber) { strcpy_s(bf, crs->getControlOrdinal(counter.level3).c_str()); } else if (pp.type == lPunchControlCode) { const oControl *ctrl=crs->getControl(counter.level3); if (ctrl) { if (ctrl->getStatus() == oControl::StatusMultiple) { string str = ctrl->getStatusS(); sprintf_s(bf, "%s.", str.substr(0, 1).c_str()); } else sprintf_s(bf, "%d", ctrl->getFirstNumber()); } } else if (pp.type == lPunchControlPlace) { int p = r->getLegPlace(counter.level3); if (p>0) sprintf_s(bf, "%d", p); } else if (pp.type == lPunchControlPlaceAcc) { int p = r->getLegPlaceAcc(counter.level3); if (p>0) sprintf_s(bf, "%d", p); } else if (pp.type == lPunchLostTime) { strcpy_s(bf, r->getMissedTimeS(counter.level3).c_str()); } } break; case lSubSubCounter: if (pp.text.empty()) sprintf_s(bf, "%d.", counter.level3+1); else sprintf_s(bf, "%d", counter.level3+1); break; case lSubCounter: if (pp.text.empty()) sprintf_s(bf, "%d.", counter.level2+1); else sprintf_s(bf, "%d", counter.level2+1); break; case lTotalCounter: if (pp.text.empty()) sprintf_s(bf, "%d.", counter.level1+1); else sprintf_s(bf, "%d", counter.level1+1); break; case lClubName: sptr = c != 0 ? &c->getDisplayName() : 0; break; case lResultModuleTime: case lResultModuleTimeTeam: if (pp.resultModuleIndex != -1) { if (t && pp.type == lResultModuleTimeTeam) sptr = &t->getTempResult(pp.resultModuleIndex).getOutputTime(legIndex); else if (r) sptr = &r->getTempResult(pp.resultModuleIndex).getOutputTime(legIndex); } break; case lResultModuleNumber: case lResultModuleNumberTeam: if (pp.resultModuleIndex != -1) { int nr = 0; if (t && pp.type == lResultModuleNumberTeam) nr = t->getTempResult(pp.resultModuleIndex).getOutputNumber(legIndex); else if (r) nr = r->getTempResult(pp.resultModuleIndex).getOutputNumber(legIndex); if (pp.text.empty() || pp.text[0]!='@') sptr = &itos(nr); else { vector out; split(pp.text.substr(1), ";", out); string &res = StringCache::getInstance().get(); size_t ix = nr; if (!out.empty() && ix >= out.size() && out.back().find_first_of('%') != out.back().npos) { ix = out.size() - 1; } if (ix < out.size()) { res.swap(out[ix]); if (res.find_first_of('%') != res.npos) { char bf2[256]; sprintf_s(bf2, res.c_str(), itos(nr).c_str()); res = bf2; } } else res = ""; return res; } } break; case lRogainingPunch: if (r && r->Card && r->getCourse(false)) { const pCourse crs = r->getCourse(false); const pPunch punch = r->Card->getPunchByIndex(counter.level3); if (punch && punch->tRogainingIndex>=0) { const pControl ctrl = crs->getControl(punch->tRogainingIndex); if (ctrl) { sprintf_s(bf, "%d, %dp, %s (%s)", punch->Type, ctrl->getRogainingPoints(), r->Card->getRogainingSplit(counter.level3, r->tStartTime).c_str(), punch->getRunningTime(r->tStartTime).c_str()); } } } break; } if (pp.type!=lString && (sptr==0 || sptr->empty()) && bf[0]==0) return _EmptyString; else if (sptr) { if (pp.text.empty()) return *sptr; else { sprintf_s(bf, pp.text.c_str(), sptr->c_str()); string &res = StringCache::getInstance().get(); res = bf; return res; } } else { if (pp.text.empty()) { string &res = StringCache::getInstance().get(); res = bf; return res; } else { char bf2[512]; sprintf_s(bf2, pp.text.c_str(), bf); string &res = StringCache::getInstance().get(); res = bf2; return res; } } } bool oEvent::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) { list::const_iterator ppit; int y=ppi.gdi.getCY(); int x=ppi.gdi.getCX(); bool updated=false; for (ppit=ppli.begin();ppit!=ppli.end();) { const oPrintPost &pp=*ppit; int limit = 0; bool keepNext = false; //Skip merged entities while (ppit != ppli.end() && ppit->doMergeNext) ++ppit; // Main increment below if ( ++ppit != ppli.end() && ppit->dy==pp.dy) limit = ppit->dx - pp.dx; else keepNext = true; limit=max(pp.fixedWidth, limit); assert(limit>=0); pRunner rr = r; if (!rr && t) { if (pp.legIndex >= 0) { int lg = pc ? pc->getLinearIndex(pp.legIndex, pp.linearLegIndex) : pp.legIndex; rr=t->getRunner(lg); } else if (legIndex >= 0) rr=t->getRunner(legIndex); else { int lg = ppi.par.getLegNumber(pc); rr = t->getRunner(lg); } } const string &text = (legIndex == -1) ? formatListString(pp, ppi.par, t, rr, c, pc, ppi.counter) : formatSpecialString(pp, ppi.par, t, legIndex, crs, ctrl, ppi.counter); updated |= !text.empty(); TextInfo *ti = 0; if (!text.empty()) { 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+ppi.gdi.scaleLength(pp.dy), x+ppi.gdi.scaleLength(pp.dx), pp.format, 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+ppi.gdi.scaleLength(pp.dy), x+ppi.gdi.scaleLength(pp.dx), pp.format, 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 + ppi.gdi.scaleLength(pp.dy), x + ppi.gdi.scaleLength(pp.dx), pp.format, text, ppi.gdi.scaleLength(limit), 0, pp.fontFace.c_str()); } if (ti && ppi.keepToghether) ti->lineBreakPrioity = -1; if (pp.color != colorDefault) ti->setColor(pp.color); } ppi.keepToghether |= keepNext; } return updated; } void oEvent::calculatePrintPostKey(const list &ppli, gdioutput &gdi, const oListParam &par, const pTeam t, const pRunner r, const pClub c, const pClass pc, oCounter &counter, string &key) { key.clear(); list::const_iterator ppit; for (ppit=ppli.begin();ppit!=ppli.end(); ++ppit) { const oPrintPost &pp=*ppit; pRunner rr = r; if (!rr && t) { int linLeg = pp.legIndex; if (pc) linLeg = pc->getLinearIndex(pp.legIndex, pp.linearLegIndex); rr=t->getRunner(linLeg); } const string &text = formatListString(pp, par, t, rr, c, pc, counter); key += text; //Skip merged entities while (ppit != ppli.end() && ppit->doMergeNext) ++ppit; } } void oEvent::listGeneratePunches(const list &ppli, gdioutput &gdi, const oListParam &par, pTeam t, pRunner r, pClub club, pClass cls) { if (!r || ppli.empty()) return; pCourse crs=r->getCourse(true); if (!crs) return; if (cls && cls->getNoTiming()) return; bool filterNamed = false; int h = gdi.getLineHeight(); int w=0; for (list::const_iterator it = ppli.begin(); it != ppli.end(); ++it) { if (it->type == lPunchNamedTime) filterNamed = true; h = max(h, gdi.getLineHeight(it->getFont(), it->fontFace.c_str()) + gdi.scaleLength(it->dy)); w = max(w, gdi.scaleLength(it->fixedWidth + it->dx)); } int xlimit=gdi.getCX()+ gdi.scaleLength(600); if (w>0) { gdi.pushX(); gdi.fillNone(); } bool neednewline = false; bool updated=false; int limit = crs->nControls + 1; if (r->Card && r->Card->getNumPunches()>limit) limit = r->Card->getNumPunches(); vector skip(limit, false); if (filterNamed) { for (int k = 0; k < crs->nControls; k++) { if (crs->getControl(k) && !crs->getControl(k)->hasName()) skip[k] = true; } for (int k = crs->nControls; k < limit; k++) { skip[k] = true; } } PrintPostInfo ppi(gdi, par); for (int k=0; k0 && updated) { updated=false; if ( gdi.getCX() + w > xlimit) { neednewline = false; gdi.popX(); gdi.setCY(gdi.getCY() + h); } else gdi.setCX(gdi.getCX()+w); } if (!skip[k]) { updated |= formatPrintPost(ppli, ppi, t, r, club, cls, 0, 0, -1); neednewline |= updated; } ppi.counter.level3++; } if (w>0) { gdi.popX(); gdi.fillDown(); if (neednewline) gdi.setCY(gdi.getCY() + h); } } void oEvent::generateList(gdioutput &gdi, bool reEvaluate, const oListInfo &li, bool updateScrollBars) { if (reEvaluate) reEvaluateAll(set(), false); oe->calcUseStartSeconds(); oe->calculateNumRemainingMaps(); oe->updateComputerTime(); vector< pair > > tagNameList; oe->getGeneralResults(false, tagNameList, false); string src; for (size_t k = 0; k < tagNameList.size(); k++) oe->getGeneralResult(tagNameList[k].second.first, src).setContext(&li.lp); string listname; if (!li.Head.empty()) { oCounter counter; const string &name = formatListString(li.Head.front(), li.lp, 0, 0, 0, 0, counter); listname = name; li.lp.updateDefaultName(name); } bool addHead = !li.lp.pageBreak && !li.lp.useLargeSize; size_t nClassesSelected = li.lp.selection.size(); if (nClassesSelected!=0 && nClassesSelected < min(Classes.size(), Classes.size()/2+5) ) { // Non-trivial class selection: Classes.sort(); string cls; for (oClassList::iterator it = Classes.begin(); it != Classes.end(); ++it) { if (li.lp.selection.count(it->getId())) { cls += MakeDash(" - "); cls += it->getName(); } } listname += cls; } if (li.lp.getLegNumberCoded() != -1) { listname += lang.tl(" Sträcka X#" + li.lp.getLegName()); } generateListInternal(gdi, li, addHead); for (list::const_iterator it = li.next.begin(); it != li.next.end(); ++it) { bool interHead = addHead && it->getParam().showInterTitle; if (li.lp.pageBreak || it->lp.pageBreak) { gdi.dropLine(1.0); gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, ""); } else if (interHead) gdi.dropLine(1.5); generateListInternal(gdi, *it, interHead); } for (size_t k = 0; k < tagNameList.size(); k++) oe->getGeneralResult(tagNameList[k].second.first, src).clearContext(); gdi.setListDescription(listname); if (updateScrollBars) gdi.updateScrollbars(); } void oEvent::generateListInternal(gdioutput &gdi, const oListInfo &li, bool formatHead) { li.setupLinks(); pClass sampleClass = 0; if (!li.lp.selection.empty()) sampleClass = getClass(*li.lp.selection.begin()); if (!sampleClass && !Classes.empty()) sampleClass = &*Classes.begin(); PrintPostInfo printPostInfo(gdi, li.lp); //oCounter counter; //Render header if (formatHead) formatPrintPost(li.Head, printPostInfo, 0,0,0,0,0,0, -1); if (li.fixedType) { 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) continue; if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId())==0) continue; it->apply(false, 0, true); } string oldKey; if ( li.listType==li.EBaseTypeRunner ) { if (li.calcCourseClassResults) calculateResults(RTClassCourseResult); if (li.calcTotalResults) { if (li.calcResults) { calculateResults(RTClassResult); calculateTeamResults(false); } calculateTeamResults(true); calculateResults(RTTotalResult); if (li.sortOrder != ClassTotalResult) sortRunners(li.sortOrder); } else if (li.calcResults) { if (li.rogainingResults) { calculateRogainingResults(); if (li.sortOrder != ClassPoints) sortRunners(li.sortOrder); } else if (li.lp.useControlIdResultTo>0 || li.lp.useControlIdResultFrom>0) calculateSplitResults(li.lp.useControlIdResultFrom, li.lp.useControlIdResultTo); else if (li.sortOrder == CourseResult) { calculateResults(RTCourseResult); } else { calculateTeamResults(false); calculateResults(RTClassResult); if (li.sortOrder != ClassResult) sortRunners(li.sortOrder); } } else sortRunners(li.sortOrder); vector rlist; rlist.reserve(Runners.size()); for (oRunnerList::iterator it=Runners.begin(); it != Runners.end(); ++it) { if (it->isRemoved() || it->tStatus == StatusNotCompetiting) continue; if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId())==0) continue; //if (it->legToRun() != li.lp.legNumber && li.lp.legNumber!=-1) if (!li.lp.matchLegNumber(it->getClassRef(), it->legToRun())) continue; if (li.filter(EFilterExcludeDNS)) if (it->tStatus==StatusDNS) continue; if (li.filter(EFilterVacant)) { if (it->isVacant()) continue; } if (li.filter(EFilterOnlyVacant)) { if (!it->isVacant()) continue; } if (li.filter(EFilterRentCard) && it->getDI().getInt("CardFee")==0) continue; if (li.filter(EFilterHasCard) && it->getCardNo()==0) continue; if (li.filter(EFilterHasNoCard) && it->getCardNo()>0) continue; rlist.push_back(&*it); } GeneralResult *gResult = 0; if (!li.resultModule.empty()) { string src; gResult = &getGeneralResult(li.resultModule, src); oListInfo::ResultType resType = li.getResultType(); gResult->calculateIndividualResults(rlist, resType, li.sortOrder == Custom, li.getParam().getInputNumber()); if (li.sortOrder == SortByFinishTime || li.sortOrder == SortByFinishTimeReverse || li.sortOrder == SortByStartTime) gResult->sort(rlist, li.sortOrder); } for (size_t k = 0; k < rlist.size(); k++) { pRunner it = rlist[k]; if (gResult && it->getTempResult(0).getStatus() == StatusNotCompetiting) continue; if (li.filter(EFilterHasResult)) { if (gResult == 0) { if (li.lp.useControlIdResultTo<=0 && it->tStatus==StatusUnknown) continue; else if ( (li.lp.useControlIdResultTo>0 || li.lp.useControlIdResultFrom>0) && it->tempStatus!=StatusOK) continue; else if (li.calcTotalResults && it->getTotalStatus() == StatusUnknown) continue; } else { const oAbstractRunner::TempResult &res = it->getTempResult(0); RunnerStatus st = res.getStatus(); if (st==StatusUnknown) continue; } } else if (li.filter(EFilterHasPrelResult)) { if (gResult == 0) { if (li.lp.useControlIdResultTo<=0 && it->tStatus==StatusUnknown && it->getRunningTime()<=0) continue; else if ( (li.lp.useControlIdResultTo>0 || li.lp.useControlIdResultFrom>0) && it->tempStatus!=StatusOK) continue; else if (li.calcTotalResults && it->getTotalStatus() == StatusUnknown && it->getTotalRunningTime()<=0) continue; } else { const oAbstractRunner::TempResult &res = it->getTempResult(0); int rt = res.getRunningTime(); RunnerStatus st = res.getStatus(); if (st==StatusUnknown && rt<=0) continue; } } string newKey; printPostInfo.par.relayLegIndex = -1; calculatePrintPostKey(li.subHead, gdi, li.lp, it->tInTeam, &*it, it->Club, it->Class, printPostInfo.counter, newKey); if (newKey != oldKey) { if (li.lp.pageBreak) { if (!oldKey.empty()) gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, ""); } gdi.addStringUT(pagePageInfo, it->getClass()); oldKey.swap(newKey); printPostInfo.counter.level2=0; printPostInfo.counter.level3=0; printPostInfo.reset(); printPostInfo.par.relayLegIndex = -1; formatPrintPost(li.subHead, printPostInfo, it->tInTeam, &*it, it->Club, it->Class, 0, 0, -1); } if (li.lp.filterMaxPer==0 || printPostInfo.counter.level2tLeg; formatPrintPost(li.listPost, printPostInfo, it->tInTeam, &*it, it->Club, it->Class, 0, 0, -1); if (li.listSubType==li.EBaseTypePunches) { listGeneratePunches(li.subListPost, gdi, li.lp, it->tInTeam, &*it, it->Club, it->Class); } } ++printPostInfo.counter; } } else if ( li.listType==li.EBaseTypeTeam ) { if (li.calcResults) calculateTeamResults(false); if (li.calcTotalResults) calculateTeamResults(true); if (li.rogainingResults && li.resultModule.empty()) throw std::exception("Not implemented"); if (li.calcCourseClassResults) calculateResults(RTClassCourseResult); if (li.resultModule.empty()) { pair legInfo = li.lp.getLegInfo(sampleClass); sortTeams(li.sortOrder, legInfo.first, legInfo.second); } vector tlist; tlist.reserve(Teams.size()); for (oTeamList::iterator it=Teams.begin(); it != Teams.end(); ++it) { if (it->isRemoved() || it->tStatus == StatusNotCompetiting) continue; if (!li.lp.selection.empty() && li.lp.selection.count(it->getClassId())==0) continue; tlist.push_back(&*it); } GeneralResult *gResult = 0; if (!li.resultModule.empty()) { string src; gResult = &getGeneralResult(li.resultModule, src); oListInfo::ResultType resType = li.getResultType(); gResult->calculateTeamResults(tlist, resType, li.sortOrder == Custom, li.getParam().getInputNumber()); } // Range of runners to include int parLegRangeMin = 0, parLegRangeMax = 1000; pClass parLegRangeClass = 0; const bool needParRange = li.subFilter(ESubFilterSameParallel) || li.subFilter(ESubFilterSameParallelNotFirst); for (size_t k = 0; k < tlist.size(); k++) { pTeam it = tlist[k]; int linearLegSpec = li.lp.getLegNumber(it->getClassRef()); if (gResult && it->getTempResult(0).getStatus() == StatusNotCompetiting) continue; if (li.filter(EFilterExcludeDNS)) if (it->tStatus==StatusDNS) continue; if (li.filter(EFilterVacant)) if (it->isVacant()) continue; if (li.filter(EFilterOnlyVacant)) { if (!it->isVacant()) continue; } if ( li.filter(EFilterHasResult) ) { if (gResult) { if (it->getTempResult(0).getStatus() == StatusUnknown) continue; } else { if (it->getLegStatus(linearLegSpec, false)==StatusUnknown) continue; else if (li.calcTotalResults && it->getLegStatus(linearLegSpec, true) == StatusUnknown) continue; } } else if ( li.filter(EFilterHasPrelResult) ) { if (gResult) { if (it->getTempResult(0).getStatus() == StatusUnknown && it->getTempResult(0).getRunningTime() <= 0) continue; } else { if (it->getLegStatus(linearLegSpec, false)==StatusUnknown && it->getLegRunningTime(linearLegSpec, false)<=0) continue; else if (li.calcTotalResults && it->getLegStatus(linearLegSpec, true) == StatusUnknown && it->getTotalRunningTime()<=0) continue; } } if (needParRange && it->Class != parLegRangeClass && it->Class) { parLegRangeClass = it->Class; parLegRangeClass->getParallelRange(linearLegSpec < 0 ? 0 : linearLegSpec, parLegRangeMin, parLegRangeMax); if (li.subFilter(ESubFilterSameParallelNotFirst)) parLegRangeMin++; } string newKey; printPostInfo.par.relayLegIndex = linearLegSpec; calculatePrintPostKey(li.subHead, gdi, li.lp, &*it, 0, it->Club, it->Class, printPostInfo.counter, newKey); if (newKey != oldKey) { if (li.lp.pageBreak) { if (!oldKey.empty()) gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, ""); } string legInfo; if (linearLegSpec >= 0 && it->getClassRef()) { // Specified leg legInfo = lang.tl(", Str. X#" + li.lp.getLegName()); } gdi.addStringUT(pagePageInfo, it->getClass() + legInfo); // Teamlist oldKey.swap(newKey); printPostInfo.counter.level2=0; printPostInfo.counter.level3=0; printPostInfo.reset(); printPostInfo.par.relayLegIndex = linearLegSpec; formatPrintPost(li.subHead, printPostInfo, &*it, 0, it->Club, it->Class, 0,0,-1); } ++printPostInfo.counter; if (li.lp.filterMaxPer==0 || printPostInfo.counter.level2<=li.lp.filterMaxPer) { printPostInfo.counter.level3=0; printPostInfo.reset(); printPostInfo.par.relayLegIndex = linearLegSpec; formatPrintPost(li.listPost, printPostInfo, &*it, 0, it->Club, it->Class, 0, 0, -1); if (li.subListPost.empty()) continue; if (li.listSubType==li.EBaseTypeRunner) { int nr = int(it->Runners.size()); vector tr; tr.reserve(nr); vector usedIx(nr, -1); for (int k=0;kRunners[k]) { if (li.filter(EFilterHasResult) || li.subFilter(ESubFilterHasResult) || li.filter(EFilterHasPrelResult) || li.subFilter(ESubFilterHasPrelResult) || li.filter(EFilterExcludeDNS) || li.subFilter(ESubFilterExcludeDNS) || li.subFilter(ESubFilterVacant)) { usedIx[k] = -2; // Skip totally } continue; } else usedIx[k] = -2; // Skip unless allowed after filters bool noResult = false; bool noPrelResult = false; bool noStart = false; if (gResult == 0) { noResult = it->Runners[k]->tStatus == StatusUnknown; noPrelResult = it->Runners[k]->tStatus == StatusUnknown && it->Runners[k]->getRunningTime() <= 0; noStart = it->Runners[k]->tStatus == StatusDNS; //XXX TODO Multiday } else { noResult = it->Runners[k]->tmpResult.status == StatusUnknown; noPrelResult = it->Runners[k]->tmpResult.status == StatusUnknown && it->Runners[k]->tmpResult.runningTime <= 0; noStart = it->Runners[k]->tmpResult.status == StatusDNS; } if (noResult && (li.filter(EFilterHasResult) || li.subFilter(ESubFilterHasResult))) continue; if (noPrelResult && (li.filter(EFilterHasPrelResult) || li.subFilter(ESubFilterHasPrelResult))) continue; if (noStart && (li.filter(EFilterExcludeDNS) || li.subFilter(ESubFilterExcludeDNS))) continue; if (it->Runners[k]->isVacant() && li.subFilter(ESubFilterVacant)) continue; if ( (it->Runners[k]->tLeg < parLegRangeMin || it->Runners[k]->tLeg > parLegRangeMax) && needParRange) continue; usedIx[k] = tr.size(); tr.push_back(it->Runners[k]); } if (gResult) { gResult->sortTeamMembers(tr); for (size_t k = 0; k < tr.size(); k++) { bool suitableBreak = k<2 || (k+2)>=tr.size(); printPostInfo.keepToghether = suitableBreak; printPostInfo.par.relayLegIndex = tr[k] ? tr[k]->tLeg : -1; formatPrintPost(li.subListPost, printPostInfo, &*it, tr[k], it->Club, tr[k]->Class, 0, 0, -1); printPostInfo.counter.level3++; } } else { for (size_t k = 0; k < usedIx.size(); k++) { if (usedIx[k] == -2) continue; // Skip bool suitableBreak = k<2 || (k+2)>=usedIx.size(); printPostInfo.keepToghether = suitableBreak; printPostInfo.par.relayLegIndex = k; if (usedIx[k] == -1) { pCourse crs = it->Class ? it->Class->getCourse(k, it->StartNo) : 0; formatPrintPost(li.subListPost, printPostInfo, &*it, 0, it->Club, it->Class, crs, 0, k); } else { formatPrintPost(li.subListPost, printPostInfo, &*it, tr[usedIx[k]], it->Club, tr[usedIx[k]]->Class, 0, 0, -1); } printPostInfo.counter.level3++; } } } else if (li.listSubType==li.EBaseTypePunches) { pRunner r=it->Runners.empty() ? 0:it->Runners[0]; if (!r) continue; listGeneratePunches(li.subListPost, gdi, li.lp, &*it, r, it->Club, it->Class); } } } } else if ( li.listType==li.EBaseTypeClub ) { if (li.calcResults) { calculateTeamResults(true); calculateTeamResults(false); } if (li.calcCourseClassResults) calculateResults(RTClassCourseResult); pair info = li.lp.getLegInfo(sampleClass); sortTeams(li.sortOrder, info.first, info.second); if ( li.calcResults ) { if (li.lp.useControlIdResultTo>0 || li.lp.useControlIdResultFrom>0) calculateSplitResults(li.lp.useControlIdResultFrom, li.lp.useControlIdResultTo); else calculateResults(RTClassResult); } else sortRunners(li.sortOrder); Clubs.sort(); oClubList::iterator it; oRunnerList::iterator rit; bool first = true; for (it = Clubs.begin(); it != Clubs.end(); ++it) { if (it->isRemoved()) continue; if (li.filter(EFilterVacant)) { if (it->getId() == getVacantClub()) continue; } if (li.filter(EFilterOnlyVacant)) { if (it->getId() != getVacantClub()) continue; } bool startClub = false; pRunner pLeader = 0; for (rit = Runners.begin(); rit != Runners.end(); ++rit) { if (rit->isRemoved() || rit->tStatus == StatusNotCompetiting) continue; if (!li.lp.selection.empty() && li.lp.selection.count(rit->getClassId())==0) continue; if (!li.lp.matchLegNumber(rit->getClassRef(), rit->legToRun())) continue; if (li.filter(EFilterExcludeDNS)) if (rit->tStatus==StatusDNS) continue; if (li.filter(EFilterHasResult)) { if (li.lp.useControlIdResultTo<=0 && rit->tStatus==StatusUnknown) continue; else if ((li.lp.useControlIdResultTo>0 || li.lp.useControlIdResultFrom>0) && rit->tempStatus!=StatusOK) continue; else if (li.calcTotalResults && rit->getTotalStatus() == StatusUnknown) continue; } if (!pLeader || pLeader->Class != rit->Class) pLeader = &*rit; if (rit->Club == &*it) { if (!startClub) { if (li.lp.pageBreak) { if (!first) gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, ""); else first = false; } gdi.addStringUT(pagePageInfo, it->getName()); printPostInfo.counter.level2=0; printPostInfo.counter.level3=0; printPostInfo.reset(); printPostInfo.par.relayLegIndex = -1; formatPrintPost(li.subHead, printPostInfo, 0, 0, &*it, 0, 0, 0, -1); startClub = true; } ++printPostInfo.counter; if (li.lp.filterMaxPer==0 || printPostInfo.counter.level2<=li.lp.filterMaxPer) { printPostInfo.counter.level3=0; printPostInfo.reset(); printPostInfo.par.relayLegIndex = rit->tLeg; formatPrintPost(li.listPost, printPostInfo, 0, &*rit, &*it, rit->Class, 0, 0, -1); if (li.subListPost.empty()) continue; } } }//Runners }//Clubs } else if (li.listType == oListInfo::EBaseTypeCourse) { Courses.sort(); oCourseList::iterator it; for (it = Courses.begin(); it != Courses.end(); ++it) { if (it->isRemoved()) continue; if (!li.lp.selection.empty()) { vector usageClass; it->getClasses(usageClass); bool used = false; while (!used && !usageClass.empty()) { used = li.lp.selection.count(usageClass.back()->getId()) > 0; usageClass.pop_back(); } if (!used) continue; } string newKey; calculatePrintPostKey(li.subHead, gdi, li.lp, 0, 0, 0, 0, printPostInfo.counter, newKey); if (newKey != oldKey) { if (li.lp.pageBreak) { if (!oldKey.empty()) gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, ""); } oldKey.swap(newKey); printPostInfo.counter.level2=0; printPostInfo.counter.level3=0; printPostInfo.reset(); formatPrintPost(li.subHead, printPostInfo, 0, 0, 0, 0, &*it, 0, 0); } if (li.lp.filterMaxPer==0 || printPostInfo.counter.level2tInTeam, &*it, it->Club, it->Class); } } ++printPostInfo.counter; } } else if (li.listType == oListInfo::EBaseTypeControl) { Controls.sort(); oControlList::iterator it; for (it = Controls.begin(); it != Controls.end(); ++it) { if (it->isRemoved()) continue; string newKey; calculatePrintPostKey(li.subHead, gdi, li.lp, 0, 0, 0, 0, printPostInfo.counter, newKey); if (newKey != oldKey) { if (li.lp.pageBreak) { if (!oldKey.empty()) gdi.addStringUT(gdi.getCY()-1, 0, pageNewPage, ""); } oldKey.swap(newKey); printPostInfo.counter.level2=0; printPostInfo.counter.level3=0; printPostInfo.reset(); formatPrintPost(li.subHead, printPostInfo, 0, 0, 0, 0, 0, &*it, 0); } if (li.lp.filterMaxPer==0 || printPostInfo.counter.level2 listMap; getListTypes(listMap, filter); //gdi.clearList(name); map::iterator it; vector< pair > v; for (it=listMap.begin(); it!=listMap.end(); ++it) { v.push_back(make_pair(it->second.Name, it->first)); //gdi.addItem(name, it->second.Name, it->first); } sort(v.begin(), v.end()); gdi.addItem(name, v); } void oEvent::getListType(EStdListType type, oListInfo &li) { map listMap; getListTypes(listMap, false); li = listMap[type]; } void oEvent::getListTypes(map &listMap, int filterResults) { listMap.clear(); if (!filterResults) { oListInfo li; li.Name=lang.tl("Startlista, individuell"); li.listType=li.EBaseTypeRunner; li.supportClasses = true; li.supportLegs = true; listMap[EStdStartList]=li; } { oListInfo li; li.Name=lang.tl("Resultat, individuell"); li.listType=li.EBaseTypeRunner; li.supportClasses = true; li.supportLegs = true; li.supportFrom = true; li.supportTo = true; listMap[EStdResultList]=li; } { oListInfo li; li.Name=lang.tl("Resultat, generell"); li.listType=li.EBaseTypeRunner; li.supportClasses = true; li.supportLegs = true; li.supportLarge = true; li.supportFrom = true; li.supportTo = true; li.calcTotalResults = true; listMap[EGeneralResultList]=li; } { oListInfo li; li.Name=lang.tl("Rogaining, individuell"); li.listType=li.EBaseTypeRunner; li.supportClasses = true; li.supportLegs = true; listMap[ERogainingInd]=li; } { oListInfo li; li.Name=lang.tl("Avgjorda klasser (prisutdelningslista)"); li.listType=li.EBaseTypeRunner; li.supportClasses = true; li.supportLegs = true; listMap[EIndPriceList]=li; } if (!filterResults) { oListInfo li; li.Name=lang.tl("Startlista, patrull"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; listMap[EStdPatrolStartList]=li; } { oListInfo li; li.Name=lang.tl("Resultat, patrull"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; listMap[EStdPatrolResultList]=li; } { oListInfo li; li.Name="Patrullresultat (STOR)"; li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; li.largeSize = true; listMap[EStdPatrolResultListLARGE]=li; } { oListInfo li; li.Name=lang.tl("Resultat (STOR)"); li.supportClasses = true; li.supportLegs = true; li.supportFrom = true; li.supportTo = true; li.largeSize = true; li.listType=li.EBaseTypeRunner; listMap[EStdResultListLARGE]=li; } /*{ oListInfo li; li.Name=lang.tl("Stafettresultat, sträcka (STOR)"); li.supportClasses = true; li.supportLegs = true; li.largeSize = true; li.listType=li.EBaseTypeTeam; listMap[EStdTeamResultListLegLARGE]=li; }*/ if (!filterResults) { oListInfo li; li.Name=lang.tl("Hyrbricksrapport"); li.listType=li.EBaseTypeRunner; li.supportClasses = false; li.supportLegs = false; listMap[EStdRentedCard]=li; } { oListInfo li; li.Name=lang.tl("Stafettresultat, delsträckor"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; listMap[EStdTeamResultListAll]=li; } { oListInfo li; li.Name=lang.tl("Stafettresultat, lag"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; listMap[EStdTeamResultList]=li; } /* { oListInfo li; li.Name=lang.tl("Stafettresultat, sträcka"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = true; listMap[EStdTeamResultListLeg]=li; }*/ if (!filterResults) { { oListInfo li; li.Name=lang.tl("Startlista, stafett (lag)"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; listMap[EStdTeamStartList]=li; } { oListInfo li; li.Name=lang.tl("Startlista, stafett (sträcka)"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = true; listMap[EStdTeamStartListLeg]=li; } { oListInfo li; li.Name=lang.tl("Bantilldelning, stafett"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; listMap[ETeamCourseList]=li; } { oListInfo li; li.Name=lang.tl("Bantilldelning, individuell"); li.listType=li.EBaseTypeRunner; li.supportClasses = true; li.supportLegs = false; listMap[EIndCourseList]=li; } { oListInfo li; li.Name=lang.tl("Individuell startlista, visst lopp"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = true; listMap[EStdIndMultiStartListLeg]=li; } } { oListInfo li; li.Name=lang.tl("Individuell resultatlista, visst lopp"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = true; listMap[EStdIndMultiResultListLeg]=li; } { oListInfo li; li.Name=lang.tl("Individuell resultatlista, visst lopp (STOR)"); li.listType=li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = true; li.largeSize = true; listMap[EStdIndMultiResultListLegLARGE]=li; } { oListInfo li; li.Name = lang.tl("Individuell resultatlista, alla lopp"); li.listType = li.EBaseTypeTeam; li.supportClasses = true; li.supportLegs = false; listMap[EStdIndMultiResultListAll]=li; } if (!filterResults) { oListInfo li; li.Name = lang.tl("Klubbstartlista"); li.listType = li.EBaseTypeClub; li.supportClasses = true; li.supportLegs = false; listMap[EStdClubStartList]=li; } { oListInfo li; li.Name = lang.tl("Klubbresultatlista"); li.listType = li.EBaseTypeClub; li.supportClasses = true; li.supportLegs = false; listMap[EStdClubResultList]=li; } if (!filterResults) { { oListInfo li; li.Name=lang.tl("Tävlingsrapport"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedReport]=li; } { oListInfo li; li.Name=lang.tl("Kontroll inför tävlingen"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedPreReport]=li; } { oListInfo li; li.Name=lang.tl("Kvar-i-skogen"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedInForest]=li; } { oListInfo li; li.Name=lang.tl("Fakturor"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedInvoices]=li; } { oListInfo li; li.Name=lang.tl("Ekonomisk sammanställning"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedEconomy]=li; } } /* { oListInfo li; li.Name=lang.tl("Först-i-mål, klassvis"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedResultFinishPerClass]=li; } { oListInfo li; li.Name=lang.tl("Först-i-mål, gemensam"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedResultFinish]=li; }*/ if (!filterResults) { oListInfo li; li.Name=lang.tl("Minutstartlista"); li.supportClasses = false; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedMinuteStartlist]=li; } { oListInfo li; li.Name=lang.tl("Händelser - tidslinje"); li.supportClasses = true; li.supportLegs = false; li.listType=li.EBaseTypeNone; listMap[EFixedTimeLine]=li; } { oListInfo li; li.Name=lang.tl("Liveresultat, deltagare"); li.listType=li.EBaseTypeRunner; li.supportClasses = true; li.supportLegs = false; li.supportFrom = true; li.supportTo = true; li.supportSplitAnalysis = false; li.supportInterResults = false; li.supportPageBreak = false; li.supportClassLimit = false; li.supportCustomTitle = false; listMap[EFixedLiveResult]=li; } { oListInfo li; li.Name=lang.tl("Stafettresultat, sträcka (STOR)"); li.supportClasses = true; li.supportLegs = false; li.largeSize = true; li.listType=li.EBaseTypeTeam; listMap[EStdTeamAllLegLARGE]=li; } getListContainer().setupListInfo(EFirstLoadedList, listMap, filterResults != 0); } void oEvent::generateListInfo(EStdListType lt, const gdioutput &gdi, int classId, oListInfo &li) { oListParam par; if (classId!=0) par.selection.insert(classId); par.listCode=lt; generateListInfo(par, gdi.getLineHeight(), li); } int openRunnerTeamCB(gdioutput *gdi, int type, void *data); void oEvent::generateFixedList(gdioutput &gdi, const oListInfo &li) { string dmy; switch (li.lp.listCode) { case EFixedPreReport: generatePreReport(gdi); break; case EFixedReport: generateCompetitionReport(gdi); break; case EFixedInForest: generateInForestList(gdi, openRunnerTeamCB, 0); break; case EFixedEconomy: printInvoices(gdi, IPTAllPrint, dmy, true); break; case EFixedInvoices: printInvoices(gdi, IPTAllPrint, dmy, false); break; case EFixedMinuteStartlist: generateMinuteStartlist(gdi); break; case EFixedLiveResult: break; case EFixedTimeLine: gdi.clearPage(false); gdi.addString("", boldLarge, MakeDash("Tidslinje - X#" + getName())); gdi.dropLine(); set<__int64> stored; vector events; map cName; for (oClassList::const_iterator it = Classes.begin(); it != Classes.end(); ++it) { if (!it->isRemoved()) cName[it->getId()] = it->getName(); } oe->getTimeLineEvents(li.lp.selection, events, stored, 3600*24*7); gdi.fillDown(); int yp = gdi.getCY(); int xp = gdi.getCX(); int w1 = gdi.scaleLength(60); int w = gdi.scaleLength(110); int w2 = w1+w; for (size_t k = 0; k(ev.getSource(*this)); if (!r) continue; if (ev.getType() == oTimeLine::TLTFinish && r->getStatus() != StatusOK) continue; string name = ""; if (r) name = r->getCompleteIdentification() + " "; gdi.addStringUT(yp, xp, 0, oe->getAbsTime(ev.getTime())); gdi.addStringUT(yp, xp + w1, 0, cName[ev.getClassId()], w-10); gdi.addStringUT(yp, xp + w2, 0, name + lang.tl(ev.getMessage())); yp += gdi.getLineHeight(); /*string detail = ev.getDetail(); if (detail.size() > 0) { gdi.addStringUT(yp, xp + w, 0, detail); yp += gdi.getLineHeight(); }*/ } gdi.refresh(); break; } } void oListInfo::setCallback(GUICALLBACK cb) { lp.cb=cb; for (list::iterator it = next.begin(); it != next.end(); ++it) { it->setCallback(cb); } } void oEvent::generateListInfo(oListParam &par, int lineHeight, oListInfo &li) { vector parV(1, par); generateListInfo(parV, lineHeight, li); } void oEvent::generateListInfo(vector &par, int lineHeight, oListInfo &li) { loadGeneralResults(false); lineHeight = 14; for (size_t k = 0; k < par.size(); k++) { par[k].cb = 0; } map listMap; getListTypes(listMap, false); if (par.size() == 1) { generateListInfoAux(par[0], lineHeight, li, listMap[par[0].listCode].Name); set used; // Add linked lists oListParam *cPar = &par[0]; while (cPar->nextList>0) { if (used.count(cPar->nextList)) break; // Circular definition used.insert(cPar->nextList); used.insert(cPar->previousList); oListParam &nextPar = oe->getListContainer().getParam(cPar->nextList-1); li.next.push_back(oListInfo()); nextPar.cb = 0; generateListInfoAux(nextPar, lineHeight, li.next.back(), ""); cPar = &nextPar; } } else { for (size_t k = 0; k < par.size(); k++) { if (k > 0) { li.next.push_back(oListInfo()); } generateListInfoAux(par[k], lineHeight, k == 0 ? li : li.next.back(), li.Name = listMap[par[0].listCode].Name); } } } void oEvent::generateListInfoAux(oListParam &par, int lineHeight, oListInfo &li, const string &name) { const int lh=lineHeight; const int vspace=lh/2; int bib; pair ln; const double scale = 1.8; string ttl; Position pos; pClass sampleClass = 0; if (!par.selection.empty()) sampleClass = getClass(*par.selection.begin()); if (!sampleClass && !Classes.empty()) sampleClass = &*Classes.begin(); EStdListType lt=par.listCode; li=oListInfo(); li.lp = par; li.Name = name; li.lp.defaultName = li.Name; if (par.defaultName.empty()) par.defaultName = li.Name; if (par.name.empty()) par.name = li.Name; if (li.lp.name.empty()) li.lp.name = li.Name; switch (lt) { case EStdStartList: { li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Startlista - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); int bib = 0; int rank = 0; if (hasBib(true, false)) { li.addListPost(oPrintPost(lRunnerBib, "", normalText, 0, 0)); bib=40; } li.addListPost(oPrintPost(lRunnerStart, "", normalText, 0+bib, 0)); li.addListPost(oPrintPost(lPatrolNameNames, "", normalText, 70+bib, 0)); li.addListPost(oPrintPost(lPatrolClubNameNames, "", normalText, 300+bib, 0)); if (hasRank()) { li.addListPost(oPrintPost(lRunnerRank, "", normalText, 470+bib, 0)); rank = 50; } li.addListPost(oPrintPost(lRunnerCard, "", normalText, 470+bib+rank, 0)); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 12)); li.addSubHead(oPrintPost(lClassLength, lang.tl("%s meter"), boldText, 300+bib, 12)); li.addSubHead(oPrintPost(lClassStartName, "", boldText, 470+bib+rank, 12)); li.addSubHead(oPrintPost(lString, "", boldText, 470+bib, 16)); li.listType=li.EBaseTypeRunner; li.sortOrder=ClassStartTime; li.setFilter(EFilterExcludeDNS); break; } case EStdClubStartList: { li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Klubbstartlista - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); if (hasBib(true, true)) { pos.add("bib", 40); li.addListPost(oPrintPost(lRunnerBib, "", normalText, 0, 0)); } pos.add("start", li.getMaxCharWidth(this, par.selection, lRunnerStart, "", normalText)); li.addListPost(oPrintPost(lRunnerStart, "", normalText, pos.get("start"), 0)); if (hasRank()) { pos.add("rank", 50); li.addListPost(oPrintPost(lRunnerRank, "", normalText, pos.get("rank"), 0)); } pos.add("name", li.getMaxCharWidth(this, par.selection, lRunnerName, "", normalText)); li.addListPost(oPrintPost(lPatrolNameNames, "", normalText, pos.get("name"), 0)); pos.add("class", li.getMaxCharWidth(this, par.selection, lClassName, "", normalText)); li.addListPost(oPrintPost(lClassName, "", normalText, pos.get("class"), 0)); pos.add("length", li.getMaxCharWidth(this, par.selection, lClassLength, "%s m", normalText)); li.addListPost(oPrintPost(lClassLength, lang.tl("%s m"), normalText, pos.get("length"), 0)); pos.add("sname", li.getMaxCharWidth(this, par.selection, lClassStartName, "", normalText)); li.addListPost(oPrintPost(lClassStartName, "", normalText, pos.get("sname"), 0)); pos.add("card", 70); li.addListPost(oPrintPost(lRunnerCard, "", normalText, pos.get("card"), 0)); li.addSubHead(oPrintPost(lClubName, "", boldText, 0, 12)); li.addSubHead(oPrintPost(lString, "", boldText, 100, 16)); li.listType=li.EBaseTypeClub; li.sortOrder=ClassTeamLeg; li.setFilter(EFilterExcludeDNS); li.setFilter(EFilterVacant); break; } case EStdClubResultList: { li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Klubbresultatlista - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); pos.add("class", li.getMaxCharWidth(this, par.selection, lClassName, "", normalText)); li.addListPost(oPrintPost(lClassName, "", normalText, pos.get("class"), 0)); pos.add("place", 40); li.addListPost(oPrintPost(lRunnerPlace, "", normalText, pos.get("place"), 0)); pos.add("name", li.getMaxCharWidth(this, par.selection, lPatrolNameNames, "", normalText)); li.addListPost(oPrintPost(lRunnerName, "", normalText, pos.get("name"), 0)); pos.add("time", li.getMaxCharWidth(this, par.selection, lRunnerTimeStatus, "", normalText)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", normalText, pos.get("time"), 0)); pos.add("after", li.getMaxCharWidth(this, par.selection, lRunnerTimeAfter, "", normalText)); li.addListPost(oPrintPost(lRunnerTimeAfter, "", normalText, pos.get("after"), 0)); li.addSubHead(oPrintPost(lClubName, "", boldText, 0, 12)); li.addSubHead(oPrintPost(lString, "", boldText, 100, 16)); li.listType=li.EBaseTypeClub; li.sortOrder=ClassResult; li.calcResults = true; li.setFilter(EFilterVacant); break; } case EStdRentedCard: { li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Hyrbricksrapport - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); li.addListPost(oPrintPost(lTotalCounter, "%s", normalText, 0, 0)); li.addListPost(oPrintPost(lRunnerCard, "", normalText, 30, 0)); li.addListPost(oPrintPost(lRunnerName, "", normalText, 130, 0)); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.setFilter(EFilterHasCard); li.setFilter(EFilterRentCard); li.setFilter(EFilterExcludeDNS); li.listType=li.EBaseTypeRunner; li.sortOrder=ClassStartTime; break; } case EStdResultList: { string stitle; getResultTitle(*this, li.lp, stitle); stitle = par.getCustomTitle(stitle); li.addHead(oPrintPost(lCmpName, MakeDash(stitle), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); pos.add("place", 25); pos.add("name", li.getMaxCharWidth(this, par.selection, lPatrolNameNames, "", normalText, 0, false, 25)); pos.add("club", li.getMaxCharWidth(this, par.selection, lPatrolClubNameNames, "", normalText, 0, false, 25)); pos.add("status", 50); pos.add("after", 50); pos.add("missed", 50); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.addListPost(oPrintPost(lRunnerPlace, "", normalText, pos.get("place"), 0)); li.addListPost(oPrintPost(lPatrolNameNames, "", normalText, pos.get("name"), 0)); li.addListPost(oPrintPost(lPatrolClubNameNames, "", normalText, pos.get("club"), 0)); if (li.lp.useControlIdResultTo<=0 && li.lp.useControlIdResultFrom<=0) { li.addSubHead(oPrintPost(lClassResultFraction, "", boldText, pos.get("club"), 10)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", normalText, pos.get("status"), 0)); li.addListPost(oPrintPost(lRunnerTimeAfter, "", normalText, pos.get("after"), 0)); if (li.lp.showInterTimes) { li.addSubListPost(oPrintPost(lPunchNamedTime, "", italicSmall, pos.get("name"), 0, make_pair(1, true))); li.subListPost.back().fixedWidth = 160; li.listSubType = li.EBaseTypePunches; } else if (li.lp.showSplitTimes) { li.addSubListPost(oPrintPost(lPunchTime, "", italicSmall, pos.get("name"), 0, make_pair(1, true))); li.subListPost.back().fixedWidth = 95; li.listSubType = li.EBaseTypePunches; } } else { li.needPunches = true; li.addListPost(oPrintPost(lRunnerTempTimeStatus, "", normalText, pos.get("status"), 0)); li.addListPost(oPrintPost(lRunnerTempTimeAfter, "", normalText, pos.get("after"), 0)); } li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldText, pos.get("status"), 10)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldText, pos.get("after"), 10)); if (li.lp.splitAnalysis) { li.addListPost(oPrintPost(lRunnerMissedTime, "", normalText, pos.get("missed"), 0)); li.addSubHead(oPrintPost(lString, lang.tl("Bomtid"), boldText, pos.get("missed"), 10)); } li.calcResults = true; li.listType=li.EBaseTypeRunner; li.sortOrder=ClassResult; li.supportFrom = true; li.supportTo = true; li.setFilter(EFilterHasPrelResult); break; } case EGeneralResultList: { string stitle; getResultTitle(*this, li.lp, stitle); stitle = par.getCustomTitle(stitle); gdiFonts normal, header, small; double s; if (par.useLargeSize) { s = scale; normal = fontLarge; header = boldLarge; small = normalText; } else { s = 1.0; normal = normalText; header = boldText; small = italicSmall; } li.addHead(oPrintPost(lCmpName, MakeDash(stitle), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); pos.add("place", li.getMaxCharWidth(this, par.selection, lRunnerGeneralPlace, "", normalText)); pos.add("name", li.getMaxCharWidth(this, par.selection, lRunnerCompleteName, "", normalText)); pos.add("status", li.getMaxCharWidth(this, par.selection, lRunnerGeneralTimeStatus, "", normalText)); pos.add("after", li.getMaxCharWidth(this, par.selection, lRunnerGeneralTimeAfter, "", normalText)); pos.add("missed", 50); li.addSubHead(oPrintPost(lClassName, "", header, 0, 10)); li.addListPost(oPrintPost(lRunnerGeneralPlace, "", normal, pos.get("place", s), 0)); li.addListPost(oPrintPost(lRunnerCompleteName, "", normal, pos.get("name", s), 0)); if (li.lp.useControlIdResultTo<=0 && li.lp.useControlIdResultFrom<=0) { li.addListPost(oPrintPost(lRunnerGeneralTimeStatus, "", normal, pos.get("status", s), 0)); li.addListPost(oPrintPost(lRunnerGeneralTimeAfter, "", normal, pos.get("after", s), 0)); if (li.lp.showInterTimes) { li.addSubListPost(oPrintPost(lPunchNamedTime, "", small, pos.get("name", s), 0, make_pair(1, true))); li.subListPost.back().fixedWidth = 160; li.listSubType = li.EBaseTypePunches; } else if (li.lp.showSplitTimes) { li.addSubListPost(oPrintPost(lPunchTime, "", small, pos.get("name", s), 0, make_pair(1, true))); li.subListPost.back().fixedWidth = 95; li.listSubType = li.EBaseTypePunches; } } else { li.needPunches = true; li.addListPost(oPrintPost(lRunnerTempTimeStatus, "", normal, pos.get("status", s), 0)); li.addListPost(oPrintPost(lRunnerTempTimeAfter, "", normal, pos.get("after", s), 0)); } li.addSubHead(oPrintPost(lString, lang.tl("Tid"), header, pos.get("status", s), 10)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), header, pos.get("after", s), 10)); li.calcResults = true; li.listType=li.EBaseTypeRunner; li.sortOrder=ClassResult; li.setFilter(EFilterHasPrelResult); li.supportFrom = true; li.supportTo = true; li.calcTotalResults = true; break; } case EIndPriceList: li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Avgjorda placeringar - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCurrentTime, lang.tl("Genererad: ") + "%s", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); pos.add("place", 25); pos.add("name", li.getMaxCharWidth(this, par.selection, lPatrolNameNames, "", normalText)); pos.add("club", li.getMaxCharWidth(this, par.selection, lPatrolClubNameNames, "", normalText)); pos.add("status", 80); pos.add("info", 80); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.addSubHead(oPrintPost(lClassResultFraction, "", boldText, pos.get("club"), 10)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldText, pos.get("status"), 10)); li.addSubHead(oPrintPost(lString, lang.tl("Avgörs kl"), boldText, pos.get("info"), 10)); li.addListPost(oPrintPost(lRunnerPlace, "", normalText, pos.get("place"), 0)); li.addListPost(oPrintPost(lPatrolNameNames, "", normalText, pos.get("name"), 0)); li.addListPost(oPrintPost(lPatrolClubNameNames, "", normalText, pos.get("club"), 0)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", normalText, pos.get("status"), 0)); li.addListPost(oPrintPost(lRunnerTimePlaceFixed, "", normalText, pos.get("info"), 0)); li.calcResults = true; li.listType = li.EBaseTypeRunner; li.sortOrder = ClassResult; li.setFilter(EFilterHasResult); break; case EStdTeamResultList: li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Resultatsammanställning - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 14)); li.addSubHead(oPrintPost(lClassResultFraction, "", normalText, 280, 14)); //Use last leg for every team (index=-1) li.addListPost(oPrintPost(lTeamPlace, "", normalText, 0, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamName, "", normalText, 25, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamTimeStatus, "", normalText, 280, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamTimeAfter, "", normalText, 340, 5, make_pair(-1, true))); li.lp.setLegNumberCoded(-1); li.calcResults=true; li.listType=li.EBaseTypeTeam; li.listSubType=li.EBaseTypeRunner; li.sortOrder=ClassResult; li.setFilter(EFilterHasResult); break; case EStdTeamResultListAll: li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Resultat - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 14)); li.addSubHead(oPrintPost(lClassResultFraction, "", boldText, 280, 14)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldText, 400, 14)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldText, 460, 14)); //Use last leg for every team (index=-1) li.addListPost(oPrintPost(lTeamPlace, "", normalText, 0, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamName, "", normalText, 25, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamTimeStatus, "", normalText, 400, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamTimeAfter, "", normalText, 460, 5, make_pair(-1, true))); li.addSubListPost(oPrintPost(lRunnerLegNumberAlpha, "%s.", normalText, 25, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lRunnerName, "", normalText, 45, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lRunnerTimeStatus, "", normalText, 280, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lTeamLegTimeStatus, "", normalText, 400, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lTeamLegTimeAfter, "", normalText, 460, 0, make_pair(0, true))); if (li.lp.splitAnalysis) { li.addSubListPost(oPrintPost(lRunnerMissedTime, "", normalText, 510, 0)); li.addSubHead(oPrintPost(lString, lang.tl("Bomtid"), boldText, 510, 14)); } li.lp.setLegNumberCoded(-1); li.calcResults=true; li.listType=li.EBaseTypeTeam; li.listSubType=li.EBaseTypeRunner; li.sortOrder=ClassResult; li.setFilter(EFilterHasResult); break; case unused_EStdTeamResultListLeg: { char title[256]; if (li.lp.getLegNumberCoded() != 1000) sprintf_s(title, (lang.tl("Resultat efter sträcka X#" + li.lp.getLegName())+" - %%s").c_str()); else sprintf_s(title, (lang.tl("Resultat efter sträckan")+" - %%s").c_str()); pos.add("place", 25); pos.add("team", li.getMaxCharWidth(this, par.selection, lTeamName, "", normalText)); pos.add("name", li.getMaxCharWidth(this, par.selection, lRunnerName, "", normalText)); pos.add("status", 50); pos.add("teamstatus", 50); pos.add("after", 50); pos.add("missed", 50); li.addHead(oPrintPost(lCmpName, MakeDash(title), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); li.addSubHead(oPrintPost(lClassName, "", boldText, pos.get("place"), 14)); li.addSubHead(oPrintPost(lClassResultFraction, "", boldText, pos.get("name"), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldText, pos.get("status"), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Totalt"), boldText, pos.get("teamstatus"), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldText, pos.get("after"), 14)); ln = li.lp.getLegInfo(sampleClass); li.addListPost(oPrintPost(lTeamPlace, "", normalText, pos.get("place"), 2, ln)); li.addListPost(oPrintPost(lTeamName, "", normalText, pos.get("team"), 2, ln)); li.addListPost(oPrintPost(lRunnerName, "", normalText, pos.get("name"), 2, ln)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", normalText, pos.get("status"), 2, ln)); li.addListPost(oPrintPost(lTeamTimeStatus, "", normalText, pos.get("teamstatus"), 2, ln)); li.addListPost(oPrintPost(lTeamTimeAfter, "", normalText, pos.get("after"), 2, ln)); if (li.lp.splitAnalysis) { li.addListPost(oPrintPost(lRunnerMissedTime, "", normalText, pos.get("missed"), 2, ln)); li.addSubHead(oPrintPost(lString, lang.tl("Bomtid"), boldText, pos.get("missed"), 14)); } li.calcResults=true; li.listType=li.EBaseTypeTeam; li.sortOrder=ClassResult; li.setFilter(EFilterHasResult); break; } case unused_EStdTeamResultListLegLARGE: { char title[256]; if (li.lp.getLegNumberCoded() != 1000) sprintf_s(title, ("%%s - "+lang.tl("sträcka X#" + li.lp.getLegName())).c_str()); else sprintf_s(title, ("%%s - "+lang.tl("slutsträckan")).c_str()); pos.add("place", 25); pos.add("team", min(120, li.getMaxCharWidth(this, par.selection, lTeamName, "", normalText))); pos.add("name", min(120, li.getMaxCharWidth(this, par.selection, lRunnerName, "", normalText))); pos.add("status", 50); pos.add("teamstatus", 50); pos.add("after", 50); pos.add("missed", 50); li.addSubHead(oPrintPost(lClassName, MakeDash(title), boldLarge, pos.get("place", scale), 14)); li.addSubHead(oPrintPost(lClassResultFraction, "", boldLarge, pos.get("name", scale), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldLarge, pos.get("status", scale), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Totalt"), boldLarge, pos.get("teamstatus", scale), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldLarge, pos.get("after", scale), 14)); ln = li.lp.getLegInfo(sampleClass); li.addListPost(oPrintPost(lTeamPlace, "", fontLarge, pos.get("place", scale), 5, ln)); li.addListPost(oPrintPost(lTeamName, "", fontLarge, pos.get("team", scale), 5, ln)); li.addListPost(oPrintPost(lRunnerName, "", fontLarge, pos.get("name", scale), 5, ln)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", fontLarge, pos.get("status", scale), 5, ln)); li.addListPost(oPrintPost(lTeamTimeStatus, "", fontLarge, pos.get("teamstatus", scale), 5, ln)); li.addListPost(oPrintPost(lTeamTimeAfter, "", fontLarge, pos.get("after", scale), 5, ln)); if (li.lp.splitAnalysis) { li.addListPost(oPrintPost(lRunnerMissedTime, "", fontLarge, pos.get("missed", scale), 5, ln)); li.addSubHead(oPrintPost(lString, lang.tl("Bomtid"), boldLarge, pos.get("missed", scale), 14)); } li.calcResults=true; li.listType=li.EBaseTypeTeam; li.sortOrder=ClassResult; li.setFilter(EFilterHasResult); break; } case EStdTeamStartList: { MetaList mList; mList.setListName("Startlista, stafett"); mList.addToHead(lCmpName).setText("Startlista - X");; mList.newHead(); mList.addToHead(lCmpDate); mList.addToSubHead(lClassName); mList.addToSubHead(MetaListPost(lClassStartTime, lNone)); mList.addToSubHead(MetaListPost(lClassLength, lNone)).setText("X meter"); mList.addToSubHead(MetaListPost(lClassStartName, lNone)); mList.addToList(lTeamBib); mList.addToList(lTeamStartCond); mList.addToList(lTeamName); mList.addToSubList(lRunnerLegNumberAlpha).align(lTeamName, false).setText("X."); mList.addToSubList(lRunnerName); mList.addToSubList(lRunnerCard).align(lClassStartName); mList.interpret(this, gdibase, par, lh, li); } li.listType=li.EBaseTypeTeam; li.listSubType=li.EBaseTypeRunner; //li.setFilter(EFilterExcludeDNS); li.setSubFilter(ESubFilterVacant); li.sortOrder = ClassStartTime; break; case ETeamCourseList: li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Bantilldelningslista - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); li.listType=li.EBaseTypeTeam; bib=0; li.addListPost(oPrintPost(lTeamBib, "", normalText, 0+bib, 4)); li.addListPost(oPrintPost(lTeamName, "", normalText, 50+bib, 4)); li.addListPost(oPrintPost(lTeamClub, "", normalText, 300+bib, 4)); li.listSubType=li.EBaseTypeRunner; li.addSubListPost(oPrintPost(lRunnerLegNumberAlpha, "%s.", normalText, 25+bib, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lRunnerName, "", normalText, 50+bib, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lRunnerCard, "", normalText, 300+bib, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lRunnerCourse, "", normalText, 400+bib, 0, make_pair(0, true))); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.addSubHead(oPrintPost(lString, lang.tl("Bricka"), boldText, 300+bib, 10)); li.addSubHead(oPrintPost(lString, lang.tl("Bana"), boldText, 400+bib, 10)); li.sortOrder = ClassStartTime; break; case EIndCourseList: { li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Bantilldelningslista - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); li.listType=li.EBaseTypeRunner; bib=0; li.addListPost(oPrintPost(lRunnerBib, "", normalText, 0+bib, 0)); oPrintPost &rn = li.addListPost(oPrintPost(lRunnerName, "", normalText, 50+bib, 0)); rn.doMergeNext = true; li.addListPost(oPrintPost(lRunnerClub, " (%s)", normalText, 50+bib, 0)); li.addListPost(oPrintPost(lRunnerCard, "", normalText, 300+bib, 0)); li.addListPost(oPrintPost(lRunnerCourse, "", normalText, 400+bib, 0)); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.addSubHead(oPrintPost(lString, lang.tl("Bricka"), boldText, 300+bib, 10)); li.addSubHead(oPrintPost(lString, lang.tl("Bana"), boldText, 400+bib, 10)); li.sortOrder = ClassStartTime; break; } case EStdTeamStartListLeg: { char title[256]; if (li.lp.getLegNumberCoded() == 1000) throw std::exception("Ogiltigt val av sträcka"); sprintf_s(title, lang.tl("Startlista %%s - sträcka X#" + li.lp.getLegName()).c_str()); li.addHead(oPrintPost(lCmpName, MakeDash(title), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); ln=li.lp.getLegInfo(sampleClass); li.listType=li.EBaseTypeTeam; bib=0; if (hasBib(false, true)) { li.addListPost(oPrintPost(lTeamBib, "", normalText, 0, 0)); bib=40; } li.addListPost(oPrintPost(lTeamStart, "", normalText, 0+bib, 0, ln)); li.addListPost(oPrintPost(lTeamName, "", normalText, 70+bib, 0, ln)); li.addListPost(oPrintPost(lTeamRunner, "", normalText, 300+bib, 0, ln)); li.addListPost(oPrintPost(lTeamRunnerCard, "", normalText, 520+bib, 0, ln)); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.addSubHead(oPrintPost(lClassStartName, "", normalText, 300+bib, 10)); li.sortOrder=ClassStartTime; //li.setFilter(EFilterExcludeDNS); break; } case EStdIndMultiStartListLeg: if (li.lp.getLegNumberCoded() == 1000) throw std::exception("Ogiltigt val av sträcka"); //sprintf_s(title, lang.tl("Startlista lopp %d - %%s").c_str(), li.lp.legNumber+1); ln=li.lp.getLegInfo(sampleClass); ttl = MakeDash(lang.tl("Startlista lopp X - Y#" + li.lp.getLegName() + "#%s")); li.addHead(oPrintPost(lCmpName, ttl, boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); li.listType=li.EBaseTypeTeam; bib=0; if (hasBib(false, true)) { li.addListPost(oPrintPost(lTeamBib, "", normalText, 0, 0)); bib=40; } li.addListPost(oPrintPost(lTeamStart, "", normalText, 0+bib, 0, ln)); li.addListPost(oPrintPost(lTeamRunner, "", normalText, 70+bib, 0, ln)); li.addListPost(oPrintPost(lTeamClub, "", normalText, 300+bib, 0, ln)); li.addListPost(oPrintPost(lTeamRunnerCard, "", normalText, 500+bib, 0, ln)); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.addSubHead(oPrintPost(lClassLength, lang.tl("%s meter"), boldText, 300+bib, 10, ln)); li.addSubHead(oPrintPost(lClassStartName, "", boldText, 500+bib, 10, ln)); li.sortOrder=ClassStartTime; li.setFilter(EFilterExcludeDNS); break; case EStdIndMultiResultListLeg: ln=li.lp.getLegInfo(sampleClass); if (li.lp.getLegNumberCoded() != 1000) ttl = lang.tl("Resultat lopp X - Y#" + li.lp.getLegName() + "#%s"); else ttl = lang.tl("Resultat - X#%s"); li.addHead(oPrintPost(lCmpName, MakeDash(ttl), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 14)); li.addSubHead(oPrintPost(lClassResultFraction, "", boldText, 260, 14)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldText, 460, 14)); li.addSubHead(oPrintPost(lString, lang.tl("Totalt"), boldText, 510, 14)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldText, 560, 14)); li.addListPost(oPrintPost(lTeamPlace, "", normalText, 0, 0, ln)); li.addListPost(oPrintPost(lRunnerName, "", normalText, 40, 0, ln)); li.addListPost(oPrintPost(lRunnerClub, "", normalText, 260, 0, ln)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", normalText, 460, 0, ln)); li.addListPost(oPrintPost(lTeamTimeStatus, "", normalText, 510, 0, ln)); li.addListPost(oPrintPost(lTeamTimeAfter, "", normalText, 560, 0, ln)); if (li.lp.splitAnalysis) { li.addListPost(oPrintPost(lRunnerMissedTime, "", normalText, 620, 0, ln)); li.addSubHead(oPrintPost(lString, lang.tl("Bomtid"), boldText, 620, 14)); } li.calcResults=true; li.listType=li.EBaseTypeTeam; li.sortOrder=ClassResult; li.setFilter(EFilterHasResult); break; case EStdIndMultiResultListLegLARGE: if (li.lp.getLegNumberCoded() == 1000) throw std::exception("Ogiltigt val av sträcka"); ln=li.lp.getLegInfo(sampleClass); pos.add("place", 25); pos.add("name", li.getMaxCharWidth(this, par.selection, lRunnerName, "", normalText)); pos.add("club", li.getMaxCharWidth(this, par.selection, lRunnerClub, "", normalText)); pos.add("status", 50); pos.add("teamstatus", 50); pos.add("after", 50); ttl = "%s - " + lang.tl("Lopp ") + li.lp.getLegName(); li.addSubHead(oPrintPost(lClassName, MakeDash(ttl), boldLarge, pos.get("place", scale), 14)); li.addSubHead(oPrintPost(lClassResultFraction, "", boldLarge, pos.get("club", scale), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldLarge, pos.get("status", scale), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Totalt"), boldLarge, pos.get("teamstatus", scale), 14)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldLarge, pos.get("after", scale), 14)); li.addListPost(oPrintPost(lTeamPlace, "", fontLarge, pos.get("place", scale), 0, ln)); li.addListPost(oPrintPost(lRunnerName, "", fontLarge, pos.get("name", scale), 0, ln)); li.addListPost(oPrintPost(lRunnerClub, "", fontLarge, pos.get("club", scale), 0, ln)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", fontLarge, pos.get("status", scale), 0, ln)); li.addListPost(oPrintPost(lTeamTimeStatus, "", fontLarge, pos.get("teamstatus", scale), 0, ln)); li.addListPost(oPrintPost(lTeamTimeAfter, "", fontLarge, pos.get("after", scale), 0, ln)); li.calcResults=true; li.listType=li.EBaseTypeTeam; li.sortOrder=ClassResult; li.setFilter(EFilterHasResult); break; case EStdIndMultiResultListAll: li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Resultat - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 14)); li.addSubHead(oPrintPost(lClassResultFraction, "", boldText, 280, 14)); li.addSubHead(oPrintPost(lClassResultFraction, lang.tl("Tid"), boldText, 480, 14)); li.addSubHead(oPrintPost(lClassResultFraction, lang.tl("Efter"), boldText, 540, 14)); //Use last leg for every team (index=-1) li.addListPost(oPrintPost(lTeamPlace, "", normalText, 0, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lRunnerName, "", normalText, 25, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lRunnerClub, "", normalText, 280, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamTimeStatus, "", normalText, 480, 5, make_pair(-1, true))); li.addListPost(oPrintPost(lTeamTimeAfter, "", normalText, 540, 5, make_pair(-1, true))); li.addSubListPost(oPrintPost(lSubSubCounter, lang.tl("Lopp %s"), normalText, 25, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lRunnerTimeStatus, "", normalText, 90, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lTeamLegTimeStatus, "", normalText, 150, 0, make_pair(0, true))); li.addSubListPost(oPrintPost(lTeamLegTimeAfter, "", normalText, 210, 0, make_pair(0, true))); li.lp.setLegNumberCoded(-1); li.calcResults=true; li.listType=li.EBaseTypeTeam; li.listSubType=li.EBaseTypeRunner; li.sortOrder=ClassResult; li.setFilter(EFilterHasResult); break; case EStdPatrolStartList: { MetaList mList; mList.setListName("Startlista, patrull"); mList.addToHead(lCmpName).setText("Startlista - X").align(false); mList.newHead(); mList.addToHead(lCmpDate).align(false); mList.addToSubHead(lClassName); mList.addToSubHead(lClassStartTime); mList.addToSubHead(lClassLength).setText("X meter"); mList.addToSubHead(lClassStartName); mList.addToList(lTeamBib); mList.addToList(lTeamStartCond).setLeg(0); mList.addToList(lTeamName); mList.newListRow(); mList.addToList(MetaListPost(lTeamRunner, lTeamName, 0)); mList.addToList(MetaListPost(lTeamRunnerCard, lAlignNext, 0)); mList.addToList(MetaListPost(lTeamRunner, lAlignNext, 1)); mList.addToList(MetaListPost(lTeamRunnerCard, lAlignNext, 1)); mList.setListType(li.EBaseTypeTeam); mList.setSortOrder(ClassStartTime); mList.addFilter(EFilterExcludeDNS); /* xmlparser xfoo, xbar; xfoo.openMemoryOutput(true); mList.save(xfoo); string res; xfoo.getMemoryOutput(res); xbar.readMemory(res, 0); MetaList mList2; mList2.load(xbar.getObject("MeOSListDefinition")); */ mList.interpret(this, gdibase, par, lh, li); break; } case EStdPatrolResultList: li.addHead(oPrintPost(lCmpName, MakeDash(lang.tl("Resultatlista - %s")), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); li.addListPost(oPrintPost(lTeamPlace, "", normalText, 0, vspace, make_pair(1, true))); li.addListPost(oPrintPost(lTeamName, "", normalText, 70, vspace)); //li.addListPost(oPrintPost(lTeamClub, "", normalText, 250, vspace)); li.addListPost(oPrintPost(lTeamTimeStatus, "", normalText, 400, vspace, make_pair(1, true))); li.addListPost(oPrintPost(lTeamTimeAfter, "", normalText, 460, vspace, make_pair(1, true))); li.addListPost(oPrintPost(lTeamRunner, "", normalText, 70, lh+vspace, make_pair(0, true))); li.addListPost(oPrintPost(lTeamRunner, "", normalText, 250, lh+vspace, make_pair(1, true))); li.setFilter(EFilterHasResult); li.addSubHead(oPrintPost(lClassName, "", boldText, 0, 10)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldText, 400, 10)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldText, 460, 10)); if (li.lp.showInterTimes) { li.addSubListPost(oPrintPost(lPunchNamedTime, "", normalText, 10, 0, make_pair(1, true))); li.subListPost.back().fixedWidth=160; li.listSubType=li.EBaseTypePunches; } if (li.lp.splitAnalysis) { li.addListPost(oPrintPost(lRunnerMissedTime, "", normalText, 520, vspace, make_pair(1, true))); li.addSubHead(oPrintPost(lString, lang.tl("Bomtid"), boldText, 520, 10)); } li.listType=li.EBaseTypeTeam; li.sortOrder=ClassResult; li.lp.setLegNumberCoded(-1); li.calcResults=true; break; case EStdPatrolResultListLARGE: pos.add("place", 25); pos.add("team", int(0.7*max(li.getMaxCharWidth(this, par.selection, lTeamName, "", normalText), li.getMaxCharWidth(this, par.selection, lPatrolNameNames, "", normalText)))); pos.add("status", 50); pos.add("after", 50); pos.add("missed", 50); li.addListPost(oPrintPost(lTeamPlace, "", fontLarge, pos.get("place", scale), vspace, make_pair(1, true))); li.addListPost(oPrintPost(lTeamName, "", fontLarge, pos.get("team", scale), vspace)); li.addListPost(oPrintPost(lTeamTimeStatus, "", fontLarge, pos.get("status", scale), vspace, make_pair(1, true))); li.addListPost(oPrintPost(lTeamTimeAfter, "", fontLarge, pos.get("after", scale), vspace, make_pair(1, true))); li.addListPost(oPrintPost(lPatrolNameNames, "", fontLarge, pos.get("team", scale), 25+vspace, make_pair(0, true))); //li.addListPost(oPrintPost(lTeamRunner, "", fontLarge, pos.get("status", scale), 25+vspace, 1)); li.addSubHead(oPrintPost(lClassName, "", boldLarge, 0, 10)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldLarge, pos.get("status", scale), 10)); li.addSubHead(oPrintPost(lString, lang.tl("Efter"), boldLarge, pos.get("after", scale), 10)); if (li.lp.showInterTimes) { li.addSubListPost(oPrintPost(lPunchNamedTime, "", normalText, 10, 0, make_pair(1, true))); li.subListPost.back().fixedWidth=200; li.listSubType=li.EBaseTypePunches; } if (li.lp.splitAnalysis) { li.addListPost(oPrintPost(lRunnerMissedTime, "", fontLarge, pos.get("missed", scale), vspace, make_pair(0, true))); li.addSubHead(oPrintPost(lString, lang.tl("Bomtid"), boldLarge, pos.get("missed", scale), 10)); } li.setFilter(EFilterHasResult); li.listType=li.EBaseTypeTeam; li.sortOrder=ClassResult; li.lp.setLegNumberCoded(-1); li.calcResults=true; break; case unused_EStdRaidResultListLARGE: li.addListPost(oPrintPost(lTeamPlace, "", fontLarge, 0, vspace)); li.addListPost(oPrintPost(lTeamName, "", fontLarge, 40, vspace)); li.addListPost(oPrintPost(lTeamTimeStatus, "", fontLarge, 490, vspace)); li.addListPost(oPrintPost(lTeamRunner, "", fontLarge, 40, 25+vspace, make_pair(0, true))); li.addListPost(oPrintPost(lTeamRunner, "", fontLarge, 300, 25+vspace, make_pair(1, true))); li.addSubListPost(oPrintPost(lPunchNamedTime, "", fontMedium, 0, 2, make_pair(1, true))); li.subListPost.back().fixedWidth=200; li.setFilter(EFilterHasResult); li.addSubHead(oPrintPost(lClassName, "", boldLarge, 0, 10)); li.listType=li.EBaseTypeTeam; li.listSubType=li.EBaseTypePunches; li.sortOrder=ClassResult; li.calcResults=true; break; case EStdResultListLARGE: pos.add("place", 25); pos.add("name", li.getMaxCharWidth(this, par.selection, lPatrolNameNames, "", normalText, 0, true)); pos.add("club", li.getMaxCharWidth(this, par.selection, lPatrolClubNameNames, "", normalText, 0, true)); pos.add("status", 50); pos.add("missed", 50); li.addListPost(oPrintPost(lRunnerPlace, "", fontLarge, pos.get("place", scale), vspace)); li.addListPost(oPrintPost(lPatrolNameNames, "", fontLarge, pos.get("name", scale), vspace)); li.addListPost(oPrintPost(lPatrolClubNameNames, "", fontLarge, pos.get("club", scale), vspace)); li.addSubHead(oPrintPost(lClassName, "", boldLarge, pos.get("place", scale), 10)); if (li.lp.useControlIdResultTo<=0 && li.lp.useControlIdResultFrom<=0) { li.addSubHead(oPrintPost(lClassResultFraction, "", boldLarge, pos.get("club", scale), 10)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", fontLarge, pos.get("status", scale), vspace)); } else { li.needPunches = true; li.addListPost(oPrintPost(lRunnerTempTimeStatus, "", normalText, pos.get("status", scale), vspace)); } if (li.lp.splitAnalysis) { li.addSubHead(oPrintPost(lString, "Bomtid", boldLarge, pos.get("missed", scale), 10)); li.addListPost(oPrintPost(lRunnerMissedTime, "", fontLarge, pos.get("missed", scale), vspace)); } if (li.lp.showInterTimes) { li.addSubListPost(oPrintPost(lPunchNamedTime, "", normalText, 0, 0, make_pair(1, true))); li.subListPost.back().fixedWidth = 160; li.listSubType = li.EBaseTypePunches; } else if (li.lp.showSplitTimes) { li.addSubListPost(oPrintPost(lPunchTime, "", normalText, 0, 0, make_pair(1, true))); li.subListPost.back().fixedWidth = 95; li.listSubType = li.EBaseTypePunches; } li.setFilter(EFilterHasResult); li.lp.setLegNumberCoded(0); li.listType=li.EBaseTypeRunner; li.sortOrder=ClassResult; li.calcResults=true; li.supportFrom = true; li.supportTo = true; break; case EStdUM_Master: li.addListPost(oPrintPost(lRunnerPlace, "", fontMedium, 0, 0)); li.addListPost(oPrintPost(lRunnerName, "", fontMedium, 40, 0)); li.addListPost(oPrintPost(lRunnerClub, "", fontMedium, 250, 0)); li.addListPost(oPrintPost(lClassName, "", fontMedium, 490, 0)); li.addListPost(oPrintPost(lRunnerUMMasterPoint, "", fontMedium, 580, 0)); li.setFilter(EFilterHasResult); li.lp.setLegNumberCoded(0); li.listType=li.EBaseTypeRunner; li.sortOrder=ClassResult; li.calcResults=true; break; case ERogainingInd: pos.add("place", 25); pos.add("name", li.getMaxCharWidth(this, par.selection, lRunnerCompleteName, "", normalText, 0, true)); pos.add("points", 50); pos.add("status", 50); li.addHead(oPrintPost(lCmpName, MakeDash(par.getCustomTitle(lang.tl("Rogainingresultat - %s"))), boldLarge, 0,0)); li.addHead(oPrintPost(lCmpDate, "", normalText, 0, 25)); generateNBestHead(par, li, 25+lh); li.addListPost(oPrintPost(lRunnerPlace, "", normalText, pos.get("place"), vspace)); li.addListPost(oPrintPost(lRunnerCompleteName, "", normalText, pos.get("name"), vspace)); li.addListPost(oPrintPost(lRunnerRogainingPoint, "%sp", normalText, pos.get("points"), vspace)); li.addListPost(oPrintPost(lRunnerTimeStatus, "", normalText, pos.get("status"), vspace)); li.setFilter(EFilterHasResult); if (li.lp.splitAnalysis || li.lp.showInterTimes) { li.addSubListPost(oPrintPost(lRogainingPunch, "", normalText, 10, 0, make_pair(1, true))); li.subListPost.back().fixedWidth=130; li.listSubType=li.EBaseTypePunches; } li.addSubHead(oPrintPost(lClassName, "", boldText, pos.get("place"), 10)); li.addSubHead(oPrintPost(lString, lang.tl("Poäng"), boldText, pos.get("points"), 10)); li.addSubHead(oPrintPost(lString, lang.tl("Tid"), boldText, pos.get("status"), 10)); li.listType=li.EBaseTypeRunner; li.sortOrder = ClassPoints; li.lp.setLegNumberCoded(-1); li.calcResults = true; li.rogainingResults = true; break; case EStdTeamAllLegLARGE: { vector< pair > out; fillLegNumbers(par.selection, false, false, out); par.listCode = oe->getListContainer().getType("legresult"); par.useLargeSize = true; for (size_t k = 0; k < out.size(); k++) { if (out[k].second >= 1000) continue; par.setLegNumberCoded(out[k].second); if (k == 0) generateListInfo(par, lineHeight, li); else { li.next.push_back(oListInfo()); generateListInfo(par, lineHeight, li.next.back()); } } } break; case EFixedPreReport: case EFixedReport: case EFixedInForest: case EFixedEconomy: case EFixedInvoices: case EFixedMinuteStartlist: case EFixedTimeLine: case EFixedLiveResult: li.fixedType = true; break; default: if (!getListContainer().interpret(this, gdibase, par, lineHeight, li)) throw std::exception("Not implemented"); } } string oPrintPost::encodeFont(const string &face, int factor) { string out(face); if (factor > 0 && factor != 100) { out += ";" + itos(factor/100) + "." + itos(factor%100); } return out; } void oListInfo::setupLinks(const list &lst) const { for (list::const_iterator it = lst.begin(); it != lst.end(); ++it) { list::const_iterator itNext = it; ++itNext; if (itNext != lst.end() && it->doMergeNext) it->mergeWithTmp = &*itNext; else it->mergeWithTmp = 0; } } void oListInfo::setupLinks() const { setupLinks(Head); setupLinks(subHead); setupLinks(listPost); setupLinks(subListPost); } oListInfo::ResultType oListInfo::getResultType() const { return resType; } bool oListParam::matchLegNumber(const pClass cls, int leg) const { if (cls == 0 || legNumber == -1 || leg < 0) return true; int number, order; cls->splitLegNumberParallel(leg, number, order); if (number == legNumber) return true; int sub = legNumber % 10000; int maj = legNumber / 10000; return maj == number + 1 && sub == order; } int oListParam::getLegNumber(const pClass cls) const { if (legNumber < 0) return legNumber; int sub = legNumber % 10000; int maj = legNumber / 10000; if (cls) { if (legNumber < 10000) return cls->getLegNumberLinear(legNumber, 0); else return cls->getLegNumberLinear(maj-1, sub); } return sub; } pair oListParam::getLegInfo(const pClass cls) const { if (legNumber == -1) return make_pair(-1, true); else if (legNumber < 10000) return make_pair(legNumber, false); int sub = legNumber % 10000; int maj = legNumber / 10000; int lin = cls ? cls->getLegNumberLinear(maj-1, sub) : sub+maj; return make_pair(lin, true); } string oListParam::getLegName() const { if (legNumber == -1) return ""; if (legNumber < 1000) return itos(legNumber + 1); int sub = legNumber % 10000; int maj = legNumber / 10000; char bf[64]; char symb = 'a' + sub; sprintf_s(bf, "%d%c", maj, symb); return bf; }