use of org.opentripplanner.model.Timetable in project OpenTripPlanner by opentripplanner.
the class TimetableSnapshotSourceTest method testHandleDelayedTrip.
@Test
public void testHandleDelayedTrip() {
final FeedScopedId tripId = new FeedScopedId(feedId, "1.1");
final FeedScopedId tripId2 = new FeedScopedId(feedId, "1.2");
final Trip trip = graph.index.getTripForId().get(tripId);
final TripPattern pattern = graph.index.getPatternForTrip().get(trip);
final int tripIndex = pattern.scheduledTimetable.getTripIndex(tripId);
final int tripIndex2 = pattern.scheduledTimetable.getTripIndex(tripId2);
final TripDescriptor.Builder tripDescriptorBuilder = TripDescriptor.newBuilder();
tripDescriptorBuilder.setTripId("1.1");
tripDescriptorBuilder.setScheduleRelationship(TripDescriptor.ScheduleRelationship.SCHEDULED);
final TripUpdate.Builder tripUpdateBuilder = TripUpdate.newBuilder();
tripUpdateBuilder.setTrip(tripDescriptorBuilder);
final StopTimeUpdate.Builder stopTimeUpdateBuilder = tripUpdateBuilder.addStopTimeUpdateBuilder();
stopTimeUpdateBuilder.setScheduleRelationship(StopTimeUpdate.ScheduleRelationship.SCHEDULED);
stopTimeUpdateBuilder.setStopSequence(2);
final StopTimeEvent.Builder arrivalBuilder = stopTimeUpdateBuilder.getArrivalBuilder();
final StopTimeEvent.Builder departureBuilder = stopTimeUpdateBuilder.getDepartureBuilder();
arrivalBuilder.setDelay(1);
departureBuilder.setDelay(1);
final TripUpdate tripUpdate = tripUpdateBuilder.build();
updater.applyTripUpdates(graph, fullDataset, Arrays.asList(tripUpdate), feedId);
final TimetableSnapshot snapshot = updater.getTimetableSnapshot();
final Timetable forToday = snapshot.resolve(pattern, serviceDate);
final Timetable schedule = snapshot.resolve(pattern, null);
assertNotSame(forToday, schedule);
assertNotSame(forToday.getTripTimes(tripIndex), schedule.getTripTimes(tripIndex));
assertSame(forToday.getTripTimes(tripIndex2), schedule.getTripTimes(tripIndex2));
assertEquals(1, forToday.getTripTimes(tripIndex).getArrivalDelay(1));
assertEquals(1, forToday.getTripTimes(tripIndex).getDepartureDelay(1));
assertEquals(RealTimeState.SCHEDULED, schedule.getTripTimes(tripIndex).getRealTimeState());
assertEquals(RealTimeState.UPDATED, forToday.getTripTimes(tripIndex).getRealTimeState());
assertEquals(RealTimeState.SCHEDULED, schedule.getTripTimes(tripIndex2).getRealTimeState());
assertEquals(RealTimeState.SCHEDULED, forToday.getTripTimes(tripIndex2).getRealTimeState());
}
use of org.opentripplanner.model.Timetable in project OpenTripPlanner by opentripplanner.
the class TransitLayerUpdater method update.
public void update(Set<Timetable> updatedTimetables) {
if (!graph.hasRealtimeTransitLayer()) {
return;
}
// Make a shallow copy of the realtime transit layer. Only the objects that are copied will be
// changed during this update process.
TransitLayer realtimeTransitLayer = new TransitLayer(graph.getRealtimeTransitLayer());
double startTime = System.currentTimeMillis();
// Map TripPatterns for this update to Raptor TripPatterns
final Map<org.opentripplanner.model.TripPattern, TripPatternWithRaptorStopIndexes> newTripPatternForOld = mapOldTripPatternToRaptorTripPattern(realtimeTransitLayer.getStopIndex(), updatedTimetables.stream().map(t -> t.pattern).collect(Collectors.toSet()));
// Instantiate a TripPatternForDateMapper with the new TripPattern mappings
TripPatternForDateMapper tripPatternForDateMapper = new TripPatternForDateMapper(serviceCodesRunningForDate, newTripPatternForOld);
// Index updated timetables by date
@SuppressWarnings("ConstantConditions") Multimap<LocalDate, Timetable> timetablesByDate = Multimaps.index(updatedTimetables, t -> ServiceCalendarMapper.localDateFromServiceDate(t.serviceDate));
for (LocalDate date : timetablesByDate.keySet()) {
Collection<Timetable> timetablesForDate = timetablesByDate.get(date);
List<TripPatternForDate> patternsForDate = realtimeTransitLayer.getTripPatternsForDateCopy(date);
if (patternsForDate == null) {
continue;
}
Map<org.opentripplanner.model.TripPattern, TripPatternForDate> patternsForDateMap = tripPatternForDateMapCache.computeIfAbsent(date, p -> patternsForDate.stream().collect(Collectors.toMap(t -> t.getTripPattern().getPattern(), t -> t)));
for (Timetable timetable : timetablesForDate) {
TripPatternForDate tripPatternForDate = tripPatternForDateMapper.map(timetable, timetable.serviceDate);
if (tripPatternForDate != null) {
patternsForDateMap.put(timetable.pattern, tripPatternForDate);
}
}
realtimeTransitLayer.replaceTripPatternsForDate(date, new ArrayList<>(patternsForDateMap.values()));
// Switch out the reference with the updated realtimeTransitLayer. This is synchronized to
// guarantee that the reference is set after all the fields have been updated.
graph.setRealtimeTransitLayer(realtimeTransitLayer);
LOG.debug("UPDATING {} tripPatterns took {} ms", updatedTimetables.size(), System.currentTimeMillis() - startTime);
}
}
use of org.opentripplanner.model.Timetable in project OpenTripPlanner by opentripplanner.
the class TripTimesShortHelper method getTripTimesShort.
public static List<TripTimeShort> getTripTimesShort(RoutingService routingService, Trip trip, ServiceDate serviceDate) {
final ServiceDay serviceDay = new ServiceDay(routingService.getServiceCodes(), serviceDate, routingService.getCalendarService(), trip.getRoute().getAgency().getId());
Timetable timetable = null;
TimetableSnapshot timetableSnapshot = routingService.getTimetableSnapshot();
if (timetableSnapshot != null) {
// Check if realtime-data is available for trip
TripPattern pattern = timetableSnapshot.getLastAddedTripPattern(trip.getId(), serviceDate);
if (pattern == null) {
pattern = routingService.getPatternForTrip().get(trip);
}
timetable = timetableSnapshot.resolve(pattern, serviceDate);
}
if (timetable == null) {
timetable = routingService.getPatternForTrip().get(trip).scheduledTimetable;
}
// This check is made here to avoid changing TripTimeShort.fromTripTimes
TripTimes times = timetable.getTripTimes(timetable.getTripIndex(trip.getId()));
if (!serviceDay.serviceRunning(times.serviceCode)) {
return new ArrayList<>();
} else {
return TripTimeShort.fromTripTimes(timetable, trip, serviceDay);
}
}
use of org.opentripplanner.model.Timetable in project OpenTripPlanner by opentripplanner.
the class TimetableSnapshotSourceTest method testHandleAddedTrip.
@Test
public void testHandleAddedTrip() throws ParseException {
// GIVEN
// Get service date of today because old dates will be purged after applying updates
final ServiceDate serviceDate = new ServiceDate(Calendar.getInstance());
final String addedTripId = "added_trip";
TripUpdate tripUpdate;
{
final TripDescriptor.Builder tripDescriptorBuilder = TripDescriptor.newBuilder();
tripDescriptorBuilder.setTripId(addedTripId);
tripDescriptorBuilder.setScheduleRelationship(TripDescriptor.ScheduleRelationship.ADDED);
tripDescriptorBuilder.setStartDate(serviceDate.asCompactString());
final Calendar calendar = serviceDate.getAsCalendar(graph.getTimeZone());
final long midnightSecondsSinceEpoch = calendar.getTimeInMillis() / 1000;
final TripUpdate.Builder tripUpdateBuilder = TripUpdate.newBuilder();
tripUpdateBuilder.setTrip(tripDescriptorBuilder);
{
// Stop A
final StopTimeUpdate.Builder stopTimeUpdateBuilder = tripUpdateBuilder.addStopTimeUpdateBuilder();
stopTimeUpdateBuilder.setScheduleRelationship(StopTimeUpdate.ScheduleRelationship.SCHEDULED);
stopTimeUpdateBuilder.setStopId("A");
{
// Arrival
final StopTimeEvent.Builder arrivalBuilder = stopTimeUpdateBuilder.getArrivalBuilder();
arrivalBuilder.setTime(midnightSecondsSinceEpoch + (8 * 3600) + (30 * 60));
arrivalBuilder.setDelay(0);
}
{
// Departure
final StopTimeEvent.Builder departureBuilder = stopTimeUpdateBuilder.getDepartureBuilder();
departureBuilder.setTime(midnightSecondsSinceEpoch + (8 * 3600) + (30 * 60));
departureBuilder.setDelay(0);
}
}
{
// Stop C
final StopTimeUpdate.Builder stopTimeUpdateBuilder = tripUpdateBuilder.addStopTimeUpdateBuilder();
stopTimeUpdateBuilder.setScheduleRelationship(StopTimeUpdate.ScheduleRelationship.SCHEDULED);
stopTimeUpdateBuilder.setStopId("C");
{
// Arrival
final StopTimeEvent.Builder arrivalBuilder = stopTimeUpdateBuilder.getArrivalBuilder();
arrivalBuilder.setTime(midnightSecondsSinceEpoch + (8 * 3600) + (40 * 60));
arrivalBuilder.setDelay(0);
}
{
// Departure
final StopTimeEvent.Builder departureBuilder = stopTimeUpdateBuilder.getDepartureBuilder();
departureBuilder.setTime(midnightSecondsSinceEpoch + (8 * 3600) + (45 * 60));
departureBuilder.setDelay(0);
}
}
{
// Stop E
final StopTimeUpdate.Builder stopTimeUpdateBuilder = tripUpdateBuilder.addStopTimeUpdateBuilder();
stopTimeUpdateBuilder.setScheduleRelationship(StopTimeUpdate.ScheduleRelationship.SCHEDULED);
stopTimeUpdateBuilder.setStopId("E");
{
// Arrival
final StopTimeEvent.Builder arrivalBuilder = stopTimeUpdateBuilder.getArrivalBuilder();
arrivalBuilder.setTime(midnightSecondsSinceEpoch + (8 * 3600) + (55 * 60));
arrivalBuilder.setDelay(0);
}
{
// Departure
final StopTimeEvent.Builder departureBuilder = stopTimeUpdateBuilder.getDepartureBuilder();
departureBuilder.setTime(midnightSecondsSinceEpoch + (8 * 3600) + (55 * 60));
departureBuilder.setDelay(0);
}
}
tripUpdate = tripUpdateBuilder.build();
}
// WHEN
updater.applyTripUpdates(graph, fullDataset, Arrays.asList(tripUpdate), feedId);
// THEN
// Find new pattern in graph starting from stop A
Stop stopA = graph.index.getStopForId(new FeedScopedId(feedId, "A"));
// Get trip pattern of last (most recently added) outgoing edge
// FIXME create a new test to see that add-trip realtime updates work
TripPattern tripPattern = null;
assertNotNull("Added trip pattern should be found", tripPattern);
final TimetableSnapshot snapshot = updater.getTimetableSnapshot();
final Timetable forToday = snapshot.resolve(tripPattern, serviceDate);
final Timetable schedule = snapshot.resolve(tripPattern, null);
assertNotSame(forToday, schedule);
final int forTodayAddedTripIndex = forToday.getTripIndex(addedTripId);
assertTrue("Added trip should be found in time table for service date", forTodayAddedTripIndex > -1);
assertEquals(RealTimeState.ADDED, forToday.getTripTimes(forTodayAddedTripIndex).getRealTimeState());
final int scheduleTripIndex = schedule.getTripIndex(addedTripId);
assertEquals("Added trip should not be found in scheduled time table", -1, scheduleTripIndex);
}
use of org.opentripplanner.model.Timetable in project OpenTripPlanner by opentripplanner.
the class SiriTimetableSnapshotSource method handleModifiedTrip.
private boolean handleModifiedTrip(Graph graph, String feedId, EstimatedVehicleJourney estimatedVehicleJourney) {
// Check if EstimatedVehicleJourney is reported as NOT monitored
if (estimatedVehicleJourney.isMonitored() != null && !estimatedVehicleJourney.isMonitored()) {
// Ignore the notMonitored-flag if the journey is NOT monitored because it has been cancelled
if (estimatedVehicleJourney.isCancellation() != null && !estimatedVehicleJourney.isCancellation()) {
return false;
}
}
// Values used in logging
String operatorRef = (estimatedVehicleJourney.getOperatorRef() != null ? estimatedVehicleJourney.getOperatorRef().getValue() : null);
String vehicleModes = "" + estimatedVehicleJourney.getVehicleModes();
String lineRef = estimatedVehicleJourney.getLineRef().getValue();
String vehicleRef = (estimatedVehicleJourney.getVehicleRef() != null ? estimatedVehicleJourney.getVehicleRef().getValue() : null);
ServiceDate serviceDate = getServiceDateForEstimatedVehicleJourney(estimatedVehicleJourney);
if (serviceDate == null) {
return false;
}
Set<TripTimes> times = new HashSet<>();
Set<TripPattern> patterns = new HashSet<>();
Trip tripMatchedByServiceJourneyId = siriFuzzyTripMatcher.findTripByDatedVehicleJourneyRef(estimatedVehicleJourney);
if (tripMatchedByServiceJourneyId != null) {
/*
Found exact match
*/
TripPattern exactPattern = routingService.getPatternForTrip().get(tripMatchedByServiceJourneyId);
if (exactPattern != null) {
Timetable currentTimetable = getCurrentTimetable(exactPattern, serviceDate);
TripTimes exactUpdatedTripTimes = createUpdatedTripTimes(graph, currentTimetable, estimatedVehicleJourney, timeZone, tripMatchedByServiceJourneyId.getId());
if (exactUpdatedTripTimes != null) {
times.add(exactUpdatedTripTimes);
patterns.add(exactPattern);
} else {
LOG.info("Failed to update TripTimes for trip found by exact match {}", tripMatchedByServiceJourneyId.getId());
return false;
}
}
} else {
/*
No exact match found - search for trips based on arrival-times/stop-patterns
*/
Set<Trip> trips = siriFuzzyTripMatcher.match(estimatedVehicleJourney);
if (trips == null || trips.isEmpty()) {
LOG.debug("No trips found for EstimatedVehicleJourney. [operator={}, vehicleModes={}, lineRef={}, vehicleRef={}]", operatorRef, vehicleModes, lineRef, vehicleRef);
return false;
}
// Find the trips that best corresponds to EstimatedVehicleJourney
Set<Trip> matchingTrips = getTripForJourney(trips, estimatedVehicleJourney);
if (matchingTrips == null || matchingTrips.isEmpty()) {
LOG.debug("Found no matching trip for SIRI ET (serviceDate, departureTime). [operator={}, vehicleModes={}, lineRef={}, vehicleJourneyRef={}]", operatorRef, vehicleModes, lineRef, vehicleRef);
return false;
}
for (Trip matchingTrip : matchingTrips) {
TripPattern pattern = getPatternForTrip(matchingTrip, estimatedVehicleJourney);
if (pattern != null) {
Timetable currentTimetable = getCurrentTimetable(pattern, serviceDate);
TripTimes updatedTripTimes = createUpdatedTripTimes(graph, currentTimetable, estimatedVehicleJourney, timeZone, matchingTrip.getId());
if (updatedTripTimes != null) {
patterns.add(pattern);
times.add(updatedTripTimes);
}
}
}
}
if (patterns.isEmpty()) {
LOG.debug("Found no matching pattern for SIRI ET (firstStopId, lastStopId, numberOfStops). [operator={}, vehicleModes={}, lineRef={}, vehicleRef={}]", operatorRef, vehicleModes, lineRef, vehicleRef);
return false;
}
if (times.isEmpty()) {
return false;
}
boolean result = false;
for (TripTimes tripTimes : times) {
Trip trip = tripTimes.trip;
for (TripPattern pattern : patterns) {
if (tripTimes.getNumStops() == pattern.stopPattern.stops.length) {
if (!tripTimes.isCanceled()) {
/*
UPDATED and MODIFIED tripTimes should be handled the same way to always allow latest realtime-update
to replace previous update regardless of realtimestate
*/
cancelScheduledTrip(feedId, trip.getId().getId(), serviceDate);
// Check whether trip id has been used for previously ADDED/MODIFIED trip message and cancel
// previously created trip
cancelPreviouslyAddedTrip(feedId, trip.getId().getId(), serviceDate);
// Calculate modified stop-pattern
Timetable currentTimetable = getCurrentTimetable(pattern, serviceDate);
List<Stop> modifiedStops = createModifiedStops(currentTimetable, estimatedVehicleJourney, routingService);
List<StopTime> modifiedStopTimes = createModifiedStopTimes(currentTimetable, tripTimes, estimatedVehicleJourney, trip, routingService);
if (modifiedStops != null && modifiedStops.isEmpty()) {
tripTimes.cancel();
} else {
// Add new trip
result = result | addTripToGraphAndBuffer(feedId, graph, trip, modifiedStopTimes, modifiedStops, tripTimes, serviceDate);
}
} else {
result = result | buffer.update(pattern, tripTimes, serviceDate);
}
LOG.debug("Applied realtime data for trip {}", trip.getId().getId());
} else {
LOG.debug("Ignoring update since number of stops do not match");
}
}
}
return result;
}
Aggregations