示例#1
0
 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();
     }
 }
示例#2
0
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"
}
示例#3
0
 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();
     }
 }
示例#4
0
 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);
     }
 }
示例#5
0
    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();
        }
    }
示例#6
0
//
// 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;
  }
}
示例#7
0
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();

}
示例#8
0
    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;
            }
        }
    }
示例#9
0
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);
}