/** * @brief Sets a result for points based contests * * @param type The type of the contest * @param traceResult The result data to set */ void CContestMgr::PointsResult(TType type, const CTrace &traceResult) { // prepare result CPointGPSArray pointArray; const CTrace::CPoint *point = traceResult.Front(); unsigned distance = 0; while(point) { if(pointArray.size()) distance += point->GPS().Distance(pointArray.back()); pointArray.push_back(point->GPS()); point = point->Next(); } // store result if(distance > _resultArray[type].Distance()) { float score; switch(type) { case TYPE_OLC_CLASSIC: case TYPE_OLC_CLASSIC_PREDICTED: score = distance / 1000.0 * 100 / _handicap; break; case TYPE_OLC_LEAGUE: score = distance / 1000.0 / 2.5 * 200 / (_handicap + 100); break; default: score = 0; } _resultArray[type] = CResult(type, distance, score, pointArray); } }
/** * @brief Solves FAI triangle based contest * * @param trace The trace to use * @param prevFront Loop front point of previous iteration * @param prevBack Loop back point of previous iteration */ void CContestMgr::SolveTriangle(const CTrace &trace, const CPointGPS *prevFront, const CPointGPS *prevBack) { CResult &result = _resultArray[TYPE_OLC_FAI]; if(trace.Size() > 2) { // check for every trace point const CTrace::CPoint *point1st = trace.Front(); while(point1st) { // check if all edges should be analysed bool skip1 = prevFront && prevBack; if(skip1 && (point1st->GPS() < *prevFront || point1st->GPS() > *prevBack)) skip1 = false; // create a map of points that may form first edge of a better triangle CDistanceMap distanceMap1st; const CTrace::CPoint *next = 0; for(next=point1st->Next(); next; next=next->Next()) { unsigned dist = point1st->GPS().Distance(next->GPS()); // check if 1st edge not too short if(!FAITriangleEdgeCheck(dist, result.Distance())) continue; distanceMap1st.insert(std::make_pair(dist, next)); } // check all possible first edges of the triangle for(CDistanceMap::reverse_iterator it1st=distanceMap1st.rbegin(); it1st!=distanceMap1st.rend(); ++it1st) { bool skip2 = skip1; if(skip2 && (it1st->second->GPS() < *prevFront || it1st->second->GPS() > *prevBack)) skip2 = false; unsigned dist1st = it1st->first; if(!FAITriangleEdgeCheck(dist1st, result.Distance())) // better solution found in the meantime break; // create a map of points that may form second edge of a better triangle CDistanceMap distanceMap2nd; const CTrace::CPoint *point2nd = it1st->second; for(next=point2nd->Next(); next; next=next->Next()) { bool skip3 = skip2; if(skip3 && (next->GPS() < *prevFront || next->GPS() > *prevBack)) skip3 = false; if(skip3) // that triangle was analysed already continue; unsigned dist = point2nd->GPS().Distance(next->GPS()); // check if 2nd edge not too long if(dist * 14 > dist1st * 20) // 45% > 25% continue; // check if 2nd edge not too short if(!FAITriangleEdgeCheck(dist, result.Distance())) continue; distanceMap2nd.insert(std::make_pair(dist, next)); } // check all possible second and third edges of the triangle for(CDistanceMap::reverse_iterator it2nd=distanceMap2nd.rbegin(); it2nd!=distanceMap2nd.rend(); ++it2nd) { unsigned dist2nd = it2nd->first; if(!FAITriangleEdgeCheck(dist2nd, result.Distance())) // better solution found in the meantime break; const CTrace::CPoint *point3rd = it2nd->second; unsigned dist3rd = point3rd->GPS().Distance(point1st->GPS()); unsigned distance = dist1st + dist2nd + dist3rd; if(distance > result.Distance()) { // check if valid FAI triangle if(FAITriangleEdgeCheck(dist1st, dist2nd, dist3rd)) { // store new result float score = distance / 1000.0 * 0.3 * 100 / _handicap; CPointGPSArray pointArray; pointArray.push_back(trace.Front()->GPS()); pointArray.push_back(point1st->GPS()); pointArray.push_back(point2nd->GPS()); pointArray.push_back(point3rd->GPS()); pointArray.push_back(trace.Back()->GPS()); _resultArray[TYPE_OLC_FAI] = CResult(TYPE_OLC_FAI, distance, score, pointArray); } } } } point1st = point1st->Next(); } } }