Search in sources :

Example 41 with TripPattern

use of org.opentripplanner.model.TripPattern 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;
}
Also used : Timetable(org.opentripplanner.model.Timetable) Trip(org.opentripplanner.model.Trip) Stop(org.opentripplanner.model.Stop) TripPattern(org.opentripplanner.model.TripPattern) ServiceDate(org.opentripplanner.model.calendar.ServiceDate) TimetableHelper.createUpdatedTripTimes(org.opentripplanner.ext.siri.TimetableHelper.createUpdatedTripTimes) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) HashSet(java.util.HashSet) StopTime(org.opentripplanner.model.StopTime)

Example 42 with TripPattern

use of org.opentripplanner.model.TripPattern in project OpenTripPlanner by opentripplanner.

the class SiriTimetableSnapshotSource method getPatternForTrip.

private TripPattern getPatternForTrip(Trip trip, EstimatedVehicleJourney journey) {
    Set<ServiceDate> serviceDates = routingService.getCalendarService().getServiceDatesForServiceId(trip.getServiceId());
    List<RecordedCall> recordedCalls = (journey.getRecordedCalls() != null ? journey.getRecordedCalls().getRecordedCalls() : new ArrayList<>());
    List<EstimatedCall> estimatedCalls = journey.getEstimatedCalls().getEstimatedCalls();
    String journeyFirstStopId;
    ServiceDate journeyDate;
    if (recordedCalls != null && !recordedCalls.isEmpty()) {
        RecordedCall recordedCall = recordedCalls.get(0);
        journeyFirstStopId = recordedCall.getStopPointRef().getValue();
        journeyDate = new ServiceDate(Date.from(recordedCall.getAimedDepartureTime().toInstant()));
    } else if (estimatedCalls != null && !estimatedCalls.isEmpty()) {
        EstimatedCall estimatedCall = estimatedCalls.get(0);
        journeyFirstStopId = estimatedCall.getStopPointRef().getValue();
        journeyDate = new ServiceDate(Date.from(estimatedCall.getAimedDepartureTime().toInstant()));
    } else {
        return null;
    }
    String journeyLastStopId = estimatedCalls.get(estimatedCalls.size() - 1).getStopPointRef().getValue();
    TripPattern lastAddedTripPattern = null;
    if (getTimetableSnapshot() != null) {
        lastAddedTripPattern = getTimetableSnapshot().getLastAddedTripPattern(trip.getId(), journeyDate);
    }
    TripPattern tripPattern;
    if (lastAddedTripPattern != null) {
        tripPattern = lastAddedTripPattern;
    } else {
        tripPattern = routingService.getPatternForTrip().get(trip);
    }
    Stop firstStop = tripPattern.getStop(0);
    Stop lastStop = tripPattern.getStop(tripPattern.getStops().size() - 1);
    if (serviceDates.contains(journeyDate)) {
        boolean firstStopIsMatch = firstStop.getId().getId().equals(journeyFirstStopId);
        boolean lastStopIsMatch = lastStop.getId().getId().equals(journeyLastStopId);
        if (!firstStopIsMatch && firstStop.isPartOfStation()) {
            Stop otherFirstStop = routingService.getStopForId(new FeedScopedId(firstStop.getId().getFeedId(), journeyFirstStopId));
            firstStopIsMatch = firstStop.isPartOfSameStationAs(otherFirstStop);
        }
        if (!lastStopIsMatch && lastStop.isPartOfStation()) {
            Stop otherLastStop = routingService.getStopForId(new FeedScopedId(lastStop.getId().getFeedId(), journeyLastStopId));
            lastStopIsMatch = lastStop.isPartOfSameStationAs(otherLastStop);
        }
        if (firstStopIsMatch & lastStopIsMatch) {
            // Found matches
            return tripPattern;
        }
        return null;
    }
    return null;
}
Also used : ServiceDate(org.opentripplanner.model.calendar.ServiceDate) Stop(org.opentripplanner.model.Stop) ArrayList(java.util.ArrayList) FeedScopedId(org.opentripplanner.model.FeedScopedId) RecordedCall(uk.org.siri.siri20.RecordedCall) EstimatedCall(uk.org.siri.siri20.EstimatedCall) TripPattern(org.opentripplanner.model.TripPattern)

