Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce builder for RealtimeTestEnvironment #6043

Open
wants to merge 26 commits into
base: dev-2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
470dbe2
Extract IDs for realtime tests
leonardehrenfried Jul 8, 2024
a2b7f48
Introduce builder for test environment
leonardehrenfried Jul 8, 2024
9d68130
Extract test constants into separate interface
leonardehrenfried Sep 4, 2024
06e485f
Use constants from interface everywhere
leonardehrenfried Sep 4, 2024
9daec64
Use upper case for all constants
leonardehrenfried Sep 4, 2024
523ac2b
Remove static variable lookups from instances
leonardehrenfried Sep 4, 2024
b06a3e3
Completely switch to constants
leonardehrenfried Sep 4, 2024
2e74f27
Clean up
leonardehrenfried Sep 4, 2024
cd50516
Remove 'public'
leonardehrenfried Sep 4, 2024
d5583b8
Apply suggestions from code review
leonardehrenfried Sep 9, 2024
c97d90a
Improve handling of IDs
leonardehrenfried Sep 9, 2024
049e0de
Remove un-needed test trip
leonardehrenfried Sep 9, 2024
a5ff803
Format code
leonardehrenfried Sep 9, 2024
a09f817
Extra records for realtime trip input
leonardehrenfried Sep 10, 2024
68ef56d
Extract more builders for test trips
leonardehrenfried Sep 10, 2024
d872b3e
Replace withTrip2()
leonardehrenfried Sep 10, 2024
0b5f0a8
Extract constant for TRIP1
leonardehrenfried Sep 10, 2024
8a05a8d
Replace withTrip1() with explicit setup
leonardehrenfried Sep 10, 2024
05764bf
Move StopCall into class
leonardehrenfried Sep 10, 2024
f548fce
Merge remote-tracking branch 'upstream/dev-2.x' into refactor-realtim…
leonardehrenfried Sep 10, 2024
13f7287
Fix code after merge
leonardehrenfried Sep 10, 2024
4633563
Fix new test cases
leonardehrenfried Sep 10, 2024
5e42b34
Rename RealtimeTripInput to TripInput
leonardehrenfried Sep 11, 2024
0d7c491
Merge remote-tracking branch 'upstream/dev-2.x' into refactor-realtim…
leonardehrenfried Sep 11, 2024
88ec563
Adapt tests to new realtime code
leonardehrenfried Sep 11, 2024
b479e20
Add operator in builder
leonardehrenfried Sep 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.opentripplanner.updater.trip;

import static org.opentripplanner.transit.model._data.TransitModelForTest.id;

import java.time.LocalDate;
import java.time.ZoneId;
import org.opentripplanner.transit.model._data.TransitModelForTest;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.model.network.Route;
import org.opentripplanner.transit.model.organization.Operator;
import org.opentripplanner.transit.model.site.RegularStop;
import org.opentripplanner.transit.model.site.Station;
import org.opentripplanner.transit.service.StopModel;

