org.opentripplanner.profile.PatternRide Maven / Gradle / Ivy
package org.opentripplanner.profile;
import org.opentripplanner.model.Stop;
import org.opentripplanner.routing.edgetype.TripPattern;
/**
* A ride between two stops on a single pattern. One or more PatternRides can be included in a Ride.
* Each Pattern needs its own separate PatternRide because stop indexes may be different on every
* pattern of a route, and we need to store indexes rather than stop objects because a stop can
* appear more than once in a pattern. When a ride is unfinished (waiting in the queue for
* exploration in the next round) its toIndex is -1 and its stats field is null.
*/
class PatternRide {
final TripPattern pattern; // TripPatterns use identity equality
final int fromIndex; // Always set, even on unfinished PatternRides
final int toIndex; // set when PatternRide is finished by extending it to a specific stop
final Stats stats; // set when PatternRide is finished by extending it to a specific stop
@Override
public boolean equals(Object o){
if(o==this) return true;
if (!(o instanceof PatternRide)) return false;
PatternRide other = (PatternRide) o;
if(!other.pattern.equals(this.pattern)) return false;
if(other.fromIndex != fromIndex) return false;
if(other.toIndex != toIndex) return false;
if(!other.stats.equals(this.stats)) return false;
return true;
}
/** Construct an unfinished PatternRide, lacking a toIndex and stats. */
public PatternRide (TripPattern pattern, int fromIndex) {
this.pattern = pattern;
this.fromIndex = fromIndex;
this.toIndex = -1;
this.stats = null;
}
/** Construct an unfinished PatternRide (lacking toIndex and stats) from another PatternRide. */
public PatternRide (PatternRide other, int toIndex, Stats stats) {
this.pattern = other.pattern;
this.fromIndex = other.fromIndex;
this.toIndex = toIndex;
this.stats = stats;
}
public Stop getFromStop() {
return pattern.getStops().get(fromIndex);
}
public Stop getToStop() {
return pattern.getStops().get(toIndex);
}
public boolean finished () {
return toIndex >= 0 && stats != null;
}
public String toString () {
return String.format("%s %d to %d", pattern.code, fromIndex, toIndex);
}
/**
* Complete an unfinished ride as a new object.
* Perhaps we should check in advance whether a pattern is running at all, but results will vary depending on the
* fromIndex and toIndex. Some indexes can be reached within the window, others not. But that's an optimization.
* It's actually advantageous to call this sequentially for each to-stop instead of incrementally along a pattern.
* This is because we store the absolute times of arrivals and departures, and by subtracting those we get accurate
* min and max ride times rather than looser lower and upper bounds on travel time.
*/
public PatternRide extendToIndex(int toIndex, TimeWindow window) {
Stats stats = Stats.create (pattern, fromIndex, toIndex, window);
/* There might not be any trips within the time window. */
if (stats == null) return null;
/* Copy most fields from this unfinished ride, setting the other fields to complete the ride. */
PatternRide ret = new PatternRide(this, toIndex, stats);
return ret;
}
}