TrainRoutePlanner::TrainRoutePlanner(Layout &layout):
goal(0),
+ path_switch_bias(15*Time::sec),
timeout(10*Time::sec),
result(PENDING),
thread(0)
{
list<RoutingStep> new_steps;
step.create_successors(new_steps);
+ if(new_steps.empty())
+ return;
+
new_steps.sort();
+ if(!queue.empty() && new_steps.front().cost_estimate<queue.front().cost_estimate+path_switch_bias)
+ new_steps.front().preferred = true;
queue.merge(new_steps);
}
Time::TimeDelta TrainRoutePlanner::TrainRoutingState::get_time_to_next_track() const
{
- return ((track->get_type().get_path_length(path)-offset)/info->speed)*Time::sec+delay;
+ return ((occupied_tracks->path_length-offset)/info->speed)*Time::sec+delay;
}
Time::TimeDelta TrainRoutePlanner::TrainRoutingState::get_time_to_pass(Track &trk) const
offset = 0;
}
+void TrainRoutePlanner::TrainRoutingState::set_path(unsigned p)
+{
+ path = p;
+ OccupiedTrack *next_occ = occupied_tracks->next;
+ if(!--occupied_tracks->refcount)
+ delete occupied_tracks;
+ occupied_tracks = new OccupiedTrack(*track, path, next_occ);
+ update_estimate();
+}
+
void TrainRoutePlanner::TrainRoutingState::update_estimate()
{
TrackIter iter = track.reverse(path);
remaining_estimate = info->metrics[waypoint]->get_distance_from(*iter.track(), iter.entry());
if(remaining_estimate>=0)
- remaining_estimate += track->get_type().get_path_length(path)-offset;
+ remaining_estimate += occupied_tracks->path_length-offset;
}
bool TrainRoutePlanner::TrainRoutingState::is_viable() const
TrainRoutePlanner::RoutingStep::RoutingStep():
+ preferred(false),
prev(0)
{ }
TrainRoutePlanner::RoutingStep::RoutingStep(const RoutingStep *p):
time(p->time),
- penalty(p->penalty),
cost_estimate(p->cost_estimate),
+ preferred(false),
trains(p->trains),
prev(p)
{ }
create_successor(next, train_index, i, new_steps);
}
- new_steps.sort();
- for(list<RoutingStep>::iterator i=new_steps.begin(); ++i!=new_steps.end(); )
- {
- i->penalty += 5*Time::sec;
- i->update_estimate();
- }
-
if(entry_ep.paths!=train.track->get_type().get_paths() && !train.critical)
{
/* Create a waiting state before the track if there's at least one path
{
TrainRoutingState &train = next.trains[train_index];
- train.path = path;
- train.update_estimate();
+ train.set_path(path);
next.update_estimate();
if(next.is_viable())
new_steps.push_back(next);
void TrainRoutePlanner::RoutingStep::update_estimate()
{
- cost_estimate = penalty;
+ cost_estimate = Time::zero;
for(vector<TrainRoutingState>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
if(i->remaining_estimate>=0)
cost_estimate += i->wait_time+i->estimated_wait+((i->distance_traveled+i->remaining_estimate)/i->info->speed)*Time::sec;
bool TrainRoutePlanner::RoutingStep::operator<(const RoutingStep &other) const
{
+ if(preferred!=other.preferred)
+ return preferred>other.preferred;
return cost_estimate<other.cost_estimate;
}