bool
dlgTaskPointType(OrderedTask &task, const unsigned index)
{
  point_types.clear();
  task.GetFactory().GetValidTypes(index)
    .CopyTo(std::back_inserter(point_types));

  if (point_types.empty()) {
    assert(1);
    return false;
  }

  if (point_types.size() == 1)
    return SetPointType(task, index, point_types[0]);

  const auto &point = task.GetPoint(index);
  const auto current_type = task.GetFactory().GetType(point);

  unsigned initial_index = 0;
  const auto b = point_types.begin(), e = point_types.end();
  auto i = std::find(b, e, current_type);
  if (i != e)
    initial_index = std::distance(b, i);

  MutateTaskPointRenderer item_renderer(current_type);

  int result = ListPicker(_("Task Point Type"),
                          point_types.size(), initial_index,
                          item_renderer.CalculateLayout(UIGlobals::GetDialogLook()),
                          item_renderer, false,
                          nullptr, TPTypeItemHelp);
  return result >= 0 && SetPointType(task, index, point_types[result]);
}
Beispiel #2
0
void
TaskEditPanel::OnMakeFinish()
{
  ordered_task->UpdateStatsGeometry();
  if (ordered_task->GetFactory().CheckAddFinish())
    ordered_task->UpdateGeometry();

  RefreshView();
}
Beispiel #3
0
inline void
TaskPointWidget::OnRemoveClicked()
{
  if (ShowMessageBox(_("Remove task point?"), _("Task point"),
                  MB_YESNO | MB_ICONQUESTION) != IDYES)
    return;

  if (!ordered_task->GetFactory().Remove(active_index))
    return;

  ordered_task->ClearName();
  task_modified = true;
  dialog.SetModalResult(mrCancel);
}
Beispiel #4
0
void TaskEditPanel::ReverseTask()
{
  if (ordered_task->TaskSize() < 2)
    return;

  const unsigned start_index = 0;
  const unsigned finish_index = ordered_task->TaskSize() - 1;
  const Waypoint start_wp = ordered_task->GetTaskPoint(start_index).GetWaypoint();
  const Waypoint finish_wp = ordered_task->GetTaskPoint(finish_index).GetWaypoint();

  if (start_wp.location != finish_wp.location) {
    // swap start/finish TP if at different location but leave OZ type intact
    ordered_task->Relocate(start_index, finish_wp);
    ordered_task->Relocate(finish_index, start_wp);

    // remove optional start points
    while (ordered_task->HasOptionalStarts())
      ordered_task->RemoveOptionalStart(0);
  }

  // reverse intermediate TPs order keeping the OZ type with the respective TP
  unsigned length = ordered_task->TaskSize()-1;
  for (unsigned i = 1; i < length - 1; ++i) {
    const OrderedTaskPoint &otp = ordered_task->GetTaskPoint(length - 1);
    if (!ordered_task->GetFactory().Insert(otp, i, false))
      return;
    if (!ordered_task->GetFactory().Remove(length, false))
      return;
  }

  *task_modified = true;
  ordered_task->ClearName();
  ordered_task->GetFactory().CheckAddFinish();
  ordered_task->UpdateStatsGeometry();
  ordered_task->UpdateGeometry();
  RefreshView();
}
Beispiel #5
0
void
TaskEditPanel::MoveDown()
{
  unsigned index = GetList().GetCursorIndex();
  if (index >= ordered_task->TaskSize())
    return;

  if (!ordered_task->GetFactory().Swap(index, true))
    return;

  GetList().SetCursorIndex(index + 1);
  *task_modified = true;

  RefreshView();
}
Beispiel #6
0
void
TaskEditPanel::MoveUp()
{
  unsigned index = GetList().GetCursorIndex();
  if (index == 0)
    return;

  if (!ordered_task->GetFactory().Swap(index - 1, true))
    return;

  GetList().SetCursorIndex(index - 1);
  *task_modified = true;

  RefreshView();
}
bool
FAITriangleValidator::Validate(const OrderedTask &task)
{
  if (!task.GetFactory().IsUnique())
    return false;

  if (task.TaskSize() != 4)
    return false;

  const fixed d1 = task.GetTaskPoint(1).GetVectorPlanned().distance;
  const fixed d2 = task.GetTaskPoint(2).GetVectorPlanned().distance;
  const fixed d3 = task.GetTaskPoint(3).GetVectorPlanned().distance;

  return TestDistances(d1, d2, d3);
}
Beispiel #8
0
inline void
TaskPointWidget::OnRelocateClicked()
{
  const GeoPoint &gpBearing = active_index > 0
    ? ordered_task->GetPoint(active_index - 1).GetLocation()
    : CommonInterface::Basic().location;

  const Waypoint *wp = ShowWaypointListDialog(gpBearing,
                                         ordered_task, active_index);
  if (wp == nullptr)
    return;

  ordered_task->GetFactory().Relocate(active_index, *wp);
  ordered_task->ClearName();
  task_modified = true;
  RefreshView();
}
Beispiel #9
0
void
TaskEditPanel::EditTaskPoint(unsigned ItemIndex)
{
  if (ItemIndex < ordered_task->TaskSize()) {
    if (dlgTaskPointShowModal(*ordered_task, ItemIndex)) {
      *task_modified = true;
      ordered_task->ClearName();
      ordered_task->UpdateGeometry();
      RefreshView();
    }
  } else if (!ordered_task->IsFull()) {

    OrderedTaskPoint* point = nullptr;
    AbstractTaskFactory &factory = ordered_task->GetFactory();
    const Waypoint* way_point =
      ShowWaypointListDialog(ordered_task->TaskSize() > 0
                             ? ordered_task->GetPoint(ordered_task->TaskSize() - 1).GetLocation()
                             : CommonInterface::Basic().location,
                        ordered_task, ItemIndex);
    if (!way_point)
      return;

    if (ItemIndex == 0) {
      point = (OrderedTaskPoint*)factory.CreateStart(*way_point);
    } else {
      point = (OrderedTaskPoint*)factory.CreateIntermediate(*way_point);
     }
    if (point == nullptr)
      return;

    if (factory.Append(*point, true)) {
      *task_modified = true;
      ordered_task->ClearName();
      ordered_task->UpdateGeometry();
      RefreshView();
    }

    delete point;
  }
}
/**
 * @return true if the task was modified
 */
