Skip to content

Commit

Permalink
Merge pull request #307 from pailakka/realtime-fixes
Browse files Browse the repository at this point in the history
Realtime fixes
  • Loading branch information
optionsome authored May 20, 2019
2 parents 74eff2e + c4366f1 commit 2c8c25a
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/opentripplanner/index/IndexAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public Response getStoptimesForStopAndDate (@PathParam("stopId") String stopIdSt
return Response.status(Status.BAD_REQUEST).entity(MSG_400).build();
}

List<StopTimesInPattern> ret = index.getStopTimesForStop(stop, sd, omitNonPickups);
List<StopTimesInPattern> ret = index.getStopTimesForStop(stop, sd, omitNonPickups, false);
return Response.status(Status.OK).entity(ret).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1440,7 +1440,7 @@ public IndexGraphQLSchema(GraphIndex index) {
.name("omitCanceled")
.description("If false, returns also canceled trips")
.type(Scalars.GraphQLBoolean)
.defaultValue(true)
.defaultValue(false)
.build())
.dataFetcher(environment -> {
ServiceDate date;
Expand All @@ -1451,15 +1451,16 @@ public IndexGraphQLSchema(GraphIndex index) {
}
Stop stop = environment.getSource();
boolean omitNonPickups = environment.getArgument("omitNonPickups");
boolean omitCanceled = environment.getArgument("omitCanceled");
if (stop.getLocationType() == 1) {
// Merge all stops if this is a station
return index.stopsForParentStation
.get(stop.getId())
.stream()
.flatMap(singleStop -> index.getStopTimesForStop(singleStop, date, omitNonPickups).stream())
.flatMap(singleStop -> index.getStopTimesForStop(singleStop, date, omitNonPickups, omitCanceled).stream())
.collect(Collectors.toList());
}
return index.getStopTimesForStop(stop, date, omitNonPickups);
return index.getStopTimesForStop(stop, date, omitNonPickups, omitCanceled);
})
.build())
.field(GraphQLFieldDefinition.newFieldDefinition()
Expand Down
49 changes: 39 additions & 10 deletions src/main/java/org/opentripplanner/routing/edgetype/Timetable.java
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone

int numStops = newTimes.getNumStops();
Integer delay = null;
Integer firstDelay = null;
boolean hasMatched = false;
for (int i = 0; i < numStops; i++) {
boolean match = false;
Expand All @@ -432,22 +433,37 @@ public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone
StopTimeUpdate.ScheduleRelationship scheduleRelationship =
update.hasScheduleRelationship() ? update.getScheduleRelationship()
: StopTimeUpdate.ScheduleRelationship.SCHEDULED;
if (scheduleRelationship == StopTimeUpdate.ScheduleRelationship.SKIPPED) {
LOG.warn("Partially canceled trips are unsupported by this method." +
" Skipping TripUpdate.");
return null;
} else if (scheduleRelationship ==
if (scheduleRelationship ==
StopTimeUpdate.ScheduleRelationship.NO_DATA) {
newTimes.updateArrivalDelay(i, 0);
newTimes.updateDepartureDelay(i, 0);
delay = 0;
if (firstDelay == null) firstDelay = delay;
} else {
long today = updateServiceDate.getAsDate(timeZone).getTime() / 1000;
StopTimeEvent arrival = null;
StopTimeEvent departure = null;

if (update.hasArrival() && (update.getArrival().hasTime() || update.getArrival().hasDelay())) {
StopTimeEvent arrival = update.getArrival();
arrival = update.getArrival();
}

if (update.hasDeparture() && (update.getDeparture().hasTime() || update.getDeparture().hasDelay())) {
departure = update.getDeparture();
}

if (arrival == null && departure != null) {
arrival = departure;
}

if (departure == null && arrival != null) {
departure = arrival;
}

if (arrival != null) {
if (arrival.hasDelay()) {
delay = arrival.getDelay();
if (firstDelay == null) firstDelay = delay;
if (arrival.hasTime()) {
newTimes.updateArrivalTime(i,
(int) (arrival.getTime() - today));
Expand All @@ -458,13 +474,14 @@ public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone
newTimes.updateArrivalTime(i,
(int) (arrival.getTime() - today));
delay = newTimes.getArrivalDelay(i);
if (firstDelay == null) firstDelay = delay;
} else {
LOG.error("Arrival time at index {} is erroneous.", i);
return null;
}
} else {
if (delay == null) {
newTimes.updateArrivalDelay(i, TripTimes.UNAVAILABLE);
newTimes.cancelArrivalTime(i);
} else {
newTimes.updateArrivalDelay(i, delay);
if (newTimes.isCanceledArrival(i)) {
Expand All @@ -473,10 +490,10 @@ public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone
}
}

if (update.hasDeparture() && (update.getDeparture().hasTime() || update.getDeparture().hasDelay())) {
StopTimeEvent departure = update.getDeparture();
if (departure != null) {
if (departure.hasDelay()) {
delay = departure.getDelay();
if (firstDelay == null) firstDelay = delay;
if (departure.hasTime()) {
newTimes.updateDepartureTime(i,
(int) (departure.getTime() - today));
Expand All @@ -487,13 +504,14 @@ public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone
newTimes.updateDepartureTime(i,
(int) (departure.getTime() - today));
delay = newTimes.getDepartureDelay(i);
if (firstDelay == null) firstDelay = delay;
} else {
LOG.error("Departure time at index {} is erroneous.", i);
return null;
}
} else {
if (delay == null) {
newTimes.updateDepartureDelay(i, TripTimes.UNAVAILABLE);
newTimes.cancelDepartureTime(i);
} else {
newTimes.updateDepartureDelay(i, delay);
if (newTimes.isCanceledDeparture(i)) {
Expand All @@ -503,6 +521,11 @@ public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone
}
}

if (scheduleRelationship == StopTimeUpdate.ScheduleRelationship.SKIPPED) {
newTimes.cancelArrivalTime(i);
newTimes.cancelDepartureTime(i);
}

if (updates.hasNext()) {
update = updates.next();
} else {
Expand Down Expand Up @@ -531,6 +554,12 @@ public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone
LOG.error("Part of a TripUpdate object could not be applied successfully to trip {}.", tripId);
return null;
}
if (firstDelay != null) {
if (newTimes.getArrivalDelay(0) != firstDelay) {
LOG.info("Trying to fix TripTimes by propagating delay backwards on trip {}.", tripId);
newTimes.propagateDelayBackwards(firstDelay);
}
}
}
if (!newTimes.timesIncreasing()) {
LOG.error("TripTimes are non-increasing after applying GTFS-RT delay propagation to trip {}.", tripId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,10 @@ protected boolean lessThan(final TripTimeShort t1, final TripTimeShort t2) {
*
* @param stop Stop object to perform the search for
* @param serviceDate Return all departures for the specified date
* @param omitCanceled
* @return
*/
public List<StopTimesInPattern> getStopTimesForStop(Stop stop, ServiceDate serviceDate, boolean omitNonPickups) {
public List<StopTimesInPattern> getStopTimesForStop(Stop stop, ServiceDate serviceDate, boolean omitNonPickups, boolean omitCanceled) {
List<StopTimesInPattern> ret = new ArrayList<>();
TimetableSnapshot snapshot = null;
if (graph.timetableSnapshotSource != null) {
Expand All @@ -885,6 +886,7 @@ public List<StopTimesInPattern> getStopTimesForStop(Stop stop, ServiceDate servi
if(omitNonPickups && pattern.stopPattern.pickups[sidx] == pattern.stopPattern.PICKDROP_NONE) continue;
for (TripTimes t : tt.tripTimes) {
if (!sd.serviceRunning(t.serviceCode)) continue;
if (omitCanceled && t.isTimeCanceled(sidx)) continue;
stopTimes.times.add(new TripTimeShort(t, sidx, stop, sd));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,4 +480,18 @@ public void unCancelDepartureTime(int i) {
public boolean isTimeCanceled(int i) {
return isCanceledArrival(i) || isCanceledDeparture(i) || isCanceled();
}

public void propagateDelayBackwards(Integer firstDelay) {
int numStops = this.getNumStops();

for (int i = 0; i < numStops; i++) {
if (this.getArrivalDelay(i) != 0) {
break;
}

this.updateArrivalDelay(i, firstDelay);
this.updateDepartureDelay(i, firstDelay);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,15 @@ private boolean handleModifiedTrip(final Graph graph, final Trip trip, final Tri
Preconditions.checkArgument(tripUpdate.getStopTimeUpdateCount() == stops.size(),
"number of stop should match the number of stop time updates");

final TripPattern pattern = getPatternForTripId(feedId, trip.getId().getId());
if (pattern != null) {
if (checkNewStopTimeUpdateStopsMatchesPatten(stops, pattern)) {
// TripUpdate stop pattern matches existing trip. Handle as scheduled trip
LOG.warn("MODIFIED trip {} matches existing SCHEDULED trip. Treating as such.", trip.getId().getId());
return handleScheduledTrip(tripUpdate, feedId, serviceDate);
}
}

// Cancel scheduled trip

final String tripId = tripUpdate.getTrip().getTripId();
Expand All @@ -885,6 +894,10 @@ private boolean handleModifiedTrip(final Graph graph, final Trip trip, final Tri
return success;
}

private boolean checkNewStopTimeUpdateStopsMatchesPatten(List<Stop> stops, TripPattern pattern) {
return stops.equals(pattern.getStops());
}

private boolean handleCanceledTrip(final TripUpdate tripUpdate, final String feedId, final ServiceDate serviceDate) {
boolean success = false;
if (tripUpdate.getTrip().hasTripId()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ public void testUpdate() {
assertNotNull(updatedTripTimes);
timetable.setTripTimes(trip_1_1_index, updatedTripTimes);

// update trip arrival time at first stop and make departure time incoherent at second stop
// update trip arrival time at first stop and make departure time incoherent at second stop,
// changes should be propagated backwards
tripDescriptorBuilder = TripDescriptor.newBuilder();
tripDescriptorBuilder.setTripId("1.1");
tripDescriptorBuilder.setScheduleRelationship(
Expand All @@ -303,6 +304,6 @@ public void testUpdate() {
stopTimeEventBuilder.setDelay(-1);
tripUpdate = tripUpdateBuilder.build();
updatedTripTimes = timetable.createUpdatedTripTimes(tripUpdate, timeZone, serviceDate);
assertNull(updatedTripTimes);
assertNotNull(updatedTripTimes);
}
}

0 comments on commit 2c8c25a

Please sign in to comment.