i->base_distance = metric.get_distance_from(*i->track.track(), i->track.entry());
}
+float TrainRouteMetric::get_distance_from(const Track &track) const
+{
+ map<Key, Data>::const_iterator i = tracks.lower_bound(Key(&track, 0));
+ map<Key, Data>::const_iterator j = tracks.upper_bound(Key(&track, 255));
+
+ float result = -1;
+ for(; i!=j; ++i)
+ {
+ float d = i->second.distance+i->second.goal->base_distance;
+ if(result<0 || d<result)
+ result = d;
+ }
+
+ return result;
+}
+
float TrainRouteMetric::get_distance_from(const Track &track, unsigned exit) const
{
map<Key, Data>::const_iterator i = tracks.find(Key(&track, exit));
distance_traveled(other.distance_traveled),
remaining_estimate(other.remaining_estimate),
wait_time(other.wait_time),
+ estimated_wait(other.estimated_wait),
blocked_by(other.blocked_by)
{
++occupied_tracks->refcount;
return ((track->get_type().get_path_length(path)-offset)/info->speed)*Time::sec+delay;
}
+Time::TimeDelta TrainRoutePlanner::TrainRoutingState::get_time_to_pass(Track &trk) const
+{
+ if(is_occupying(trk))
+ return Time::zero;
+
+ for(unsigned wp=waypoint; wp<info->waypoints.size(); ++wp)
+ {
+ float distance = info->metrics[wp]->get_distance_from(trk);
+ if(distance>=0 && distance<remaining_estimate)
+ return ((remaining_estimate-distance)/info->speed)*Time::sec+delay;
+ }
+
+ return Time::day;
+}
+
bool TrainRoutePlanner::TrainRoutingState::is_occupying(Track &trk) const
{
if(state==ARRIVED && !duration && info->has_duration)
if(duration)
duration = max(duration-secs*Time::sec, Time::zero);
+ if(estimated_wait)
+ estimated_wait = max(estimated_wait-secs*Time::sec, Time::zero);
+
if(state==MOVING)
advance(info->speed*secs);
else if(state!=ARRIVED)
RoutingStep wait(this);
wait.advance(dt);
wait.trains[train_index].state = WAITING;
- wait.penalty += 15*Time::sec;
+
+ Time::TimeDelta estimated_wait = Time::day;
+ for(unsigned i=0; i<wait.trains.size(); ++i)
+ if(i!=static_cast<unsigned>(train_index) && wait.trains[i].state!=ARRIVED)
+ {
+ Time::TimeDelta ttp = wait.trains[i].get_time_to_pass(*train.track);
+ estimated_wait = min(estimated_wait, ttp);
+ }
+ wait.trains[train_index].estimated_wait = estimated_wait;
+
wait.update_estimate();
if(wait.is_viable())
new_steps.push_back(wait);
cost_estimate = penalty;
for(vector<TrainRoutingState>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
if(i->remaining_estimate>=0)
- cost_estimate += i->wait_time+((i->distance_traveled+i->remaining_estimate)/i->info->speed)*Time::sec;
+ cost_estimate += i->wait_time+i->estimated_wait+((i->distance_traveled+i->remaining_estimate)/i->info->speed)*Time::sec;
}
bool TrainRoutePlanner::RoutingStep::is_viable() const
float distance_traveled;
float remaining_estimate;
Msp::Time::TimeDelta wait_time;
+ Msp::Time::TimeDelta estimated_wait;
int blocked_by;
TrainRoutingState(TrainRoutingInfo &);
~TrainRoutingState();
Msp::Time::TimeDelta get_time_to_next_track() const;
+ Msp::Time::TimeDelta get_time_to_pass(Track &) const;
bool is_occupying(Track &) const;
bool check_arrival();
void advance(float);