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]); }
void TaskEditPanel::OnMakeFinish() { ordered_task->UpdateStatsGeometry(); if (ordered_task->GetFactory().CheckAddFinish()) ordered_task->UpdateGeometry(); RefreshView(); }
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); }
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(); }
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(); }
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); }
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(); }
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; }
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; }
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; }
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); } }
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; }
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; }
/** * Accessor for factory system for constructing tasks * * @return Factory */ gcc_pure AbstractTaskFactory& GetFactory() const { return task_ordered.GetFactory(); }
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); }
void TaskEditPanel::OnMakeFinish() { ordered_task->GetFactory().CheckAddFinish(); RefreshView(); }