static bool
SetPointType(OrderedTask &task, unsigned index,
             TaskPointFactoryType type)
{
  AbstractTaskFactory &factory = task.GetFactory();
  const auto &old_point = task.GetPoint(index);
  const auto current_type = factory.GetType(old_point);
  if (type == current_type)
    // no change
    return false;

  bool task_modified = false;

  auto point = factory.CreateMutatedPoint(old_point, type);
  if (point == nullptr)
    return false;

  if (factory.Replace(*point, index, true))
    task_modified = true;
  delete point;

  return task_modified;
}
Beispiel #11
0
OrderedTask*
TaskFileIGC::GetTask(const TaskBehaviour &task_behaviour,
                     const Waypoints *waypoints, unsigned index) const
{
  assert(index == 0);

  IGCDeclarationHeader header;
  std::list<IGCDeclarationTurnpoint> turnpoints;

  if (!ReadIGCDeclaration(path, header, turnpoints))
    return nullptr;

  // Number of turnpoints including start and finish
  unsigned num_turnpoints = header.num_turnpoints + 2;

  if (num_turnpoints + 2 == turnpoints.size()) {
    // Remove takeoff and landing points from the turnpoints list
    turnpoints.pop_front();
    turnpoints.pop_back();
  } else if (num_turnpoints != turnpoints.size())
    // Declared number of turnpoints is not matching parsed number of turnpoints
    return nullptr;

  // Create a blank task
  OrderedTask *task = new OrderedTask(task_behaviour);
  AbstractTaskFactory &fact = task->GetFactory();

  unsigned i = 0;
  for (const auto &it : turnpoints) {
    StaticString<256> waypoint_name;
    if (!it.name.empty()) {
      waypoint_name.clear();
      waypoint_name.UnsafeAppendASCII(it.name);
    } else if (i == 0)
      waypoint_name = _T("Start");
    else if (i == num_turnpoints - 1)
      waypoint_name = _T("Finish");
    else
      waypoint_name.Format(_T("%s #%u"), _T("Turnpoint"), i);

    Waypoint wp(it.location);
    wp.name = waypoint_name.c_str();

    /* we don't know the elevation, so we just set it to zero; this is
       not correct, but better than leaving it uninitialised */
    wp.elevation = fixed(0);

    OrderedTaskPoint *tp;

    if (i == 0)
      tp = fact.CreateStart(wp);
    else if (i == num_turnpoints - 1)
      tp = fact.CreateFinish(wp);
    else
      tp = fact.CreateIntermediate(wp);

    if (tp != nullptr) {
      fact.Append(*tp);
      delete tp;
    }

    ++i;
  }

  return task;
}
Beispiel #12
0
OrderedTask*
TaskFileSeeYou::GetTask(const TaskBehaviour &task_behaviour,
                        const Waypoints *waypoints, unsigned index) const
{
  // Create FileReader for reading the task
  FileLineReader reader(path, IgnoreError(), Charset::AUTO);
  if (reader.error())
    return nullptr;

  // Read waypoints from the CUP file
  Waypoints file_waypoints;
  {
    const WaypointFactory factory(WaypointOrigin::NONE);
    WaypointReaderSeeYou waypoint_file(factory);
    NullOperationEnvironment operation;
    waypoint_file.Parse(file_waypoints, reader, operation);
  }
  file_waypoints.Optimise();

  if (!reader.Rewind())
    return nullptr;

  TCHAR *line = AdvanceReaderToTask(reader, index);
  if (line == nullptr)
    return nullptr;

  // Read waypoint list
  // e.g. "Club day 4 Racing task","085PRI","083BOJ","170D_K","065SKY","0844YY", "0844YY"
  //       TASK NAME              , TAKEOFF, START  , TP1    , TP2    , FINISH ,  LANDING
  TCHAR waypoints_buffer[1024];
  const TCHAR *wps[30];
  size_t n_waypoints = ExtractParameters(line, waypoints_buffer, wps, 30,
                                         true, _T('"'));

  // Some versions of StrePla append a trailing ',' without a following
  // WP name resulting an empty last entry. Remove it from the results
  if (n_waypoints > 0 && wps[n_waypoints - 1][0] == _T('\0'))
    n_waypoints --;

  // At least taskname and takeoff, start, finish and landing points are needed
  if (n_waypoints < 5)
    return nullptr;

  // Remove taskname, start point and landing point from count
  n_waypoints -= 3;

  SeeYouTaskInformation task_info;
  SeeYouTurnpointInformation turnpoint_infos[30];
  WaypointPtr waypoints_in_task[30];

  ParseCUTaskDetails(reader, &task_info, turnpoint_infos);

  OrderedTask *task = new OrderedTask(task_behaviour);
  task->SetFactory(task_info.wp_dis ?
                    TaskFactoryType::RACING : TaskFactoryType::AAT);
  AbstractTaskFactory& fact = task->GetFactory();
  const TaskFactoryType factType = task->GetFactoryType();

  OrderedTaskSettings beh = task->GetOrderedTaskSettings();
  if (factType == TaskFactoryType::AAT) {
    beh.aat_min_time = task_info.task_time;
  }
  if (factType == TaskFactoryType::AAT ||
      factType == TaskFactoryType::RACING) {
    beh.start_constraints.max_height = (unsigned)task_info.max_start_altitude;
    beh.start_constraints.max_height_ref = AltitudeReference::MSL;
  }
  task->SetOrderedTaskSettings(beh);

  // mark task waypoints.  Skip takeoff and landing point
  for (unsigned i = 0; i < n_waypoints; i++) {
    auto file_wp = file_waypoints.LookupName(wps[i + 2]);
    if (file_wp == nullptr)
      return nullptr;

    // Try to find waypoint by name
    auto wp = waypoints->LookupName(file_wp->name);

    // If waypoint by name found and closer than 10m to the original
    if (wp != nullptr &&
        wp->location.DistanceS(file_wp->location) <= fixed(10)) {
      // Use this waypoint for the task
      waypoints_in_task[i] = wp;
      continue;
    }

    // Try finding the closest waypoint to the original one
    wp = waypoints->GetNearest(file_wp->location, fixed(10));

    // If closest waypoint found and closer than 10m to the original
    if (wp != nullptr &&
        wp->location.DistanceS(file_wp->location) <= fixed(10)) {
      // Use this waypoint for the task
      waypoints_in_task[i] = wp;
      continue;
    }

    // Use the original waypoint
    waypoints_in_task[i] = file_wp;
  }

  //now create TPs and OZs
  for (unsigned i = 0; i < n_waypoints; i++) {

    ObservationZonePoint* oz = CreateOZ(turnpoint_infos[i], i, n_waypoints,
                                        waypoints_in_task, factType);
    assert(waypoints_in_task[i]);
    OrderedTaskPoint *pt = CreatePoint(i, n_waypoints,
                                       WaypointPtr(waypoints_in_task[i]),
                                       fact, oz, factType);

    if (pt != nullptr)
      fact.Append(*pt, false);

    delete pt;
  }
  return task;
}
Beispiel #13
0
void
TaskPointWidget::RefreshView()
{
  map.Invalidate();

  OrderedTaskPoint &tp = ordered_task->GetPoint(active_index);

  properties_dock.SetWidget(new PanelWidget());

  ObservationZonePoint &oz = tp.GetObservationZone();
  const bool is_fai_general =
    ordered_task->GetFactoryType() == TaskFactoryType::FAI_GENERAL;
  properties_widget = CreateObservationZoneEditWidget(oz, is_fai_general);
  if (properties_widget != nullptr) {
    properties_widget->SetListener(this);
    properties_dock.SetWidget(properties_widget);
  }

  type_label.SetCaption(OrderedTaskPointName(ordered_task->GetFactory().GetType(tp)));

  previous_button->SetEnabled(active_index > 0);
  next_button->SetEnabled(active_index < (ordered_task->TaskSize() - 1));

  optional_starts.SetVisible(active_index == 0);
  if (!ordered_task->HasOptionalStarts())
    optional_starts.SetCaption(_("Enable Alternate Starts"));
  else {
    StaticString<50> tmp;
    tmp.Format(_T("%s (%d)"), _("Edit Alternates"),
               ordered_task->GetOptionalStartPointCount());
    optional_starts.SetCaption(tmp);
  }

  if (tp.GetType() == TaskPointType::AST) {
    const ASTPoint &ast = (const ASTPoint &)tp;
    score_exit.Show();
    score_exit.SetState(ast.GetScoreExit());
  } else
    score_exit.Hide();

  StaticString<100> name_prefix_buffer, type_buffer;

  switch (tp.GetType()) {
  case TaskPointType::START:
    type_buffer = _("Start point");
    name_prefix_buffer = _T("Start: ");
    break;

  case TaskPointType::AST:
    type_buffer = _("Task point");
    name_prefix_buffer.Format(_T("%d: "), active_index);
    break;

  case TaskPointType::AAT:
    type_buffer = _("Assigned area point");
    name_prefix_buffer.Format(_T("%d: "), active_index);
    break;

  case TaskPointType::FINISH:
    type_buffer = _("Finish point");
    name_prefix_buffer = _T("Finish: ");
    break;

  default:
    gcc_unreachable();
  }

  dialog.SetCaption(type_buffer);

  {
    StaticString<100> buffer;
    buffer.Format(_T("%s %s"), name_prefix_buffer.c_str(),
                  tp.GetWaypoint().name.c_str());
    waypoint_name.SetCaption(buffer);
  }
}
Beispiel #14
0
OrderedTask*
TaskFileIGC::GetTask(const TaskBehaviour &task_behaviour,
                     const Waypoints *waypoints, unsigned index) const
{
  assert(index == 0);

  IGCDeclarationHeader header;
  std::list<IGCDeclarationTurnpoint> turnpoints;

  if (!ReadIGCDeclaration(path, header, turnpoints))
    return NULL;

  // Number of turnpoints including start and finish
  unsigned num_turnpoints = header.num_turnpoints + 2;

  if (num_turnpoints + 2 == turnpoints.size()) {
    // Remove takeoff and landing points from the turnpoints list
    turnpoints.pop_front();
    turnpoints.pop_back();
  } else if (num_turnpoints != turnpoints.size())
    // Declared number of turnpoints is not matching parsed number of turnpoints
    return NULL;

  // Create a blank task
  OrderedTask *task = new OrderedTask(task_behaviour);
  AbstractTaskFactory &fact = task->GetFactory();

  unsigned i = 0;
  for (auto it = turnpoints.begin(), it_end = turnpoints.end();
       it != it_end; ++it) {
    StaticString<256> waypoint_name;
    if (!it->name.empty()) {
      waypoint_name.clear();
      waypoint_name.UnsafeAppendASCII(it->name);
    } else if (i == 0)
      waypoint_name = _T("Start");
    else if (i == num_turnpoints - 1)
      waypoint_name = _T("Finish");
    else
      waypoint_name.Format(_T("%s #%u"), _T("Turnpoint"), i);

    Waypoint wp(it->location);
    wp.name = waypoint_name.c_str();


    OrderedTaskPoint *tp;

    if (i == 0)
      tp = fact.CreateStart(wp);
    else if (i == num_turnpoints - 1)
      tp = fact.CreateFinish(wp);
    else
      tp = fact.CreateIntermediate(wp);

    if (tp != NULL) {
      fact.Append(*tp);
      delete tp;
    }

    ++i;
  }

  return task;
}
Beispiel #15
0
OrderedTask*
TaskFileSeeYou::GetTask(const TaskBehaviour &task_behaviour,
                        const Waypoints *waypoints, unsigned index) const
{
  // Create FileReader for reading the task
  FileLineReader reader(path, ConvertLineReader::AUTO);
  if (reader.error())
    return NULL;

  // Read waypoints from the CUP file
  Waypoints file_waypoints;
  {
    WaypointReaderSeeYou waypoint_file(0);
    NullOperationEnvironment operation;
    waypoint_file.Parse(file_waypoints, reader, operation);
  }
  file_waypoints.Optimise();

  if (!reader.Rewind())
    return NULL;

  TCHAR *line = AdvanceReaderToTask(reader, index);
  if (line == NULL)
    return NULL;

  // Read waypoint list
  // e.g. "Club day 4 Racing task","085PRI","083BOJ","170D_K","065SKY","0844YY", "0844YY"
  //       TASK NAME              , TAKEOFF, START  , TP1    , TP2    , FINISH ,  LANDING
  TCHAR waypoints_buffer[1024];
  const TCHAR *wps[30];
  size_t n_waypoints = WaypointReaderBase::
      ExtractParameters(line, waypoints_buffer, wps, 30, true, _T('"')) - 3;

  SeeYouTaskInformation task_info;
  SeeYouTurnpointInformation turnpoint_infos[30];
  const Waypoint *waypoints_in_task[30];

  ParseCUTaskDetails(reader, &task_info, turnpoint_infos);

  OrderedTask *task = new OrderedTask(task_behaviour);
  task->SetFactory(task_info.wp_dis ?
                    TaskFactoryType::RACING : TaskFactoryType::AAT);
  AbstractTaskFactory& fact = task->GetFactory();
  const TaskFactoryType factType = task->GetFactoryType();

  OrderedTaskSettings beh = task->GetOrderedTaskSettings();
  if (factType == TaskFactoryType::AAT) {
    beh.aat_min_time = task_info.task_time;
  }
  if (factType == TaskFactoryType::AAT ||
      factType == TaskFactoryType::RACING) {
    beh.start_constraints.max_height = (unsigned)task_info.max_start_altitude;
    beh.start_constraints.max_height_ref = AltitudeReference::MSL;
  }
  task->SetOrderedTaskSettings(beh);

  // mark task waypoints.  Skip takeoff and landing point
  for (unsigned i = 0; i < n_waypoints; i++) {
    const Waypoint* file_wp = file_waypoints.LookupName(wps[i + 2]);
    if (file_wp == NULL)
      return NULL;

    // Try to find waypoint by name
    const Waypoint* wp = waypoints->LookupName(file_wp->name);

    // If waypoint by name found and closer than 10m to the original
    if (wp != NULL &&
        wp->location.Distance(file_wp->location) <= fixed(10)) {
      // Use this waypoint for the task
      waypoints_in_task[i] = wp;
      continue;
    }

    // Try finding the closest waypoint to the original one
    wp = waypoints->GetNearest(file_wp->location, fixed(10));

    // If closest waypoint found and closer than 10m to the original
    if (wp != NULL &&
        wp->location.Distance(file_wp->location) <= fixed(10)) {
      // Use this waypoint for the task
      waypoints_in_task[i] = wp;
      continue;
    }

    // Use the original waypoint
    waypoints_in_task[i] = file_wp;
  }

  //now create TPs and OZs
  for (unsigned i = 0; i < n_waypoints; i++) {

    ObservationZonePoint* oz = CreateOZ(turnpoint_infos[i], i, n_waypoints,
                                        waypoints_in_task, factType);
    assert(waypoints_in_task[i]);
    OrderedTaskPoint *pt = CreatePoint(i, n_waypoints, waypoints_in_task[i],
                                       fact, oz, factType);

    if (pt != NULL)
      fact.Append(*pt, false);

    delete pt;
  }
  return task;
}
Beispiel #16
0
 /**
  * Accessor for factory system for constructing tasks
  *
  * @return Factory
  */
 gcc_pure
 AbstractTaskFactory& GetFactory() const {
     return task_ordered.GetFactory();
 }
