16
16
import static org .opentripplanner .transit .model .basic .TransitMode .FERRY ;
17
17
import static org .opentripplanner .transit .model .timetable .OccupancyStatus .FEW_SEATS_AVAILABLE ;
18
18
19
+ import com .google .transit .realtime .GtfsRealtime ;
19
20
import jakarta .ws .rs .core .Response ;
20
21
import java .io .IOException ;
21
22
import java .nio .file .Files ;
22
23
import java .nio .file .Path ;
23
24
import java .nio .file .StandardOpenOption ;
24
25
import java .time .Instant ;
26
+ import java .time .LocalDate ;
25
27
import java .time .OffsetDateTime ;
28
+ import java .time .ZoneId ;
26
29
import java .time .temporal .ChronoUnit ;
27
30
import java .util .Arrays ;
28
31
import java .util .Comparator ;
42
45
import org .opentripplanner .framework .i18n .I18NString ;
43
46
import org .opentripplanner .framework .i18n .NonLocalizedString ;
44
47
import org .opentripplanner .framework .model .Grams ;
48
+ import org .opentripplanner .graph_builder .issue .api .DataImportIssueStore ;
45
49
import org .opentripplanner .model .FeedInfo ;
50
+ import org .opentripplanner .model .calendar .CalendarServiceData ;
46
51
import org .opentripplanner .model .fare .FareMedium ;
47
52
import org .opentripplanner .model .fare .FareProduct ;
48
53
import org .opentripplanner .model .fare .ItineraryFares ;
60
65
import org .opentripplanner .routing .alertpatch .EntitySelector ;
61
66
import org .opentripplanner .routing .alertpatch .TimePeriod ;
62
67
import org .opentripplanner .routing .alertpatch .TransitAlert ;
68
+ import org .opentripplanner .routing .algorithm .raptoradapter .transit .TransitLayer ;
69
+ import org .opentripplanner .routing .algorithm .raptoradapter .transit .TransitTuningParameters ;
70
+ import org .opentripplanner .routing .algorithm .raptoradapter .transit .mappers .TransitLayerMapper ;
71
+ import org .opentripplanner .routing .algorithm .raptoradapter .transit .mappers .TransitLayerUpdater ;
63
72
import org .opentripplanner .routing .api .request .RouteRequest ;
64
73
import org .opentripplanner .routing .graph .Graph ;
65
74
import org .opentripplanner .routing .graphfinder .GraphFinder ;
91
100
import org .opentripplanner .transit .model .site .RegularStop ;
92
101
import org .opentripplanner .transit .model .site .StopLocation ;
93
102
import org .opentripplanner .transit .model .timetable .RealTimeTripTimes ;
103
+ import org .opentripplanner .transit .model .timetable .Trip ;
94
104
import org .opentripplanner .transit .model .timetable .TripTimesFactory ;
95
105
import org .opentripplanner .transit .service .DefaultTransitService ;
96
106
import org .opentripplanner .transit .service .TimetableRepository ;
97
107
import org .opentripplanner .transit .service .TransitEditorService ;
98
108
import org .opentripplanner .transit .service .TransitService ;
109
+ import org .opentripplanner .updater .GtfsRealtimeFuzzyTripMatcher ;
110
+ import org .opentripplanner .updater .TimetableSnapshotSourceParameters ;
111
+ import org .opentripplanner .updater .trip .BackwardsDelayPropagationType ;
112
+ import org .opentripplanner .updater .trip .TimetableSnapshotSource ;
113
+ import org .opentripplanner .updater .trip .TripUpdateBuilder ;
114
+ import org .opentripplanner .updater .trip .UpdateIncrementality ;
99
115
import org .opentripplanner .utils .collection .ListUtils ;
100
116
101
117
class GraphQLIntegrationTest {
@@ -116,6 +132,10 @@ class GraphQLIntegrationTest {
116
132
.map (p -> (RegularStop ) p .stop )
117
133
.toList ();
118
134
private static final Route ROUTE = TimetableRepositoryForTest .route ("a-route" ).build ();
135
+ private static final String ADDED_TRIP_ID = "ADDED_TRIP" ;
136
+ private static final String REPLACEMENT_TRIP_ID = "REPLACEMENT_TRIP" ;
137
+ public static final ZoneId TIME_ZONE = ZoneIds .BERLIN ;
138
+ public static final String FEED_ID = TimetableRepositoryForTest .FEED_ID ;
119
139
120
140
private static VehicleRentalStation VEHICLE_RENTAL_STATION = new TestVehicleRentalStationBuilder ()
121
141
.withVehicles (10 )
@@ -137,6 +157,8 @@ class GraphQLIntegrationTest {
137
157
static final Instant ALERT_END_TIME = ALERT_START_TIME .plus (1 , ChronoUnit .DAYS );
138
158
private static final int TEN_MINUTES = 10 * 60 ;
139
159
160
+ private static final LocalDate SERVICE_DATE = LocalDate .of (2024 , 1 , 1 );
161
+
140
162
private static GraphQLRequestContext context ;
141
163
142
164
private static final Deduplicator DEDUPLICATOR = new Deduplicator ();
@@ -157,38 +179,59 @@ static void setup() {
157
179
List .of ()
158
180
);
159
181
160
- var siteRepository = TEST_MODEL .siteRepositoryBuilder ();
161
- STOP_LOCATIONS .forEach (siteRepository ::withRegularStop );
162
- var model = siteRepository .build ();
163
- var timetableRepository = new TimetableRepository (model , DEDUPLICATOR );
182
+ var siteRepositoryBuilder = TEST_MODEL .siteRepositoryBuilder ();
183
+ STOP_LOCATIONS .forEach (siteRepositoryBuilder ::withRegularStop );
184
+ var siteRepository = siteRepositoryBuilder .build ();
185
+ var timetableRepository = new TimetableRepository (siteRepository , DEDUPLICATOR );
164
186
165
187
var trip = TimetableRepositoryForTest
166
188
.trip ("123" )
167
189
.withHeadsign (I18NString .of ("Trip Headsign" ))
168
190
.build ();
169
191
var stopTimes = TEST_MODEL .stopTimesEvery5Minutes (3 , trip , T11_00 );
170
192
var tripTimes = TripTimesFactory .tripTimes (trip , stopTimes , DEDUPLICATOR );
193
+
194
+ var calendar = new CalendarServiceData ();
195
+ FeedScopedId serviceId = calendar .getOrCreateServiceIdForDate (SERVICE_DATE );
196
+
197
+ var tripToBeReplaced = TimetableRepositoryForTest
198
+ .trip (REPLACEMENT_TRIP_ID )
199
+ .withServiceId (serviceId )
200
+ .build ();
171
201
final TripPattern pattern = TEST_MODEL
172
202
.pattern (BUS )
173
- .withScheduledTimeTableBuilder (builder -> builder .addTripTimes (tripTimes ))
203
+ .withScheduledTimeTableBuilder (builder ->
204
+ builder
205
+ .addTripTimes (tripTimes )
206
+ .addTripTimes (
207
+ TripTimesFactory .tripTimes (
208
+ tripToBeReplaced ,
209
+ TEST_MODEL .stopTimesEvery5Minutes (3 , tripToBeReplaced , T11_30 ),
210
+ DEDUPLICATOR
211
+ )
212
+ )
213
+ )
174
214
.build ();
175
215
176
216
timetableRepository .addTripPattern (id ("pattern-1" ), pattern );
177
217
178
- var feedId = "testfeed" ;
179
- var feedInfo = FeedInfo .dummyForTest (feedId );
218
+ var feedInfo = FeedInfo .dummyForTest (FEED_ID );
180
219
timetableRepository .addFeedInfo (feedInfo );
181
220
182
221
var agency = Agency
183
- .of (new FeedScopedId (feedId , "agency-xx" ))
222
+ .of (new FeedScopedId (FEED_ID , "agency-xx" ))
184
223
.withName ("speedtransit" )
185
224
.withUrl ("www.otp-foo.bar" )
186
225
.withTimezone ("Europe/Berlin" )
187
226
.build ();
188
227
timetableRepository .addAgency (agency );
189
228
190
- timetableRepository .initTimeZone (ZoneIds .BERLIN );
229
+ timetableRepository .initTimeZone (TIME_ZONE );
230
+ var serviceCodes = timetableRepository .getServiceCodes ();
231
+ serviceCodes .put (serviceId , serviceCodes .size ());
232
+ timetableRepository .updateCalendarServiceData (true , calendar , DataImportIssueStore .NOOP );
191
233
timetableRepository .index ();
234
+
192
235
var routes = Arrays
193
236
.stream (TransitMode .values ())
194
237
.sorted (Comparator .comparing (Enum ::name ))
@@ -226,6 +269,29 @@ public Set<Route> getRoutesForStop(StopLocation stop) {
226
269
};
227
270
routes .forEach (transitService ::addRoutes );
228
271
272
+ timetableRepository .setTransitLayer (
273
+ TransitLayerMapper .map (TransitTuningParameters .FOR_TEST , timetableRepository )
274
+ );
275
+ timetableRepository .setRealtimeTransitLayer (
276
+ new TransitLayer (timetableRepository .getTransitLayer ())
277
+ );
278
+ var transitLayerUpdater = new TransitLayerUpdater (transitService );
279
+ timetableRepository .setTransitLayerUpdater (transitLayerUpdater );
280
+
281
+ var timetableSnapshotProvider = new TimetableSnapshotSource (
282
+ TimetableSnapshotSourceParameters .DEFAULT ,
283
+ timetableRepository ,
284
+ () -> SERVICE_DATE
285
+ );
286
+ timetableSnapshotProvider .applyTripUpdates (
287
+ new GtfsRealtimeFuzzyTripMatcher (transitService ),
288
+ BackwardsDelayPropagationType .REQUIRED_NO_DATA ,
289
+ UpdateIncrementality .FULL_DATASET ,
290
+ List .of (getAddedTrip (busRoute ), getReplacementTrip (tripToBeReplaced )),
291
+ FEED_ID
292
+ );
293
+ timetableSnapshotProvider .flushBuffer ();
294
+
229
295
var step1 = walkStep ("street" )
230
296
.withRelativeDirection (RelativeDirection .DEPART )
231
297
.withAbsoluteDirection (20 )
@@ -323,6 +389,35 @@ public Set<Route> getRoutesForStop(StopLocation stop) {
323
389
);
324
390
}
325
391
392
+ private static GtfsRealtime .TripUpdate getAddedTrip (Route route ) {
393
+ var tripUpdateBuilder = new TripUpdateBuilder (
394
+ route .getId ().getId (),
395
+ ADDED_TRIP_ID ,
396
+ SERVICE_DATE ,
397
+ GtfsRealtime .TripDescriptor .ScheduleRelationship .ADDED ,
398
+ TIME_ZONE
399
+ );
400
+ tripUpdateBuilder .addStopTime (A .stop .getId ().getId (), 0 );
401
+ tripUpdateBuilder .addStopTime (B .stop .getId ().getId (), 300 );
402
+ tripUpdateBuilder .addStopTime (C .stop .getId ().getId (), 600 );
403
+ tripUpdateBuilder .addStopTime (D .stop .getId ().getId (), 900 );
404
+ return tripUpdateBuilder .build ();
405
+ }
406
+
407
+ private static GtfsRealtime .TripUpdate getReplacementTrip (Trip trip ) {
408
+ var tripUpdateBuilder = new TripUpdateBuilder (
409
+ trip .getId ().getId (),
410
+ SERVICE_DATE ,
411
+ GtfsRealtime .TripDescriptor .ScheduleRelationship .REPLACEMENT ,
412
+ TIME_ZONE
413
+ );
414
+ tripUpdateBuilder .addStopTime (A .stop .getId ().getId (), 0 );
415
+ tripUpdateBuilder .addStopTime (B .stop .getId ().getId (), 300 );
416
+ tripUpdateBuilder .addStopTime (C .stop .getId ().getId (), 600 );
417
+ tripUpdateBuilder .addStopTime (D .stop .getId ().getId (), 900 );
418
+ return tripUpdateBuilder .build ();
419
+ }
420
+
326
421
private static BikeAccess bikesAllowed (TransitMode m ) {
327
422
return switch (m .ordinal () % 3 ) {
328
423
case 0 -> BikeAccess .ALLOWED ;
0 commit comments