Skip to content

Commit 5d1eae2

Browse files
Merge branch 'dev-2.x' into combine-trip-pattern-caches
2 parents 94ebdb8 + 8a88111 commit 5d1eae2

21 files changed

+753
-713
lines changed

application/src/main/java/org/opentripplanner/updater/trip/gtfs/AbstractBackwardsDelayInterpolator.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
abstract class AbstractBackwardsDelayInterpolator implements BackwardsDelayInterpolator {
77

88
/**
9-
* Propagate backwards from the first stop with real-time information
9+
* Propagate backwards from the first stop with real-time information. This includes propagating
10+
* the delay from the departure time to the same stop's arrival time if it's missing.
11+
*
1012
* @return The first stop position with given time if propagation is done.
1113
*/
1214
public OptionalInt propagateBackwards(RealTimeTripTimesBuilder builder) {
1315
var firstUpdatedIndex = getFirstUpdatedIndex(builder);
14-
// if the first stop already has a real-time update, there is nothing to propagate
15-
if (firstUpdatedIndex == 0) {
16+
// Don't need to do anything if the first stop has an updated arrival time already
17+
if (firstUpdatedIndex == 0 && builder.getArrivalTime(0) != null) {
1618
return OptionalInt.empty();
1719
}
1820
fillInMissingTimes(builder, firstUpdatedIndex);

application/src/main/java/org/opentripplanner/updater/trip/gtfs/GtfsRealTimeTripUpdateAdapter.java

Lines changed: 122 additions & 431 deletions
Large diffs are not rendered by default.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package org.opentripplanner.updater.trip.gtfs;
2+
3+
import java.util.Objects;
4+
import java.util.Optional;
5+
import org.opentripplanner.core.model.i18n.I18NString;
6+
import org.opentripplanner.core.model.i18n.NonLocalizedString;
7+
import org.opentripplanner.core.model.id.FeedScopedId;
8+
import org.opentripplanner.gtfs.mapping.TransitModeMapper;
9+
import org.opentripplanner.transit.model.basic.TransitMode;
10+
import org.opentripplanner.transit.model.network.Route;
11+
import org.opentripplanner.transit.model.organization.Agency;
12+
import org.opentripplanner.transit.service.TransitService;
13+
import org.opentripplanner.updater.trip.gtfs.model.AddedRoute;
14+
import org.opentripplanner.updater.trip.gtfs.model.TripUpdate;
15+
16+
/**
17+
* Factory for creating routes based on GTFS real-time trip updates.
18+
*/
19+
class RouteFactory {
20+
21+
record Result(boolean newRouteCreated, Route route) {}
22+
23+
private final TransitService transitService;
24+
25+
public RouteFactory(TransitService transitService) {
26+
this.transitService = transitService;
27+
}
28+
29+
/**
30+
* Extract a new route from the given trip update, creating one if it doesn't exist.
31+
*/
32+
Result getOrCreate(TripUpdate update) {
33+
var optionalRoute = findRoute(update);
34+
var route = optionalRoute.orElseGet(() -> createRoute(update));
35+
return new Result(optionalRoute.isEmpty(), route);
36+
}
37+
38+
private Route createRoute(TripUpdate update) {
39+
var tripId = update.tripId();
40+
// the route in this update doesn't already exist, but the update contains the information so it will be created
41+
var routeId = update.routeId();
42+
return routeId
43+
.map(id -> {
44+
var builder = Route.of(id);
45+
46+
var addedRouteExtension = AddedRoute.ofTripDescriptor(update);
47+
48+
var agency = transitService
49+
.findAgency(new FeedScopedId(tripId.getFeedId(), addedRouteExtension.agencyId()))
50+
.orElseGet(() -> fallbackAgency(tripId.getFeedId()));
51+
52+
builder.withAgency(agency);
53+
54+
builder.withGtfsType(addedRouteExtension.routeType());
55+
var mode = TransitModeMapper.mapMode(addedRouteExtension.routeType());
56+
builder.withMode(mode);
57+
58+
// Create route name
59+
var name = Objects.requireNonNullElse(
60+
addedRouteExtension.routeLongName(),
61+
tripId.toString()
62+
);
63+
builder.withLongName(new NonLocalizedString(name));
64+
builder.withUrl(addedRouteExtension.routeUrl());
65+
return builder.build();
66+
})
67+
.orElseGet(() -> {
68+
I18NString longName = NonLocalizedString.ofNullable(tripId.getId());
69+
return Route.of(tripId)
70+
.withAgency(fallbackAgency(tripId.getFeedId()))
71+
// Guess the route type as it doesn't exist yet in the specifications
72+
// Bus. Used for short- and long-distance bus routes.
73+
.withGtfsType(3)
74+
.withMode(TransitMode.BUS)
75+
// Create route name
76+
.withLongName(longName)
77+
.build();
78+
});
79+
}
80+
81+
private Optional<Route> findRoute(TripUpdate tripUpdate) {
82+
return tripUpdate.routeId().flatMap(id -> Optional.ofNullable(transitService.getRoute(id)));
83+
}
84+
85+
/**
86+
* Create dummy agency for added trips.
87+
*/
88+
private Agency fallbackAgency(String feedId) {
89+
return Agency.of(new FeedScopedId(feedId, "autogenerated-gtfs-rt-added-route"))
90+
.withName("Agency automatically added by GTFS-RT update")
91+
.withTimezone(transitService.getTimeZone().toString())
92+
.build();
93+
}
94+
}

0 commit comments

Comments
 (0)