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 "Task/MapTaskManager.hpp"
24 #include "Task/ProtectedTaskManager.hpp"
25 #include "Components.hpp"
26 #include "Protection.hpp"
27 #include "Engine/Task/Ordered/OrderedTask.hpp"
28 #include "Engine/Task/Ordered/Points/OrderedTaskPoint.hpp"
29 #include "Engine/Task/Factory/AbstractTaskFactory.hpp"
30 #include "Interface.hpp"
32 static const TaskBehaviour
&
35 return CommonInterface::GetComputerSettings().task
;
38 static MapTaskManager::TaskEditResult
39 AppendToTask(OrderedTask
*task
, const Waypoint
&waypoint
)
41 if (task
->TaskSize()==0)
42 return MapTaskManager::NOTASK
;
44 int i
= task
->TaskSize() - 1;
45 // skip all finish points
47 const OrderedTaskPoint
&tp
= task
->GetPoint(i
);
48 if (tp
.IsSuccessorAllowed()) {
56 const AbstractTaskFactory
&factory
= task
->GetFactory();
57 OrderedTaskPoint
*task_point
=
58 (OrderedTaskPoint
*)factory
.CreateIntermediate(waypoint
);
59 if (task_point
== NULL
)
60 return MapTaskManager::UNMODIFIED
;
62 bool success
= i
>= 0 ? task
->Insert(*task_point
, i
) : task
->Append(*task_point
);
66 return MapTaskManager::UNMODIFIED
;
68 if (!task
->CheckTask())
69 return MapTaskManager::INVALID
;
71 return MapTaskManager::SUCCESS
;
74 static MapTaskManager::TaskEditResult
75 MutateFromGoto(OrderedTask
*task
, const Waypoint
&finish_waypoint
,
76 const Waypoint
&start_waypoint
)
78 const AbstractTaskFactory
&factory
= task
->GetFactory();
79 OrderedTaskPoint
*start_point
=
80 (OrderedTaskPoint
*)factory
.CreateStart(start_waypoint
);
81 if (start_point
== NULL
)
82 return MapTaskManager::UNMODIFIED
;
84 bool success
= task
->Append(*start_point
);
87 return MapTaskManager::UNMODIFIED
;
89 OrderedTaskPoint
*finish_point
=
90 (OrderedTaskPoint
*)factory
.CreateFinish(finish_waypoint
);
91 if (finish_point
== NULL
)
92 return MapTaskManager::UNMODIFIED
;
94 success
= task
->Append(*finish_point
);
98 return MapTaskManager::UNMODIFIED
;
100 return MapTaskManager::MUTATED_FROM_GOTO
;
103 MapTaskManager::TaskEditResult
104 MapTaskManager::AppendToTask(const Waypoint
&waypoint
)
106 assert(protected_task_manager
!= NULL
);
107 ProtectedTaskManager::ExclusiveLease
task_manager(*protected_task_manager
);
108 TaskEditResult result
= MapTaskManager::UNMODIFIED
;
109 if (task_manager
->GetOrderedTask().CheckTask()) {
110 OrderedTask
*task
= task_manager
->Clone(GetTaskBehaviour());
111 result
= AppendToTask(task
, waypoint
);
112 if (result
== SUCCESS
)
113 task_manager
->Commit(*task
);
115 } else { // ordered task invalid
116 switch (task_manager
->GetMode()) {
118 case TaskType::ABORT
:
119 case TaskType::ORDERED
:
120 result
= task_manager
->DoGoto(waypoint
) ? MapTaskManager::MUTATED_TO_GOTO
:
121 MapTaskManager::UNMODIFIED
;
125 OrderedTask
*task
= task_manager
->Clone(GetTaskBehaviour());
126 const TaskWaypoint
*OldGotoTWP
= task_manager
->GetActiveTaskPoint();
130 const Waypoint
&OldGotoWp
= OldGotoTWP
->GetWaypoint();
131 result
= MutateFromGoto(task
, waypoint
, OldGotoWp
);
132 if (result
== MUTATED_FROM_GOTO
)
133 task_manager
->Commit(*task
);
143 static MapTaskManager::TaskEditResult
144 InsertInTask(OrderedTask
*task
, const Waypoint
&waypoint
)
146 if (task
->TaskSize()==0)
147 return MapTaskManager::NOTASK
;
149 int i
= task
->GetActiveIndex();
150 /* skip all start points */
152 if (i
>= (int)task
->TaskSize())
153 return MapTaskManager::UNMODIFIED
;
155 const OrderedTaskPoint
&task_point
= task
->GetPoint(i
);
156 if (task_point
.IsPredecessorAllowed())
162 const AbstractTaskFactory
&factory
= task
->GetFactory();
163 OrderedTaskPoint
*task_point
=
164 (OrderedTaskPoint
*)factory
.CreateIntermediate(waypoint
);
165 if (task_point
== NULL
)
166 return MapTaskManager::UNMODIFIED
;
168 bool success
= task
->Insert(*task_point
, i
);
171 return MapTaskManager::UNMODIFIED
;
172 if (!task
->CheckTask())
173 return MapTaskManager::INVALID
;
174 return MapTaskManager::SUCCESS
;
177 MapTaskManager::TaskEditResult
178 MapTaskManager::InsertInTask(const Waypoint
&waypoint
)
180 assert(protected_task_manager
!= NULL
);
181 ProtectedTaskManager::ExclusiveLease
task_manager(*protected_task_manager
);
182 TaskEditResult result
= MapTaskManager::UNMODIFIED
;
183 if (task_manager
->GetOrderedTask().CheckTask()) {
184 OrderedTask
*task
= task_manager
->Clone(GetTaskBehaviour());
186 result
= InsertInTask(task
, waypoint
);
187 if (result
== SUCCESS
)
188 task_manager
->Commit(*task
);
190 } else { // ordered task invalid
191 switch (task_manager
->GetMode()) {
193 case TaskType::ABORT
:
194 case TaskType::ORDERED
:
195 result
= task_manager
->DoGoto(waypoint
) ? MapTaskManager::MUTATED_TO_GOTO
:
196 MapTaskManager::UNMODIFIED
;
200 OrderedTask
*task
= task_manager
->Clone(GetTaskBehaviour());
201 const TaskWaypoint
*OldGotoTWP
= task_manager
->GetActiveTaskPoint();
204 const Waypoint
&OldGotoWp
= OldGotoTWP
->GetWaypoint();
205 result
= MutateFromGoto(task
, OldGotoWp
, waypoint
);
206 if (result
== MUTATED_FROM_GOTO
)
207 task_manager
->Commit(*task
);
216 MapTaskManager::TaskEditResult
217 MapTaskManager::InsertInMatProForma(OrderedTask
&task
,
218 const Waypoint
&waypoint
)
220 assert(task
.CheckTask());
221 return InsertInTask(&task
, waypoint
);
224 static MapTaskManager::TaskEditResult
225 ReplaceInTask(OrderedTask
*task
, const Waypoint
&waypoint
)
227 if (task
->TaskSize()==0)
228 return MapTaskManager::NOTASK
;
230 unsigned i
= task
->GetActiveIndex();
231 if (i
>= task
->TaskSize())
232 return MapTaskManager::UNMODIFIED
;
234 task
->Relocate(i
, waypoint
);
236 if (!task
->CheckTask())
237 return MapTaskManager::INVALID
;
239 return MapTaskManager::SUCCESS
;
242 MapTaskManager::TaskEditResult
243 MapTaskManager::ReplaceInTask(const Waypoint
&waypoint
)
245 assert(protected_task_manager
!= NULL
);
246 ProtectedTaskManager::ExclusiveLease
task_manager(*protected_task_manager
);
247 OrderedTask
*task
= task_manager
->Clone(GetTaskBehaviour());
249 TaskEditResult result
= ReplaceInTask(task
, waypoint
);
250 if (result
== SUCCESS
)
251 task_manager
->Commit(*task
);
258 GetUnachievedIndexInTask(const OrderedTask
&task
,
259 const Waypoint
&waypoint
)
261 if (task
.TaskSize() < 2)
264 unsigned last_achieved_index
= task
.GetLastIntermediateAchieved();
267 for (unsigned i
= task
.TaskSize() - 2; i
> last_achieved_index
; i
--) {
268 const OrderedTaskPoint
&tp
= task
.GetPoint(i
);
270 if (tp
.GetWaypoint() == waypoint
) {
279 MapTaskManager::GetUnachievedIndexInTask(const Waypoint
&waypoint
)
281 assert(protected_task_manager
!= NULL
);
282 ProtectedTaskManager::Lease
task_manager(*protected_task_manager
);
284 if (task_manager
->GetMode() == TaskType::ORDERED
) {
285 const OrderedTask
&task
= task_manager
->GetOrderedTask();
286 return GetUnachievedIndexInTask(task
, waypoint
);
292 GetIndexInTask(const OrderedTask
&task
, const Waypoint
&waypoint
)
294 if (task
.TaskSize() == 0)
297 unsigned i
= task
.GetActiveIndex();
298 if (i
>= task
.TaskSize())
302 for (unsigned i
= task
.TaskSize(); i
--;) {
303 const OrderedTaskPoint
&tp
= task
.GetPoint(i
);
305 if (tp
.GetWaypoint() == waypoint
) {
314 MapTaskManager::GetIndexInTask(const Waypoint
&waypoint
)
316 assert(protected_task_manager
!= NULL
);
317 ProtectedTaskManager::ExclusiveLease
task_manager(*protected_task_manager
);
318 if (task_manager
->GetMode() == TaskType::ORDERED
) {
319 const OrderedTask
&task
= task_manager
->GetOrderedTask();
320 return GetIndexInTask(task
, waypoint
);
325 static MapTaskManager::TaskEditResult
326 RemoveFromTask(OrderedTask
*task
, const Waypoint
&waypoint
)
328 if (task
->TaskSize()==0)
329 return MapTaskManager::NOTASK
;
331 int i
= GetIndexInTask(*task
, waypoint
);
333 task
->GetFactory().Remove(i
);
335 // if finish was removed
336 if (i
== (int)task
->TaskSize())
337 task
->GetFactory().CheckAddFinish();
340 return MapTaskManager::UNMODIFIED
;
342 if (!task
->CheckTask())
343 return MapTaskManager::INVALID
;
345 return MapTaskManager::SUCCESS
;
348 MapTaskManager::TaskEditResult
349 MapTaskManager::RemoveFromTask(const Waypoint
&wp
)
351 assert(protected_task_manager
!= NULL
);
352 ProtectedTaskManager::ExclusiveLease
task_manager(*protected_task_manager
);
353 OrderedTask
*task
= task_manager
->Clone(GetTaskBehaviour());
355 TaskEditResult result
= RemoveFromTask(task
, wp
);
356 if (result
== SUCCESS
)
357 task_manager
->Commit(*task
);