]> git.tdb.fi Git - r2c2.git/commitdiff
Keep better track of routes
authorMikko Rasa <tdb@tdb.fi>
Tue, 15 Apr 2014 15:25:34 +0000 (18:25 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 15 Apr 2014 15:34:17 +0000 (18:34 +0300)
Finding the correct route for each allocated block from scratch is prone
to errors if the combined route contains loops.

source/libr2c2/trainrouter.cpp
source/libr2c2/trainrouter.h

index 4b7e1bc9ca54395a3a9221c71230e93eb9832dec..44a97f52c3e3606ae6d87eeed2c791cc93ab126f 100644 (file)
@@ -84,10 +84,30 @@ const Route *TrainRouter::get_route() const
 
 void TrainRouter::route_changed()
 {
-       train.stop_at(0);
-       arriving = 0;
        BlockIter fncb = train.get_first_noncritical_block();
-       train.refresh_blocks_from(*fncb);
+
+       reserving_route = routes.begin();
+       bool already_at_end = false;
+       if(!routes.empty())
+       {
+               TrackIter track = train.get_block_allocator().first().track_iter();
+               for(; track; track=track.next())
+               {
+                       if(!advance_to_track(reserving_route, *track))
+                       {
+                               already_at_end = true;
+                               break;
+                       }
+                       if(&track->get_block()==fncb.block())
+                               break;
+               }
+       }
+
+       if(!already_at_end)
+       {
+               train.stop_at(0);
+               train.refresh_blocks_from(*fncb);
+       }
 
        const Route *route = get_route();
        signal_route_changed.emit(route);
@@ -238,6 +258,9 @@ void TrainRouter::save(list<DataFile::Statement> &st) const
 
 void TrainRouter::block_reserved(Block &block, Train *t)
 {
+       if(routes.empty())
+               return;
+
        if(t!=&train)
        {
                if(!t)
@@ -265,35 +288,46 @@ void TrainRouter::block_reserved(Block &block, Train *t)
                }
        }
 
-       BlockIter b_iter = t->get_block_allocator().iter_for(block);
+       TrackIter track = train.get_block_allocator().iter_for(block).track_iter();
 
-       RouteList::iterator route = routes.begin();
-       if(advance_route(route, block))
+       // Is the block a turnout?  If so, set it to the proper path.
+       if(unsigned taddr = block.get_turnout_address())
        {
-               // Check if the block is a turnout and set it to proper path
-               if(unsigned taddr = block.get_turnout_address())
+               int path = (*reserving_route)->get_turnout(taddr);
+               if(path>=0)
+                       track->set_active_path(path);
+       }
+
+       if(reserving_route==routes.end() || !(*reserving_route)->has_track(*track))
+       {
+               reserving_route = routes.begin();
+               track = t->get_block_allocator().first().track_iter();
+               for(; track; track=track.next())
                {
-                       int path = (*route)->get_turnout(taddr);
-                       if(path>=0)
-                               b_iter.track_iter()->set_active_path(path);
+                       if(!advance_to_track(reserving_route, *track))
+                               throw logic_error("internal error (reservation outside of route)");
+                       else if(&track->get_block()==&block)
+                               break;
                }
+       }
 
-               // Check if the next block is still part of the designated route
-               BlockIter b_iter_next = b_iter.next(*route);
-
-               RouteList::iterator next_route = route;
-               if(!advance_route(next_route, *b_iter_next))
+       // Do we need to move to the next route?
+       for(; track; track=track.next((*reserving_route)->get_path(*track)))
+       {
+               if(!advance_to_track(reserving_route, *track))
                {
                        train.stop_at(&block);
                        return;
                }
+               if(&track->get_block()!=&block)
+                       break;
+       }
 
-               if(!sequence_points.empty())
-               {
-                       SequencePoint &sp = sequence_points.front();
-                       if(sp.block==b_iter_next.block() && !sp.is_cleared())
-                               train.stop_at(&block);
-               }
+       if(!sequence_points.empty())
+       {
+               SequencePoint &sp = sequence_points.front();
+               if(sp.block==&track->get_block() && !sp.is_cleared())
+                       train.stop_at(&block);
        }
 }
 
@@ -406,26 +440,27 @@ Route *TrainRouter::create_lead_route(Route *lead, const Route *target)
        return lead;
 }
 
-bool TrainRouter::advance_route(RouteList::iterator &iter, const Block &block)
+bool TrainRouter::is_valid_for_track(const Route &route, Track &track) const
 {
-       const set<Track *> &tracks = block.get_tracks();
-       unsigned turnout_addr = block.get_turnout_address();
-       for(; iter!=routes.end(); ++iter)
-       {
-               if(turnout_addr && (*iter)->get_turnout(turnout_addr)<0)
-                       continue;
-               for(set<Track *>::const_iterator j=tracks.begin(); j!=tracks.end(); ++j)
-                       if((*iter)->has_track(**j))
-                               return true;
-       }
-
-       return false;
+       if(!route.has_track(track))
+               return false;
+       if(track.get_type().is_turnout() && route.get_turnout(track.get_turnout_address())<0)
+               return false;
+       return true;
 }
 
-bool TrainRouter::is_on_route(const Block &block)
+bool TrainRouter::advance_to_track(RouteList::iterator &route, Track &track)
 {
-       RouteList::iterator iter = routes.begin();
-       return advance_route(iter, block);
+       if(!is_valid_for_track(**route, track))
+       {
+               ++route;
+               if(route==routes.end())
+                       return false;
+               if(!is_valid_for_track(**route, track))
+                       throw logic_error("internal error (routes are not continuous)");
+       }
+
+       return true;
 }
 
 void TrainRouter::start_planning(Layout &layout)
index 47a409cd7cb2bdb36064f753e5c2f9cadd4bca77..1c523d89e96fe1d2d1c7bb04fa9d4f141d95b76b 100644 (file)
@@ -46,6 +46,7 @@ private:
 
        int priority;
        RouteList routes;
+       RouteList::iterator reserving_route;
        unsigned arriving;
        const TrackChain *destination;
        std::vector<const TrackChain *> waypoints;
@@ -94,8 +95,8 @@ private:
 
        void create_metrics();
        Route *create_lead_route(Route *, const Route *);
-       bool advance_route(RouteList::iterator &, const Block &);
-       bool is_on_route(const Block &);
+       bool is_valid_for_track(const Route &, Track &) const;
+       bool advance_to_track(RouteList::iterator &, Track &);
 
        static void start_planning(Layout &);
 };