public interface RealtimeTestConstants {
LocalDate SERVICE_DATE = LocalDate.of(2024, 5, 8);
FeedScopedId SERVICE_ID = TransitModelForTest.id("CAL_1");
String STOP_A1_ID = "A1";
String STOP_B1_ID = "B1";
String STOP_C1_ID = "C1";
String TRIP_1_ID = "TestTrip1";
String TRIP_2_ID = "TestTrip2";
String OPERATOR_1_ID = "TestOperator1";
Operator OPERATOR1 = Operator.of(id(OPERATOR_1_ID)).withName(OPERATOR_1_ID).build();
String ROUTE_1_ID = "TestRoute1";

TransitModelForTest TEST_MODEL = TransitModelForTest.of();
ZoneId TIME_ZONE = ZoneId.of(TransitModelForTest.TIME_ZONE_ID);
Station STATION_A = TEST_MODEL.station("A").build();
Station STATION_B = TEST_MODEL.station("B").build();
Station STATION_C = TEST_MODEL.station("C").build();
Station STATION_D = TEST_MODEL.station("D").build();
RegularStop STOP_A1 = TEST_MODEL.stop(STOP_A1_ID).withParentStation(STATION_A).build();
RegularStop STOP_B1 = TEST_MODEL.stop(STOP_B1_ID).withParentStation(STATION_B).build();
RegularStop STOP_B2 = TEST_MODEL.stop("B2").withParentStation(STATION_B).build();
RegularStop STOP_C1 = TEST_MODEL.stop(STOP_C1_ID).withParentStation(STATION_C).build();
RegularStop STOP_D1 = TEST_MODEL.stop("D1").withParentStation(STATION_D).build();
StopModel STOP_MODEL = TEST_MODEL
.stopModelBuilder()
.withRegularStop(STOP_A1)
.withRegularStop(STOP_B1)
.withRegularStop(STOP_B2)
.withRegularStop(STOP_C1)
.withRegularStop(STOP_D1)
.build();

Route ROUTE_1 = TransitModelForTest.route(ROUTE_1_ID).build();
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,25 @@
package org.opentripplanner.updater.trip;

import static org.opentripplanner.transit.model._data.TransitModelForTest.id;
import static org.opentripplanner.updater.trip.UpdateIncrementality.DIFFERENTIAL;
import static org.opentripplanner.updater.trip.UpdateIncrementality.FULL_DATASET;

import com.google.transit.realtime.GtfsRealtime;
import java.time.Duration;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.opentripplanner.DateTimeHelper;
import org.opentripplanner.ext.siri.SiriTimetableSnapshotSource;
import org.opentripplanner.ext.siri.updater.EstimatedTimetableHandler;
import org.opentripplanner.framework.i18n.I18NString;
import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore;
import org.opentripplanner.model.StopTime;
import org.opentripplanner.model.TimetableSnapshot;
import org.opentripplanner.model.calendar.CalendarServiceData;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.transit.model._data.TransitModelForTest;
import org.opentripplanner.transit.model.framework.Deduplicator;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.model.network.Route;
import org.opentripplanner.transit.model.network.TripPattern;
import org.opentripplanner.transit.model.organization.Operator;
import org.opentripplanner.transit.model.site.RegularStop;
import org.opentripplanner.transit.model.site.Station;
import org.opentripplanner.transit.model.site.StopLocation;
import org.opentripplanner.transit.model.timetable.Trip;
import org.opentripplanner.transit.model.timetable.TripOnServiceDate;
import org.opentripplanner.transit.model.timetable.TripTimes;
import org.opentripplanner.transit.model.timetable.TripTimesFactory;
import org.opentripplanner.transit.model.timetable.TripTimesStringBuilder;
import org.opentripplanner.transit.service.DefaultTransitService;
import org.opentripplanner.transit.service.StopModel;
import org.opentripplanner.transit.service.TransitModel;
import org.opentripplanner.transit.service.TransitService;
import org.opentripplanner.updater.DefaultRealTimeUpdateContext;
Expand All @@ -50,102 +34,43 @@
* <p>
* It is however a goal to change that and then these two can be combined.
*/
public final class RealtimeTestEnvironment {
public final class RealtimeTestEnvironment implements RealtimeTestConstants {

// static constants
private static final TimetableSnapshotSourceParameters PARAMETERS = new TimetableSnapshotSourceParameters(
Duration.ZERO,
false
);
public static final LocalDate SERVICE_DATE = LocalDate.of(2024, 5, 8);
public static final FeedScopedId SERVICE_ID = TransitModelForTest.id("CAL_1");
public static final String STOP_A1_ID = "A1";
public static final String STOP_B1_ID = "B1";
public static final String STOP_C1_ID = "C1";
private final TransitModelForTest testModel = TransitModelForTest.of();
public final ZoneId timeZone = ZoneId.of(TransitModelForTest.TIME_ZONE_ID);
public final Station stationA = testModel.station("A").build();
public final Station stationB = testModel.station("B").build();
public final Station stationC = testModel.station("C").build();
public final Station stationD = testModel.station("D").build();
public final RegularStop stopA1 = testModel.stop(STOP_A1_ID).withParentStation(stationA).build();
public final RegularStop stopB1 = testModel.stop(STOP_B1_ID).withParentStation(stationB).build();
public final RegularStop stopB2 = testModel.stop("B2").withParentStation(stationB).build();
public final RegularStop stopC1 = testModel.stop(STOP_C1_ID).withParentStation(stationC).build();
public final RegularStop stopD1 = testModel.stop("D1").withParentStation(stationD).build();
public final StopModel stopModel = testModel
.stopModelBuilder()
.withRegularStop(stopA1)
.withRegularStop(stopB1)
.withRegularStop(stopB2)
.withRegularStop(stopC1)
.withRegularStop(stopD1)
.build();
public final FeedScopedId operator1Id = TransitModelForTest.id("TestOperator1");
public final FeedScopedId route1Id = TransitModelForTest.id("TestRoute1");
public final Trip trip1;
public final Trip trip2;
public final Operator operator1;

public final TransitModel transitModel;
private final SiriTimetableSnapshotSource siriSource;
private final TimetableSnapshotSource gtfsSource;
private final DateTimeHelper dateTimeHelper;

private enum SourceType {
enum SourceType {
GTFS_RT,
SIRI,
}

/**
* Siri and GTFS-RT cannot be run at the same time, so you need to decide.
*/
public static RealtimeTestEnvironment siri() {
return new RealtimeTestEnvironment(SourceType.SIRI);
public static RealtimeTestEnvironmentBuilder siri() {
return new RealtimeTestEnvironmentBuilder().withSourceType(SourceType.SIRI);
}

/**
* Siri and GTFS-RT cannot be run at the same time, so you need to decide.
*/
public static RealtimeTestEnvironment gtfs() {
return new RealtimeTestEnvironment(SourceType.GTFS_RT);
public static RealtimeTestEnvironmentBuilder gtfs() {
return new RealtimeTestEnvironmentBuilder().withSourceType(SourceType.GTFS_RT);
}

private RealtimeTestEnvironment(SourceType sourceType) {
transitModel = new TransitModel(stopModel, new Deduplicator());
transitModel.initTimeZone(timeZone);
transitModel.addAgency(TransitModelForTest.AGENCY);

operator1 = Operator.of(operator1Id).withName("Operator 1").build();
transitModel.getOperators().add(operator1);

Route route1 = TransitModelForTest.route(route1Id).withOperator(operator1).build();

trip1 =
createTrip(
"TestTrip1",
route1,
List.of(new StopCall(stopA1, 10, 11), new StopCall(stopB1, 20, 21))
);
trip2 =
createTrip(
"TestTrip2",
route1,
List.of(
new StopCall(stopA1, 60, 61),
new StopCall(stopB1, 70, 71),
new StopCall(stopC1, 80, 81)
)
);

CalendarServiceData calendarServiceData = new CalendarServiceData();
calendarServiceData.putServiceDatesForServiceId(
SERVICE_ID,
List.of(SERVICE_DATE.minusDays(1), SERVICE_DATE, SERVICE_DATE.plusDays(1))
);
transitModel.getServiceCodes().put(SERVICE_ID, 0);
transitModel.updateCalendarServiceData(true, calendarServiceData, DataImportIssueStore.NOOP);

transitModel.index();
RealtimeTestEnvironment(SourceType sourceType, TransitModel transitModel) {
Objects.requireNonNull(sourceType);
this.transitModel = transitModel;

this.transitModel.index();
// SIRI and GTFS-RT cannot be registered with the transit model at the same time
// we are actively refactoring to remove this restriction
// for the time being you cannot run a SIRI and GTFS-RT test at the same time
Expand All @@ -156,11 +81,7 @@ private RealtimeTestEnvironment(SourceType sourceType) {
gtfsSource = new TimetableSnapshotSource(PARAMETERS, transitModel);
siriSource = null;
}
dateTimeHelper = new DateTimeHelper(timeZone, RealtimeTestEnvironment.SERVICE_DATE);
}

public static FeedScopedId id(String id) {
return TransitModelForTest.id(id);
dateTimeHelper = new DateTimeHelper(TIME_ZONE, SERVICE_DATE);
}

/**
Expand Down Expand Up @@ -190,7 +111,11 @@ private EstimatedTimetableHandler getEstimatedTimetableHandler(boolean fuzzyMatc
}

public TripPattern getPatternForTrip(FeedScopedId tripId) {
return getPatternForTrip(tripId, RealtimeTestEnvironment.SERVICE_DATE);
return getPatternForTrip(tripId, SERVICE_DATE);
}

public TripPattern getPatternForTrip(String id) {
return getPatternForTrip(id(id));
}

public TripPattern getPatternForTrip(FeedScopedId tripId, LocalDate serviceDate) {
Expand All @@ -199,13 +124,6 @@ public TripPattern getPatternForTrip(FeedScopedId tripId, LocalDate serviceDate)
return transitService.getPatternForTrip(trip.getTrip(), serviceDate);
}

/**
* Find the current TripTimes for a trip id on the default serviceDate
*/
public TripTimes getTripTimesForTrip(Trip trip) {
return getTripTimesForTrip(trip.getId(), SERVICE_DATE);
}

/**
* Find the current TripTimes for a trip id on the default serviceDate
*/
Expand All @@ -217,10 +135,6 @@ public DateTimeHelper getDateTimeHelper() {
return dateTimeHelper;
}

public TripPattern getPatternForTrip(Trip trip) {
return getTransitService().getPatternForTrip(trip);
}

public TimetableSnapshot getTimetableSnapshot() {
if (siriSource != null) {
return siriSource.getTimetableSnapshot();
Expand All @@ -233,10 +147,6 @@ public String getRealtimeTimetable(String tripId) {
return getRealtimeTimetable(id(tripId), SERVICE_DATE);
}

public String getRealtimeTimetable(Trip trip) {
return getRealtimeTimetable(trip.getId(), SERVICE_DATE);
}

public String getRealtimeTimetable(FeedScopedId tripId, LocalDate serviceDate) {
var tt = getTripTimesForTrip(tripId, serviceDate);
var pattern = getPatternForTrip(tripId);
Expand Down Expand Up @@ -325,59 +235,4 @@ private void commitTimetableSnapshot() {
gtfsSource.flushBuffer();
}
}

private Trip createTrip(String id, Route route, List<StopCall> stops) {
var trip = Trip
.of(id(id))
.withRoute(route)
.withHeadsign(I18NString.of("Headsign of %s".formatted(id)))
.withServiceId(SERVICE_ID)
.build();

var tripOnServiceDate = TripOnServiceDate
.of(trip.getId())
.withTrip(trip)
.withServiceDate(SERVICE_DATE)
.build();

transitModel.addTripOnServiceDate(tripOnServiceDate.getId(), tripOnServiceDate);

var stopTimes = IntStream
.range(0, stops.size())
.mapToObj(i -> {
var stop = stops.get(i);
return createStopTime(trip, i, stop.stop(), stop.arrivalTime(), stop.departureTime());
})
.collect(Collectors.toList());

TripTimes tripTimes = TripTimesFactory.tripTimes(trip, stopTimes, null);

final TripPattern pattern = TransitModelForTest
.tripPattern(id + "Pattern", route)
.withStopPattern(TransitModelForTest.stopPattern(stops.stream().map(StopCall::stop).toList()))
.build();
pattern.add(tripTimes);

transitModel.addTripPattern(pattern.getId(), pattern);

return trip;
}

private StopTime createStopTime(
Trip trip,
int stopSequence,
StopLocation stop,
int arrivalTime,
int departureTime
) {
var st = new StopTime();
st.setTrip(trip);
st.setStopSequence(stopSequence);
st.setStop(stop);
st.setArrivalTime(arrivalTime);
st.setDepartureTime(departureTime);
return st;
}

private record StopCall(RegularStop stop, int arrivalTime, int departureTime) {}
}
Loading
Loading