Example 43 with TripPattern

use of org.opentripplanner.model.TripPattern in project OpenTripPlanner by opentripplanner.

the class TripServiceDateKey method getOrCreateTripPattern.

/**
 * Get cached trip pattern or create one if it doesn't exist yet. If a trip pattern is created, vertices
 * and edges for this trip pattern are also created in the graph.
 *
 * @param stopPattern stop pattern to retrieve/create trip pattern
 * @param trip Trip containing route of new trip pattern in case a new trip pattern will be created
 * @param graph graph to add vertices and edges in case a new trip pattern will be created
 * @param serviceDate
 * @return cached or newly created trip pattern
 */
public synchronized TripPattern getOrCreateTripPattern(@NotNull final StopPattern stopPattern, @NotNull final Trip trip, @NotNull final Graph graph, @NotNull ServiceDate serviceDate) {
    // Check cache for trip pattern
    StopPatternServiceDateKey key = new StopPatternServiceDateKey(stopPattern, serviceDate);
    TripPattern tripPattern = cache.get(key);
    // Create TripPattern if it doesn't exist yet
    if (tripPattern == null) {
        tripPattern = new TripPattern(trip.getRoute(), stopPattern);
        // Generate unique code for trip pattern
        // TODO - SIRI: Is this a good way to generate new trippPattern.id?
        tripPattern.setId(new FeedScopedId(trip.getId().getFeedId(), generateUniqueTripPatternCode(tripPattern)));
        // Create an empty bitset for service codes (because the new pattern does not contain any trips)
        tripPattern.setServiceCodes(graph.getServiceCodes());
        // Finish scheduled time table
        tripPattern.scheduledTimetable.finish();
        // Create vertices and edges for new TripPattern
        // TODO: purge these vertices and edges once in a while?
        // tripPattern.makePatternVerticesAndEdges(graph, graph.index.stopVertexForStop);
        // TODO - SIRI: Add pattern to graph index?
        TripPattern originalTripPattern = graph.index.getPatternForTrip().get(trip);
        // Copy information from the TripPattern this is replacing
        if (originalTripPattern != null) {
            tripPattern.setId(originalTripPattern.getId());
            tripPattern.setHopGeometriesFromPattern(originalTripPattern);
        }
        // Add pattern to cache
        cache.put(key, tripPattern);
    }
    /**
     * When the StopPattern is first modified (e.g. change of platform), then updated (or vice versa), the stopPattern is altered, and
     * the StopPattern-object for the different states will not be equal.
     *
     * This causes both tripPatterns to be added to all unchanged stops along the route, which again causes duplicate results
     * in departureRow-searches (one departure for "updated", one for "modified").
     *
     * Full example:
     *      Planned stops: Stop 1 - Platform 1, Stop 2 - Platform 1
     *
     *      StopPattern #rt1: "updated" stopPattern cached in 'patternsForStop':
     *          - Stop 1, Platform 1
     *          	- StopPattern #rt1
     *          - Stop 2, Platform 1
     *          	- StopPattern #rt1
     *
     *      "modified" stopPattern: Stop 1 - Platform 1, Stop 2 - Platform 2
     *
     *      StopPattern #rt2: "modified" stopPattern cached in 'patternsForStop' will then be:
     *          - Stop 1, Platform 1
     *          	- StopPattern #rt1, StopPattern #rt2
     *          - Stop 2, Platform 1
     *          	- StopPattern #rt1
     *          - Stop 2, Platform 2
     *          	- StopPattern #rt2
     *
     * Therefore, we must cleanup the duplicates by deleting the previously added (and thus outdated)
     * tripPattern for all affected stops. In example above, "StopPattern #rt1" should be removed from all stops
     */
    TripServiceDateKey tripServiceDateKey = new TripServiceDateKey(trip, serviceDate);
    if (updatedTripPatternsForTripCache.containsKey(tripServiceDateKey)) {
        /**
         * Remove previously added TripPatterns for the trip currently being updated - if the stopPattern does not match
         */
        TripPattern cachedTripPattern = updatedTripPatternsForTripCache.get(tripServiceDateKey);
        if (cachedTripPattern != null && !tripPattern.stopPattern.equals(cachedTripPattern.stopPattern)) {
            int sizeBefore = patternsForStop.values().size();
            long t1 = System.currentTimeMillis();
            patternsForStop.values().removeAll(Arrays.asList(cachedTripPattern));
            int sizeAfter = patternsForStop.values().size();
            log.info("Removed outdated TripPattern for {} stops in {} ms - tripId: {}", (sizeBefore - sizeAfter), (System.currentTimeMillis() - t1), trip.getId());
        /*
                  TODO: Also remove previously updated - now outdated - TripPattern from cache ?
                  cache.remove(new StopPatternServiceDateKey(cachedTripPattern.stopPattern, serviceDate));
                */
        }
    }
    // To make these trip patterns visible for departureRow searches.
    for (Stop stop : tripPattern.getStops()) {
        if (!patternsForStop.containsEntry(stop, tripPattern)) {
            patternsForStop.put(stop, tripPattern);
        }
    }
    /**
     * Cache the last added tripPattern that has been used to update a specific trip
     */
    updatedTripPatternsForTripCache.put(tripServiceDateKey, tripPattern);
    return tripPattern;
}
Also used : Stop(org.opentripplanner.model.Stop) FeedScopedId(org.opentripplanner.model.FeedScopedId) TripPattern(org.opentripplanner.model.TripPattern)