Beispiel #17
0
void
Deserialiser::DeserialiseTaskpoint(OrderedTask &data)
{
  const TCHAR *type = node.GetAttribute(_T("type"));
  if (type == nullptr)
    return;

  std::unique_ptr<DataNode> wp_node(node.GetChildNamed(_T("Waypoint")));
  if (!wp_node)
    return;

  Deserialiser wser(*wp_node, waypoints);
  std::unique_ptr<Waypoint> wp(wser.DeserialiseWaypoint());
  if (!wp)
    return;

  std::unique_ptr<DataNode> oz_node(node.GetChildNamed(_T("ObservationZone")));

  AbstractTaskFactory &fact = data.GetFactory();

  ObservationZonePoint* oz = nullptr;
  std::unique_ptr<OrderedTaskPoint> pt;

  if (oz_node) {
    bool is_turnpoint = StringIsEqual(type, _T("Turn")) ||
      StringIsEqual(type, _T("Area"));

    Deserialiser oser(*oz_node, waypoints);
    oz = oser.DeserialiseOZ(*wp, is_turnpoint);
  }

  if (StringIsEqual(type, _T("Start"))) {
    pt.reset(oz != nullptr
             ? fact.CreateStart(oz, *wp)
             : fact.CreateStart(*wp));

  } else if (StringIsEqual(type, _T("OptionalStart"))) {
    pt.reset(oz != nullptr
             ? fact.CreateStart(oz, *wp)
             : fact.CreateStart(*wp));
    fact.AppendOptionalStart(*pt);

    // don't let generic code below add it
    pt.reset();

  } else if (StringIsEqual(type, _T("Turn"))) {
    pt.reset(oz != nullptr
             ? fact.CreateASTPoint(oz, *wp)
             : fact.CreateIntermediate(*wp));

  } else if (StringIsEqual(type, _T("Area"))) {
    pt.reset(oz != nullptr
             ? fact.CreateAATPoint(oz, *wp)
             : fact.CreateIntermediate(*wp));

  } else if (StringIsEqual(type, _T("Finish"))) {
    pt.reset(oz != nullptr
             ? fact.CreateFinish(oz, *wp)
             : fact.CreateFinish(*wp));
  } 

  if (!pt)
    return;

  if (pt->GetType() == TaskPointType::AST) {
    ASTPoint &ast = (ASTPoint &)*pt;
    bool score_exit = false;
    if (node.GetAttribute(_T("score_exit"), score_exit))
      ast.SetScoreExit(score_exit);
  }

  fact.Append(*pt, false);
}
Beispiel #18
0
void
TaskEditPanel::OnMakeFinish()
{
  ordered_task->GetFactory().CheckAddFinish();
  RefreshView();
}