* @param graph the graph where annotations will be registered
*/
private void filterStopTimes(List<StopTime> stopTimes, Graph graph) {
if (stopTimes.size() < 2) return;
StopTime st0 = stopTimes.get(0);
/* Set departure time if it is missing */
if (!st0.isDepartureTimeSet() && st0.isArrivalTimeSet()) {
st0.setDepartureTime(st0.getArrivalTime());
}
/* If the feed does not specify any timepoints, we want to mark all times that are present as timepoints. */
boolean hasTimepoints = false;
for (StopTime stopTime : stopTimes) {
if (stopTime.getTimepoint() == 1) {
hasTimepoints = true;
break;
}
}
// TODO verify that the first (and last?) stop should always be considered a timepoint.
if (!hasTimepoints) st0.setTimepoint(1);
/* Indicates that stop times in this trip are being shifted forward one day. */
boolean midnightCrossed = false;
for (int i = 1; i < stopTimes.size(); i++) {
boolean st1bogus = false;
StopTime st1 = stopTimes.get(i);
/* If the feed did not specify any timepoints, mark all times that are present as timepoints. */
if ( !hasTimepoints && (st1.isDepartureTimeSet() || st1.isArrivalTimeSet())) {
st1.setTimepoint(1);
}
if (midnightCrossed) {
if (st1.isDepartureTimeSet())
st1.setDepartureTime(st1.getDepartureTime() + 24 * SECONDS_IN_HOUR);
if (st1.isArrivalTimeSet())
st1.setArrivalTime(st1.getArrivalTime() + 24 * SECONDS_IN_HOUR);
}
/* Set departure time if it is missing. */
// TODO: doc: what if arrival time is missing?
if (!st1.isDepartureTimeSet() && st1.isArrivalTimeSet()) {
st1.setDepartureTime(st1.getArrivalTime());
}
/* Do not process (skip over) non-timepoint stoptimes, leaving them in place for interpolation. */
// All non-timepoint stoptimes in a series will have identical arrival and departure values of MISSING_VALUE.
if ( ! (st1.isArrivalTimeSet() && st1.isDepartureTimeSet())) {
continue;
}
int dwellTime = st0.getDepartureTime() - st0.getArrivalTime();
if (dwellTime < 0) {
LOG.warn(graph.addBuilderAnnotation(new NegativeDwellTime(st0)));
if (st0.getArrivalTime() > 23 * SECONDS_IN_HOUR && st0.getDepartureTime() < 1 * SECONDS_IN_HOUR) {
midnightCrossed = true;
st0.setDepartureTime(st0.getDepartureTime() + 24 * SECONDS_IN_HOUR);
} else {
st0.setDepartureTime(st0.getArrivalTime());
}
}
int runningTime = st1.getArrivalTime() - st0.getDepartureTime();
if (runningTime < 0) {
LOG.warn(graph.addBuilderAnnotation(new NegativeHopTime(new StopTime(st0), new StopTime(st1))));
// negative hops are usually caused by incorrect coding of midnight crossings
midnightCrossed = true;
if (st0.getDepartureTime() > 23 * SECONDS_IN_HOUR && st1.getArrivalTime() < 1 * SECONDS_IN_HOUR) {
st1.setArrivalTime(st1.getArrivalTime() + 24 * SECONDS_IN_HOUR);
} else {
st1.setArrivalTime(st0.getDepartureTime());
}
}
double hopDistance = distanceLibrary.fastDistance(
st0.getStop().getLat(), st0.getStop().getLon(),
st1.getStop().getLat(), st1.getStop().getLon());
double hopSpeed = hopDistance/runningTime;
/* zero-distance hops are probably not harmful, though they could be better
* represented as dwell times
if (hopDistance == 0) {
LOG.warn(GraphBuilderAnnotation.register(graph,
Variety.HOP_ZERO_DISTANCE, runningTime,
st1.getTrip().getId(),
st1.getStopSequence()));
}
*/
// sanity-check the hop
if (st0.getArrivalTime() == st1.getArrivalTime() ||
st0.getDepartureTime() == st1.getDepartureTime()) {
LOG.trace("{} {}", st0, st1);
// series of identical stop times at different stops
LOG.trace(graph.addBuilderAnnotation(new HopZeroTime((float) hopDistance,
st1.getTrip(), st1.getStopSequence())));
// clear stoptimes that are obviously wrong, causing them to later be interpolated
/* FIXME (lines commented out because they break routability in multi-feed NYC for some reason -AMB) */
// st1.clearArrivalTime();
// st1.clearDepartureTime();
st1bogus = true;