Example 44 with TripPattern

use of org.opentripplanner.model.TripPattern in project OpenTripPlanner by opentripplanner.

the class LegacyGraphQLStopImpl method stopTimesForPattern.

@Override
public DataFetcher<Iterable<TripTimeShort>> stopTimesForPattern() {
    return environment -> getValue(environment, stop -> {
        RoutingService routingService = getRoutingService(environment);
        LegacyGraphQLTypes.LegacyGraphQLStopStopTimesForPatternArgs args = new LegacyGraphQLTypes.LegacyGraphQLStopStopTimesForPatternArgs(environment.getArguments());
        TripPattern pattern = routingService.getTripPatternForId(FeedScopedId.parseId(args.getLegacyGraphQLId()));
        if (pattern == null) {
            return null;
        }
        ;
        return routingService.stopTimesForPatternAtStop(stop, pattern, args.getLegacyGraphQLStartTime(), args.getLegacyGraphQLTimeRange(), args.getLegacyGraphQLNumberOfDepartures(), args.getLegacyGraphQLOmitNonPickups());
    }, station -> null);
}
Also used : DataFetchingEnvironment(graphql.schema.DataFetchingEnvironment) StopAtDistance(org.opentripplanner.routing.graphfinder.StopAtDistance) RoutingService(org.opentripplanner.routing.RoutingService) StopTimesInPattern(org.opentripplanner.model.StopTimesInPattern) Function(java.util.function.Function) LegacyGraphQLTypes(org.opentripplanner.ext.legacygraphqlapi.generated.LegacyGraphQLTypes) ServiceDate(org.opentripplanner.model.calendar.ServiceDate) LegacyGraphQLRequestContext(org.opentripplanner.ext.legacygraphqlapi.LegacyGraphQLRequestContext) ArrayList(java.util.ArrayList) TripTimeShort(org.opentripplanner.model.TripTimeShort) Map(java.util.Map) DataFetcher(graphql.schema.DataFetcher) ParseException(java.text.ParseException) FeedScopedId(org.opentripplanner.model.FeedScopedId) Station(org.opentripplanner.model.Station) TripPattern(org.opentripplanner.model.TripPattern) Stop(org.opentripplanner.model.Stop) Collection(java.util.Collection) Collectors(java.util.stream.Collectors) GeometryUtils(org.opentripplanner.common.geometry.GeometryUtils) TransitAlert(org.opentripplanner.routing.alertpatch.TransitAlert) List(java.util.List) Route(org.opentripplanner.model.Route) Stream(java.util.stream.Stream) SimpleTransfer(org.opentripplanner.model.SimpleTransfer) LegacyGraphQLDataFetchers(org.opentripplanner.ext.legacygraphqlapi.generated.LegacyGraphQLDataFetchers) Relay(graphql.relay.Relay) Comparator(java.util.Comparator) Edge(org.opentripplanner.routing.graph.Edge) RoutingService(org.opentripplanner.routing.RoutingService) TripPattern(org.opentripplanner.model.TripPattern) LegacyGraphQLTypes(org.opentripplanner.ext.legacygraphqlapi.generated.LegacyGraphQLTypes)

