void UpdateToStartLine() { if ((mIdx == 0) || (mIdx == (size_t) getFinalWaypoint())) { UpdateSymLine(); } else { StartupStore(_T("..Cup Task : LINE Turnpoint is only supported for Start or Finish%s"), NEWLINE); mA1 = 90.0; UpdateToStartSector(); } }
void ReverseTask() { int lower=0; int upper = getFinalWaypoint(); while(lower<upper) { //Swap in pairs starting from the sides of task array std::swap(Task[lower++],Task[upper--]); } ResetTask(false); // Reset the task without showing the message about task reset RefreshTask(); //Recalculate the task DoStatusMessage(gettext(TEXT("_@M1853_"))); // LKTOKEN _@M1853_ "TASK REVERSED" }
void UpdateSymLine() { if (mIdx == 0) { StartLine = 1; StartRadius = mR1; } else if (mIdx == (size_t) getFinalWaypoint()) { FinishLine = 1; FinishRadius = mR1; } else { StartupStore(_T("..Cup Task : LINE Turnpoint is only supported for Start or Finish%s"), NEWLINE); mA1 = 90.0; UpdateSymSector(); } }
void UpdateFixedSector() { if (mIdx == 0) { StartLine = 2; StartRadius = mR1; } else if (mIdx == (size_t) getFinalWaypoint()) { FinishLine = 2; FinishRadius = mR1; } else { Task[mIdx].AATType = SECTOR; Task[mIdx].AATSectorRadius = mR1; Task[mIdx].AATStartRadial = mA12 - 180.0 - (mA1); Task[mIdx].AATFinishRadial = mA12 - 180.0 + (mA1); } }
void UpdateSymSector() { if (mIdx == 0) { UpdateToNextSector(); } else if (mIdx == ((size_t) getFinalWaypoint())) { UpdateToPrevSector(); } else { const WAYPOINT *CurrPt = TaskWayPoint(mIdx); const WAYPOINT *PrevPt = TaskWayPoint(mIdx - 1); const WAYPOINT *NextPt = TaskWayPoint(mIdx + 1); double InB = 0; double OutB = 0; // bearing to prev DistanceBearing(CurrPt->Latitude, CurrPt->Longitude, PrevPt->Latitude, PrevPt->Longitude, NULL, &InB); // bearing to next DistanceBearing(CurrPt->Latitude, CurrPt->Longitude, NextPt->Latitude, NextPt->Longitude, NULL, &OutB); mA12 = BiSector(InB, OutB); UpdateFixedSector(); } }
// // twp is a task index reference, not a waypoint index // CAREFUL> FAIFinishHeight is considering SafetyAltitude if enabled for the wp type. // in Calculations height_above_finish is the difference between first and last task wp, // but they may have different safetyaltitude appliances! This is why it should not be // allowed to enter a landable inside a task until we get rid of this stuff. // double FAIFinishHeight(NMEA_INFO *Basic, DERIVED_INFO *Calculated, int twp) { int FinalWayPoint = getFinalWaypoint(); double safetyaltitudearrival=SAFETYALTITUDEARRIVAL; if (twp== -1) { twp = FinalWayPoint; } double wp_alt; if(ValidTaskPoint(twp)) { wp_alt = WayPointList[Task[twp].Index].Altitude; if (!CheckSafetyAltitudeApplies(Task[twp].Index)) safetyaltitudearrival=0; } else { #if TESTBENCH StartupStore(_T("..... FAIFinishHeight invalid twp=%d%s"),twp,NEWLINE); #endif wp_alt = 0; } if (twp==FinalWayPoint) { if (EnableFAIFinishHeight && !AATEnabled) { // maximum allowed loss of height in order to conform to FAI rules double maxHeightLoss = min(1000.0, (Calculated->TaskDistanceCovered+Calculated->TaskDistanceToGo) * 0.01); return max(max(FinishMinHeight/1000.0, safetyaltitudearrival)+ wp_alt, Calculated->TaskStartAltitude-maxHeightLoss); } else { return max(FinishMinHeight/1000.0, safetyaltitudearrival)+wp_alt; } } else { return wp_alt + safetyaltitudearrival; } }
void TaskStatistics(NMEA_INFO *Basic, DERIVED_INFO *Calculated, const double this_maccready) { if (!ValidTaskPoint(ActiveWayPoint) || ((ActiveWayPoint>0) && !ValidTaskPoint(ActiveWayPoint-1))) { Calculated->LegSpeed = 0; Calculated->LegDistanceToGo = 0; Calculated->LegDistanceCovered = 0; Calculated->LegTimeToGo = 0; if (!AATEnabled) { Calculated->AATTimeToGo = 0; } // Calculated->TaskSpeed = 0; Calculated->TaskDistanceToGo = 0; Calculated->TaskDistanceCovered = 0; Calculated->TaskTimeToGo = 0; Calculated->LKTaskETE = 0; Calculated->TaskTimeToGoTurningNow = -1; Calculated->TaskAltitudeRequired = 0; Calculated->TaskAltitudeDifference = 0; Calculated->TaskAltitudeDifference0 = 0; Calculated->TaskAltitudeArrival = 0; Calculated->TerrainWarningLatitude = 0.0; Calculated->TerrainWarningLongitude = 0.0; Calculated->GRFinish = INVALID_GR; Calculated->FinalGlide = false; CheckGlideThroughTerrain(Basic, Calculated); // BUGFIX 091123 // no task selected, so work things out at current heading GlidePolar::MacCreadyAltitude(this_maccready, 100.0, Basic->TrackBearing, Calculated->WindSpeed, Calculated->WindBearing, &(Calculated->BestCruiseTrack), &(Calculated->VMacCready), (Calculated->FinalGlide==true), NULL, 1.0e6, CRUISE_EFFICIENCY); return; } // LockFlightData(); LockTaskData(); // Calculate Task Distances // First calculate distances for this waypoint double LegCovered, LegToGo=0, LegXTD=0, LegCurrentCourse; double LegDistance, LegBearing=0; bool calc_turning_now; double w1lat; double w1lon; double w0lat; double w0lon; if (AATEnabled && (ActiveWayPoint>0) && (ValidTaskPoint(ActiveWayPoint))) { w1lat = Task[ActiveWayPoint].AATTargetLat; w1lon = Task[ActiveWayPoint].AATTargetLon; } else { w1lat = WayPointList[TASKINDEX].Latitude; w1lon = WayPointList[TASKINDEX].Longitude; } DistanceBearing(Basic->Latitude, Basic->Longitude, w1lat, w1lon, &LegToGo, &LegBearing); if (AATEnabled && (ActiveWayPoint>0) && ValidTaskPoint(ActiveWayPoint+1) && Calculated->IsInSector && (this_maccready>0.1) ) { calc_turning_now = true; } else { calc_turning_now = false; } if (ActiveWayPoint<1) { LegCovered = 0; LegCurrentCourse=LegBearing; if (ValidTaskPoint(ActiveWayPoint+1)) { // BUGFIX 091221 LegToGo=0; } } else { if (AATEnabled) { LKASSERT((ActiveWayPoint-1)>=0); // TODO accuracy: Get best range point to here... w0lat = Task[ActiveWayPoint-1].AATTargetLat; w0lon = Task[ActiveWayPoint-1].AATTargetLon; } else { LKASSERT((ActiveWayPoint-1)>=0); LKASSERT(ValidTaskPoint(ActiveWayPoint-1)); w0lat = WayPointList[Task[ActiveWayPoint-1].Index].Latitude; w0lon = WayPointList[Task[ActiveWayPoint-1].Index].Longitude; } DistanceBearing(w1lat, w1lon, w0lat, w0lon, &LegDistance, NULL); LegCovered = ProjectedDistance(w0lon, w0lat, w1lon, w1lat, Basic->Longitude, Basic->Latitude, &LegXTD, &LegCurrentCourse); if ((StartLine==0) && (ActiveWayPoint==1)) { // Correct speed calculations for radius // JMW TODO accuracy: legcovered replace this with more accurate version // LegDistance -= StartRadius; LegCovered = max(0.0, LegCovered-StartRadius); } } Calculated->LegDistanceToGo = LegToGo; Calculated->LegDistanceCovered = LegCovered; Calculated->LegCrossTrackError = LegXTD; Calculated->LegActualTrueCourse = LegCurrentCourse; Calculated->TaskDistanceCovered = LegCovered; if (Basic->Time > Calculated->LegStartTime) { if (flightstats.LegStartTime[ActiveWayPoint]<0) { flightstats.LegStartTime[ActiveWayPoint] = Basic->Time; } Calculated->LegSpeed = Calculated->LegDistanceCovered / (Basic->Time - Calculated->LegStartTime); } // Now add distances for start to previous waypoint if (!AATEnabled) { for(int i=0;i< ActiveWayPoint-1; i++) { if (!ValidTaskPoint(i) || !ValidTaskPoint(i+1)) continue; w1lat = WayPointList[Task[i].Index].Latitude; w1lon = WayPointList[Task[i].Index].Longitude; w0lat = WayPointList[Task[i+1].Index].Latitude; w0lon = WayPointList[Task[i+1].Index].Longitude; DistanceBearing(w1lat, w1lon, w0lat, w0lon, &LegDistance, NULL); Calculated->TaskDistanceCovered += LegDistance; } } else if (ActiveWayPoint>0) { // JMW added correction for distance covered Calculated->TaskDistanceCovered = aatdistance.DistanceCovered(Basic->Longitude, Basic->Latitude, ActiveWayPoint); } CheckTransitionFinalGlide(Basic, Calculated); // accumulators double TaskAltitudeRequired = 0; double TaskAltitudeRequired0 = 0; Calculated->TaskDistanceToGo = 0; Calculated->TaskTimeToGo = 0; Calculated->LKTaskETE = 0; Calculated->TaskTimeToGoTurningNow = 0; Calculated->TaskAltitudeArrival = 0; double LegTime0; // Calculate Final Glide To Finish int FinalWayPoint = getFinalWaypoint(); double final_height = FAIFinishHeight(Basic, Calculated, -1); double total_energy_height = Calculated->NavAltitude + Calculated->EnergyHeight; double height_above_finish = total_energy_height - final_height; if (ISPARAGLIDER) { TaskAltitudeRequired = final_height; TaskAltitudeRequired0 = final_height; } // Now add it for remaining waypoints int task_index= FinalWayPoint; double StartBestCruiseTrack = -1; while ((task_index>ActiveWayPoint) && (ValidTaskPoint(task_index))) { double this_LegTimeToGo; bool this_is_final = (task_index==FinalWayPoint) || ForceFinalGlide; this_is_final = true; // JMW CHECK FGAMT if (AATEnabled) { w1lat = Task[task_index].AATTargetLat; w1lon = Task[task_index].AATTargetLon; w0lat = Task[task_index-1].AATTargetLat; w0lon = Task[task_index-1].AATTargetLon; } else { w1lat = WayPointList[Task[task_index].Index].Latitude; w1lon = WayPointList[Task[task_index].Index].Longitude; w0lat = WayPointList[Task[task_index-1].Index].Latitude; w0lon = WayPointList[Task[task_index-1].Index].Longitude; } double NextLegDistance, NextLegBearing; DistanceBearing(w0lat, w0lon, w1lat, w1lon, &NextLegDistance, &NextLegBearing); double LegAltitude = GlidePolar:: MacCreadyAltitude(this_maccready, NextLegDistance, NextLegBearing, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, this_is_final, &this_LegTimeToGo, height_above_finish, CRUISE_EFFICIENCY); double LegAltitude0 = GlidePolar:: MacCreadyAltitude(0, NextLegDistance, NextLegBearing, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, true, &LegTime0, 1.0e6, CRUISE_EFFICIENCY ); if (LegTime0>=0.9*ERROR_TIME) { // can't make it, so assume flying at current mc LegAltitude0 = LegAltitude; } TaskAltitudeRequired += LegAltitude; TaskAltitudeRequired0 += LegAltitude0; if(ISPARAGLIDER) { // if required altitude is less than previous turpoint altitude, // use previous turn point altitude double w0Alt = FAIFinishHeight(Basic, Calculated, task_index-1); if(TaskAltitudeRequired < w0Alt) { Calculated->TaskAltitudeArrival += w0Alt - TaskAltitudeRequired; TaskAltitudeRequired = w0Alt; } if(TaskAltitudeRequired0 < w0Alt) { TaskAltitudeRequired0 = w0Alt; } } Calculated->TaskDistanceToGo += NextLegDistance; Calculated->TaskTimeToGo += this_LegTimeToGo; if (task_index==1) { StartBestCruiseTrack = NextLegBearing; } if (calc_turning_now) { if (task_index == ActiveWayPoint+1) { double NextLegDistanceTurningNow, NextLegBearingTurningNow; double this_LegTimeToGo_turningnow=0; DistanceBearing(Basic->Latitude, Basic->Longitude, w1lat, w1lon, &NextLegDistanceTurningNow, &NextLegBearingTurningNow); GlidePolar:: MacCreadyAltitude(this_maccready, NextLegDistanceTurningNow, NextLegBearingTurningNow, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, this_is_final, &this_LegTimeToGo_turningnow, height_above_finish, CRUISE_EFFICIENCY); Calculated->TaskTimeToGoTurningNow += this_LegTimeToGo_turningnow; } else { Calculated->TaskTimeToGoTurningNow += this_LegTimeToGo; } } height_above_finish-= LegAltitude; task_index--; } // current waypoint, do this last! if (AATEnabled && (ActiveWayPoint>0) && ValidTaskPoint(ActiveWayPoint+1) && Calculated->IsInSector) { if (Calculated->WaypointDistance<AATCloseDistance()*3.0) { LegBearing = AATCloseBearing(Basic, Calculated); } } #ifdef BCT_ALT_FIX // Don't calculate BCT yet. LegAltitude will be used to calculate // task altitude difference, which will then be used to calculate BCT. #endif double LegAltitude = GlidePolar::MacCreadyAltitude(this_maccready, LegToGo, LegBearing, Calculated->WindSpeed, Calculated->WindBearing, #ifdef BCT_ALT_FIX 0, #else &(Calculated->BestCruiseTrack), #endif &(Calculated->VMacCready), // (Calculated->FinalGlide==1), true, // JMW CHECK FGAMT &(Calculated->LegTimeToGo), height_above_finish, CRUISE_EFFICIENCY); double LegAltitude0 = GlidePolar::MacCreadyAltitude(0, LegToGo, LegBearing, Calculated->WindSpeed, Calculated->WindBearing, 0, 0, true, &LegTime0, 1.0e6, CRUISE_EFFICIENCY ); #ifndef BCT_ALT_FIX // fix problem of blue arrow wrong in task sector if (StartBestCruiseTrack>=0) // use it only if assigned, workaround if (Calculated->IsInSector && (ActiveWayPoint==0)) { // set best cruise track to first leg bearing when in start sector Calculated->BestCruiseTrack = StartBestCruiseTrack; } #endif // JMW TODO accuracy: Use safetymc where appropriate if (LegTime0>= 0.9*ERROR_TIME) { // can't make it, so assume flying at current mc LegAltitude0 = LegAltitude; } TaskAltitudeRequired += LegAltitude; TaskAltitudeRequired0 += LegAltitude0; Calculated->TaskDistanceToGo += LegToGo; Calculated->TaskTimeToGo += Calculated->LegTimeToGo; #ifndef BCT_ALT_FIX height_above_finish-= LegAltitude; #endif if (calc_turning_now) { Calculated->TaskTimeToGoTurningNow += Basic->Time-Calculated->TaskStartTime; } else { Calculated->TaskTimeToGoTurningNow = -1; } if (ISPARAGLIDER) { Calculated->TaskAltitudeRequired = TaskAltitudeRequired; } else { Calculated->TaskAltitudeRequired = TaskAltitudeRequired + final_height; TaskAltitudeRequired0 += final_height; } Calculated->TaskAltitudeDifference = total_energy_height - Calculated->TaskAltitudeRequired; Calculated->TaskAltitudeDifference0 = total_energy_height - TaskAltitudeRequired0; Calculated->NextAltitudeDifference0 = total_energy_height - Calculated->NextAltitudeRequired0; Calculated->TaskAltitudeArrival += Calculated->TaskAltitudeDifference; Calculated->GRFinish= CalculateGlideRatio(Calculated->TaskDistanceToGo, Calculated->NavAltitude - final_height); if (Calculated->TaskSpeedAchieved >0) Calculated->LKTaskETE = Calculated->TaskDistanceToGo/Calculated->TaskSpeedAchieved; else Calculated->LKTaskETE=0; #ifdef BCT_ALT_FIX // This MCA call's only purpose is to update BestCruiseTrack (BCT). // It must occur after TaskAltitudeDifference (TAD) is updated, // since BCT depends on TAD. GlidePolar::MacCreadyAltitude(this_maccready, LegToGo, LegBearing, Calculated->WindSpeed, Calculated->WindBearing, &(Calculated->BestCruiseTrack), 0, true, 0, height_above_finish, CRUISE_EFFICIENCY, Calculated->TaskAltitudeDifference); // fix problem of blue arrow wrong in task sector if (StartBestCruiseTrack>=0) // use it only if assigned, workaround if (Calculated->IsInSector && (ActiveWayPoint==0)) { // set best cruise track to first leg bearing when in start sector Calculated->BestCruiseTrack = StartBestCruiseTrack; } height_above_finish-= LegAltitude; #endif CheckGlideThroughTerrain(Basic, Calculated); CheckForceFinalGlide(Basic, Calculated); UnlockTaskData(); }
void UpdateTask() { if (mA1 == 180.0) { if (mIdx == 0) { StartLine = 0; StartRadius = mR1; } else if (mIdx == (size_t) getFinalWaypoint()) { FinishLine = 0; FinishRadius = mR1; } else { Task[mIdx].AATType = CIRCLE; Task[mIdx].AATCircleRadius = mR1; } } else { switch (mType) { case 0: // - Fixed value, if (mLine) { StartupStore(_T("..Cup Task : \"Fixed\" LINE Turnpoint is not supported%s"), NEWLINE); UpdateFixedLine(); } else { UpdateFixedSector(); } break; case 1: // - Symmetrical, if (mLine) { StartupStore(_T("..Cup Task : \"Symmetrical\" LINE Turnpoint is not supported%s"), NEWLINE); UpdateSymLine(); } else { UpdateSymSector(); } break; case 2: // - To next point, if (mLine) { if (mIdx > 0) { StartupStore(_T("..Cup Task : \"To next point\" LINE Turnpoint is not supported%s"), NEWLINE); } UpdateToNextLine(); } else { UpdateToNextSector(); } break; case 3: // - To previous point, if (mLine) { if (mIdx < (size_t) getFinalWaypoint()) { StartupStore(_T("..Cup Task : \"To previous point\" LINE Turnpoint is not supported%s"), NEWLINE); } UpdateToPrevLine(); } else { UpdateToPrevSector(); } break; case 4: // - To start point if (mLine) { StartupStore(_T("..Cup Task : \"To start point\" LINE Turnpoint is not supported%s"), NEWLINE); UpdateToStartLine(); } else { UpdateToStartSector(); } break; } } }
bool LoadCupTask(LPCTSTR szFileName) { // LockTaskData(); mapCode2Waypoint_t mapWaypoint; // ClearTask(); size_t idxTP = 0; bool bTakeOff = true; bool bLoadComplet = true; bool bLastInvalid=true; TCHAR szString[READLINE_LENGTH + 1]; TCHAR TpCode[NAME_SIZE + 1]; szString[READLINE_LENGTH] = _T('\0'); TpCode[NAME_SIZE] = _T('\0'); memset(szString, 0, sizeof (szString)); // clear Temp Buffer WAYPOINT newPoint = {0}; WAYPOINT* WPtoAdd=NULL; enum { none, Waypoint, TaskTp, Option } FileSection = none; zzip_stream stream(szFileName, "rt"); iNO_Tasks =0; TaskIndex =0; for (int i =0 ; i< MAX_TASKS;i++) szTaskStrings[ i] = NULL; #define MULTITASKS_CUP #ifdef MULTITASKS_CUP if (stream) { while (stream.read_line(szString)) { if ((FileSection == none) && ((_tcsncmp(_T("name,code,country"), szString, 17) == 0) || (_tcsncmp(_T("Title,Code,Country"), szString, 18) == 0))) { FileSection = Waypoint; continue; } else if ((FileSection == Waypoint) && (_tcscmp(szString, _T("-----Related Tasks-----")) == 0)) { FileSection = TaskTp; continue; } if( FileSection == TaskTp) { if(_tcsstr(szString, _T("\",\""))!= NULL) // really a task? (not an option) { if(iNO_Tasks < MAX_TASKS) // Space in List left {//[READLINE_LENGTH + 1]; szTaskStrings[ iNO_Tasks] = new TCHAR[READLINE_LENGTH + 1]; if( szTaskStrings[ iNO_Tasks] != NULL) { _tcscpy(szTaskStrings[ iNO_Tasks] , szString); // copy task string // StartupStore(_T("..Cup Task : %s %s"), szTaskStrings[ iNO_Tasks], NEWLINE); iNO_Tasks++; } else StartupStore(_T("..Cup Task: no memory %s"), NEWLINE); } else StartupStore(_T("..Cup Task Too many Tasks (more than %i) %s"), MAX_TASKS, NEWLINE); } } } stream.close(); StartupStore(_T("..Cup Selected Task:%i %s %s"), TaskIndex, szTaskStrings[ TaskIndex] , NEWLINE); } int res = 0; if(iNO_Tasks >1) // Selection only if more than one task found res = dlgTaskSelectListShowModal(); for (int i =0 ; i< MAX_TASKS;i++) // free dynamic memory if(szTaskStrings[i] != NULL) { // StartupStore(_T("..Cup Task : delete dynamic memoryLine %i %s"), i,NEWLINE); delete[] szTaskStrings[i]; szTaskStrings[i] = NULL; } if(res == mrCancel) return false; /***********************************************************************************/ LockTaskData(); ClearTask(); stream.open(szFileName, "rt"); #endif FileSection = none; int i=0; if (stream) { while (stream.read_line(szString)) { if ((FileSection == none) && ((_tcsncmp(_T("name,code,country"), szString, 17) == 0) || (_tcsncmp(_T("Title,Code,Country"), szString, 18) == 0))) { FileSection = Waypoint; continue; } else if ((FileSection == Waypoint) && (_tcscmp(szString, _T("-----Related Tasks-----")) == 0)) { FileSection = TaskTp; continue; } TCHAR *pToken = NULL; TCHAR *pWClast = NULL; switch (FileSection) { case Waypoint: memset(&newPoint, 0, sizeof(newPoint)); if (ParseCUPWayPointString(szString, &newPoint)) { mapWaypoint[newPoint.Name] = newPoint; } break; case TaskTp: // 1. Description // First column is the description of the task. If filled it should be double quoted. // If left empty, then SeeYou will determine the task type on runtime. if ((pToken = strsep_r(szString, TEXT(","), &pWClast)) == NULL) { // UnlockTaskData(); // no need to skip if only name missing!!! // return false; } // 2. and all successive columns, separated by commas // Each column represents one waypoint name double quoted. The waypoint name must be exactly the // same as the Long name of a waypoint listed above the Related tasks. WPtoAdd=NULL; if (i++ == TaskIndex) // load selected task { while (bLoadComplet && (pToken = strsep_r(NULL, TEXT(","), &pWClast)) != NULL) { if (idxTP < MAXTASKPOINTS) { _tcsncpy(TpCode, pToken, NAME_SIZE); CleanCupCode(TpCode); mapCode2Waypoint_t::iterator It = mapWaypoint.find(TpCode); if(!ISGAAIRCRAFT) { if (It != mapWaypoint.end()) { if (bTakeOff) { // skip TakeOff Set At Home Waypoint int ix = FindOrAddWaypoint(&(It->second),false); if (ix>=0) { #if 0 // REMOVE // We must not change HomeWaypoint without user knowing! // The takeoff and homewaypoint are independent from task. // In addition, this is a bug because on next run the index is invalid // and we have no more HowWaypoint! HomeWaypoint = ix; #endif bTakeOff = false; } #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } else { int ix = FindOrAddWaypoint(&(It->second),false); if (ix>=0) Task[idxTP++].Index = ix; #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } bLastInvalid=false; } else { // An invalid takeoff, probably a "???" , which we ignore #if TESTBENCH if (bTakeOff) StartupStore(_T("....... CUP Takeoff not found: <%s>\n"),TpCode); #endif // in any case bTakeOff now is false bTakeOff=false; bLastInvalid=true; } } else { //ISGAIRRCRAFT if(It != mapWaypoint.end()) { if(WPtoAdd!=NULL) { //add what we found in previous cycle: it was not the last one int ix = FindOrAddWaypoint(WPtoAdd,false); if (ix>=0) Task[idxTP++].Index = ix; #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } if (bTakeOff) { //it's the first: may be we have a corresponding airfield //look for departure airfield and add it int ix = FindOrAddWaypoint(&(It->second),true); if (ix>=0) { Task[idxTP++].Index = ix; bTakeOff = false; } #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } else WPtoAdd=&(It->second); //store it for next cycle (may be it is the last one) } } } else { bLoadComplet = false; } } if(ISGAAIRCRAFT) { //For GA: check if we have an airport corresponding to the last WP if(WPtoAdd!=NULL) { //if we have the last one (probably an airfield) still to add... if(idxTP<MAXTASKPOINTS) { int ix=FindOrAddWaypoint(WPtoAdd,true); //look for arrival airport and add it if (ix>=0) { Task[idxTP++].Index= ix; } #if BUGSTOP else LKASSERT(0); // .. else is unmanaged, TODO #endif } else bLoadComplet=false; } } FileSection = Option; } break; case Option: if ((pToken = strsep_r(szString, TEXT(","), &pWClast)) != NULL) { if (_tcscmp(pToken, _T("Options")) == 0) { while ((pToken = strsep_r(NULL, TEXT(","), &pWClast)) != NULL) { if (_tcsstr(pToken, _T("NoStart=")) == pToken) { // Opening of start line PGNumberOfGates = 1; StrToTime(pToken + 8, &PGOpenTimeH, &PGOpenTimeM); } else if (_tcsstr(pToken, _T("TaskTime=")) == pToken) { // Designated Time for the task // TODO : } else if (_tcsstr(pToken, _T("WpDis=")) == pToken) { // Task distance calculation. False = use fixes, True = use waypoints // TODO : } else if (_tcsstr(pToken, _T("NearDis=")) == pToken) { // Distance tolerance // TODO : } else if (_tcsstr(pToken, _T("NearAlt=")) == pToken) { // Altitude tolerance // TODO : } else if (_tcsstr(pToken, _T("MinDis=")) == pToken) { // Uncompleted leg. // False = calculate maximum distance from last observation zone. // TODO : } else if (_tcsstr(pToken, _T("RandomOrder=")) == pToken) { // if true, then Random order of waypoints is checked // TODO : } else if (_tcsstr(pToken, _T("MaxPts=")) == pToken) { // Maximum number of points // TODO : } else if (_tcsstr(pToken, _T("BeforePts=")) == pToken) { // Number of mandatory waypoints at the beginning. 1 means start line only, two means // start line plus first point in task sequence (Task line). // TODO : } else if (_tcsstr(pToken, _T("AfterPts=")) == pToken) { // Number of mandatory waypoints at the end. 1 means finish line only, two means finish line // and one point before finish in task sequence (Task line). // TODO : } else if (_tcsstr(pToken, _T("Bonus=")) == pToken) { // Bonus for crossing the finish line // TODO : } } } else if (_tcsstr(pToken, _T("ObsZone=")) == pToken) { TCHAR *sz = NULL; CupObsZoneUpdater TmpZone; TmpZone.mIdx = _tcstol(pToken + 8, &sz, 10); if (TmpZone.mIdx < MAXTASKPOINTS) { while ((pToken = strsep_r(NULL, TEXT(","), &pWClast)) != NULL) { if (_tcsstr(pToken, _T("Style=")) == pToken) { // Direction. 0 - Fixed value, 1 - Symmetrical, 2 - To next point, 3 - To previous point, 4 - To start point TmpZone.mType = _tcstol(pToken + 6, &sz, 10); } else if (_tcsstr(pToken, _T("R1=")) == pToken) { // Radius 1 TmpZone.mR1 = ReadLength(pToken + 3); } else if (_tcsstr(pToken, _T("A1=")) == pToken) { // Angle 1 in degrees TmpZone.mA1 = _tcstod(pToken + 3, &sz); } else if (_tcsstr(pToken, _T("R2=")) == pToken) { // Radius 2 TmpZone.mR2 = ReadLength(pToken + 3); } else if (_tcsstr(pToken, _T("A2=")) == pToken) { // Angle 2 in degrees TmpZone.mA2 = _tcstod(pToken + 3, &sz); } else if (_tcsstr(pToken, _T("A12=")) == pToken) { // Angle 12 TmpZone.mA12 = _tcstod(pToken + 4, &sz); } else if (_tcsstr(pToken, _T("Line=")) == pToken) { // true For Line Turmpoint type // Exist only for start an Goalin LK TmpZone.mLine = (_tcstol(pToken + 5, &sz, 10) == 1); } } TmpZone.UpdateTask(); } } } break; case none: default: break; } memset(szString, 0, sizeof (szString)); // clear Temp Buffer } } if(!ISGAAIRCRAFT) { // Landing don't exist in LK Task Systems, so Remove It; if ( bLoadComplet && !bLastInvalid ) { RemoveTaskPoint(getFinalWaypoint()); } } UnlockTaskData(); for (mapCode2Waypoint_t::iterator It = mapWaypoint.begin(); It != mapWaypoint.end(); ++It) { if (It->second.Comment) { free(It->second.Comment); } if (It->second.Details) { free(It->second.Details); } } mapWaypoint.clear(); return ValidTaskPoint(0); }