/************************************************************************ 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 fro 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 #include #include #include #include #include #include "oEvent.h" #include "oDataContainer.h" #include "meosException.h" #include "TabBase.h" #include "meos.h" #include "meos_util.h" #include "generalresult.h" #include "metalist.h" #include "TabList.h" #include "listeditor.h" void oEvent::calculateSplitResults(int controlIdFrom, int controlIdTo) { oRunnerList::iterator it; for (it=Runners.begin(); it!=Runners.end(); ++it) { int st = 0; if (controlIdFrom > 0) { RunnerStatus stat; it->getSplitTime(controlIdFrom, stat, st); if (stat != StatusOK) { it->tempStatus = stat; it->tempRT = 0; continue; } } if (controlIdTo == 0) { it->tempRT = max(0, it->FinishTime - (st + it->tStartTime) ); if (it->tempRT > 0) it->tempRT += it->getTimeAdjustment(); it->tempStatus = it->tStatus; } else { int ft = 0; it->getSplitTime(controlIdTo, it->tempStatus, ft); if (it->tempStatus==StatusOK && it->tStatus > StatusOK) it->tempStatus=it->tStatus; it->tempRT = max(0, ft - st); } } Runners.sort(oRunner::sortSplit); int cClassId=-1; int cPlace=0; int vPlace=0; int cTime=0; for (it=Runners.begin(); it != Runners.end(); ++it){ if (it->getClassId()!=cClassId){ cClassId=it->getClassId(); cPlace=0; vPlace=0; cTime=0; it->Class->tLegLeaderTime=9999999; } if (it->tempStatus==StatusOK) { cPlace++; if (it->Class) it->Class->tLegLeaderTime=min(it->tempRT, it->Class->tLegLeaderTime); if (it->tempRT>cTime) vPlace=cPlace; cTime=it->tempRT; it->tPlace=vPlace; } else it->tPlace=99000+it->tStatus; } } void oEvent::calculateResults(ResultType resultType) { const bool totalResults = resultType == RTTotalResult; const bool courseResults = resultType == RTCourseResult; const bool classCourseResults = resultType == RTClassCourseResult; if (classCourseResults) sortRunners(ClassCourseResult); else if (courseResults) sortRunners(CourseResult); else if (!totalResults) sortRunners(ClassResult); else sortRunners(ClassTotalResult); oRunnerList::iterator it; int cClassId=-1; int cPlace=0; int vPlace=0; int cTime=0; int cDuplicateLeg=0; int cLegEquClass = 0; bool invalidClass = false; bool useResults = false; for (it=Runners.begin(); it != Runners.end(); ++it) { if (it->isRemoved()) continue; // Start new "class" if (classCourseResults) { const pCourse crs = it->getCourse(false); int crsId = it->getClassId() * 997 + (crs ? crs->getId() : 0); if (crsId != cClassId) { cClassId = crsId; cPlace=0; vPlace=0; cTime=0; useResults = it->Class ? !it->Class->getNoTiming() : false; invalidClass = it->Class ? it->Class->getClassStatus() != oClass::Normal : false; } } else if (courseResults) { const pCourse crs = it->getCourse(false); int crsId = crs ? crs->getId() : 0; if (crsId != cClassId) { cClassId = crsId; useResults = crs != 0; cPlace=0; vPlace=0; cTime=0; } } else if (it->getClassId() != cClassId || it->tDuplicateLeg!=cDuplicateLeg || it->tLegEquClass != cLegEquClass) { cClassId=it->getClassId(); useResults = it->Class ? !it->Class->getNoTiming() : false; cPlace=0; vPlace=0; cTime=0; cDuplicateLeg = it->tDuplicateLeg; cLegEquClass = it->tLegEquClass; invalidClass = it->Class ? it->Class->getClassStatus() != oClass::Normal : false; } // Calculate results if (invalidClass) { it->tTotalPlace = 0; it->tPlace = 0; } else if (!totalResults) { int tPlace = 0; if (it->tStatus==StatusOK){ cPlace++; int rt = it->getRunningTime() + it->getNumShortening() * 3600 * 24* 8; if (rt > cTime) vPlace=cPlace; cTime = rt; if (useResults && cTime > 0) tPlace = vPlace; } else tPlace = 99000 + it->tStatus; if (!classCourseResults) it->tPlace = tPlace; else it->tCoursePlace = tPlace; } else { int tt = it->getTotalRunningTime(it->FinishTime); if (it->getTotalStatus() == StatusOK && tt>0) { cPlace++; if (tt > cTime) vPlace = cPlace; cTime = tt; if (useResults) it->tTotalPlace = vPlace; else it->tTotalPlace = 0; } else it->tTotalPlace = 99000 + it->tStatus; } } } void oEvent::calculateRogainingResults() { sortRunners(ClassPoints); oRunnerList::iterator it; int cClassId=-1; int cPlace = 0; int vPlace = 0; int cTime = numeric_limits::min(); int cDuplicateLeg=0; bool useResults = false; bool isRogaining = false; bool invalidClass = false; for (it=Runners.begin(); it != Runners.end(); ++it) { if (it->isRemoved()) continue; if (it->getClassId()!=cClassId || it->tDuplicateLeg!=cDuplicateLeg) { cClassId = it->getClassId(); useResults = it->Class ? !it->Class->getNoTiming() : false; cPlace = 0; vPlace = 0; cTime = numeric_limits::min(); cDuplicateLeg = it->tDuplicateLeg; isRogaining = it->Class ? it->Class->isRogaining() : false; invalidClass = it->Class ? it->Class->getClassStatus() != oClass::Normal : false; } if (!isRogaining) continue; if (invalidClass) { it->tTotalPlace = 0; it->tPlace = 0; } else if (it->tStatus==StatusOK) { cPlace++; int cmpRes = 3600 * 24 * 7 * it->tRogainingPoints - it->getRunningTime(); if (cmpRes != cTime) vPlace = cPlace; cTime = cmpRes; if (useResults) it->tPlace = vPlace; else it->tPlace = 0; } else it->tPlace = 99000 + it->tStatus; } } bool oEvent::calculateTeamResults(int leg, bool totalMultiday) { oTeamList::iterator it; bool hasRunner; if (totalMultiday) hasRunner = sortTeams(ClassTotalResult, leg, true); else hasRunner = sortTeams(ClassResult, leg, true); if (!hasRunner) return false; int cClassId=0; int cPlace=0; int vPlace=0; int cTime=0; bool invalidClass = false; for (it=Teams.begin(); it != Teams.end(); ++it){ if (it->isRemoved()) continue; if (it->Class && it->Class->Id!=cClassId){ cClassId=it->Class->Id; cPlace=0; vPlace=0; cTime=0; invalidClass = it->Class->getClassStatus() != oClass::Normal; } int sleg; if (leg==-1) sleg=it->Runners.size()-1; else sleg=leg; int p; if (invalidClass) { p = 0; } else if (it->_cachedStatus == StatusOK){ cPlace++; if (it->_sortTime>cTime) vPlace=cPlace; cTime = it->_sortTime; p = vPlace; } else { p = 99000+it->_sortStatus; //XXX Set to zero!? } if (totalMultiday) it->_places[sleg].totalP = p; else it->_places[sleg].p = p; } return true; } void oEvent::calculateTeamResults(bool multidayTotal) { for(int i=0;i0) loadGeneralResults(false); for (size_t k = 0; k < generalResults.size(); k++) { if (tag == generalResults[k].tag) { if (generalResults[k].ptr == 0) throw meosException("Internal error"); sourceFileOut = generalResults[k].fileSource; if (sourceFileOut == "*") sourceFileOut = ""; return *generalResults[k].ptr; } } } throw meosException("Result module not found: " + tag); } void oEvent::loadGeneralResults(bool forceReload) const { // OutputDebugString("Load General Results\n"); char bf[260]; getUserFile(bf, ""); vector res; expandDirectory(bf, "*.rules", res); vector res2; expandDirectory(bf, "*.brules", res2); DynamicResult dr; pair err; vector newGeneralResults; set loaded; set tags; set loadedRes; for (size_t k = 0; k < generalResults.size(); k++) { if (forceReload) { if (!generalResults[k].isDynamic()) newGeneralResults.push_back(generalResults[k]); } else if (generalResults[k].isDynamic()) { loaded.insert(generalResults[k].fileSource); tags.insert(generalResults[k].tag); loadedRes.insert(dynamic_cast(*generalResults[k].ptr).getHashCode()); } } if (forceReload) generalResults.clear(); else swap(generalResults, newGeneralResults); size_t builtIn = res2.size(); for (size_t k = 0; k < res.size(); k++) res2.push_back(res[k]); for (size_t k = 0; k < res2.size(); k++) { try { if (loaded.count(res2[k])) continue; dr.load(res2[k]); while (tags.count(dr.getTag())) { dr.setTag(dr.getTag() + "x"); } tags.insert(dr.getTag()); DynamicResult *drp = new DynamicResult(dr); if (k < builtIn) drp->setBuiltIn(); loadedRes.insert(drp->getHashCode()); newGeneralResults.push_back(GeneralResultCtr(res2[k], drp)); } catch (std::exception &ex) { if (err.first.empty()) { err.first = res2[k]; err.second = ex.what(); } } } vector rmAll; for (int k = 0; k < getListContainer().getNumLists(); k++) { vector rm; //if (!getListContainer().isExternal(k)) // continue; getListContainer().getList(k).getDynamicResults(rm); if (!getListContainer().isExternal(k)) { for (size_t j = 0; j < rm.size(); j++) { if (rm[j].res) rm[j].res->setReadOnly(); } } rmAll.insert(rmAll.end(), rm.begin(), rm.end()); } // Get the open list from list editor TabList &tl = dynamic_cast(*gdibase.getTabs().get(TListTab)); ListEditor *le = tl.getListeditor(); if (le) { MetaList *editorList = le->getCurrentList(); if (editorList) { vector rm; editorList->getDynamicResults(rm); rmAll.insert(rmAll.end(), rm.begin(), rm.end()); } } for (size_t ii = 1; ii <= rmAll.size(); ii++) { size_t i = rmAll.size() - ii; if (!rmAll[i].res) continue; long long hash = rmAll[i].res->getHashCode(); string newTag = rmAll[i].res->getTag(); string db = "Load result " + newTag + ", h=" + itos(hash) + "\n"; // OutputDebugString(db.c_str()); if (loadedRes.count(hash) && tags.count(newTag)) continue; // Already loaded if (tags.count(newTag)) { int n = 1; newTag = DynamicResult::undecorateTag(newTag); while(tags.count(newTag + "-v" + itos(n))) { n++; } newTag += "-v" + itos(n); string db = "Retag " + newTag + "\n"; // OutputDebugString(db.c_str()); rmAll[i].ctr->retagResultModule(newTag, true); } tags.insert(rmAll[i].res->getTag()); DynamicResult *drp = new DynamicResult(*rmAll[i].res); if (rmAll[i].res->isReadOnly()) drp->setReadOnly(); drp->setAnnotation(rmAll[i].ctr->getListName()); string file = "*"; newGeneralResults.push_back(GeneralResultCtr(file, drp)); } swap(newGeneralResults, generalResults); if (!err.first.empty()) throw meosException("Error loading X (Y)#" + err.first + "#" + err.second); } void oEvent::getGeneralResults(bool onlyEditable, vector< pair > > &tagNameList, bool includeDate) const { tagNameList.clear(); for (size_t k = 0; k < generalResults.size(); k++) { if (!onlyEditable || generalResults[k].isDynamic()) { tagNameList.push_back(make_pair(100 + k, make_pair(generalResults[k].tag, lang.tl(generalResults[k].name)))); if (includeDate && generalResults[k].isDynamic()) { const DynamicResult &dr = dynamic_cast(*generalResults[k].ptr); const string &date = dr.getTimeStamp(); if (!date.empty()) tagNameList.back().second.second += " [" + date + "]"; } } } }