]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/train.cpp
ccb7cc25bbf8714706e549c3bb4cee6ff07e2b32
[r2c2.git] / source / libmarklin / train.cpp
1 /* $Id$
2
3 This file is part of the MSP Märklin suite
4 Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
6 */
7
8 #include <cmath>
9 #include <msp/strings/formatter.h>
10 #include <msp/time/units.h>
11 #include <msp/time/utils.h>
12 #include "aicontrol.h"
13 #include "catalogue.h"
14 #include "driver.h"
15 #include "layout.h"
16 #include "route.h"
17 #include "simplecontroller.h"
18 #include "timetable.h"
19 #include "tracktype.h"
20 #include "train.h"
21 #include "vehicle.h"
22 #include "vehicletype.h"
23
24 using namespace std;
25 using namespace Msp;
26
27 namespace {
28
29 struct SetFlag
30 {
31         bool &flag;
32
33         SetFlag(bool &f): flag(f) { flag = true; }
34         ~SetFlag() { flag = false; }
35 };
36
37 }
38
39
40 namespace Marklin {
41
42 Train::Train(Layout &l, const VehicleType &t, unsigned a):
43         layout(l),
44         loco_type(t),
45         address(a),
46         priority(0),
47         yielding_to(0),
48         pending_block(0),
49         reserving(false),
50         advancing(false),
51         controller(new AIControl(*this, new SimpleController)),
52         timetable(0),
53         active(false),
54         current_speed(0),
55         speed_changing(false),
56         reverse(false),
57         functions(0),
58         end_of_route(false),
59         status("Unplaced"),
60         travel_dist(0),
61         pure_speed(false),
62         real_speed(15),
63         accurate_position(false),
64         overshoot_dist(false)
65 {
66         if(!loco_type.is_locomotive())
67                 throw InvalidParameterValue("Initial vehicle must be a locomotive");
68
69         vehicles.push_back(new Vehicle(layout, loco_type));
70
71         layout.add_train(*this);
72
73         layout.get_driver().add_loco(address);
74         layout.get_driver().signal_loco_speed.connect(sigc::mem_fun(this, &Train::loco_speed_event));
75         layout.get_driver().signal_loco_function.connect(sigc::mem_fun(this, &Train::loco_func_event));
76
77         layout.signal_block_reserved.connect(sigc::mem_fun(this, &Train::block_reserved));
78         layout.get_driver().signal_sensor.connect(sigc::mem_fun(this, &Train::sensor_event));
79         layout.get_driver().signal_turnout.connect(sigc::mem_fun(this, &Train::turnout_event));
80
81         layout.get_driver().signal_halt.connect(sigc::mem_fun(this, &Train::halt_event));
82
83         controller->signal_control_changed.connect(sigc::mem_fun(this, &Train::control_changed));
84 }
85
86 Train::~Train()
87 {
88         delete controller;
89         delete timetable;
90         for(vector<Vehicle *>::iterator i=vehicles.begin(); i!=vehicles.end(); ++i)
91                 delete *i;
92         layout.remove_train(*this);
93 }
94
95 void Train::set_name(const string &n)
96 {
97         name = n;
98
99         signal_name_changed.emit(name);
100 }
101
102 void Train::set_priority(int p)
103 {
104         priority = p;
105 }
106
107 void Train::yield_to(const Train &t)
108 {
109         yielding_to = &t;
110 }
111
112 void Train::add_vehicle(const VehicleType &vt)
113 {
114         Vehicle *veh = new Vehicle(layout, vt);
115         vehicles.back()->attach_back(*veh);
116         vehicles.push_back(veh);
117 }
118
119 void Train::remove_vehicle(unsigned i)
120 {
121         if(i>=vehicles.size())
122                 throw InvalidParameterValue("Vehicle index out of range");
123         if(i==0)
124                 throw InvalidParameterValue("Can't remove the locomotive");
125         delete vehicles[i];
126         vehicles.erase(vehicles.begin()+i);
127         if(i<vehicles.size())
128                 vehicles[i-1]->attach_back(*vehicles[i]);
129 }
130
131 unsigned Train::get_n_vehicles() const
132 {
133         return vehicles.size();
134 }
135
136 Vehicle &Train::get_vehicle(unsigned i)
137 {
138         if(i>=vehicles.size())
139                 throw InvalidParameterValue("Vehicle index out of range");
140         return *vehicles[i];
141 }
142
143 const Vehicle &Train::get_vehicle(unsigned i) const
144 {
145         if(i>=vehicles.size())
146                 throw InvalidParameterValue("Vehicle index out of range");
147         return *vehicles[i];
148 }
149
150 void Train::set_control(const string &n, float v)
151 {
152         controller->set_control(n, v);
153 }
154
155 void Train::set_active(bool a)
156 {
157         if(a==active)
158                 return;
159         if(!a && controller->get_speed())
160                 throw InvalidState("Can't deactivate while moving");
161
162         active = a;
163         if(active)
164         {
165                 stop_timeout = Time::TimeStamp();
166                 reserve_more();
167         }
168         else
169         {
170                 stop_timeout = Time::now()+2*Time::sec;
171                 set_status("Stopped");
172         }
173 }
174
175 void Train::set_function(unsigned func, bool state)
176 {
177         if(!loco_type.get_functions().count(func))
178                 throw InvalidParameterValue("Invalid function");
179         if(func<5)
180                 layout.get_driver().set_loco_function(address, func, state);
181         else
182                 layout.get_driver().set_loco_function(address+1, func-4, state);
183 }
184
185 float Train::get_control(const string &ctrl) const
186 {
187         return controller->get_control(ctrl).value;
188 }
189
190 float Train::get_speed() const
191 {
192         return controller->get_speed();
193 }
194
195 bool Train::get_function(unsigned func) const
196 {
197         return (functions>>func)&1;
198 }
199
200 void Train::set_timetable(Timetable *tt)
201 {
202         delete timetable;
203         timetable = tt;
204 }
205
206 void Train::set_route(const Route *r)
207 {
208         free_noncritical_blocks();
209
210         routes.clear();
211         if(r)
212                 routes.push_back(r);
213         end_of_route = false;
214
215         if(r && !cur_blocks.empty())
216         {
217                 BlockRef &first = cur_blocks.front();
218                 BlockRef &last = (rsv_blocks.empty() ? cur_blocks.back() : rsv_blocks.back());
219                 BlockRef next = last.next();
220                 const Block::Endpoint &first_ep = first.block->get_endpoints()[first.entry];
221                 const Block::Endpoint &next_ep = next.block->get_endpoints()[next.entry];
222                 if(!r->get_tracks().count(next_ep.track))
223                 {
224                         Route *lead = Route::find(*next_ep.track, next_ep.track_ep, *r);
225                         create_lead_route(lead, lead);
226                         routes.push_front(lead);
227                 }
228                 else if(!r->get_tracks().count(first_ep.track))
229                         routes.push_front(create_lead_route(0, r));
230         }
231
232         reserve_more();
233
234         signal_route_changed.emit(get_route());
235 }
236
237 void Train::go_to(const Track &to)
238 {
239         for(list<BlockRef>::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
240                 if(i->block->get_tracks().count(const_cast<Track *>(&to)))
241                 {
242                         signal_arrived.emit();
243                         set_route(0);
244                         return;
245                 }
246
247         free_noncritical_blocks();
248
249         BlockRef &last = (rsv_blocks.empty() ? cur_blocks.back() : rsv_blocks.back());
250         BlockRef next = last.next();
251         const Block::Endpoint &ep = next.block->get_endpoints()[next.entry];
252
253         Route *route = Route::find(*ep.track, ep.track_ep, to);
254         create_lead_route(route, route);
255         set_route(route);
256 }
257
258 bool Train::divert(Track &from)
259 {
260         if(!from.get_turnout_id())
261                 throw InvalidParameterValue("Can't divert from a non-turnout");
262         if(routes.empty())
263                 return false;
264
265         int path = -1;
266         unsigned from_ep = 0;
267         list<RouteRef>::iterator route = routes.begin();
268         Block *block = cur_blocks.back().block;
269         unsigned entry = cur_blocks.back().entry;
270         set<const Track *> visited;
271
272         // Follow our routes to find out where we're entering the turnout
273         while(1)
274         {
275                 Block *link = block->get_link(block->traverse(entry, route->route));
276                 entry = link->get_endpoint_by_link(*block);
277                 block = link;
278
279                 const Block::Endpoint &entry_ep = block->get_endpoints()[entry];
280
281                 if(visited.count(entry_ep.track))
282                         return false;
283                 visited.insert(entry_ep.track);
284
285                 if(!advance_route(route, *entry_ep.track))
286                         return false;
287
288                 if(entry_ep.track==&from)
289                 {
290                         if(block->get_train()==this && !free_block(*block))
291                                 return false;
292
293                         from_ep = entry_ep.track_ep;
294                         path = route->route->get_turnout(from.get_turnout_id());
295                         break;
296                 }
297         }
298
299         // Check that more than one path is available
300         unsigned ep_paths = from.get_type().get_endpoints()[from_ep].paths;
301         if(!(ep_paths&(ep_paths-1)))
302                 return false;
303
304         // Choose some other path
305         for(int i=0; ep_paths>>i; ++i)
306                 if((ep_paths&(1<<i)) && i!=path)
307                 {
308                         path = i;
309                         break;
310                 }
311
312         Track *track = from.get_link(from.traverse(from_ep, path));
313         if(!track)
314                 return false;
315
316         unsigned ep = track->get_endpoint_by_link(from);
317
318         set<const Track *> tracks;
319         for(list<RouteRef>::iterator i=routes.begin(); i!=routes.end(); ++i)
320                 tracks.insert(i->route->get_tracks().begin(), i->route->get_tracks().end());
321         Route *diversion = 0;
322         try
323         {
324                 diversion = Route::find(*track, ep, tracks);
325         }
326         catch(const Msp::Exception &)
327         {
328                 return false;
329         }
330
331         diversion->set_name("Diversion");
332         diversion->add_track(from);
333         diversion->set_turnout(from.get_turnout_id(), path);
334
335         if(!is_valid_diversion(*diversion, from, from_ep))
336         {
337                 delete diversion;
338                 return false;
339         }
340
341         // Follow the diversion route until we get back to the original route
342         list<RouteRef>::iterator end = routes.end();
343         while(1)
344         {
345                 path = 0;
346                 if(track->get_turnout_id())
347                         path = diversion->get_turnout(track->get_turnout_id());
348                 Track *next = track->get_link(track->traverse(ep, path));
349
350                 for(list<RouteRef>::iterator i=route; (end==routes.end() && i!=routes.end()); ++i)
351                         if(i->route->get_tracks().count(next))
352                                 end = i;
353
354                 if(end!=routes.end())
355                         break;
356                 else if(!diversion->get_tracks().count(next))
357                         throw Exception("Pathfinder returned a bad route");
358
359                 ep = next->get_endpoint_by_link(*track);
360                 track = next;
361         }
362
363         if(route==end)
364                 // We are rejoining the same route we diverted from, duplicate it
365                 routes.insert(end, *route);
366         else
367         {
368                 ++route;
369                 routes.erase(route, end);
370         }
371         routes.insert(end, RouteRef(diversion, from.get_turnout_id()));
372
373         return true;
374 }
375
376 const Route *Train::get_route() const
377 {
378         if(routes.empty())
379                 return 0;
380         return routes.front().route;
381 }
382
383 void Train::place(Block &block, unsigned entry)
384 {
385         if(controller->get_speed())
386                 throw InvalidState("Must be stopped before placing");
387
388         release_blocks(rsv_blocks);
389         release_blocks(cur_blocks);
390
391         set_active(false);
392         accurate_position = false;
393
394         if(!block.reserve(this))
395         {
396                 set_status("Unplaced");
397                 return;
398         }
399
400         cur_blocks.push_back(BlockRef(&block, entry));
401         if(reverse)
402         {
403                 unsigned exit = block.traverse(entry);
404                 const Block::Endpoint &bep = block.get_endpoints()[exit];
405                 Track *track = bep.track->get_link(bep.track_ep);
406                 unsigned ep = track->get_endpoint_by_link(*bep.track);
407                 vehicles.front()->place(*track, ep, 0, Vehicle::FRONT_BUFFER);
408         }
409         else
410         {
411                 const Block::Endpoint &bep = block.get_endpoints()[entry];
412                 vehicles.back()->place(*bep.track, bep.track_ep, 0, Vehicle::BACK_BUFFER);
413         }
414 }
415
416 void Train::unplace()
417 {
418         if(controller->get_speed())
419                 throw InvalidState("Must be stopped before unplacing");
420
421         release_blocks(rsv_blocks);
422         release_blocks(cur_blocks);
423
424         set_active(false);
425         accurate_position = false;
426
427         for(vector<Vehicle *>::iterator i=vehicles.begin(); i!=vehicles.end(); ++i)
428                 (*i)->unplace();
429
430         set_status("Unplaced");
431 }
432
433 bool Train::free_block(Block &block)
434 {
435         float margin = 10*layout.get_catalogue().get_scale();
436         if(get_reserved_distance_until(&block, false)<controller->get_braking_distance()*1.3+margin)
437                 return false;
438
439         unsigned nsens = 0;
440         for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
441         {
442                 if(i->block==&block)
443                 {
444                         if(nsens<1)
445                                 return false;
446                         release_blocks(rsv_blocks, i, rsv_blocks.end());
447                         return true;
448                 }
449                 else if(i->block->get_sensor_id())
450                         ++nsens;
451         }
452
453         return false;
454 }
455
456 void Train::free_noncritical_blocks()
457 {
458         if(cur_blocks.empty() || rsv_blocks.empty())
459                 return;
460
461         if(controller->get_speed()==0)
462         {
463                 release_blocks(rsv_blocks);
464                 return;
465         }
466
467         float margin = 10*layout.get_catalogue().get_scale();
468         float min_dist = controller->get_braking_distance()*1.3+margin;
469
470         Vehicle &veh = *(reverse ? vehicles.back() : vehicles.front());
471
472         Track *track = veh.get_track();
473         list<BlockRef>::iterator block = cur_blocks.begin();
474         bool in_rsv = false;
475         while(block!=rsv_blocks.end() && !block->block->get_tracks().count(track))
476         {
477                 ++block;
478                 if(block==cur_blocks.end())
479                 {
480                         block = rsv_blocks.begin();
481                         in_rsv = true;
482                 }
483         }
484
485         unsigned entry = veh.get_entry();
486         float dist = veh.get_offset();
487         if(reverse)
488                 entry = track->traverse(entry);
489         else
490                 dist = track->get_type().get_path_length(track->get_active_path())-dist;
491         dist -= veh.get_type().get_length()/2;
492
493         bool nsens = 0;
494         while(1)
495         {
496                 Track *next = track->get_link(track->traverse(entry));
497                 entry = next->get_endpoint_by_link(*track);
498                 track = next;
499
500                 if(!block->block->get_tracks().count(track))
501                 {
502                         ++block;
503                         if(block==cur_blocks.end())
504                         {
505                                 block = rsv_blocks.begin();
506                                 in_rsv = true;
507                         }
508                         if(block==rsv_blocks.end())
509                                 return;
510
511                         if(dist>min_dist && nsens>0)
512                         {
513                                 release_blocks(rsv_blocks, block, rsv_blocks.end());
514                                 return;
515                         }
516
517                         if(in_rsv && block->block->get_sensor_id())
518                                 ++nsens;
519                 }
520
521                 dist += track->get_type().get_path_length(track->get_active_path());
522         }
523 }
524
525 int Train::get_entry_to_block(Block &block) const
526 {
527         for(list<BlockRef>::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
528                 if(i->block==&block)
529                         return i->entry;
530         for(list<BlockRef>::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
531                 if(i->block==&block)
532                         return i->entry;
533         return -1;
534 }
535
536 float Train::get_reserved_distance() const
537 {
538         return get_reserved_distance_until(0, false);
539 }
540
541 void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt)
542 {
543         if(!active && stop_timeout && t>=stop_timeout)
544         {
545                 release_blocks(rsv_blocks);
546                 end_of_route = false;
547                 stop_timeout = Time::TimeStamp();
548         }
549
550         Driver &driver = layout.get_driver();
551
552         if(timetable)
553                 timetable->tick(t);
554         controller->tick(dt);
555         float speed = controller->get_speed();
556         unsigned speed_notch = find_speed(speed);
557
558         if(controller->get_reverse()!=reverse)
559         {
560                 reverse = controller->get_reverse();
561                 driver.set_loco_reverse(address, reverse);
562
563                 release_blocks(rsv_blocks);
564                 reverse_blocks(cur_blocks);
565
566                 reserve_more();
567         }
568         if(speed_notch!=current_speed && !speed_changing && !driver.is_halted() && driver.get_power())
569         {
570                 speed_changing = true;
571                 driver.set_loco_speed(address, speed_notch);
572
573                 pure_speed = false;
574
575                 if(speed_notch)
576                         set_status(format("Traveling %d kmh", get_travel_speed()));
577                 else
578                         set_status("Waiting");
579         }
580
581         if(speed)
582         {
583                 if(!active)
584                         set_active(true);
585
586                 Vehicle &vehicle = *(reverse ? vehicles.back() : vehicles.front());
587                 Track *track = vehicle.get_track();
588
589                 bool ok = false;
590                 for(list<BlockRef>::const_iterator i=cur_blocks.begin(); (!ok && i!=cur_blocks.end()); ++i)
591                         ok = i->block->get_tracks().count(track);
592
593                 float d = get_real_speed(current_speed)*(dt/Time::sec);
594                 if(ok)
595                 {
596                         SetFlag setf(advancing);
597                         vehicle.advance(reverse ? -d : d);
598                 }
599                 else if(accurate_position)
600                 {
601                         overshoot_dist += d;
602                         if(overshoot_dist>40*layout.get_catalogue().get_scale())
603                         {
604                                 layout.emergency(name+" has not arrived at sensor");
605                                 accurate_position = false;
606                         }
607                 }
608         }
609         else if(end_of_route && rsv_blocks.empty())
610         {
611                 set_active(false);
612                 signal_arrived.emit();
613                 set_route(0);
614         }
615
616         if(!cur_blocks.empty() && !cur_blocks.front().block->get_sensor_id())
617         {
618                 float dist = get_reserved_distance_until(cur_blocks.front().block, true);
619
620                 if(dist>10*layout.get_catalogue().get_scale())
621                 {
622                         cur_blocks.front().block->reserve(0);
623                         cur_blocks.pop_front();
624                 }
625         }
626 }
627
628 void Train::save(list<DataFile::Statement> &st) const
629 {
630         st.push_back((DataFile::Statement("name"), name));
631
632         st.push_back((DataFile::Statement("priority"), priority));
633
634         for(vector<Vehicle *>::const_iterator i=vehicles.begin(); i!=vehicles.end(); ++i)
635                 if(i!=vehicles.begin())
636                         st.push_back((DataFile::Statement("vehicle"), (*i)->get_type().get_article_number()));
637
638         for(unsigned i=0; i<=14; ++i)
639                 if(real_speed[i].weight)
640                         st.push_back((DataFile::Statement("real_speed"), i, real_speed[i].speed, real_speed[i].weight));
641
642         if(!cur_blocks.empty())
643         {
644                 list<BlockRef> blocks = cur_blocks;
645                 if(reverse)
646                         reverse_blocks(blocks);
647
648                 Block *prev = blocks.front().block->get_endpoints()[blocks.front().entry].link;
649                 st.push_back((DataFile::Statement("block_hint"), prev->get_id()));
650
651                 for(list<BlockRef>::const_iterator i=blocks.begin(); i!=blocks.end(); ++i)
652                         st.push_back((DataFile::Statement("block"), i->block->get_id()));
653         }
654
655         if(!routes.empty())
656         {
657                 list<RouteRef>::const_iterator i = routes.begin();
658                 for(; (i!=routes.end() && i->route->is_temporary()); ++i) ;
659                 if(i!=routes.end())
660                         st.push_back((DataFile::Statement("route"), i->route->get_name()));
661         }
662
663         if(timetable)
664         {
665                 DataFile::Statement ss("timetable");
666                 timetable->save(ss.sub);
667                 st.push_back(ss);
668         }
669 }
670
671 void Train::control_changed(const Controller::Control &ctrl)
672 {
673         signal_control_changed.emit(ctrl.name, ctrl.value);
674 }
675
676 void Train::loco_speed_event(unsigned addr, unsigned speed, bool)
677 {
678         if(addr==address)
679         {
680                 current_speed = speed;
681                 speed_changing = false;
682                 pure_speed = false;
683         }
684 }
685
686 void Train::loco_func_event(unsigned addr, unsigned func, bool state)
687 {
688         if(addr==address || (addr==address+1 && loco_type.get_max_function()>4))
689         {
690                 if(addr==address+1)
691                         func += 4;
692                 if(state)
693                         functions |= 1<<func;
694                 else
695                         functions &= ~(1<<func);
696
697                 signal_function_changed.emit(func, state);
698         }
699 }
700
701 void Train::sensor_event(unsigned addr, bool state)
702 {
703         if(state)
704         {
705                 // Find the first sensor block from our reserved blocks that isn't this sensor
706                 list<BlockRef>::iterator i;
707                 unsigned result = 0;
708                 for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
709                         if(i->block->get_sensor_id())
710                         {
711                                 if(i->block->get_sensor_id()!=addr)
712                                 {
713                                         if(result==0)
714                                                 result = 2;
715                                         else if(result==1)
716                                                 break;
717                                 }
718                                 else if(result==0)
719                                         result = 1;
720                                 else if(result==2)
721                                         result = 3;
722                         }
723
724                 if(result==1 && i!=rsv_blocks.begin())
725                 {
726                         // Compute speed and update related state
727                         float travel_time_secs = (Time::now()-last_entry_time)/Time::sec;
728
729                         if(pure_speed)
730                         {
731                                 if(current_speed)
732                                 {
733                                         RealSpeed &rs = real_speed[current_speed];
734                                         rs.add(travel_dist/travel_time_secs, travel_time_secs);
735                                 }
736                                 set_status(format("Traveling %d kmh", get_travel_speed()));
737                         }
738
739                         travel_dist = 0;
740                         float block_len;
741                         for(list<BlockRef>::iterator j=rsv_blocks.begin(); j!=i; ++j)
742                         {
743                                 j->block->traverse(j->entry, &block_len);
744                                 travel_dist += block_len;
745
746                                 if(j->block->get_sensor_id()==addr && !advancing)
747                                 {
748                                         const Block::Endpoint &bep = j->block->get_endpoints()[j->entry];
749                                         if(reverse)
750                                         {
751                                                 Track *track = bep.track->get_link(bep.track_ep);
752                                                 unsigned ep = track->get_endpoint_by_link(*bep.track);
753                                                 vehicles.back()->place(*track, ep, 0, Vehicle::BACK_AXLE);
754                                         }
755                                         else
756                                                 vehicles.front()->place(*bep.track, bep.track_ep, 0, Vehicle::FRONT_AXLE);
757                                 }
758                         }
759                         last_entry_time = Time::now();
760                         pure_speed = true;
761                         accurate_position = true;
762                         overshoot_dist = 0;
763
764                         // Check if we've reached the next route
765                         if(routes.size()>1)
766                         {
767                                 const set<const Track *> &rtracks = (++routes.begin())->route->get_tracks();
768                                 for(list<BlockRef>::iterator j=rsv_blocks.begin(); j!=i; ++j)
769                                         if(rtracks.count(j->block->get_endpoints()[j->entry].track))
770                                         {
771                                                 routes.pop_front();
772                                                 // XXX Exceptions?
773                                                 signal_route_changed.emit(routes.front().route);
774                                                 break;
775                                         }
776                         }
777
778                         // Move blocks up to the next sensor to our current blocks
779                         cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
780
781                         // Try to get more blocks if we're moving
782                         if(active)
783                                 reserve_more();
784                 }
785                 else if(result==3)
786                         layout.emergency("Sensor for "+name+" triggered out of order");
787         }
788         else
789         {
790                 const Vehicle &veh = *(reverse ? vehicles.front() : vehicles.back());
791
792                 // Find the first sensor in our current blocks that's still active
793                 list<BlockRef>::iterator end = cur_blocks.begin();
794                 for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
795                 {
796                         if(i->block->get_tracks().count(veh.get_track()))
797                                 break;
798                         if(i->block->get_sensor_id())
799                         {
800                                 if(layout.get_driver().get_sensor(i->block->get_sensor_id()))
801                                         break;
802                                 else
803                                 {
804                                         end = i;
805                                         ++end;
806                                 }
807                         }
808                 }
809                 
810                 if(end!=cur_blocks.begin() && end!=cur_blocks.end())
811                         // Free blocks up to the last inactive sensor
812                         release_blocks(cur_blocks, cur_blocks.begin(), end);
813         }
814 }
815
816 void Train::turnout_event(unsigned addr, bool)
817 {
818         if(pending_block && (!pending_block->get_train() || pending_block->get_train()==this))
819         {
820                 unsigned pending_addr = pending_block->get_turnout_id();
821                 bool double_addr = (*pending_block->get_tracks().begin())->get_type().is_double_address();
822                 if(addr==pending_addr || (double_addr && addr==pending_addr+1))
823                 {
824                         if(reserving)
825                                 pending_block = 0;
826                         else
827                                 reserve_more();
828                 }
829         }
830 }
831
832 void Train::halt_event(bool h)
833 {
834         if(h)
835                 accurate_position = false;
836 }
837
838 void Train::block_reserved(const Block &block, const Train *train)
839 {
840         if(&block==pending_block && !train && !reserving)
841                 reserve_more();
842 }
843
844 unsigned Train::reserve_more()
845 {
846         if(!active)
847                 return 0;
848
849         BlockRef *start = 0;
850         if(!rsv_blocks.empty())
851                 start = &rsv_blocks.back();
852         else if(!cur_blocks.empty())
853                 start = &cur_blocks.back();
854         if(!start)
855                 return 0;
856
857         pending_block = 0;
858
859         // See how many sensor blocks and how much track we already have
860         unsigned nsens = 0;
861         float dist = 0;
862         for(list<BlockRef>::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
863         {
864                 if(i->block->get_sensor_id())
865                         ++nsens;
866                 if(nsens>0)
867                 {
868                         float length = 0;
869                         i->block->traverse(i->entry, &length);
870                         dist += length;
871                 }
872         }
873         
874         if(end_of_route)
875                 return nsens;
876
877         list<RouteRef>::iterator cur_route = routes.begin();
878         advance_route(cur_route, *start->block->get_endpoints()[start->entry].track);
879
880         float approach_margin = 50*layout.get_catalogue().get_scale();
881         float min_dist = controller->get_braking_distance()*1.3+approach_margin*2;
882
883         BlockRef *last = start;
884         BlockRef *good = start;
885         Track *divert_track = 0;
886         bool try_divert = false;
887         unsigned good_sens = nsens;
888         float good_dist = dist;
889         Train *blocking_train = 0;
890         std::list<BlockRef> contested_blocks;
891
892         SetFlag setf(reserving);
893
894         while(good_sens<3 || good_dist<min_dist || !contested_blocks.empty())
895         {
896                 // Traverse to the next block
897                 float length = 0;
898                 Block *link = 0;
899                 {
900                         const Route *route = (cur_route!=routes.end() ? cur_route->route : 0);
901                         unsigned exit = last->block->traverse(last->entry, route, &length);
902                         link = last->block->get_link(exit);
903                 }
904                 if(!link)
905                         break;
906
907                 int entry = link->get_endpoint_by_link(*last->block);
908                 if(entry<0)
909                         throw LogicError("Block links are inconsistent!");
910
911                 const Block::Endpoint &entry_ep = link->get_endpoints()[entry];
912
913                 if(cur_route!=routes.end())
914                 {
915                         if(!advance_route(cur_route, *entry_ep.track))
916                         {
917                                 // Keep the blocks if we arrived at the end of the route
918                                 if(!blocking_train)
919                                 {
920                                         good = last;
921                                         good_sens = nsens;
922                                         good_dist = dist;
923                                         end_of_route = true;
924                                 }
925                                 break;
926                         }
927                 }
928                 else if(!routes.empty() && routes.front().route->get_tracks().count(entry_ep.track))
929                         cur_route = routes.begin();
930
931                 if(link->get_endpoints().size()<2)
932                 {
933                         if(!blocking_train)
934                         {
935                                 good = last;
936                                 good_sens = nsens;
937                                 good_dist = dist;
938                         }
939                         break;
940                 }
941
942                 if(blocking_train)
943                 {
944                         if(link->get_train()!=blocking_train)
945                         {
946                                 if(blocking_train->free_block(*contested_blocks.back().block))
947                                 {
948                                         // Roll back and start actually reserving the blocks
949                                         last = &rsv_blocks.back();
950                                         cur_route = routes.begin();
951                                         advance_route(cur_route, *last->block->get_endpoints()[last->entry].track);
952                                         if(blocking_train->get_priority()==priority)
953                                                 blocking_train->yield_to(*this);
954                                         blocking_train = 0;
955                                         continue;
956                                 }
957                                 else
958                                 {
959                                         yield_to(*blocking_train);
960                                         pending_block = contested_blocks.front().block;
961                                         try_divert = divert_track;
962                                         break;
963                                 }
964                         }
965                         else
966                         {
967                                 contested_blocks.push_back(BlockRef(link, entry));
968                                 last = &contested_blocks.back();
969                                 continue;
970                         }
971                 }
972
973                 bool reserved = link->reserve(this);
974                 if(!reserved)
975                 {
976                         /* We've found another train.  If it wants to exit the block from the
977                         same endpoint we're trying to enter from or the other way around,
978                         treat it as coming towards us.  Otherwise treat it as going in the
979                         same direction. */
980                         Train *other_train = link->get_train();
981                         int other_entry = other_train->get_entry_to_block(*link);
982                         if(other_entry<0)
983                                 throw LogicError("Block reservation inconsistency");
984
985                         bool entry_conflict = (static_cast<unsigned>(entry)==link->traverse(other_entry));
986                         bool exit_conflict = (link->traverse(entry)==static_cast<unsigned>(other_entry));
987                         if(!entry_conflict && !last->block->get_turnout_id())
988                         {
989                                 /* The other train is not coming to the blocks we're holding, so we
990                                 can keep them. */
991                                 good = last;
992                                 good_sens = nsens;
993                                 good_dist = dist;
994                         }
995
996                         int other_prio = other_train->get_priority();
997
998                         if(!entry_conflict && !exit_conflict && other_prio<priority)
999                         {
1000                                 /* Ask a lesser priority train going to the same direction to free
1001                                 the block for us */
1002                                 if(other_train->free_block(*link))
1003                                         reserved = link->reserve(this);
1004                         }
1005                         else if(other_train!=yielding_to && (other_prio<priority || (other_prio==priority && entry_conflict)))
1006                         {
1007                                 /* A lesser priority train is coming at us, we must ask it to free
1008                                 enough blocks to get clear of it to avoid a potential deadlock */
1009                                 blocking_train = other_train;
1010                                 contested_blocks.clear();
1011                                 contested_blocks.push_back(BlockRef(link, entry));
1012                                 last = &contested_blocks.back();
1013                                 continue;
1014                         }
1015                         else if(divert_track && (entry_conflict || exit_conflict))
1016                                 // We are blocked, but there's a diversion possibility
1017                                 try_divert = true;
1018
1019                         if(!reserved)
1020                         {
1021                                 pending_block = link;
1022                                 break;
1023                         }
1024                 }
1025
1026                 if(link->get_turnout_id())
1027                 {
1028                         const Endpoint &track_ep = entry_ep.track->get_type().get_endpoints()[entry_ep.track_ep];
1029                         bool multiple_paths = (track_ep.paths&(track_ep.paths-1));
1030
1031                         if(multiple_paths || !last->block->get_turnout_id())
1032                         {
1033                                 /* We can keep the blocks reserved so far if we are facing the
1034                                 points or if there was no turnout immediately before this one.
1035                                 With multiple successive turnouts (as is common in crossovers) it's
1036                                 best to hold at one we can divert from. */
1037                                 good = last;
1038                                 good_sens = nsens;
1039                                 good_dist = dist;
1040                         }
1041
1042                         // Figure out what path we'd like to take on the turnout
1043                         int path = -1;
1044                         for(list<RouteRef>::iterator i=cur_route; (path<0 && i!=routes.end()); ++i)
1045                                 path = i->route->get_turnout(link->get_turnout_id());
1046                         if(path<0)
1047                                 path = entry_ep.track->get_active_path();
1048                         if(!(track_ep.paths&(1<<path)))
1049                         {
1050                                 for(unsigned i=0; track_ep.paths>>i; ++i)
1051                                         if(track_ep.paths&(1<<i))
1052                                                 path = i;
1053                         }
1054
1055                         if(path!=static_cast<int>(entry_ep.track->get_active_path()))
1056                         {
1057                                 // The turnout is set to wrong path - switch and wait for it
1058                                 pending_block = link;
1059                                 entry_ep.track->set_active_path(path);
1060                                 if(pending_block)
1061                                 {
1062                                         link->reserve(0);
1063                                         break;
1064                                 }
1065                         }
1066
1067                         if(multiple_paths && cur_route!=routes.end() && cur_route->diversion!=link->get_turnout_id())
1068                                 /* There's multiple paths to be taken and we are on a route - take
1069                                 note of the diversion possibility */
1070                                 divert_track = entry_ep.track;
1071                 }
1072
1073                 if(!contested_blocks.empty() && contested_blocks.front().block==link)
1074                         contested_blocks.pop_front();
1075
1076                 rsv_blocks.push_back(BlockRef(link, entry));
1077                 last = &rsv_blocks.back();
1078                 if(last->block->get_sensor_id())
1079                         ++nsens;
1080                 if(nsens>0)
1081                         dist += length;
1082         }
1083
1084         // Unreserve blocks that were not good
1085         while(!rsv_blocks.empty() && &rsv_blocks.back()!=good)
1086         {
1087                 rsv_blocks.back().block->reserve(0);
1088                 rsv_blocks.pop_back();
1089         }
1090
1091         if(!rsv_blocks.empty() && &rsv_blocks.back()!=start)
1092                 // We got some new blocks, so no longer need to yield
1093                 yielding_to = 0;
1094
1095         // Make any sensorless blocks at the beginning immediately current
1096         list<BlockRef>::iterator i;
1097         for(i=rsv_blocks.begin(); (i!=rsv_blocks.end() && !i->block->get_sensor_id()); ++i) ;
1098         if(i!=rsv_blocks.begin())
1099                 cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i);
1100
1101         if(try_divert && divert(*divert_track))
1102                 return reserve_more();
1103
1104         return good_sens;
1105 }
1106
1107 float Train::get_reserved_distance_until(const Block *until_block, bool back) const
1108 {
1109         if(cur_blocks.empty())
1110                 return 0;
1111
1112         Vehicle &veh = *(reverse!=back ? vehicles.back() : vehicles.front());
1113         const VehicleType &vtype = veh.get_type();
1114
1115         Track *track = veh.get_track();
1116         if(!track)
1117                 return 0;
1118
1119         list<BlockRef>::const_iterator block = cur_blocks.begin();
1120         while(block!=rsv_blocks.end() && !block->block->get_tracks().count(track))
1121         {
1122                 ++block;
1123                 if(block==cur_blocks.end())
1124                 {
1125                         if(back)
1126                                 return 0;
1127                         block = rsv_blocks.begin();
1128                 }
1129         }
1130         if(block==rsv_blocks.end() || block->block==until_block)
1131                 return 0;
1132
1133         unsigned entry = veh.get_entry();
1134
1135         float result = veh.get_offset();
1136         if(reverse!=back)
1137                 entry = track->traverse(entry);
1138         else
1139                 result = track->get_type().get_path_length(track->get_active_path())-result;
1140         result -= vtype.get_length()/2;
1141
1142         while(1)
1143         {
1144                 if(track->get_type().get_endpoints().size()<2)
1145                         break;
1146
1147                 Track *next = track->get_link(track->traverse(entry));
1148
1149                 if(!block->block->get_tracks().count(next))
1150                 {
1151                         if(back)
1152                         {
1153                                 if(block==cur_blocks.begin())
1154                                         break;
1155                                 --block;
1156                         }
1157                         else
1158                         {
1159                                 ++block;
1160                                 if(block==cur_blocks.end())
1161                                         block = rsv_blocks.begin();
1162                                 if(block==rsv_blocks.end())
1163                                         break;
1164                         }
1165
1166                         if(block->block==until_block)
1167                                 break;
1168                 }
1169
1170                 entry = next->get_endpoint_by_link(*track);
1171                 track = next;
1172
1173                 result += track->get_type().get_path_length(track->get_active_path());
1174         }
1175
1176         return result;
1177 }
1178
1179 float Train::get_real_speed(unsigned i) const
1180 {
1181         if(real_speed[i].weight)
1182                 return real_speed[i].speed;
1183
1184         unsigned low;
1185         unsigned high;
1186         for(low=i; low>0; --low)
1187                 if(real_speed[low].weight)
1188                         break;
1189         for(high=i; high<14; ++high)
1190                 if(real_speed[high].weight)
1191                         break;
1192
1193         if(real_speed[high].weight)
1194         {
1195                 if(real_speed[low].weight)
1196                 {
1197                         float f = float(i-low)/(high-low);
1198                         return real_speed[low].speed*(1-f)+real_speed[high].speed*f;
1199                 }
1200                 else
1201                         return real_speed[high].speed*float(i)/high;
1202         }
1203         else if(real_speed[low].weight)
1204                 return real_speed[low].speed*float(i)/low;
1205         else
1206                 return 0;
1207 }
1208
1209 unsigned Train::find_speed(float real) const
1210 {
1211         if(real<=real_speed[0].speed)
1212                 return 0;
1213
1214         unsigned low = 0;
1215         unsigned high = 0;
1216         unsigned last = 0;
1217         for(unsigned i=0; (!high && i<=14); ++i)
1218                 if(real_speed[i].weight)
1219                 {
1220                         last = i;
1221                         if(real_speed[i].speed<real)
1222                                 low = i;
1223                         else
1224                                 high = i;
1225                 }
1226         if(!high)
1227         {
1228                 if(!low)
1229                 {
1230                         if(real)
1231                                 return 3;
1232                         else
1233                                 return 0;
1234                 }
1235                 return min(min(static_cast<unsigned>(low*real/real_speed[low].speed), 14U), last+3);
1236         }
1237
1238         float f = (real-real_speed[low].speed)/(real_speed[high].speed-real_speed[low].speed);
1239         return static_cast<unsigned>(low*(1-f)+high*f+0.5);
1240 }
1241
1242 float Train::get_travel_speed() const
1243 {
1244         float speed = get_real_speed(current_speed);
1245         float scale = layout.get_catalogue().get_scale();
1246         return static_cast<int>(round(speed/scale*3.6/5))*5;
1247 }
1248
1249 void Train::set_status(const string &s)
1250 {
1251         status = s;
1252         signal_status_changed.emit(s);
1253 }
1254
1255 void Train::release_blocks(list<BlockRef> &blocks)
1256 {
1257         release_blocks(blocks, blocks.begin(), blocks.end());
1258 }
1259
1260 void Train::release_blocks(list<BlockRef> &blocks, list<BlockRef>::iterator begin, list<BlockRef>::iterator end)
1261 {
1262         while(begin!=end)
1263         {
1264                 Block *block = begin->block;
1265                 blocks.erase(begin++);
1266                 block->reserve(0);
1267         }
1268 }
1269
1270 void Train::reverse_blocks(list<BlockRef> &blocks) const
1271 {
1272         blocks.reverse();
1273         for(list<BlockRef>::iterator i=blocks.begin(); i!=blocks.end(); ++i)
1274                 i->entry = i->block->traverse(i->entry);
1275 }
1276
1277 bool Train::advance_route(list<RouteRef>::iterator &iter, const Track &track)
1278 {
1279         while(iter!=routes.end() && !iter->route->get_tracks().count(&track))
1280                 ++iter;
1281         if(iter==routes.end())
1282                 return false;
1283
1284         list<RouteRef>::iterator next = iter;
1285         ++next;
1286         if(next!=routes.end() && next->diversion && next->route->get_tracks().count(&track))
1287                 iter = next;
1288
1289         return true;
1290 }
1291
1292 Route *Train::create_lead_route(Route *lead, const Route *target)
1293 {
1294         if(!lead)
1295         {
1296                 lead = new Route(layout);
1297                 lead->set_name("Lead");
1298                 lead->set_temporary(true);
1299         }
1300
1301         set<const Track *> tracks;
1302         for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=rsv_blocks.end(); )
1303         {
1304                 const set<Track *> &btracks = i->block->get_tracks();
1305                 for(set<Track *>::const_iterator j=btracks.begin(); j!=btracks.end(); ++j)
1306                         if(!target || !target->get_tracks().count(*j))
1307                                 tracks.insert(*j);
1308
1309                 if(++i==cur_blocks.end())
1310                         i = rsv_blocks.begin();
1311         }
1312
1313         lead->add_tracks(tracks);
1314
1315         return lead;
1316 }
1317
1318 bool Train::is_valid_diversion(const Route &diversion, const Track &from, unsigned from_ep)
1319 {
1320         float diversion_len = 0;
1321         const Track *track = &from;
1322         unsigned ep = from_ep;
1323         while(diversion.get_tracks().count(track))
1324         {
1325                 unsigned path = 0;
1326                 if(track->get_turnout_id())
1327                         path = diversion.get_turnout(track->get_turnout_id());
1328                 diversion_len += track->get_type().get_path_length(path);
1329
1330                 const Track *next = track->get_link(track->traverse(ep, path));
1331                 ep = next->get_endpoint_by_link(*track);
1332                 track = next;
1333
1334                 if(track==&from)
1335                         return false;
1336         }
1337
1338         list<RouteRef>::iterator route = routes.begin();
1339         if(!advance_route(route, from))
1340                 return false;
1341
1342         set<const Track *> visited;
1343         float route_len = 0;
1344         track = &from;
1345         ep = from_ep;
1346         while(1)
1347         {
1348                 unsigned path = 0;
1349                 if(track->get_turnout_id())
1350                         path = route->route->get_turnout(track->get_turnout_id());
1351                 route_len += track->get_type().get_path_length(path);
1352
1353                 if(track!=&from && diversion.get_tracks().count(track))
1354                         break;
1355
1356                 if(visited.count(track))
1357                         return false;
1358                 visited.insert(track);
1359
1360                 const Track *next = track->get_link(track->traverse(ep, path));
1361                 ep = next->get_endpoint_by_link(*track);
1362                 track = next;
1363
1364                 if(!advance_route(route, *track))
1365                         return false;
1366         }
1367
1368         return diversion_len<route_len*1.2;
1369 }
1370
1371
1372 Train::BlockRef::BlockRef(Block *b, unsigned e):
1373         block(b),
1374         entry(e)
1375 { }
1376
1377 Train::BlockRef Train::BlockRef::next() const
1378 {
1379         Block *blk = block->get_endpoints()[block->traverse(entry)].link;
1380         if(!blk)
1381                 throw InvalidState("At end of line");
1382
1383         int ep = blk->get_endpoint_by_link(*block);
1384         if(ep<0)
1385                 throw LogicError("Block links are inconsistent");
1386
1387         return BlockRef(blk, ep);
1388 }
1389
1390
1391 Train::RouteRef::RouteRef(const Route *r, unsigned d):
1392         route(r),
1393         diversion(d)
1394 { }
1395
1396
1397 Train::RealSpeed::RealSpeed():
1398         speed(0),
1399         weight(0)
1400 { }
1401
1402 void Train::RealSpeed::add(float s, float w)
1403 {
1404         speed = (speed*weight+s*w)/(weight+w);
1405         weight = min(weight+w, 300.0f);
1406 }
1407
1408
1409 Train::Loader::Loader(Train &t):
1410         DataFile::BasicLoader<Train>(t),
1411         prev_block(0),
1412         blocks_valid(true)
1413 {
1414         add("block",       &Loader::block);
1415         add("block_hint",  &Loader::block_hint);
1416         add("name",        &Loader::name);
1417         add("priority",    &Train::priority);
1418         add("real_speed",  &Loader::real_speed);
1419         add("route",       &Loader::route);
1420         add("timetable",   &Loader::timetable);
1421         add("vehicle",     &Loader::vehicle);
1422 }
1423
1424 void Train::Loader::finish()
1425 {
1426         if(!obj.cur_blocks.empty())
1427         {
1428                 const BlockRef &blkref = obj.cur_blocks.front();
1429                 const Block::Endpoint &bep = blkref.block->get_endpoints()[blkref.entry];
1430                 float offset = 2*obj.layout.get_catalogue().get_scale();
1431                 obj.vehicles.back()->place(*bep.track, bep.track_ep, offset, Vehicle::BACK_BUFFER);
1432
1433                 obj.set_status("Stopped");
1434         }
1435 }
1436
1437 void Train::Loader::block(unsigned id)
1438 {
1439         if(!blocks_valid)
1440                 return;
1441
1442         Block *blk;
1443         try
1444         {
1445                 blk = &obj.layout.get_block(id);
1446         }
1447         catch(const KeyError &)
1448         {
1449                 blocks_valid = false;
1450                 return;
1451         }
1452
1453         int entry = -1;
1454         if(prev_block)
1455                 entry = blk->get_endpoint_by_link(*prev_block);
1456         if(entry<0)
1457                 entry = 0;
1458
1459         blk->reserve(&obj);
1460         obj.cur_blocks.push_back(BlockRef(blk, entry));
1461
1462         if(blk->get_sensor_id())
1463                 obj.layout.get_driver().set_sensor(blk->get_sensor_id(), true);
1464
1465         prev_block = blk;
1466 }
1467
1468 void Train::Loader::block_hint(unsigned id)
1469 {
1470         try
1471         {
1472                 prev_block = &obj.layout.get_block(id);
1473         }
1474         catch(const KeyError &)
1475         {
1476                 blocks_valid = false;
1477         }
1478 }
1479
1480 void Train::Loader::name(const string &n)
1481 {
1482         obj.set_name(n);
1483 }
1484
1485 void Train::Loader::real_speed(unsigned i, float speed, float weight)
1486 {
1487         obj.real_speed[i].speed = speed;
1488         obj.real_speed[i].weight = weight;
1489 }
1490
1491 void Train::Loader::route(const string &n)
1492 {
1493         obj.set_route(&obj.layout.get_route(n));
1494 }
1495
1496 void Train::Loader::timetable()
1497 {
1498         if(obj.timetable)
1499                 throw InvalidState("A timetable has already been loaded");
1500
1501         obj.timetable = new Timetable(obj);
1502         load_sub(*obj.timetable);
1503 }
1504
1505 void Train::Loader::vehicle(unsigned n)
1506 {
1507         const VehicleType &vtype = obj.layout.get_catalogue().get_vehicle(n);
1508         Vehicle *veh = new Vehicle(obj.layout, vtype);
1509         obj.vehicles.back()->attach_back(*veh);
1510         obj.vehicles.push_back(veh);
1511 }
1512
1513 } // namespace Marklin