Example 45 with TripPattern

use of org.opentripplanner.model.TripPattern in project OpenTripPlanner by opentripplanner.

the class AddTransitModelEntitiesToGraph method addStopsToGraphAndGenerateStopVertexes.

private void addStopsToGraphAndGenerateStopVertexes(Graph graph) {
    // Compute the set of modes for each stop based on all the TripPatterns it is part of
    Map<Stop, Set<TransitMode>> stopModeMap = new HashMap<>();
    for (TripPattern pattern : transitService.getTripPatterns()) {
        TransitMode mode = pattern.getMode();
        graph.addTransitMode(mode);
        for (Stop stop : pattern.getStops()) {
            Set<TransitMode> set = stopModeMap.computeIfAbsent(stop, s -> new HashSet<>());
            set.add(mode);
        }
    }
    // It is now possible for these vertices to not be connected to any edges.
    for (Stop stop : transitService.getAllStops()) {
        Set<TransitMode> modes = stopModeMap.get(stop);
        TransitStopVertex stopVertex = new TransitStopVertex(graph, stop, modes);
        if (modes != null && modes.contains(TransitMode.SUBWAY)) {
            stopVertex.setStreetToStopTime(subwayAccessTime);
        }
        // Add stops to internal index for Pathways to be created from this map
        stationElementNodes.put(stop, stopVertex);
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) Stop(org.opentripplanner.model.Stop) HashMap(java.util.HashMap) TransitStopVertex(org.opentripplanner.routing.vertextype.TransitStopVertex) TransitMode(org.opentripplanner.model.TransitMode) TripPattern(org.opentripplanner.model.TripPattern)

Aggregations

TripPattern (org.opentripplanner.model.TripPattern)61 Trip (org.opentripplanner.model.Trip)26 FeedScopedId (org.opentripplanner.model.FeedScopedId)23 Stop (org.opentripplanner.model.Stop)23 ArrayList (java.util.ArrayList)19 TripTimes (org.opentripplanner.routing.trippattern.TripTimes)19 Timetable (org.opentripplanner.model.Timetable)13 ServiceDate (org.opentripplanner.model.calendar.ServiceDate)13 Route (org.opentripplanner.model.Route)12 Test (org.junit.Test)11 HashSet (java.util.HashSet)8 RoutingService (org.opentripplanner.routing.RoutingService)8 List (java.util.List)7 StopPattern (org.opentripplanner.model.StopPattern)7 TimetableSnapshot (org.opentripplanner.model.TimetableSnapshot)7 GET (javax.ws.rs.GET)6 Path (javax.ws.rs.Path)6 StopTime (org.opentripplanner.model.StopTime)5 TripUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate)4 StopTimeUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate)4