TaskManager: allocate the task objects dynamically
[xcsoar.git] / src / Task / Deserialiser.cpp
blob9d23c1d9758feb29debf7e30cc10f4f8a805ebff
1 /* Copyright_License {
3 XCSoar Glide Computer - http://www.xcsoar.org/
4 Copyright (C) 2000-2013 The XCSoar Project
5 A detailed list of copyright holders can be found in the file "AUTHORS".
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "Deserialiser.hpp"
24 #include "Task/Ordered/OrderedTaskBehaviour.hpp"
25 #include "Task/Ordered/OrderedTask.hpp"
26 #include "Task/Ordered/Points/StartPoint.hpp"
27 #include "Task/Ordered/Points/FinishPoint.hpp"
28 #include "Task/Ordered/Points/AATPoint.hpp"
29 #include "Task/Ordered/Points/ASTPoint.hpp"
30 #include "Task/ObservationZones/LineSectorZone.hpp"
31 #include "Task/ObservationZones/FAISectorZone.hpp"
32 #include "Task/ObservationZones/KeyholeZone.hpp"
33 #include "Task/ObservationZones/BGAFixedCourseZone.hpp"
34 #include "Task/ObservationZones/BGAEnhancedOptionZone.hpp"
35 #include "Task/ObservationZones/BGAStartSectorZone.hpp"
36 #include "Task/ObservationZones/AnnularSectorZone.hpp"
37 #include "Task/ObservationZones/MatCylinderZone.hpp"
38 #include "Task/Factory/AbstractTaskFactory.hpp"
39 #include "XML/DataNode.hpp"
40 #include "Engine/Waypoint/Waypoints.hpp"
42 #include <assert.h>
43 #include <memory>
45 void
46 Deserialiser::DeserialiseTaskpoint(OrderedTask &data)
48 const TCHAR *type = node.GetAttribute(_T("type"));
49 if (type == nullptr)
50 return;
52 std::unique_ptr<DataNode> wp_node(node.GetChildNamed(_T("Waypoint")));
53 if (!wp_node)
54 return;
56 Deserialiser wser(*wp_node, waypoints);
57 std::unique_ptr<Waypoint> wp(wser.DeserialiseWaypoint());
58 if (!wp)
59 return;
61 std::unique_ptr<DataNode> oz_node(node.GetChildNamed(_T("ObservationZone")));
63 AbstractTaskFactory &fact = data.GetFactory();
65 ObservationZonePoint* oz = nullptr;
66 std::unique_ptr<OrderedTaskPoint> pt;
68 if (oz_node) {
69 bool is_turnpoint = StringIsEqual(type, _T("Turn")) ||
70 StringIsEqual(type, _T("Area"));
72 Deserialiser oser(*oz_node, waypoints);
73 oz = oser.DeserialiseOZ(*wp, is_turnpoint);
76 if (StringIsEqual(type, _T("Start"))) {
77 pt.reset(oz != nullptr
78 ? fact.CreateStart(oz, *wp)
79 : fact.CreateStart(*wp));
81 } else if (StringIsEqual(type, _T("OptionalStart"))) {
82 pt.reset(oz != nullptr
83 ? fact.CreateStart(oz, *wp)
84 : fact.CreateStart(*wp));
85 fact.AppendOptionalStart(*pt);
87 // don't let generic code below add it
88 pt.reset();
90 } else if (StringIsEqual(type, _T("Turn"))) {
91 pt.reset(oz != nullptr
92 ? fact.CreateASTPoint(oz, *wp)
93 : fact.CreateIntermediate(*wp));
95 } else if (StringIsEqual(type, _T("Area"))) {
96 pt.reset(oz != nullptr
97 ? fact.CreateAATPoint(oz, *wp)
98 : fact.CreateIntermediate(*wp));
100 } else if (StringIsEqual(type, _T("Finish"))) {
101 pt.reset(oz != nullptr
102 ? fact.CreateFinish(oz, *wp)
103 : fact.CreateFinish(*wp));
106 if (pt)
107 fact.Append(*pt, false);
110 ObservationZonePoint*
111 Deserialiser::DeserialiseOZ(const Waypoint &wp, bool is_turnpoint)
113 const TCHAR *type = node.GetAttribute(_T("type"));
114 if (type == nullptr)
115 return nullptr;
117 if (StringIsEqual(type, _T("Line"))) {
118 LineSectorZone *ls = new LineSectorZone(wp.location);
120 fixed length;
121 if (node.GetAttribute(_T("length"), length) && positive(length))
122 ls->SetLength(length);
124 return ls;
125 } else if (StringIsEqual(type, _T("Cylinder"))) {
126 CylinderZone *ls = new CylinderZone(wp.location);
128 fixed radius;
129 if (node.GetAttribute(_T("radius"), radius) && positive(radius))
130 ls->SetRadius(radius);
132 return ls;
133 } else if (StringIsEqual(type, _T("MatCylinder"))) {
134 MatCylinderZone *ls = new MatCylinderZone(wp.location);
136 return ls;
137 } else if (StringIsEqual(type, _T("Sector"))) {
139 fixed radius, inner_radius;
140 Angle start, end;
141 SectorZone *ls;
143 if (node.GetAttribute(_T("inner_radius"), inner_radius)) {
144 AnnularSectorZone *als = new AnnularSectorZone(wp.location);
145 als->SetInnerRadius(inner_radius);
146 ls = als;
147 } else
148 ls = new SectorZone(wp.location);
150 if (node.GetAttribute(_T("radius"), radius) && positive(radius))
151 ls->SetRadius(radius);
152 if (node.GetAttribute(_T("start_radial"), start))
153 ls->SetStartRadial(start);
154 if (node.GetAttribute(_T("end_radial"), end))
155 ls->SetEndRadial(end);
157 return ls;
158 } else if (StringIsEqual(type, _T("FAISector")))
159 return new FAISectorZone(wp.location, is_turnpoint);
160 else if (StringIsEqual(type, _T("Keyhole")))
161 return new KeyholeZone(wp.location);
162 else if (StringIsEqual(type, _T("BGAStartSector")))
163 return new BGAStartSectorZone(wp.location);
164 else if (StringIsEqual(type, _T("BGAFixedCourse")))
165 return new BGAFixedCourseZone(wp.location);
166 else if (StringIsEqual(type, _T("BGAEnhancedOption")))
167 return new BGAEnhancedOptionZone(wp.location);
169 assert(1);
170 return nullptr;
173 void
174 Deserialiser::Deserialise(GeoPoint &data)
176 node.GetAttribute(_T("longitude"), data.longitude);
177 node.GetAttribute(_T("latitude"), data.latitude);
180 Waypoint*
181 Deserialiser::DeserialiseWaypoint()
183 std::unique_ptr<DataNode> loc_node(node.GetChildNamed(_T("Location")));
184 if (!loc_node)
185 return nullptr;
187 GeoPoint loc;
188 Deserialiser lser(*loc_node, waypoints);
189 lser.Deserialise(loc);
191 const TCHAR *name = node.GetAttribute(_T("name"));
192 if (name == nullptr)
193 // Turnpoints need names
194 return nullptr;
196 if (waypoints != nullptr) {
197 // Try to find waypoint by name
198 const Waypoint *from_database = waypoints->LookupName(name);
200 // If waypoint by name found and closer than 10m to the original
201 if (from_database != nullptr &&
202 from_database->location.Distance(loc) <= fixed(10))
203 // Use this waypoint for the task
204 return new Waypoint(*from_database);
206 // Try finding the closest waypoint to the original one
207 from_database = waypoints->GetNearest(loc, fixed(10));
209 // If closest waypoint found and closer than 10m to the original
210 if (from_database != nullptr &&
211 from_database->location.Distance(loc) <= fixed(10))
212 // Use this waypoint for the task
213 return new Waypoint(*from_database);
216 // Create a new waypoint from the original one
217 Waypoint *wp = new Waypoint(loc);
218 wp->name = name;
220 node.GetAttribute(_T("id"), wp->id);
222 const TCHAR *comment = node.GetAttribute(_T("comment"));
223 if (comment != nullptr)
224 wp->comment.assign(comment);
226 node.GetAttribute(_T("altitude"), wp->elevation);
228 return wp;
231 void
232 Deserialiser::Deserialise(OrderedTaskBehaviour &data)
234 node.GetAttribute(_T("aat_min_time"), data.aat_min_time);
235 node.GetAttribute(_T("start_max_speed"), data.start_constraints.max_speed);
236 node.GetAttribute(_T("start_max_height"), data.start_constraints.max_height);
237 data.start_constraints.max_height_ref =
238 GetHeightRef(_T("start_max_height_ref"));
239 data.start_constraints.open_time_span =
240 node.GetAttributeRoughTimeSpan(_T("start_open_time"),
241 _T("start_close_time"));
242 node.GetAttribute(_T("finish_min_height"),
243 data.finish_constraints.min_height);
244 data.finish_constraints.min_height_ref =
245 GetHeightRef(_T("finish_min_height_ref"));
246 node.GetAttribute(_T("fai_finish"), data.finish_constraints.fai_finish);
247 data.start_constraints.fai_finish = data.finish_constraints.fai_finish;
250 void
251 Deserialiser::Deserialise(OrderedTask &task)
253 task.Clear();
254 task.SetFactory(GetTaskFactoryType());
255 task.Reset();
257 OrderedTaskBehaviour beh = task.GetOrderedTaskBehaviour();
258 Deserialise(beh);
259 task.SetOrderedTaskBehaviour(beh);
261 const DataNode::List children = node.ListChildrenNamed(_T("Point"));
262 for (const auto &i : children) {
263 std::unique_ptr<DataNode> point_node(i);
264 Deserialiser pser(*point_node, waypoints);
265 pser.DeserialiseTaskpoint(task);
269 AltitudeReference
270 Deserialiser::GetHeightRef(const TCHAR *nodename) const
272 const TCHAR *type = node.GetAttribute(nodename);
273 if (type != nullptr && StringIsEqual(type, _T("MSL")))
274 return AltitudeReference::MSL;
276 return AltitudeReference::AGL;
279 TaskFactoryType
280 Deserialiser::GetTaskFactoryType() const
282 const TCHAR *type = node.GetAttribute(_T("type"));
283 if (type == nullptr)
284 return TaskFactoryType::FAI_GENERAL;
286 if (StringIsEqual(type, _T("FAIGeneral")))
287 return TaskFactoryType::FAI_GENERAL;
288 else if (StringIsEqual(type, _T("FAITriangle")))
289 return TaskFactoryType::FAI_TRIANGLE;
290 else if (StringIsEqual(type, _T("FAIOR")))
291 return TaskFactoryType::FAI_OR;
292 else if (StringIsEqual(type, _T("FAIGoal")))
293 return TaskFactoryType::FAI_GOAL;
294 else if (StringIsEqual(type, _T("RT")))
295 return TaskFactoryType::RACING;
296 else if (StringIsEqual(type, _T("AAT")))
297 return TaskFactoryType::AAT;
298 else if (StringIsEqual(type, _T("MAT")))
299 return TaskFactoryType::MAT;
300 else if (StringIsEqual(type, _T("Mixed")))
301 return TaskFactoryType::MIXED;
302 else if (StringIsEqual(type, _T("Touring")))
303 return TaskFactoryType::TOURING;
305 assert(1);
306 return TaskFactoryType::FAI_GENERAL;