From 4b052d5398c4a9ac920ae91a0b50471f214c3669 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Mon, 2 Oct 2023 17:01:59 +0300 Subject: [PATCH 01/98] Draft upcoming cancelled trips query --- .../apis/gtfs/datafetchers/DatedTripImpl.java | 37 ++++++++++++ .../gtfs/datafetchers/NodeTypeResolver.java | 4 ++ .../apis/gtfs/datafetchers/QueryTypeImpl.java | 20 +++++++ .../gtfs/generated/GraphQLDataFetchers.java | 38 ++++++++++++ .../apis/gtfs/generated/GraphQLTypes.java | 60 +++++++++++++++++++ .../apis/gtfs/generated/graphql-codegen.yml | 3 + .../transit/model/timetable/DatedTrip.java | 8 +++ .../service/DefaultTransitService.java | 32 ++++++++++ .../transit/service/TransitService.java | 3 + .../opentripplanner/apis/gtfs/schema.graphqls | 31 ++++++++++ 10 files changed, 236 insertions(+) create mode 100644 src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java create mode 100644 src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java new file mode 100644 index 00000000000..07f7c482754 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java @@ -0,0 +1,37 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.relay.Relay; +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import org.opentripplanner.api.mapping.LocalDateMapper; +import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.transit.model.timetable.DatedTrip; +import org.opentripplanner.transit.model.timetable.Trip; + +public class DatedTripImpl implements GraphQLDataFetchers.GraphQLDatedTrip { + + @Override + public DataFetcher date() { + return env -> LocalDateMapper.mapToApi(getSource(env).serviceDate()); + } + + @Override + public DataFetcher trip() { + return env -> getSource(env).trip(); + } + + @Override + public DataFetcher id() { + return env -> + new Relay.ResolvedGlobalId( + "DatedTrip", + getSource(env).trip().getId().toString() + + ';' + + LocalDateMapper.mapToApi(getSource(env).serviceDate()) + ); + } + + private DatedTrip getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java index 437d75e03e9..63f80fb643f 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java @@ -20,6 +20,7 @@ import org.opentripplanner.transit.model.organization.Agency; import org.opentripplanner.transit.model.site.RegularStop; import org.opentripplanner.transit.model.site.Station; +import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; public class NodeTypeResolver implements TypeResolver { @@ -85,6 +86,9 @@ public GraphQLObjectType getType(TypeResolutionEnvironment environment) { if (o instanceof Trip) { return schema.getObjectType("Trip"); } + if (o instanceof DatedTrip) { + return schema.getObjectType("DatedTrip"); + } return null; } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index dfa4a60ce1c..0af024b284e 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -63,6 +63,7 @@ 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.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.service.TransitService; import org.opentripplanner.updater.GtfsRealtimeFuzzyTripMatcher; @@ -422,6 +423,8 @@ public DataFetcher node() { return new PlaceAtDistance(place, Double.parseDouble(parts[0])); } + case "DatedTrip": + return null; // ???? case "Route": return transitService.getRouteForId(FeedScopedId.parse(id)); case "Stop": @@ -787,6 +790,23 @@ public DataFetcher> trips() { }; } + @Override + public DataFetcher> cancelledTrips() { + return environment -> { + // var args = new GraphQLTypes.GraphQLQueryTypeGetTripsArgs(environment.getArguments()); + + Stream tripStream = getTransitService(environment).getCancelledTrips().stream(); + + /* if (args.getGraphQLFeeds() != null) { + List feeds = args.getGraphQLFeeds(); + tripStream = tripStream.filter(datedTrip -> feeds.contains(datedTrip.getTrip().getId().getFeedId())); + }*/ + + var datedTrips = tripStream.collect(Collectors.toList()); + return new SimpleListConnection<>(datedTrips).get(environment); + }; + } + @Override public DataFetcher vehicleParking() { return environment -> { diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index d0562215f70..b4050392ed7 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -2,11 +2,16 @@ package org.opentripplanner.apis.gtfs.generated; import graphql.relay.Connection; +import graphql.relay.Connection; +import graphql.relay.Connection; +import graphql.relay.Edge; +import graphql.relay.Edge; import graphql.relay.Edge; import graphql.schema.DataFetcher; import graphql.schema.TypeResolver; import java.util.Currency; import java.util.Map; +import java.util.Map; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.opentripplanner.api.resource.DebugOutput; @@ -20,7 +25,11 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; import org.opentripplanner.apis.gtfs.model.RideHailingProvider; +import org.opentripplanner.apis.gtfs.model.RouteTypeModel; +import org.opentripplanner.apis.gtfs.model.StopOnRouteModel; +import org.opentripplanner.apis.gtfs.model.StopOnTripModel; import org.opentripplanner.apis.gtfs.model.StopPosition; +import org.opentripplanner.apis.gtfs.model.UnknownModel; import org.opentripplanner.ext.fares.model.FareRuleSet; import org.opentripplanner.ext.ridehailing.model.RideEstimate; import org.opentripplanner.model.StopTimesInPattern; @@ -42,6 +51,8 @@ import org.opentripplanner.routing.graphfinder.PatternAtStop; import org.opentripplanner.routing.graphfinder.PlaceAtDistance; import org.opentripplanner.routing.vehicle_parking.VehicleParking; +import org.opentripplanner.routing.vehicle_parking.VehicleParking; +import org.opentripplanner.routing.vehicle_parking.VehicleParking; import org.opentripplanner.routing.vehicle_parking.VehicleParkingSpaces; import org.opentripplanner.routing.vehicle_parking.VehicleParkingState; import org.opentripplanner.service.vehiclepositions.model.RealtimeVehiclePosition; @@ -50,11 +61,13 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; +import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; import org.opentripplanner.transit.model.basic.Money; import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.organization.Agency; +import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; public class GraphQLDataFetchers { @@ -293,6 +306,29 @@ public interface GraphQLCurrency { public DataFetcher digits(); } + /** Trip on a specific date */ + public interface GraphQLDatedTrip { + public DataFetcher date(); + + public DataFetcher id(); + + public DataFetcher trip(); + } + + /** A connection to a list of dated trips */ + public interface GraphQLDatedTripConnection { + public DataFetcher>> edges(); + + public DataFetcher pageInfo(); + } + + /** An edge for DatedTrip connection */ + public interface GraphQLDatedTripEdge { + public DataFetcher cursor(); + + public DataFetcher node(); + } + /** * The standard case of a fare product: it only has a single price to be paid by the passenger * and no discounts are applied. @@ -665,6 +701,8 @@ public interface GraphQLQueryType { public DataFetcher> cancelledTripTimes(); + public DataFetcher> cancelledTrips(); + public DataFetcher carPark(); public DataFetcher> carParks(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 3593145e274..202364238ae 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -1,6 +1,7 @@ // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. package org.opentripplanner.apis.gtfs.generated; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -1205,6 +1206,65 @@ public void setGraphQLTrips(List trips) { } } + public static class GraphQLQueryTypeCancelledTripsArgs { + + private String after; + private String before; + private List feeds; + private Integer first; + private Integer last; + + public GraphQLQueryTypeCancelledTripsArgs(Map args) { + if (args != null) { + this.after = (String) args.get("after"); + this.before = (String) args.get("before"); + this.feeds = (List) args.get("feeds"); + this.first = (Integer) args.get("first"); + this.last = (Integer) args.get("last"); + } + } + + public String getGraphQLAfter() { + return this.after; + } + + public String getGraphQLBefore() { + return this.before; + } + + public List getGraphQLFeeds() { + return this.feeds; + } + + public Integer getGraphQLFirst() { + return this.first; + } + + public Integer getGraphQLLast() { + return this.last; + } + + public void setGraphQLAfter(String after) { + this.after = after; + } + + public void setGraphQLBefore(String before) { + this.before = before; + } + + public void setGraphQLFeeds(List feeds) { + this.feeds = feeds; + } + + public void setGraphQLFirst(Integer first) { + this.first = first; + } + + public void setGraphQLLast(Integer last) { + this.last = last; + } + } + public static class GraphQLQueryTypeCarParkArgs { private String id; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 14d00ec1bd4..25002da4659 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -47,6 +47,9 @@ config: ContactInfo: org.opentripplanner.transit.model.organization.ContactInfo Cluster: Object Coordinates: org.locationtech.jts.geom.Coordinate#Coordinate + DatedTrip: org.opentripplanner.transit.model.timetable.DatedTrip#DatedTrip + DatedTripConnection: graphql.relay.Connection#Connection + DatedTripEdge: graphql.relay.Edge#Edge debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java b/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java new file mode 100644 index 00000000000..0d544bb0c72 --- /dev/null +++ b/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java @@ -0,0 +1,8 @@ +package org.opentripplanner.transit.model.timetable; + +import java.time.LocalDate; + +/** + * Class which represents a trin on a specific date + */ +public record DatedTrip(Trip trip, LocalDate serviceDate) {} diff --git a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 31c453056af..21521024384 100644 --- a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -8,6 +8,7 @@ import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -46,6 +47,8 @@ import org.opentripplanner.transit.model.site.Station; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.model.site.StopLocationsGroup; +import org.opentripplanner.transit.model.timetable.DatedTrip; +import org.opentripplanner.transit.model.timetable.RealTimeState; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; @@ -247,6 +250,35 @@ public Trip getTripForId(FeedScopedId id) { return this.transitModelIndex.getTripForId().get(id); } + @Override + public Collection getCancelledTrips() { + OTPRequestTimeoutException.checkForTimeout(); + List cancelledTrips = new ArrayList<>(); + var timetableSnapshot = lazyGetTimeTableSnapShot(); + if (timetableSnapshot == null) { + return cancelledTrips; + } + var calendarService = getCalendarService(); + var patternMap = transitModelIndex.getPatternForTrip(); + + transitModelIndex + .getTripForId() + .values() + .forEach(trip -> { + Set serviceDates = calendarService.getServiceDatesForServiceId( + trip.getServiceId() + ); + var pattern = patternMap.get(trip); + for (LocalDate date : serviceDates) { + var tt = timetableSnapshot.resolve(pattern, date); + if (tt.getTripTimes(trip).getRealTimeState() == RealTimeState.CANCELED) { + cancelledTrips.add(new DatedTrip(trip, date)); + } + } + }); + return cancelledTrips; + } + @Override public Collection getAllTrips() { OTPRequestTimeoutException.checkForTimeout(); diff --git a/src/main/java/org/opentripplanner/transit/service/TransitService.java b/src/main/java/org/opentripplanner/transit/service/TransitService.java index 78c867ac83e..b612462fbca 100644 --- a/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -38,6 +38,7 @@ import org.opentripplanner.transit.model.site.Station; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.model.site.StopLocationsGroup; +import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; @@ -108,6 +109,8 @@ public interface TransitService { Collection getAllTrips(); + Collection getCancelledTrips(); + Collection getAllRoutes(); TripPattern getPatternForTrip(Trip trip); diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index aaf312244d1..20837e7699c 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -2649,6 +2649,16 @@ type QueryType { maxArrivalTime: Int ): [Stoptime] + """Get cancelled Trips""" + cancelledTrips( + """Feed feedIds (e.g. ["HSL"]).""" + feeds: [String] + before: String + after: String + first: Int + last: Int + ): DatedTripConnection + """Get all patterns""" patterns: [Pattern] @@ -3974,6 +3984,27 @@ type Trip implements Node { ): [Alert] } +""" +Trip on a specific date +""" +type DatedTrip implements Node { + id: ID! + trip: Trip! + date: String! +} + +"""An edge for DatedTrip connection""" +type DatedTripEdge { + node: DatedTrip + cursor: String! +} + +"""A connection to a list of dated trips""" +type DatedTripConnection { + edges: [DatedTripEdge] + pageInfo: PageInfo! +} + """Entities, which are relevant for a trip and can contain alerts""" enum TripAlertType { """Alerts affecting the trip""" From 2e6529e9699e241ccfc9d15a55105df79ec75d12 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 3 Oct 2023 07:42:42 +0300 Subject: [PATCH 02/98] Remove duplicate imports --- .../apis/gtfs/generated/GraphQLDataFetchers.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index b4050392ed7..5f835dbbfc7 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -2,16 +2,11 @@ package org.opentripplanner.apis.gtfs.generated; import graphql.relay.Connection; -import graphql.relay.Connection; -import graphql.relay.Connection; -import graphql.relay.Edge; -import graphql.relay.Edge; import graphql.relay.Edge; import graphql.schema.DataFetcher; import graphql.schema.TypeResolver; import java.util.Currency; import java.util.Map; -import java.util.Map; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.opentripplanner.api.resource.DebugOutput; @@ -51,8 +46,6 @@ import org.opentripplanner.routing.graphfinder.PatternAtStop; import org.opentripplanner.routing.graphfinder.PlaceAtDistance; import org.opentripplanner.routing.vehicle_parking.VehicleParking; -import org.opentripplanner.routing.vehicle_parking.VehicleParking; -import org.opentripplanner.routing.vehicle_parking.VehicleParking; import org.opentripplanner.routing.vehicle_parking.VehicleParkingSpaces; import org.opentripplanner.routing.vehicle_parking.VehicleParkingState; import org.opentripplanner.service.vehiclepositions.model.RealtimeVehiclePosition; @@ -61,7 +54,6 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; -import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; import org.opentripplanner.transit.model.basic.Money; import org.opentripplanner.transit.model.network.Route; From 627d251c3890fe1179a78e73ecf223ba29de027c Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 3 Oct 2023 15:20:52 +0300 Subject: [PATCH 03/98] Node resolver for DatedTrip --- .../apis/gtfs/datafetchers/QueryTypeImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index 0af024b284e..4d1fb20f5a5 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -13,6 +13,7 @@ import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import graphql.schema.DataFetchingEnvironmentImpl; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -424,7 +425,11 @@ public DataFetcher node() { return new PlaceAtDistance(place, Double.parseDouble(parts[0])); } case "DatedTrip": - return null; // ???? + { + String[] parts = id.split(";"); + var trip = transitService.getTripForId(FeedScopedId.parse(parts[0])); + return new DatedTrip(trip, LocalDate.parse(parts[1])); + } case "Route": return transitService.getRouteForId(FeedScopedId.parse(id)); case "Stop": From 6c264348bd23c995f8badd5a786b4963df330b58 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 4 Oct 2023 12:15:03 +0300 Subject: [PATCH 04/98] Hook in DatedTrip data fetcher --- .../java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index d7b936a6198..d4ada6e4552 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -38,6 +38,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl; import org.opentripplanner.apis.gtfs.datafetchers.CurrencyImpl; +import org.opentripplanner.apis.gtfs.datafetchers.DatedTripImpl; import org.opentripplanner.apis.gtfs.datafetchers.DefaultFareProductImpl; import org.opentripplanner.apis.gtfs.datafetchers.DepartureRowImpl; import org.opentripplanner.apis.gtfs.datafetchers.FareProductTypeResolver; @@ -170,6 +171,7 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(CurrencyImpl.class)) .type(typeWiring.build(FareProductUseImpl.class)) .type(typeWiring.build(DefaultFareProductImpl.class)) + .type(typeWiring.build(DatedTripImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring); From fb71d748a1ff84266a6948396bd87b8aff4ccca0 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 4 Oct 2023 14:33:18 +0300 Subject: [PATCH 05/98] Feed filtering parameter for cancelled trips query --- .../apis/gtfs/datafetchers/QueryTypeImpl.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index 4d1fb20f5a5..19acfcaaef2 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -798,14 +798,15 @@ public DataFetcher> trips() { @Override public DataFetcher> cancelledTrips() { return environment -> { - // var args = new GraphQLTypes.GraphQLQueryTypeGetTripsArgs(environment.getArguments()); + var args = new GraphQLTypes.GraphQLQueryTypeCancelledTripsArgs(environment.getArguments()); Stream tripStream = getTransitService(environment).getCancelledTrips().stream(); - /* if (args.getGraphQLFeeds() != null) { - List feeds = args.getGraphQLFeeds(); - tripStream = tripStream.filter(datedTrip -> feeds.contains(datedTrip.getTrip().getId().getFeedId())); - }*/ + List feeds = args.getGraphQLFeeds(); + if (feeds != null) { + tripStream = + tripStream.filter(datedTrip -> feeds.contains(datedTrip.trip().getId().getFeedId())); + } var datedTrips = tripStream.collect(Collectors.toList()); return new SimpleListConnection<>(datedTrips).get(environment); From 184e7e2ca27a1e5534db0f6f11af313c4b489fe8 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 4 Oct 2023 15:07:53 +0300 Subject: [PATCH 06/98] More efficient iteration over all trips --- .../service/DefaultTransitService.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 21521024384..787a501adfe 100644 --- a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -260,22 +260,21 @@ public Collection getCancelledTrips() { } var calendarService = getCalendarService(); var patternMap = transitModelIndex.getPatternForTrip(); - - transitModelIndex - .getTripForId() - .values() - .forEach(trip -> { - Set serviceDates = calendarService.getServiceDatesForServiceId( - trip.getServiceId() - ); - var pattern = patternMap.get(trip); - for (LocalDate date : serviceDates) { - var tt = timetableSnapshot.resolve(pattern, date); - if (tt.getTripTimes(trip).getRealTimeState() == RealTimeState.CANCELED) { - cancelledTrips.add(new DatedTrip(trip, date)); - } + var trips = transitModelIndex.getTripForId(); + + for (Map.Entry entry : trips.entrySet()) { + var trip = entry.getValue(); + Set serviceDates = calendarService.getServiceDatesForServiceId( + trip.getServiceId() + ); + var pattern = patternMap.get(trip); + for (LocalDate date : serviceDates) { + var tt = timetableSnapshot.resolve(pattern, date); + if (tt.getTripTimes(trip).getRealTimeState() == RealTimeState.CANCELED) { + cancelledTrips.add(new DatedTrip(trip, date)); } - }); + } + } return cancelledTrips; } From 2787b7e2e6f68d501280354362596e294e9e424d Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 4 Oct 2023 16:12:08 +0300 Subject: [PATCH 07/98] Sort cancelled trips by ascending time --- .../service/DefaultTransitService.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 787a501adfe..05424da9208 100644 --- a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -10,6 +10,7 @@ import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -254,6 +255,8 @@ public Trip getTripForId(FeedScopedId id) { public Collection getCancelledTrips() { OTPRequestTimeoutException.checkForTimeout(); List cancelledTrips = new ArrayList<>(); + Map departures = new HashMap<>(); + var timetableSnapshot = lazyGetTimeTableSnapShot(); if (timetableSnapshot == null) { return cancelledTrips; @@ -269,12 +272,32 @@ public Collection getCancelledTrips() { ); var pattern = patternMap.get(trip); for (LocalDate date : serviceDates) { - var tt = timetableSnapshot.resolve(pattern, date); - if (tt.getTripTimes(trip).getRealTimeState() == RealTimeState.CANCELED) { + var timetable = timetableSnapshot.resolve(pattern, date); + var tripTimes = timetable.getTripTimes(trip); + if (tripTimes.getRealTimeState() == RealTimeState.CANCELED) { // use UPDATED for faked testing cancelledTrips.add(new DatedTrip(trip, date)); + // store departure time from first stop + departures.put(trip, tripTimes.sortIndex()); } } } + cancelledTrips.sort((t1, t2) -> { + if (t1.serviceDate().isBefore(t2.serviceDate())) { + return -1; + } else if (t2.serviceDate().isBefore(t1.serviceDate())) { + return 1; + } + var departure1 = departures.get(t1.trip()); + var departure2 = departures.get(t2.trip()); + if (departure1 < departure2) { + return -1; + } else if (departure1 > departure2) { + return 1; + } else { + // identical departure day and time, so sort by unique feedscope id + return t1.trip().getId().compareTo(t2.trip().getId()); + } + }); return cancelledTrips; } From 58f0387ef867cd6061d2311dde41e644d2850ddc Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 4 Oct 2023 16:44:31 +0300 Subject: [PATCH 08/98] Move filtering by feed into transit service It is much more efficient to filter trips in early stage --- .../apis/gtfs/datafetchers/QueryTypeImpl.java | 14 ++++---------- .../transit/service/DefaultTransitService.java | 9 ++++++--- .../transit/service/TransitService.java | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index 19acfcaaef2..cf1f6c87f0f 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -799,16 +799,10 @@ public DataFetcher> trips() { public DataFetcher> cancelledTrips() { return environment -> { var args = new GraphQLTypes.GraphQLQueryTypeCancelledTripsArgs(environment.getArguments()); - - Stream tripStream = getTransitService(environment).getCancelledTrips().stream(); - - List feeds = args.getGraphQLFeeds(); - if (feeds != null) { - tripStream = - tripStream.filter(datedTrip -> feeds.contains(datedTrip.trip().getId().getFeedId())); - } - - var datedTrips = tripStream.collect(Collectors.toList()); + var datedTrips = getTransitService(environment) + .getCancelledTrips(args.getGraphQLFeeds()) + .stream() + .collect(Collectors.toList()); return new SimpleListConnection<>(datedTrips).get(environment); }; } diff --git a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 05424da9208..cecb62d7635 100644 --- a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -252,7 +252,7 @@ public Trip getTripForId(FeedScopedId id) { } @Override - public Collection getCancelledTrips() { + public Collection getCancelledTrips(List feeds) { OTPRequestTimeoutException.checkForTimeout(); List cancelledTrips = new ArrayList<>(); Map departures = new HashMap<>(); @@ -267,6 +267,9 @@ public Collection getCancelledTrips() { for (Map.Entry entry : trips.entrySet()) { var trip = entry.getValue(); + if (feeds != null && !feeds.contains(trip.getId().getFeedId())) { + continue; + } Set serviceDates = calendarService.getServiceDatesForServiceId( trip.getServiceId() ); @@ -276,7 +279,7 @@ public Collection getCancelledTrips() { var tripTimes = timetable.getTripTimes(trip); if (tripTimes.getRealTimeState() == RealTimeState.CANCELED) { // use UPDATED for faked testing cancelledTrips.add(new DatedTrip(trip, date)); - // store departure time from first stop + // store departure time from first stop departures.put(trip, tripTimes.sortIndex()); } } @@ -294,7 +297,7 @@ public Collection getCancelledTrips() { } else if (departure1 > departure2) { return 1; } else { - // identical departure day and time, so sort by unique feedscope id + // identical departure day and time, so sort by unique feedscope id return t1.trip().getId().compareTo(t2.trip().getId()); } }); diff --git a/src/main/java/org/opentripplanner/transit/service/TransitService.java b/src/main/java/org/opentripplanner/transit/service/TransitService.java index b612462fbca..bb3b1b54ab1 100644 --- a/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -109,7 +109,7 @@ public interface TransitService { Collection getAllTrips(); - Collection getCancelledTrips(); + Collection getCancelledTrips(List feeds); Collection getAllRoutes(); From 20df02b87e3598524100587dc9fbe30ee87117e8 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Wed, 7 Aug 2024 19:52:54 +0300 Subject: [PATCH 09/98] Use LocalDate for date and include trip's fields instead of trip --- .../apis/gtfs/datafetchers/DatedTripImpl.java | 88 +++++++++++++++++-- .../gtfs/generated/GraphQLDataFetchers.java | 14 ++- .../apis/gtfs/generated/GraphQLTypes.java | 41 ++++++--- .../transit/model/timetable/DatedTrip.java | 2 +- .../opentripplanner/apis/gtfs/schema.graphqls | 28 +++++- 5 files changed, 150 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java index 599f4038190..f8bdf40dbc2 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java @@ -3,21 +3,26 @@ import graphql.relay.Relay; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; +import java.time.Instant; +import java.time.LocalDate; +import java.util.List; +import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.ext.restapi.mapping.LocalDateMapper; +import org.opentripplanner.framework.time.ServiceDateUtils; +import org.opentripplanner.model.Timetable; +import org.opentripplanner.model.TripTimeOnDate; +import org.opentripplanner.transit.model.network.Route; +import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; +import org.opentripplanner.transit.service.TransitService; public class DatedTripImpl implements GraphQLDataFetchers.GraphQLDatedTrip { @Override - public DataFetcher date() { - return env -> LocalDateMapper.mapToApi(getSource(env).serviceDate()); - } - - @Override - public DataFetcher trip() { - return env -> getSource(env).trip(); + public DataFetcher date() { + return env -> getSource(env).serviceDate(); } @Override @@ -31,6 +36,75 @@ public DataFetcher id() { ); } + @Override + public DataFetcher pattern() { + return this::getTripPattern; + } + + @Override + public DataFetcher route() { + return environment -> getSource(environment).trip().getRoute(); + } + + @Override + public DataFetcher> stops() { + return this::getStops; + } + + @Override + public DataFetcher> stoptimes() { + return environment -> { + TransitService transitService = getTransitService(environment); + Trip trip = getSource(environment).trip(); + + var serviceDate = getSource(environment).serviceDate(); + TripPattern tripPattern = transitService.getPatternForTrip(trip, serviceDate); + // no matching pattern found + if (tripPattern == null) { + return List.of(); + } + + Instant midnight = ServiceDateUtils + .asStartOfService(serviceDate, transitService.getTimeZone()) + .toInstant(); + Timetable timetable = transitService.getTimetableForTripPattern(tripPattern, serviceDate); + if (timetable == null) { + return List.of(); + } + return TripTimeOnDate.fromTripTimes(timetable, trip, serviceDate, midnight); + }; + } + + @Override + public DataFetcher tripHeadsign() { + return environment -> + org.opentripplanner.framework.graphql.GraphQLUtils.getTranslation( + getSource(environment).trip().getHeadsign(), + environment + ); + } + + @Override + public DataFetcher tripShortName() { + return environment -> getSource(environment).trip().getShortName(); + } + + private List getStops(DataFetchingEnvironment environment) { + TripPattern tripPattern = getTripPattern(environment); + if (tripPattern == null) { + return List.of(); + } + return List.copyOf(tripPattern.getStops()); + } + + private TripPattern getTripPattern(DataFetchingEnvironment environment) { + return getTransitService(environment).getPatternForTrip(getSource(environment).trip()); + } + + private TransitService getTransitService(DataFetchingEnvironment environment) { + return environment.getContext().transitService(); + } + private DatedTrip getSource(DataFetchingEnvironment environment) { return environment.getSource(); } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index b23a3273518..5c11022cac2 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -317,11 +317,21 @@ public interface GraphQLCurrency { /** Trip on a specific date */ public interface GraphQLDatedTrip { - public DataFetcher date(); + public DataFetcher date(); public DataFetcher id(); - public DataFetcher trip(); + public DataFetcher pattern(); + + public DataFetcher route(); + + public DataFetcher> stops(); + + public DataFetcher> stoptimes(); + + public DataFetcher tripHeadsign(); + + public DataFetcher tripShortName(); } /** A connection to a list of dated trips */ diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 96212d00b39..acac4d61969 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -601,8 +601,8 @@ public void setGraphQLType(GraphQLCyclingOptimizationType type) { } /** - * Predefined optimization alternatives for bicycling routing. For more customization, one can use - * the triangle factors. + * Predefined optimization alternatives for bicycling routing. For more customization, + * one can use the triangle factors. */ public enum GraphQLCyclingOptimizationType { FLAT_STREETS, @@ -611,6 +611,25 @@ public enum GraphQLCyclingOptimizationType { SHORTEST_DURATION, } + public static class GraphQLDatedTripTripHeadsignArgs { + + private String language; + + public GraphQLDatedTripTripHeadsignArgs(Map args) { + if (args != null) { + this.language = (String) args.get("language"); + } + } + + public String getGraphQLLanguage() { + return this.language; + } + + public void setGraphQLLanguage(String language) { + this.language = language; + } + } + public static class GraphQLDepartureRowStoptimesArgs { private Integer numberOfDepartures; @@ -2007,8 +2026,8 @@ public enum GraphQLPropulsionType { } /** - * Additional qualifier for a transport mode. Note that qualifiers can only be used with certain - * transport modes. + * Additional qualifier for a transport mode. + * Note that qualifiers can only be used with certain transport modes. */ public enum GraphQLQualifier { ACCESS, @@ -4118,8 +4137,8 @@ public void setGraphQLType(GraphQLScooterOptimizationType type) { } /** - * Predefined optimization alternatives for scooter routing. For more customization, one can use - * the triangle factors. + * Predefined optimization alternatives for scooter routing. For more customization, + * one can use the triangle factors. */ public enum GraphQLScooterOptimizationType { FLAT_STREETS, @@ -4673,9 +4692,9 @@ public void setGraphQLSlack(java.time.Duration slack) { } /** - * Transit modes include modes that are used within organized transportation networks run by - * public transportation authorities, taxi companies etc. Equivalent to GTFS route_type or to - * NeTEx TransportMode. + * Transit modes include modes that are used within organized transportation networks + * run by public transportation authorities, taxi companies etc. + * Equivalent to GTFS route_type or to NeTEx TransportMode. */ public enum GraphQLTransitMode { AIRPLANE, @@ -5076,8 +5095,8 @@ public void setGraphQLUnpreferredCost(Integer unpreferredCost) { } /** - * The state of the vehicle parking. TEMPORARILY_CLOSED and CLOSED are distinct states so that - * they may be represented differently to the user. + * The state of the vehicle parking. TEMPORARILY_CLOSED and CLOSED are distinct states so that they + * may be represented differently to the user. */ public enum GraphQLVehicleParkingState { CLOSED, diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java b/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java index 0d544bb0c72..2227421ed0e 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java @@ -3,6 +3,6 @@ import java.time.LocalDate; /** - * Class which represents a trin on a specific date + * Class which represents a trip on a specific date */ public record DatedTrip(Trip trip, LocalDate serviceDate) {} diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 6725126fe9d..5dbbc397b29 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -386,9 +386,33 @@ type Currency { "Trip on a specific date" type DatedTrip implements Node { - date: String! + """ + The service date when the trip occurs. + + **Note**: A service date is a technical term useful for transit planning purposes and might not + correspond to a how a passenger thinks of a calendar date. For example, a night bus running + on Sunday morning at 1am to 3am, might have the previous Saturday's service date. + """ + date: LocalDate! + "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! - trip: Trip! + "The pattern the trip is running on" + pattern: Pattern + "The route the trip is running on" + route: Route! + "List of stops this trip passes through" + stops: [Stop!]! + "List of times when this trip arrives to or departs from a stop" + stoptimes: [Stoptime] + "Headsign of the vehicle when running on this trip" + tripHeadsign( + """ + If a translated headsign is found from GTFS translation.txt and wanted language is not same as + feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. + """ + language: String + ): String + tripShortName: String } "A connection to a list of dated trips" From 2a9df2aaff1a4789b8fd2c1a190bfb7d65020a8c Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Thu, 8 Aug 2024 11:31:48 +0300 Subject: [PATCH 10/98] Improve documentation and mark cancelledTripTimes as deprecated --- .../gtfs/generated/GraphQLDataFetchers.java | 10 ++++-- .../opentripplanner/apis/gtfs/schema.graphqls | 35 ++++++++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 5c11022cac2..2239c61d6cb 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -334,14 +334,20 @@ public interface GraphQLDatedTrip { public DataFetcher tripShortName(); } - /** A connection to a list of dated trips */ + /** + * A connection to a list of dated trips that follows + * [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + */ public interface GraphQLDatedTripConnection { public DataFetcher>> edges(); public DataFetcher pageInfo(); } - /** An edge for DatedTrip connection */ + /** + * An edge for DatedTrip connection. Part of the + * [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + */ public interface GraphQLDatedTripEdge { public DataFetcher cursor(); diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 5dbbc397b29..7072ef4b376 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -388,7 +388,7 @@ type Currency { type DatedTrip implements Node { """ The service date when the trip occurs. - + **Note**: A service date is a technical term useful for transit planning purposes and might not correspond to a how a passenger thinks of a calendar date. For example, a night bus running on Sunday morning at 1am to 3am, might have the previous Saturday's service date. @@ -415,15 +415,37 @@ type DatedTrip implements Node { tripShortName: String } -"A connection to a list of dated trips" +""" +A connection to a list of dated trips that follows +[GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). +""" type DatedTripConnection { + """ + Edges which contain the trips. Part of the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ edges: [DatedTripEdge] + """ + Contains cursors to fetch more pages of trips. + Part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ pageInfo: PageInfo! } -"An edge for DatedTrip connection" +""" +An edge for DatedTrip connection. Part of the +[GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). +""" type DatedTripEdge { + """ + The cursor of the edge. Part of the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ cursor: String! + """ + Dated trip as a node. Part of the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ node: DatedTrip } @@ -1170,8 +1192,11 @@ type QueryType { routes: [String], "Trip gtfsIds (e.g. [\"HSL:1098_20190405_Ma_2_1455\"])." trips: [String] - ): [Stoptime] - "Get cancelled Trips" + ): [Stoptime] @deprecated(reason : "`cancelledTripTimes` is deprecated. Use `cancelledTrips` instead.") + """ + Get pages of cancelled Trips. Follows the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ cancelledTrips( after: String, before: String, From b142bdf06d08eebb40f76d9ef043424bf24fe46e Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Thu, 8 Aug 2024 15:59:27 +0300 Subject: [PATCH 11/98] Add start and end to schema --- .../apis/gtfs/GraphQLUtils.java | 15 ++++ .../apis/gtfs/datafetchers/DatedTripImpl.java | 86 +++++++++++++++++-- .../apis/gtfs/datafetchers/StoptimeImpl.java | 25 ++---- .../gtfs/generated/GraphQLDataFetchers.java | 15 ++++ .../apis/gtfs/generated/graphql-codegen.yml | 1 + .../apis/gtfs/model/DatedTripTime.java | 31 +++++++ .../model/plan/ScheduledTransitLeg.java | 7 +- .../model/timetable/RealTimeTripTimes.java | 7 ++ .../model/timetable/ScheduledTripTimes.java | 5 ++ .../transit/model/timetable/TripTimes.java | 5 ++ .../opentripplanner/apis/gtfs/schema.graphqls | 15 ++++ 11 files changed, 182 insertions(+), 30 deletions(-) create mode 100644 src/main/java/org/opentripplanner/apis/gtfs/model/DatedTripTime.java diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GraphQLUtils.java b/src/main/java/org/opentripplanner/apis/gtfs/GraphQLUtils.java index 3fb339daa32..fe63add7d49 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GraphQLUtils.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GraphQLUtils.java @@ -2,6 +2,7 @@ import java.time.Instant; import java.util.Locale; +import javax.annotation.Nullable; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLFilterPlaceType; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLFormFactor; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLInputField; @@ -9,6 +10,7 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLWheelchairBoarding; import org.opentripplanner.framework.i18n.I18NString; +import org.opentripplanner.model.StopTime; import org.opentripplanner.routing.api.response.InputField; import org.opentripplanner.routing.api.response.RoutingErrorCode; import org.opentripplanner.routing.graphfinder.PlaceType; @@ -109,4 +111,17 @@ public static boolean startsWith(String str, String name, Locale locale) { public static boolean startsWith(I18NString str, String name, Locale locale) { return str != null && str.toString(locale).toLowerCase(locale).startsWith(name); } + + /** + * Generally the missing values are removed during the graph build. However, for flex trips they + * are not and have to be converted to null here. + */ + @Nullable + public static Integer stopTimeToInt(int value) { + if (value == StopTime.MISSING_VALUE) { + return null; + } else { + return value; + } + } } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java index f8bdf40dbc2..eb820fc06c5 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java @@ -1,13 +1,18 @@ package org.opentripplanner.apis.gtfs.datafetchers; +import static org.opentripplanner.apis.gtfs.GraphQLUtils.stopTimeToInt; + import graphql.relay.Relay; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import java.time.Instant; import java.time.LocalDate; +import java.time.ZonedDateTime; import java.util.List; +import javax.annotation.Nullable; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.apis.gtfs.model.DatedTripTime; import org.opentripplanner.ext.restapi.mapping.LocalDateMapper; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.Timetable; @@ -16,6 +21,7 @@ import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; +import org.opentripplanner.transit.model.timetable.TripTimes; import org.opentripplanner.transit.service.TransitService; public class DatedTripImpl implements GraphQLDataFetchers.GraphQLDatedTrip { @@ -25,6 +31,24 @@ public DataFetcher date() { return env -> getSource(env).serviceDate(); } + @Override + public DataFetcher end() { + return env -> { + var tripTimes = getTripTimes(env); + if (tripTimes == null) { + return null; + } + var stopIndex = tripTimes.getNumStops() - 1; + var scheduledTime = getZonedDateTime(env, tripTimes.getScheduledArrivalTime(stopIndex)); + if (scheduledTime == null) { + return null; + } + return tripTimes.isRealtimeUpdated(stopIndex) + ? DatedTripTime.of(scheduledTime, tripTimes.getArrivalDelay(stopIndex)) + : DatedTripTime.ofStatic(scheduledTime); + }; + } + @Override public DataFetcher id() { return env -> @@ -46,6 +70,23 @@ public DataFetcher route() { return environment -> getSource(environment).trip().getRoute(); } + @Override + public DataFetcher start() { + return env -> { + var tripTimes = getTripTimes(env); + if (tripTimes == null) { + return null; + } + var scheduledTime = getZonedDateTime(env, tripTimes.getScheduledDepartureTime(0)); + if (scheduledTime == null) { + return null; + } + return tripTimes.isRealtimeUpdated(0) + ? DatedTripTime.of(scheduledTime, tripTimes.getDepartureDelay(0)) + : DatedTripTime.ofStatic(scheduledTime); + }; + } + @Override public DataFetcher> stops() { return this::getStops; @@ -56,18 +97,12 @@ public DataFetcher> stoptimes() { return environment -> { TransitService transitService = getTransitService(environment); Trip trip = getSource(environment).trip(); - var serviceDate = getSource(environment).serviceDate(); - TripPattern tripPattern = transitService.getPatternForTrip(trip, serviceDate); - // no matching pattern found - if (tripPattern == null) { - return List.of(); - } Instant midnight = ServiceDateUtils .asStartOfService(serviceDate, transitService.getTimeZone()) .toInstant(); - Timetable timetable = transitService.getTimetableForTripPattern(tripPattern, serviceDate); + Timetable timetable = getTimetable(environment, trip, serviceDate); if (timetable == null) { return List.of(); } @@ -101,6 +136,43 @@ private TripPattern getTripPattern(DataFetchingEnvironment environment) { return getTransitService(environment).getPatternForTrip(getSource(environment).trip()); } + @Nullable + private Timetable getTimetable( + DataFetchingEnvironment environment, + Trip trip, + LocalDate serviceDate + ) { + TransitService transitService = getTransitService(environment); + TripPattern tripPattern = transitService.getPatternForTrip(trip, serviceDate); + // no matching pattern found + if (tripPattern == null) { + return null; + } + + return transitService.getTimetableForTripPattern(tripPattern, serviceDate); + } + + @Nullable + private TripTimes getTripTimes(DataFetchingEnvironment environment) { + Trip trip = getSource(environment).trip(); + var serviceDate = getSource(environment).serviceDate(); + var timetable = getTimetable(environment, trip, serviceDate); + if (timetable == null) { + return null; + } + return timetable.getTripTimes(trip); + } + + private ZonedDateTime getZonedDateTime(DataFetchingEnvironment environment, int time) { + var fixedTime = stopTimeToInt(time); + if (fixedTime == null) { + return null; + } + var serviceDate = getSource(environment).serviceDate(); + TransitService transitService = getTransitService(environment); + return ServiceDateUtils.toZonedDateTime(serviceDate, transitService.getTimeZone(), fixedTime); + } + private TransitService getTransitService(DataFetchingEnvironment environment) { return environment.getContext().transitService(); } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java index faf59ef9d6e..706c5a4fd5e 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java @@ -1,10 +1,11 @@ package org.opentripplanner.apis.gtfs.datafetchers; +import static org.opentripplanner.apis.gtfs.GraphQLUtils.stopTimeToInt; + import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.framework.graphql.GraphQLUtils; -import org.opentripplanner.model.StopTime; import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.transit.model.timetable.RealTimeState; import org.opentripplanner.transit.model.timetable.Trip; @@ -13,7 +14,7 @@ public class StoptimeImpl implements GraphQLDataFetchers.GraphQLStoptime { @Override public DataFetcher arrivalDelay() { - return environment -> missingValueToNull(getSource(environment).getArrivalDelay()); + return environment -> stopTimeToInt(getSource(environment).getArrivalDelay()); } @Override @@ -58,12 +59,12 @@ public DataFetcher realtime() { @Override public DataFetcher realtimeArrival() { - return environment -> missingValueToNull(getSource(environment).getRealtimeArrival()); + return environment -> stopTimeToInt(getSource(environment).getRealtimeArrival()); } @Override public DataFetcher realtimeDeparture() { - return environment -> missingValueToNull(getSource(environment).getRealtimeDeparture()); + return environment -> stopTimeToInt(getSource(environment).getRealtimeDeparture()); } @Override @@ -76,12 +77,12 @@ public DataFetcher realtimeState() { @Override public DataFetcher scheduledArrival() { - return environment -> missingValueToNull(getSource(environment).getScheduledArrival()); + return environment -> stopTimeToInt(getSource(environment).getScheduledArrival()); } @Override public DataFetcher scheduledDeparture() { - return environment -> missingValueToNull(getSource(environment).getScheduledDeparture()); + return environment -> stopTimeToInt(getSource(environment).getScheduledDeparture()); } @Override @@ -112,16 +113,4 @@ public DataFetcher trip() { private TripTimeOnDate getSource(DataFetchingEnvironment environment) { return environment.getSource(); } - - /** - * Generally the missing values are removed during the graph build. However, for flex trips they - * are not and have to be converted to null here. - */ - private Integer missingValueToNull(int value) { - if (value == StopTime.MISSING_VALUE) { - return null; - } else { - return value; - } - } } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 2239c61d6cb..259d6db86b0 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -21,6 +21,7 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRelativeDirection; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; +import org.opentripplanner.apis.gtfs.model.DatedTripTime; import org.opentripplanner.apis.gtfs.model.FeedPublisher; import org.opentripplanner.apis.gtfs.model.PlanPageInfo; import org.opentripplanner.apis.gtfs.model.RideHailingProvider; @@ -319,12 +320,16 @@ public interface GraphQLCurrency { public interface GraphQLDatedTrip { public DataFetcher date(); + public DataFetcher end(); + public DataFetcher id(); public DataFetcher pattern(); public DataFetcher route(); + public DataFetcher start(); + public DataFetcher> stops(); public DataFetcher> stoptimes(); @@ -354,6 +359,16 @@ public interface GraphQLDatedTripEdge { public DataFetcher node(); } + /** + * Information about a dated trip's start or end times. May contain real-time information if + * available. + */ + public interface GraphQLDatedTripTime { + public DataFetcher estimated(); + + public DataFetcher scheduledTime(); + } + /** * The standard case of a fare product: it only has a single price to be paid by the passenger * and no discounts are applied. diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 465321a58e3..6eb98a7f95b 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -62,6 +62,7 @@ config: DatedTrip: org.opentripplanner.transit.model.timetable.DatedTrip#DatedTrip DatedTripConnection: graphql.relay.Connection#Connection DatedTripEdge: graphql.relay.Edge#Edge + DatedTripTime: org.opentripplanner.apis.gtfs.model.DatedTripTime#DatedTripTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step diff --git a/src/main/java/org/opentripplanner/apis/gtfs/model/DatedTripTime.java b/src/main/java/org/opentripplanner/apis/gtfs/model/DatedTripTime.java new file mode 100644 index 00000000000..a83eb50fe1d --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/model/DatedTripTime.java @@ -0,0 +1,31 @@ +package org.opentripplanner.apis.gtfs.model; + +import java.time.Duration; +import java.time.ZonedDateTime; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * A scheduled time of a trip's start or end with an optional realtime information. + */ +public record DatedTripTime( + @Nonnull ZonedDateTime scheduledTime, + @Nullable RealTimeEstimate estimated +) { + @Nonnull + public static DatedTripTime of(ZonedDateTime realtime, int delaySecs) { + var delay = Duration.ofSeconds(delaySecs); + return new DatedTripTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); + } + + @Nonnull + public static DatedTripTime ofStatic(ZonedDateTime staticTime) { + return new DatedTripTime(staticTime, null); + } + + /** + * Realtime information about a vehicle at a certain place. + * @param delay Delay or "earliness" of a vehicle. Earliness is expressed as a negative number. + */ + record RealTimeEstimate(ZonedDateTime time, Duration delay) {} +} diff --git a/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java b/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java index d94ec1895c2..4a84ac6e799 100644 --- a/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java +++ b/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java @@ -219,11 +219,8 @@ public int getArrivalDelay() { @Override public boolean getRealTime() { return ( - !tripTimes.isScheduled() && - ( - !tripTimes.isNoDataStop(boardStopPosInPattern) || - !tripTimes.isNoDataStop(alightStopPosInPattern) - ) + tripTimes.isRealtimeUpdated(boardStopPosInPattern) || + tripTimes.isRealtimeUpdated(alightStopPosInPattern) ); } diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java b/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java index 711eb1c221c..ca5897b7b24 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java @@ -198,6 +198,13 @@ public boolean isPredictionInaccurate(int stop) { return isStopRealTimeStates(stop, StopRealTimeState.INACCURATE_PREDICTIONS); } + public boolean isRealtimeUpdated(int stop) { + return ( + realTimeState != RealTimeState.SCHEDULED && + !isStopRealTimeStates(stop, StopRealTimeState.NO_DATA) + ); + } + public void setOccupancyStatus(int stop, OccupancyStatus occupancyStatus) { prepareForRealTimeUpdates(); this.occupancyStatus[stop] = occupancyStatus; diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java b/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java index d367932d24d..3799fd7b140 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java @@ -234,6 +234,11 @@ public boolean isPredictionInaccurate(int stop) { return false; } + @Override + public boolean isRealtimeUpdated(int stop) { + return false; + } + @Override public I18NString getTripHeadsign() { return trip.getHeadsign(); diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java b/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java index e5cd1f1ff28..ea1a3f8ab2b 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java @@ -123,6 +123,11 @@ default int compareTo(TripTimes other) { boolean isPredictionInaccurate(int stop); + /** + * Return if trip has been updated and stop has not been given a NO_DATA update. + */ + boolean isRealtimeUpdated(int stop); + /** * @return the whole trip's headsign. Individual stops can have different headsigns. */ diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 7072ef4b376..fb287c5c117 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -394,12 +394,16 @@ type DatedTrip implements Node { on Sunday morning at 1am to 3am, might have the previous Saturday's service date. """ date: LocalDate! + "The time when the trip ends including real-time information, if available." + end: DatedTripTime "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! "The pattern the trip is running on" pattern: Pattern "The route the trip is running on" route: Route! + "The time when the trip starts including real-time information, if available." + start: DatedTripTime "List of stops this trip passes through" stops: [Stop!]! "List of times when this trip arrives to or departs from a stop" @@ -449,6 +453,17 @@ type DatedTripEdge { node: DatedTrip } +""" +Information about a dated trip's start or end times. May contain real-time information if +available. +""" +type DatedTripTime { + "The estimated time of the event. If no real-time information is available, this is null." + estimated: RealTimeEstimate + "The scheduled time of the event." + scheduledTime: OffsetDateTime +} + """ The standard case of a fare product: it only has a single price to be paid by the passenger and no discounts are applied. From 8e12d3a626c5d7c685be9c89c3f1977eece7c9d4 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 9 Aug 2024 16:08:11 +0300 Subject: [PATCH 12/98] Create DatedStopTime type and use it in DatedTrip --- .../apis/gtfs/GtfsGraphQLIndex.java | 2 + .../gtfs/datafetchers/DatedStopTimeImpl.java | 117 ++++++++++++++++++ .../apis/gtfs/datafetchers/DatedTripImpl.java | 14 +-- .../apis/gtfs/datafetchers/StoptimeImpl.java | 19 +-- .../gtfs/generated/GraphQLDataFetchers.java | 48 +++++-- .../apis/gtfs/generated/GraphQLTypes.java | 29 +++++ .../apis/gtfs/generated/graphql-codegen.yml | 4 +- .../apis/gtfs/mapping/PickDropMapper.java | 18 +++ ...ripTime.java => ArrivalDepartureTime.java} | 13 +- .../opentripplanner/model/TripTimeOnDate.java | 8 ++ .../opentripplanner/apis/gtfs/schema.graphqls | 96 +++++++++++--- 11 files changed, 311 insertions(+), 57 deletions(-) create mode 100644 src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeImpl.java create mode 100644 src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java rename src/main/java/org/opentripplanner/apis/gtfs/model/{DatedTripTime.java => ArrivalDepartureTime.java} (56%) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index 163b32de751..a160e197611 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -35,6 +35,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl; import org.opentripplanner.apis.gtfs.datafetchers.CurrencyImpl; +import org.opentripplanner.apis.gtfs.datafetchers.DatedStopTimeImpl; import org.opentripplanner.apis.gtfs.datafetchers.DatedTripImpl; import org.opentripplanner.apis.gtfs.datafetchers.DefaultFareProductImpl; import org.opentripplanner.apis.gtfs.datafetchers.DepartureRowImpl; @@ -180,6 +181,7 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(FareProductUseImpl.class)) .type(typeWiring.build(DefaultFareProductImpl.class)) .type(typeWiring.build(DatedTripImpl.class)) + .type(typeWiring.build(DatedStopTimeImpl.class)) .type(typeWiring.build(TripOccupancyImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeImpl.java new file mode 100644 index 00000000000..3ed12ac4fb6 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeImpl.java @@ -0,0 +1,117 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import static org.opentripplanner.apis.gtfs.GraphQLUtils.stopTimeToInt; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.time.ZonedDateTime; +import org.opentripplanner.apis.gtfs.GraphQLRequestContext; +import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; +import org.opentripplanner.apis.gtfs.mapping.PickDropMapper; +import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; +import org.opentripplanner.framework.graphql.GraphQLUtils; +import org.opentripplanner.framework.time.ServiceDateUtils; +import org.opentripplanner.model.TripTimeOnDate; +import org.opentripplanner.transit.service.TransitService; + +public class DatedStopTimeImpl implements GraphQLDataFetchers.GraphQLDatedStopTime { + + @Override + public DataFetcher arrival() { + return environment -> { + var tripTime = getSource(environment); + var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledArrival()); + if (scheduledTime == null) { + return null; + } + return tripTime.isRealtime() + ? ArrivalDepartureTime.of(scheduledTime, tripTime.getArrivalDelay()) + : ArrivalDepartureTime.ofStatic(scheduledTime); + }; + } + + @Override + public DataFetcher departure() { + return environment -> { + var tripTime = getSource(environment); + var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledDeparture()); + if (scheduledTime == null) { + return null; + } + return tripTime.isRealtime() + ? ArrivalDepartureTime.of(scheduledTime, tripTime.getDepartureDelay()) + : ArrivalDepartureTime.ofStatic(scheduledTime); + }; + } + + @Override + public DataFetcher dropoffType() { + return environment -> PickDropMapper.map(getSource(environment).getDropoffType()); + } + + @Override + public DataFetcher headsign() { + return environment -> + GraphQLUtils.getTranslation(getSource(environment).getHeadsign(), environment); + } + + @Override + public DataFetcher pickupType() { + return environment -> PickDropMapper.map(getSource(environment).getPickupType()); + } + + @Override + public DataFetcher realtimeState() { + return environment -> { + var tripTime = getSource(environment); + // TODO support ADDED state + if (tripTime.isCanceledEffectively()) { + return GraphQLTypes.GraphQLStopRealTimeState.CANCELED; + } + if (tripTime.isNoDataStop()) { + return GraphQLTypes.GraphQLStopRealTimeState.NO_DATA; + } + if (tripTime.isRecordedStop()) { + return GraphQLTypes.GraphQLStopRealTimeState.RECORDED; + } + if (tripTime.isRealtime()) { + return GraphQLTypes.GraphQLStopRealTimeState.UPDATED; + } + return GraphQLTypes.GraphQLStopRealTimeState.UNUPDATED; + }; + } + + @Override + public DataFetcher stopPosition() { + return environment -> getSource(environment).getGtfsSequence(); + } + + @Override + public DataFetcher stop() { + return environment -> getSource(environment).getStop(); + } + + @Override + public DataFetcher timepoint() { + return environment -> getSource(environment).isTimepoint(); + } + + private TransitService getTransitService(DataFetchingEnvironment environment) { + return environment.getContext().transitService(); + } + + private ZonedDateTime getZonedDateTime(DataFetchingEnvironment environment, int time) { + var fixedTime = stopTimeToInt(time); + if (fixedTime == null) { + return null; + } + var serviceDate = getSource(environment).getServiceDay(); + TransitService transitService = getTransitService(environment); + return ServiceDateUtils.toZonedDateTime(serviceDate, transitService.getTimeZone(), fixedTime); + } + + private TripTimeOnDate getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java index eb820fc06c5..5d567d83264 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java @@ -12,7 +12,7 @@ import javax.annotation.Nullable; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; -import org.opentripplanner.apis.gtfs.model.DatedTripTime; +import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; import org.opentripplanner.ext.restapi.mapping.LocalDateMapper; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.Timetable; @@ -32,7 +32,7 @@ public DataFetcher date() { } @Override - public DataFetcher end() { + public DataFetcher end() { return env -> { var tripTimes = getTripTimes(env); if (tripTimes == null) { @@ -44,8 +44,8 @@ public DataFetcher end() { return null; } return tripTimes.isRealtimeUpdated(stopIndex) - ? DatedTripTime.of(scheduledTime, tripTimes.getArrivalDelay(stopIndex)) - : DatedTripTime.ofStatic(scheduledTime); + ? ArrivalDepartureTime.of(scheduledTime, tripTimes.getArrivalDelay(stopIndex)) + : ArrivalDepartureTime.ofStatic(scheduledTime); }; } @@ -71,7 +71,7 @@ public DataFetcher route() { } @Override - public DataFetcher start() { + public DataFetcher start() { return env -> { var tripTimes = getTripTimes(env); if (tripTimes == null) { @@ -82,8 +82,8 @@ public DataFetcher start() { return null; } return tripTimes.isRealtimeUpdated(0) - ? DatedTripTime.of(scheduledTime, tripTimes.getDepartureDelay(0)) - : DatedTripTime.ofStatic(scheduledTime); + ? ArrivalDepartureTime.of(scheduledTime, tripTimes.getDepartureDelay(0)) + : ArrivalDepartureTime.ofStatic(scheduledTime); }; } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java index 706c5a4fd5e..2a433fadee0 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java @@ -5,6 +5,7 @@ import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.apis.gtfs.mapping.PickDropMapper; import org.opentripplanner.framework.graphql.GraphQLUtils; import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.transit.model.timetable.RealTimeState; @@ -24,14 +25,7 @@ public DataFetcher departureDelay() { @Override public DataFetcher dropoffType() { - return environment -> - switch (getSource(environment).getDropoffType()) { - case SCHEDULED -> "SCHEDULED"; - case NONE -> "NONE"; - case CALL_AGENCY -> "CALL_AGENCY"; - case COORDINATE_WITH_DRIVER -> "COORDINATE_WITH_DRIVER"; - case CANCELLED -> null; - }; + return environment -> PickDropMapper.map(getSource(environment).getDropoffType()); } @Override @@ -42,14 +36,7 @@ public DataFetcher headsign() { @Override public DataFetcher pickupType() { - return environment -> - switch (getSource(environment).getPickupType()) { - case SCHEDULED -> "SCHEDULED"; - case NONE -> "NONE"; - case CALL_AGENCY -> "CALL_AGENCY"; - case COORDINATE_WITH_DRIVER -> "COORDINATE_WITH_DRIVER"; - case CANCELLED -> null; - }; + return environment -> PickDropMapper.map(getSource(environment).getPickupType()); } @Override diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 259d6db86b0..ff12746df68 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -20,8 +20,9 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLOccupancyStatus; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRelativeDirection; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; +import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLStopRealTimeState; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; -import org.opentripplanner.apis.gtfs.model.DatedTripTime; +import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; import org.opentripplanner.apis.gtfs.model.FeedPublisher; import org.opentripplanner.apis.gtfs.model.PlanPageInfo; import org.opentripplanner.apis.gtfs.model.RideHailingProvider; @@ -141,6 +142,16 @@ public interface GraphQLAlert { /** Entity related to an alert */ public interface GraphQLAlertEntity extends TypeResolver {} + /** + * Timing of an arrival or a departure to or from a stop. May contain real-time information if + * available. + */ + public interface GraphQLArrivalDepartureTime { + public DataFetcher estimated(); + + public DataFetcher scheduledTime(); + } + /** Bike park represents a location where bicycles can be parked. */ public interface GraphQLBikePark { public DataFetcher bikeParkId(); @@ -316,11 +327,32 @@ public interface GraphQLCurrency { public DataFetcher digits(); } + /** Stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. */ + public interface GraphQLDatedStopTime { + public DataFetcher arrival(); + + public DataFetcher departure(); + + public DataFetcher dropoffType(); + + public DataFetcher headsign(); + + public DataFetcher pickupType(); + + public DataFetcher realtimeState(); + + public DataFetcher stop(); + + public DataFetcher stopPosition(); + + public DataFetcher timepoint(); + } + /** Trip on a specific date */ public interface GraphQLDatedTrip { public DataFetcher date(); - public DataFetcher end(); + public DataFetcher end(); public DataFetcher id(); @@ -328,7 +360,7 @@ public interface GraphQLDatedTrip { public DataFetcher route(); - public DataFetcher start(); + public DataFetcher start(); public DataFetcher> stops(); @@ -359,16 +391,6 @@ public interface GraphQLDatedTripEdge { public DataFetcher node(); } - /** - * Information about a dated trip's start or end times. May contain real-time information if - * available. - */ - public interface GraphQLDatedTripTime { - public DataFetcher estimated(); - - public DataFetcher scheduledTime(); - } - /** * The standard case of a fare product: it only has a single price to be paid by the passenger * and no discounts are applied. diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index acac4d61969..3d9b627154a 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -611,6 +611,25 @@ public enum GraphQLCyclingOptimizationType { SHORTEST_DURATION, } + public static class GraphQLDatedStopTimeHeadsignArgs { + + private String language; + + public GraphQLDatedStopTimeHeadsignArgs(Map args) { + if (args != null) { + this.language = (String) args.get("language"); + } + } + + public String getGraphQLLanguage() { + return this.language; + } + + public void setGraphQLLanguage(String language) { + this.language = language; + } + } + public static class GraphQLDatedTripTripHeadsignArgs { private String language; @@ -4584,6 +4603,16 @@ public enum GraphQLStopAlertType { TRIPS, } + /** Whether stop has been updated through a realtime update and if so, how. */ + public enum GraphQLStopRealTimeState { + ADDED, + CANCELED, + NO_DATA, + RECORDED, + UNUPDATED, + UPDATED, + } + public static class GraphQLStoptimeHeadsignArgs { private String language; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 6eb98a7f95b..1d5ebd31a4f 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -59,10 +59,11 @@ config: ContactInfo: org.opentripplanner.transit.model.organization.ContactInfo Cluster: Object Coordinates: org.locationtech.jts.geom.Coordinate#Coordinate + DatedStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate DatedTrip: org.opentripplanner.transit.model.timetable.DatedTrip#DatedTrip DatedTripConnection: graphql.relay.Connection#Connection DatedTripEdge: graphql.relay.Edge#Edge - DatedTripTime: org.opentripplanner.apis.gtfs.model.DatedTripTime#DatedTripTime + ArrivalDepartureTime: org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime#ArrivalDepartureTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step @@ -101,6 +102,7 @@ config: stopAtDistanceEdge: graphql.relay.Edge#Edge StopOnRoute: org.opentripplanner.apis.gtfs.model.StopOnRouteModel#StopOnRouteModel StopOnTrip: org.opentripplanner.apis.gtfs.model.StopOnTripModel#StopOnTripModel + StopRealTimeState: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLStopRealTimeState#GraphQLStopRealTimeState Stoptime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate StoptimesInPattern: org.opentripplanner.model.StopTimesInPattern#StopTimesInPattern TicketType: org.opentripplanner.ext.fares.model.FareRuleSet#FareRuleSet diff --git a/src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java b/src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java new file mode 100644 index 00000000000..c8e4d212999 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java @@ -0,0 +1,18 @@ +package org.opentripplanner.apis.gtfs.mapping; + +import javax.annotation.Nullable; +import org.opentripplanner.model.PickDrop; + +public final class PickDropMapper { + + @Nullable + public static String map(PickDrop pickDrop) { + return switch (pickDrop) { + case SCHEDULED -> "SCHEDULED"; + case NONE -> "NONE"; + case CALL_AGENCY -> "CALL_AGENCY"; + case COORDINATE_WITH_DRIVER -> "COORDINATE_WITH_DRIVER"; + case CANCELLED -> null; + }; + } +} diff --git a/src/main/java/org/opentripplanner/apis/gtfs/model/DatedTripTime.java b/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java similarity index 56% rename from src/main/java/org/opentripplanner/apis/gtfs/model/DatedTripTime.java rename to src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java index a83eb50fe1d..529d83c7459 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/model/DatedTripTime.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java @@ -6,21 +6,22 @@ import javax.annotation.Nullable; /** - * A scheduled time of a trip's start or end with an optional realtime information. + * Timing of an arrival or a departure to or from a stop. May contain real-time information + * if available. */ -public record DatedTripTime( +public record ArrivalDepartureTime( @Nonnull ZonedDateTime scheduledTime, @Nullable RealTimeEstimate estimated ) { @Nonnull - public static DatedTripTime of(ZonedDateTime realtime, int delaySecs) { + public static ArrivalDepartureTime of(ZonedDateTime realtime, int delaySecs) { var delay = Duration.ofSeconds(delaySecs); - return new DatedTripTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); + return new ArrivalDepartureTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); } @Nonnull - public static DatedTripTime ofStatic(ZonedDateTime staticTime) { - return new DatedTripTime(staticTime, null); + public static ArrivalDepartureTime ofStatic(ZonedDateTime staticTime) { + return new ArrivalDepartureTime(staticTime, null); } /** diff --git a/src/main/java/org/opentripplanner/model/TripTimeOnDate.java b/src/main/java/org/opentripplanner/model/TripTimeOnDate.java index 1bfb0184138..8128c36e4db 100644 --- a/src/main/java/org/opentripplanner/model/TripTimeOnDate.java +++ b/src/main/java/org/opentripplanner/model/TripTimeOnDate.java @@ -190,6 +190,14 @@ public boolean isNoDataStop() { return tripTimes.isNoDataStop(stopIndex); } + /** + * Is the real-time time a recorded time (i.e. has the vehicle already passed the stop). + * This information is currently only available from SIRI feeds. + */ + public boolean isRecordedStop() { + return tripTimes.isRecordedStop(stopIndex); + } + public RealTimeState getRealTimeState() { return tripTimes.isNoDataStop(stopIndex) ? RealTimeState.SCHEDULED diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index fb287c5c117..dcef5f67096 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -154,6 +154,17 @@ type Alert implements Node { trip: Trip @deprecated(reason : "Alert can have multiple affected entities now instead of there being duplicate alerts\nfor different entities. This will return only one of the affected trips.\nUse entities instead.") } +""" +Timing of an arrival or a departure to or from a stop. May contain real-time information if +available. +""" +type ArrivalDepartureTime { + "The estimated time of the event. If no real-time information is available, this is null." + estimated: RealTimeEstimate + "The scheduled time of the event." + scheduledTime: OffsetDateTime +} + "Bike park represents a location where bicycles can be parked." type BikePark implements Node & PlaceInterface { "ID of the bike park" @@ -384,6 +395,55 @@ type Currency { digits: Int! } +"Stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop." +type DatedStopTime { + "Scheduled arrival time to the stop and a realtime estimate, if one exists." + arrival: ArrivalDepartureTime + "Scheduled departure time from the stop and a realtime estimate, if one exists." + departure: ArrivalDepartureTime + """ + Whether the vehicle can be disembarked at this stop. This field can also be + used to indicate if disembarkation is possible only with special arrangements. + """ + dropoffType: PickupDropoffType + """ + Vehicle headsign of the trip on this stop. Trip headsigns can change during + the trip (e.g. on routes which run on loops), so this value should be used + instead of `tripHeadsign` to display the headsign relevant to the user. + """ + headsign( + """ + If translated headsign is found from gtfs translation.txt and wanted language is not same as + feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. + """ + language: String + ): String + """ + Whether the vehicle can be boarded at this stop. This field can also be used + to indicate if boarding is possible only with special arrangements. + """ + pickupType: PickupDropoffType + "Whether stop has been updated through a realtime update and if so, how." + realtimeState: StopRealTimeState! + "The stop where this arrival/departure happens" + stop: Stop + """ + The sequence of the stop in the pattern. This is not required to start from 0 or be consecutive - any + increasing integer sequence along the stops is valid. + + The purpose of this field is to identify the stop within the pattern so it can be cross-referenced + between it and the itinerary. It is safe to cross-reference when done quickly, i.e. within seconds. + However, it should be noted that real-time updates can change the values, so don't store it for + longer amounts of time. + + Depending on the source data, this might not be the GTFS `stop_sequence` but another value, perhaps + even generated. + """ + stopPosition: Int + "true, if this stop is used as a time equalization stop. false otherwise." + timepoint: Boolean +} + "Trip on a specific date" type DatedTrip implements Node { """ @@ -395,7 +455,7 @@ type DatedTrip implements Node { """ date: LocalDate! "The time when the trip ends including real-time information, if available." - end: DatedTripTime + end: ArrivalDepartureTime "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! "The pattern the trip is running on" @@ -403,11 +463,11 @@ type DatedTrip implements Node { "The route the trip is running on" route: Route! "The time when the trip starts including real-time information, if available." - start: DatedTripTime + start: ArrivalDepartureTime "List of stops this trip passes through" stops: [Stop!]! "List of times when this trip arrives to or departs from a stop" - stoptimes: [Stoptime] + stoptimes: [DatedStopTime] "Headsign of the vehicle when running on this trip" tripHeadsign( """ @@ -453,17 +513,6 @@ type DatedTripEdge { node: DatedTrip } -""" -Information about a dated trip's start or end times. May contain real-time information if -available. -""" -type DatedTripTime { - "The estimated time of the event. If no real-time information is available, this is null." - estimated: RealTimeEstimate - "The scheduled time of the event." - scheduledTime: OffsetDateTime -} - """ The standard case of a fare product: it only has a single price to be paid by the passenger and no discounts are applied. @@ -3517,6 +3566,25 @@ enum StopAlertType { TRIPS } +"Whether stop has been updated through a realtime update and if so, how." +enum StopRealTimeState { + "The stop has been added through a realtime update." + ADDED + "The stop has been cancelled through a realtime update." + CANCELED + "The realtime feed has indicated that there is no data available for this stop." + NO_DATA + """ + The vehicle has arrived to the stop or already visited it and the times are no longer estimates. + Note, not all realtime feeds indicate this information even if the vehicle has already passed the stop. + """ + RECORDED + "There have been no realtime updates." + UNUPDATED + "The trip's arrival and/or departure time has been updated." + UPDATED +} + """ Transit modes include modes that are used within organized transportation networks run by public transportation authorities, taxi companies etc. From 53ff5d56d991bb3ea39998f454d0c12abaab772e Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 9 Aug 2024 16:40:24 +0300 Subject: [PATCH 13/98] cancelled -> canceled --- .../apis/gtfs/datafetchers/QueryTypeImpl.java | 6 +- .../gtfs/generated/GraphQLDataFetchers.java | 4 +- .../apis/gtfs/generated/GraphQLTypes.java | 118 +++++++++--------- .../service/DefaultTransitService.java | 12 +- .../transit/service/TransitService.java | 7 +- .../opentripplanner/apis/gtfs/schema.graphqls | 54 ++++---- 6 files changed, 103 insertions(+), 98 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index 7cac038a165..4d893802d02 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -814,11 +814,11 @@ public DataFetcher> trips() { } @Override - public DataFetcher> cancelledTrips() { + public DataFetcher> canceledTrips() { return environment -> { - var args = new GraphQLTypes.GraphQLQueryTypeCancelledTripsArgs(environment.getArguments()); + var args = new GraphQLTypes.GraphQLQueryTypeCanceledTripsArgs(environment.getArguments()); var datedTrips = getTransitService(environment) - .getCancelledTrips(args.getGraphQLFeeds()) + .getCanceledTrips(args.getGraphQLFeeds()) .stream() .collect(Collectors.toList()); return new SimpleListConnection<>(datedTrips).get(environment); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index ff12746df68..3f6f7df22a0 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -840,9 +840,9 @@ public interface GraphQLQueryType { public DataFetcher> bikeRentalStations(); - public DataFetcher> cancelledTripTimes(); + public DataFetcher> canceledTrips(); - public DataFetcher> cancelledTrips(); + public DataFetcher> cancelledTripTimes(); public DataFetcher carPark(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 3d9b627154a..70e98ab17a0 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -2236,6 +2236,65 @@ public void setGraphQLIds(List ids) { } } + public static class GraphQLQueryTypeCanceledTripsArgs { + + private String after; + private String before; + private List feeds; + private Integer first; + private Integer last; + + public GraphQLQueryTypeCanceledTripsArgs(Map args) { + if (args != null) { + this.after = (String) args.get("after"); + this.before = (String) args.get("before"); + this.feeds = (List) args.get("feeds"); + this.first = (Integer) args.get("first"); + this.last = (Integer) args.get("last"); + } + } + + public String getGraphQLAfter() { + return this.after; + } + + public String getGraphQLBefore() { + return this.before; + } + + public List getGraphQLFeeds() { + return this.feeds; + } + + public Integer getGraphQLFirst() { + return this.first; + } + + public Integer getGraphQLLast() { + return this.last; + } + + public void setGraphQLAfter(String after) { + this.after = after; + } + + public void setGraphQLBefore(String before) { + this.before = before; + } + + public void setGraphQLFeeds(List feeds) { + this.feeds = feeds; + } + + public void setGraphQLFirst(Integer first) { + this.first = first; + } + + public void setGraphQLLast(Integer last) { + this.last = last; + } + } + public static class GraphQLQueryTypeCancelledTripTimesArgs { private List feeds; @@ -2345,65 +2404,6 @@ public void setGraphQLTrips(List trips) { } } - public static class GraphQLQueryTypeCancelledTripsArgs { - - private String after; - private String before; - private List feeds; - private Integer first; - private Integer last; - - public GraphQLQueryTypeCancelledTripsArgs(Map args) { - if (args != null) { - this.after = (String) args.get("after"); - this.before = (String) args.get("before"); - this.feeds = (List) args.get("feeds"); - this.first = (Integer) args.get("first"); - this.last = (Integer) args.get("last"); - } - } - - public String getGraphQLAfter() { - return this.after; - } - - public String getGraphQLBefore() { - return this.before; - } - - public List getGraphQLFeeds() { - return this.feeds; - } - - public Integer getGraphQLFirst() { - return this.first; - } - - public Integer getGraphQLLast() { - return this.last; - } - - public void setGraphQLAfter(String after) { - this.after = after; - } - - public void setGraphQLBefore(String before) { - this.before = before; - } - - public void setGraphQLFeeds(List feeds) { - this.feeds = feeds; - } - - public void setGraphQLFirst(Integer first) { - this.first = first; - } - - public void setGraphQLLast(Integer last) { - this.last = last; - } - } - public static class GraphQLQueryTypeCarParkArgs { private String id; diff --git a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 4d7ce68218c..8f5b86ad24e 100644 --- a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -289,14 +289,14 @@ public void addTripForId(FeedScopedId tripId, Trip trip) { } @Override - public Collection getCancelledTrips(List feeds) { + public Collection getCanceledTrips(List feeds) { OTPRequestTimeoutException.checkForTimeout(); - List cancelledTrips = new ArrayList<>(); + List canceledTrips = new ArrayList<>(); Map departures = new HashMap<>(); var timetableSnapshot = lazyGetTimeTableSnapShot(); if (timetableSnapshot == null) { - return cancelledTrips; + return canceledTrips; } var calendarService = getCalendarService(); var patternMap = transitModelIndex.getPatternForTrip(); @@ -315,13 +315,13 @@ public Collection getCancelledTrips(List feeds) { var timetable = timetableSnapshot.resolve(pattern, date); var tripTimes = timetable.getTripTimes(trip); if (tripTimes.getRealTimeState() == RealTimeState.CANCELED) { // use UPDATED for faked testing - cancelledTrips.add(new DatedTrip(trip, date)); + canceledTrips.add(new DatedTrip(trip, date)); // store departure time from first stop departures.put(trip, tripTimes.sortIndex()); } } } - cancelledTrips.sort((t1, t2) -> { + canceledTrips.sort((t1, t2) -> { if (t1.serviceDate().isBefore(t2.serviceDate())) { return -1; } else if (t2.serviceDate().isBefore(t1.serviceDate())) { @@ -338,7 +338,7 @@ public Collection getCancelledTrips(List feeds) { return t1.trip().getId().compareTo(t2.trip().getId()); } }); - return cancelledTrips; + return canceledTrips; } @Override diff --git a/src/main/java/org/opentripplanner/transit/service/TransitService.java b/src/main/java/org/opentripplanner/transit/service/TransitService.java index f867a22deff..c2edd0b2751 100644 --- a/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -137,7 +137,12 @@ public interface TransitService { Collection getAllTrips(); - Collection getCancelledTrips(List feeds); + /** + * Get canceled trips. + * + * @param feeds If not null, used for filtering. + */ + Collection getCanceledTrips(List feeds); Collection getAllRoutes(); diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index dcef5f67096..3be30ece04f 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1222,31 +1222,43 @@ type QueryType { """ ids: [String] ): [BikeRentalStation] @deprecated(reason : "Use rentalVehicles or vehicleRentalStations instead") - "Get cancelled TripTimes." + """ + Get pages of canceled Trips. Follows the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ + canceledTrips( + after: String, + before: String, + "Feed feedIds (e.g. [\"HSL\"])." + feeds: [String], + first: Int, + last: Int + ): DatedTripConnection + "Get canceled TripTimes." cancelledTripTimes( "Feed feedIds (e.g. [\"HSL\"])." feeds: [String], """ - Only cancelled trip times that have last stop arrival time at maxArrivalTime + Only canceled trip times that have last stop arrival time at maxArrivalTime or before are returned. Format: seconds since midnight of maxDate. """ maxArrivalTime: Int, - "Only cancelled trip times scheduled to run on maxDate or before are returned. Format: \"2019-12-23\" or \"20191223\"." + "Only canceled trip times scheduled to run on maxDate or before are returned. Format: \"2019-12-23\" or \"20191223\"." maxDate: String, """ - Only cancelled trip times that have first stop departure time at + Only canceled trip times that have first stop departure time at maxDepartureTime or before are returned. Format: seconds since midnight of maxDate. """ maxDepartureTime: Int, """ - Only cancelled trip times that have last stop arrival time at minArrivalTime + Only canceled trip times that have last stop arrival time at minArrivalTime or after are returned. Format: seconds since midnight of minDate. """ minArrivalTime: Int, - "Only cancelled trip times scheduled to run on minDate or after are returned. Format: \"2019-12-23\" or \"20191223\"." + "Only canceled trip times scheduled to run on minDate or after are returned. Format: \"2019-12-23\" or \"20191223\"." minDate: String, """ - Only cancelled trip times that have first stop departure time at + Only canceled trip times that have first stop departure time at minDepartureTime or after are returned. Format: seconds since midnight of minDate. """ minDepartureTime: Int, @@ -1256,19 +1268,7 @@ type QueryType { routes: [String], "Trip gtfsIds (e.g. [\"HSL:1098_20190405_Ma_2_1455\"])." trips: [String] - ): [Stoptime] @deprecated(reason : "`cancelledTripTimes` is deprecated. Use `cancelledTrips` instead.") - """ - Get pages of cancelled Trips. Follows the - [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). - """ - cancelledTrips( - after: String, - before: String, - "Feed feedIds (e.g. [\"HSL\"])." - feeds: [String], - first: Int, - last: Int - ): DatedTripConnection + ): [Stoptime] @deprecated(reason : "`cancelledTripTimes` is deprecated. Use `canceledTrips` instead.") "Get a single car park based on its ID, i.e. value of field `carParkId`" carPark(id: String!): CarPark @deprecated(reason : "carPark is deprecated. Use vehicleParking instead.") "Get all car parks" @@ -2893,7 +2893,7 @@ enum AlertSeverityLevelType { INFO """ Severe alerts are used when a significant part of public transport services is - affected, for example: All train services are cancelled due to technical problems. + affected, for example: All train services are canceled due to technical problems. """ SEVERE "Severity of alert is unknown" @@ -3570,7 +3570,7 @@ enum StopAlertType { enum StopRealTimeState { "The stop has been added through a realtime update." ADDED - "The stop has been cancelled through a realtime update." + "The stop has been canceled through a realtime update." CANCELED "The realtime feed has indicated that there is no data available for this stop." NO_DATA @@ -4342,21 +4342,21 @@ input TimetablePreferencesInput { When false, real-time updates are considered during the routing. In practice, when this option is set as true, some of the suggestions might not be realistic as the transfers could be invalid due to delays, - trips can be cancelled or stops can be skipped. + trips can be canceled or stops can be skipped. """ excludeRealTimeUpdates: Boolean """ - When true, departures that have been cancelled ahead of time will be + When true, departures that have been canceled ahead of time will be included during the routing. This means that an itinerary can include - a cancelled departure while some other alternative that contains no cancellations + a canceled departure while some other alternative that contains no cancellations could be filtered out as the alternative containing a cancellation would normally be better. """ includePlannedCancellations: Boolean """ - When true, departures that have been cancelled through a real-time feed will be + When true, departures that have been canceled through a real-time feed will be included during the routing. This means that an itinerary can include - a cancelled departure while some other alternative that contains no cancellations + a canceled departure while some other alternative that contains no cancellations could be filtered out as the alternative containing a cancellation would normally be better. This option can't be set to true while `includeRealTimeUpdates` is false. """ From 0469361d24a711bc2cc8b13750e05e4f0d6bcc8f Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 9 Aug 2024 18:09:32 +0300 Subject: [PATCH 14/98] Add graphql test --- .../apis/gtfs/GraphQLIntegrationTest.java | 30 +++- .../gtfs/expectations/canceled-trips.json | 129 ++++++++++++++++++ .../apis/gtfs/queries/canceled-trips.graphql | 80 +++++++++++ 3 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json create mode 100644 src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql diff --git a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java index 79590ca2775..adbb05ddcbf 100644 --- a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java +++ b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java @@ -22,6 +22,7 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.time.Instant; +import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -43,7 +44,10 @@ import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.framework.model.Grams; +import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; import org.opentripplanner.model.FeedInfo; +import org.opentripplanner.model.TimetableSnapshot; +import org.opentripplanner.model.calendar.CalendarServiceData; import org.opentripplanner.model.fare.FareMedium; import org.opentripplanner.model.fare.FareProduct; import org.opentripplanner.model.fare.ItineraryFares; @@ -161,7 +165,12 @@ static void setup() { var transitModel = new TransitModel(model, DEDUPLICATOR); final TripPattern pattern = TEST_MODEL.pattern(BUS).build(); - var trip = TransitModelForTest.trip("123").withHeadsign(I18NString.of("Trip Headsign")).build(); + var cal_id = TransitModelForTest.id("CAL_1"); + var trip = TransitModelForTest + .trip("123") + .withHeadsign(I18NString.of("Trip Headsign")) + .withServiceId(cal_id) + .build(); var stopTimes = TEST_MODEL.stopTimesEvery5Minutes(3, trip, T11_00); var tripTimes = TripTimesFactory.tripTimes(trip, stopTimes, DEDUPLICATOR); pattern.add(tripTimes); @@ -212,6 +221,25 @@ public TransitAlertService getTransitAlertService() { }; routes.forEach(transitService::addRoutes); + // Crate a calendar (needed for testing cancelled trips) + CalendarServiceData calendarServiceData = new CalendarServiceData(); + calendarServiceData.putServiceDatesForServiceId( + cal_id, + List.of(LocalDate.of(2024, 8, 8), LocalDate.of(2024, 8, 9)) + ); + transitModel.getServiceCodes().put(cal_id, 0); + transitModel.updateCalendarServiceData(true, calendarServiceData, DataImportIssueStore.NOOP); + transitModel.initTimetableSnapshotProvider(() -> { + TimetableSnapshot timetableSnapshot = new TimetableSnapshot(); + var canceledStopTimes = TEST_MODEL.stopTimesEvery5Minutes(3, trip, T11_30); + var canceledTripTimes = TripTimesFactory.tripTimes(trip, canceledStopTimes, DEDUPLICATOR); + pattern.add(canceledTripTimes); + canceledTripTimes.cancelTrip(); + timetableSnapshot.update(pattern, canceledTripTimes, LocalDate.now()); + + return timetableSnapshot.commit(); + }); + var step1 = walkStep("street") .withRelativeDirection(RelativeDirection.DEPART) .withAbsoluteDirection(20) diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json new file mode 100644 index 00000000000..98da1d79bae --- /dev/null +++ b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json @@ -0,0 +1,129 @@ +{ + "data": { + "canceledTrips": { + "pageInfo" : { + "hasNextPage" : false, + "hasPreviousPage" : false, + "startCursor" : "c2ltcGxlLWN1cnNvcjA=", + "endCursor" : "c2ltcGxlLWN1cnNvcjA=" + }, + "edges": [ + { + "node": { + "date": "2024-08-09", + "end": { + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:40:00+02:00" + }, + "scheduledTime": "2024-08-09T11:40:00+02:00" + }, + "start": { + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:30:00+02:00" + }, + "scheduledTime": "2024-08-09T11:30:00+02:00" + }, + "pattern": { + "code": "F:BUS" + }, + "route": { + "gtfsId": "F:R123" + }, + "stops": [ + { + "gtfsId": "F:Stop_0" + }, + { + "gtfsId": "F:Stop_1" + }, + { + "gtfsId": "F:Stop_2" + } + ], + "tripHeadsign": "Trip Headsign", + "tripShortName": null, + "stoptimes": [ + { + "dropoffType": null, + "headsign": "Stop headsign at stop 10", + "pickupType": null, + "realtimeState": "CANCELED", + "stop": { + "gtfsId": "F:Stop_0" + }, + "stopPosition": 10, + "timepoint": false, + "arrival": { + "scheduledTime": "2024-08-09T11:30:00+02:00", + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:30:00+02:00" + } + }, + "departure": { + "scheduledTime": "2024-08-09T11:30:00+02:00", + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:30:00+02:00" + } + } + }, + { + "dropoffType": null, + "headsign": "Stop headsign at stop 20", + "pickupType": null, + "realtimeState": "CANCELED", + "stop": { + "gtfsId": "F:Stop_1" + }, + "stopPosition": 20, + "timepoint": false, + "arrival": { + "scheduledTime": "2024-08-09T11:35:00+02:00", + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:35:00+02:00" + } + }, + "departure": { + "scheduledTime": "2024-08-09T11:35:00+02:00", + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:35:00+02:00" + } + } + }, + { + "dropoffType": null, + "headsign": "Stop headsign at stop 30", + "pickupType": null, + "realtimeState": "CANCELED", + "stop": { + "gtfsId": "F:Stop_2" + }, + "stopPosition": 30, + "timepoint": false, + "arrival": { + "scheduledTime": "2024-08-09T11:40:00+02:00", + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:40:00+02:00" + } + }, + "departure": { + "scheduledTime": "2024-08-09T11:40:00+02:00", + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:40:00+02:00" + } + } + } + ] + } + } + ] + } + } +} \ No newline at end of file diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql new file mode 100644 index 00000000000..a92a710c540 --- /dev/null +++ b/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -0,0 +1,80 @@ +{ + canceledTrips(feeds: "F") { + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + edges { + node { + date + end { + estimated { + delay + time + } + scheduledTime + } + start { + estimated { + delay + time + } + scheduledTime + } + pattern { + code + } + route { + gtfsId + } + stops { + gtfsId + } + tripHeadsign + tripShortName + stoptimes { + dropoffType + headsign + pickupType + realtimeState + stop { + gtfsId + } + stopPosition + timepoint + arrival { + scheduledTime + estimated { + delay + time + } + } + departure { + scheduledTime + estimated { + delay + time + } + } + } + date + start { + estimated { + time + delay + } + scheduledTime + } + end { + estimated { + time + delay + } + scheduledTime + } + } + } + } +} From c0648b799b63d08965d5ce1a5bae518328be8f9d Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 9 Aug 2024 18:11:43 +0300 Subject: [PATCH 15/98] Rename method --- .../opentripplanner/ext/restapi/mapping/LegMapper.java | 2 +- .../apis/gtfs/datafetchers/LegImpl.java | 2 +- .../apis/transmodel/model/plan/LegType.java | 2 +- src/main/java/org/opentripplanner/model/plan/Leg.java | 2 +- .../model/plan/ScheduledTransitLeg.java | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegMapper.java b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegMapper.java index b642426cd6d..f274a87ebd3 100644 --- a/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegMapper.java +++ b/src/ext/java/org/opentripplanner/ext/restapi/mapping/LegMapper.java @@ -87,7 +87,7 @@ public ApiLeg mapLeg( api.departureDelay = domain.getDepartureDelay(); api.arrivalDelay = domain.getArrivalDelay(); - api.realTime = domain.getRealTime(); + api.realTime = domain.isRealTimeUpdated(); api.isNonExactFrequency = domain.getNonExactFrequency(); api.headway = domain.getHeadway(); api.distance = round3Decimals(domain.getDistanceMeters()); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java index 9ec83a4bf67..3e3e39b6340 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java @@ -186,7 +186,7 @@ public DataFetcher pickupType() { @Override public DataFetcher realTime() { - return environment -> getSource(environment).getRealTime(); + return environment -> getSource(environment).isRealTimeUpdated(); } // TODO diff --git a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/LegType.java b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/LegType.java index be05d00e16d..b794fc4703f 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/model/plan/LegType.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/model/plan/LegType.java @@ -198,7 +198,7 @@ public static GraphQLObjectType create( .name("realtime") .description("Whether there is real-time data about this leg") .type(new GraphQLNonNull(Scalars.GraphQLBoolean)) - .dataFetcher(env -> leg(env).getRealTime()) + .dataFetcher(env -> leg(env).isRealTimeUpdated()) .build() ) .field( diff --git a/src/main/java/org/opentripplanner/model/plan/Leg.java b/src/main/java/org/opentripplanner/model/plan/Leg.java index 2a0b6726560..2cd8db0fc2f 100644 --- a/src/main/java/org/opentripplanner/model/plan/Leg.java +++ b/src/main/java/org/opentripplanner/model/plan/Leg.java @@ -240,7 +240,7 @@ default int getArrivalDelay() { /** * Whether there is real-time data about this Leg */ - default boolean getRealTime() { + default boolean isRealTimeUpdated() { return false; } diff --git a/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java b/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java index 4a84ac6e799..c8358e19155 100644 --- a/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java +++ b/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java @@ -164,7 +164,7 @@ public Accessibility getTripWheelchairAccessibility() { @Override public LegTime start() { - if (getRealTime()) { + if (isRealTimeUpdated()) { return LegTime.of(startTime, getDepartureDelay()); } else { return LegTime.ofStatic(startTime); @@ -173,7 +173,7 @@ public LegTime start() { @Override public LegTime end() { - if (getRealTime()) { + if (isRealTimeUpdated()) { return LegTime.of(endTime, getArrivalDelay()); } else { return LegTime.ofStatic(endTime); @@ -217,7 +217,7 @@ public int getArrivalDelay() { } @Override - public boolean getRealTime() { + public boolean isRealTimeUpdated() { return ( tripTimes.isRealtimeUpdated(boardStopPosInPattern) || tripTimes.isRealtimeUpdated(alightStopPosInPattern) @@ -276,7 +276,7 @@ public List getIntermediateStops() { for (int i = boardStopPosInPattern + 1; i < alightStopPosInPattern; i++) { StopLocation stop = tripPattern.getStop(i); - final StopArrival visit = mapper.map(i, stop, getRealTime()); + final StopArrival visit = mapper.map(i, stop, isRealTimeUpdated()); visits.add(visit); } return visits; @@ -410,7 +410,7 @@ public String toString() { .addObj("to", getTo()) .addTime("startTime", startTime) .addTime("endTime", endTime) - .addBool("realTime", getRealTime()) + .addBool("realTime", isRealTimeUpdated()) .addNum("distance", distanceMeters, "m") .addNum("cost", generalizedCost) .addNum("routeType", getRouteType()) From 6437bd727d83535950365be2a9d694dfd7910646 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 9 Aug 2024 18:13:38 +0300 Subject: [PATCH 16/98] Add small tests --- .../model/TripTimeOnDateTest.java | 21 +++++++++++++++++++ .../model/plan/ScheduledTransitLegTest.java | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/src/test/java/org/opentripplanner/model/TripTimeOnDateTest.java b/src/test/java/org/opentripplanner/model/TripTimeOnDateTest.java index 78002e46eae..82e0f1a63f0 100644 --- a/src/test/java/org/opentripplanner/model/TripTimeOnDateTest.java +++ b/src/test/java/org/opentripplanner/model/TripTimeOnDateTest.java @@ -1,6 +1,8 @@ package org.opentripplanner.model; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.LocalTime; import org.junit.jupiter.api.Test; @@ -29,4 +31,23 @@ void gtfsSequence() { var departure = LocalTime.ofSecondOfDay(subject.getScheduledDeparture()); assertEquals(LocalTime.of(11, 10), departure); } + + @Test + void isRecordedStop() { + var testModel = TransitModelForTest.of(); + var pattern = testModel.pattern(TransitMode.BUS).build(); + var trip = TransitModelForTest.trip("123").build(); + var stopTimes = testModel.stopTimesEvery5Minutes(3, trip, T11_00); + + var tripTimes = TripTimesFactory.tripTimes(trip, stopTimes, new Deduplicator()); + tripTimes.setRecorded(1); + + var subject = new TripTimeOnDate(tripTimes, 0, pattern); + + assertFalse(subject.isRecordedStop()); + + subject = new TripTimeOnDate(tripTimes, 1, pattern); + + assertTrue(subject.isRecordedStop()); + } } diff --git a/src/test/java/org/opentripplanner/model/plan/ScheduledTransitLegTest.java b/src/test/java/org/opentripplanner/model/plan/ScheduledTransitLegTest.java index b41ace81e8d..af497f97bfb 100644 --- a/src/test/java/org/opentripplanner/model/plan/ScheduledTransitLegTest.java +++ b/src/test/java/org/opentripplanner/model/plan/ScheduledTransitLegTest.java @@ -1,8 +1,10 @@ package org.opentripplanner.model.plan; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opentripplanner.transit.model._data.TransitModelForTest.id; import java.time.OffsetDateTime; @@ -49,6 +51,7 @@ void legTimesWithoutRealTime() { assertNull(leg.start().estimated()); assertNull(leg.end().estimated()); + assertFalse(leg.isRealTimeUpdated()); } @Test @@ -67,6 +70,7 @@ void legTimesWithRealTime() { assertNotNull(leg.start().estimated()); assertNotNull(leg.end().estimated()); + assertTrue(leg.isRealTimeUpdated()); } private static ScheduledTransitLegBuilder builder() { From 6e143d9a41751ade4e24f9a7a7e80e4baeb7ca4c Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 9 Aug 2024 18:39:04 +0300 Subject: [PATCH 17/98] Realtime -> RealTime --- .../opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java | 4 ++-- .../org/opentripplanner/model/plan/ScheduledTransitLeg.java | 4 ++-- .../transit/model/timetable/RealTimeTripTimes.java | 2 +- .../transit/model/timetable/ScheduledTripTimes.java | 2 +- .../opentripplanner/transit/model/timetable/TripTimes.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java index 5d567d83264..9046fa6807c 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java @@ -43,7 +43,7 @@ public DataFetcher end() { if (scheduledTime == null) { return null; } - return tripTimes.isRealtimeUpdated(stopIndex) + return tripTimes.isRealTimeUpdated(stopIndex) ? ArrivalDepartureTime.of(scheduledTime, tripTimes.getArrivalDelay(stopIndex)) : ArrivalDepartureTime.ofStatic(scheduledTime); }; @@ -81,7 +81,7 @@ public DataFetcher start() { if (scheduledTime == null) { return null; } - return tripTimes.isRealtimeUpdated(0) + return tripTimes.isRealTimeUpdated(0) ? ArrivalDepartureTime.of(scheduledTime, tripTimes.getDepartureDelay(0)) : ArrivalDepartureTime.ofStatic(scheduledTime); }; diff --git a/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java b/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java index c8358e19155..df0a84d6aaa 100644 --- a/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java +++ b/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java @@ -219,8 +219,8 @@ public int getArrivalDelay() { @Override public boolean isRealTimeUpdated() { return ( - tripTimes.isRealtimeUpdated(boardStopPosInPattern) || - tripTimes.isRealtimeUpdated(alightStopPosInPattern) + tripTimes.isRealTimeUpdated(boardStopPosInPattern) || + tripTimes.isRealTimeUpdated(alightStopPosInPattern) ); } diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java b/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java index ca5897b7b24..b9159cb4fd7 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimes.java @@ -198,7 +198,7 @@ public boolean isPredictionInaccurate(int stop) { return isStopRealTimeStates(stop, StopRealTimeState.INACCURATE_PREDICTIONS); } - public boolean isRealtimeUpdated(int stop) { + public boolean isRealTimeUpdated(int stop) { return ( realTimeState != RealTimeState.SCHEDULED && !isStopRealTimeStates(stop, StopRealTimeState.NO_DATA) diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java b/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java index 3799fd7b140..423b0f8d9c7 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/ScheduledTripTimes.java @@ -235,7 +235,7 @@ public boolean isPredictionInaccurate(int stop) { } @Override - public boolean isRealtimeUpdated(int stop) { + public boolean isRealTimeUpdated(int stop) { return false; } diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java b/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java index ea1a3f8ab2b..c1065256700 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/TripTimes.java @@ -126,7 +126,7 @@ default int compareTo(TripTimes other) { /** * Return if trip has been updated and stop has not been given a NO_DATA update. */ - boolean isRealtimeUpdated(int stop); + boolean isRealTimeUpdated(int stop); /** * @return the whole trip's headsign. Individual stops can have different headsigns. From 1de24b2713794efcee5610da9be9f98600543145 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 9 Aug 2024 21:05:05 +0300 Subject: [PATCH 18/98] Add more tests --- .../timetable/RealTimeTripTimesTest.java | 11 +++++ .../service/DefaultTransitServiceTest.java | 42 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimesTest.java b/src/test/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimesTest.java index 5b3a8f76052..a47a7d61141 100644 --- a/src/test/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimesTest.java +++ b/src/test/java/org/opentripplanner/transit/model/timetable/RealTimeTripTimesTest.java @@ -402,6 +402,17 @@ public void testNoData() { assertFalse(updatedTripTimesA.isNoDataStop(2)); } + @Test + public void testRealTimeUpdated() { + RealTimeTripTimes updatedTripTimesA = createInitialTripTimes().copyScheduledTimes(); + assertFalse(updatedTripTimesA.isRealTimeUpdated(1)); + updatedTripTimesA.setRealTimeState(RealTimeState.UPDATED); + assertTrue(updatedTripTimesA.isRealTimeUpdated(1)); + updatedTripTimesA.setNoData(1); + assertTrue(updatedTripTimesA.isRealTimeUpdated(0)); + assertFalse(updatedTripTimesA.isRealTimeUpdated(1)); + } + @Nested class GtfsStopSequence { diff --git a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index 54733f084d6..6f0591b1a2c 100644 --- a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -1,6 +1,7 @@ package org.opentripplanner.transit.service; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opentripplanner.model.plan.PlanTestConstants.T11_30; import static org.opentripplanner.transit.model.basic.TransitMode.BUS; import static org.opentripplanner.transit.model.basic.TransitMode.FERRY; import static org.opentripplanner.transit.model.basic.TransitMode.RAIL; @@ -12,16 +13,23 @@ import java.util.Set; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.opentripplanner.framework.i18n.I18NString; +import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; import org.opentripplanner.model.TimetableSnapshot; +import org.opentripplanner.model.calendar.CalendarServiceData; 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.StopPattern; import org.opentripplanner.transit.model.network.TripPattern; 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.DatedTrip; import org.opentripplanner.transit.model.timetable.RealTimeTripTimes; import org.opentripplanner.transit.model.timetable.ScheduledTripTimes; +import org.opentripplanner.transit.model.timetable.Trip; +import org.opentripplanner.transit.model.timetable.TripTimesFactory; class DefaultTransitServiceTest { @@ -46,6 +54,13 @@ class DefaultTransitServiceTest { .withCreatedByRealtimeUpdater(true) .build(); + static FeedScopedId CALENDAR_ID = TransitModelForTest.id("CAL_1"); + static Trip TRIP = TransitModelForTest + .trip("123") + .withHeadsign(I18NString.of("Trip Headsign")) + .withServiceId(CALENDAR_ID) + .build(); + @BeforeAll static void setup() { var stopModel = TEST_MODEL @@ -55,8 +70,23 @@ static void setup() { .withStation(STATION) .build(); - var transitModel = new TransitModel(stopModel, new Deduplicator()); + var deduplicator = new Deduplicator(); + var transitModel = new TransitModel(stopModel, deduplicator); + var canceledStopTimes = TEST_MODEL.stopTimesEvery5Minutes(3, TRIP, T11_30); + var canceledTripTimes = TripTimesFactory.tripTimes(TRIP, canceledStopTimes, deduplicator); + RAIL_PATTERN.add(canceledTripTimes); + canceledTripTimes.cancelTrip(); transitModel.addTripPattern(RAIL_PATTERN.getId(), RAIL_PATTERN); + + // Crate a calendar (needed for testing cancelled trips) + CalendarServiceData calendarServiceData = new CalendarServiceData(); + calendarServiceData.putServiceDatesForServiceId( + CALENDAR_ID, + List.of(LocalDate.of(2024, 8, 8), LocalDate.of(2024, 8, 9)) + ); + transitModel.getServiceCodes().put(CALENDAR_ID, 0); + transitModel.updateCalendarServiceData(true, calendarServiceData, DataImportIssueStore.NOOP); + transitModel.index(); transitModel.initTimetableSnapshotProvider(() -> { @@ -69,6 +99,7 @@ static void setup() { .build() ); timetableSnapshot.update(REAL_TIME_PATTERN, tripTimes, LocalDate.now()); + timetableSnapshot.update(RAIL_PATTERN, canceledTripTimes, LocalDate.now()); return timetableSnapshot.commit(); }); @@ -115,4 +146,13 @@ void getPatternForStopsWithRealTime() { Collection patternsForStop = service.getPatternsForStop(STOP_B, true); assertEquals(Set.of(FERRY_PATTERN, RAIL_PATTERN, REAL_TIME_PATTERN), patternsForStop); } + + @Test + void getCanceledTrips() { + Collection canceledTrips = service.getCanceledTrips(null); + assertEquals( + "[DatedTrip[trip=Trip{F:123 RR123}, serviceDate=2024-08-08], DatedTrip[trip=Trip{F:123 RR123}, serviceDate=2024-08-09]]", + canceledTrips.toString() + ); + } } From 7251391e55c2ba5b7d52652fc9369ad82aed9544 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 9 Sep 2024 16:03:00 +0300 Subject: [PATCH 19/98] Refactor canceled trips fetching to be more efficient --- .../model/TimetableSnapshot.java | 30 +++++++++++++ .../service/DefaultTransitService.java | 45 ++++++------------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/opentripplanner/model/TimetableSnapshot.java b/src/main/java/org/opentripplanner/model/TimetableSnapshot.java index c0a7737abce..f92a16ecc56 100644 --- a/src/main/java/org/opentripplanner/model/TimetableSnapshot.java +++ b/src/main/java/org/opentripplanner/model/TimetableSnapshot.java @@ -5,24 +5,28 @@ import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.SetMultimap; import java.time.LocalDate; +import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +import java.util.stream.Collectors; import javax.annotation.Nullable; import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.TransitLayerUpdater; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.framework.Result; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.site.StopLocation; +import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate; import org.opentripplanner.transit.model.timetable.TripTimes; import org.opentripplanner.updater.spi.UpdateError; @@ -176,6 +180,32 @@ public TripPattern getRealtimeAddedTripPattern(FeedScopedId tripId, LocalDate se return realtimeAddedTripPattern.get(tripIdAndServiceDate); } + /** + * Get trips which have been canceled. + * + * @param feeds if not null, only return trips from these feeds + */ + public ArrayList getCanceledTrips(List feeds) { + return timetables + .values() + .stream() + .flatMap(timetables -> + timetables + .stream() + .flatMap(timetable -> + timetable + .getTripTimes() + .stream() + .filter(tripTimes -> + tripTimes.isCanceled() && + (feeds == null || feeds.contains(tripTimes.getTrip().getId().getFeedId())) + ) + .map(tripTimes -> new DatedTrip(tripTimes.getTrip(), timetable.getServiceDate())) + ) + ) + .collect(Collectors.toCollection(ArrayList::new)); + } + /** * @return if any trip patterns were added. */ diff --git a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 8f5b86ad24e..7eb28e50c7c 100644 --- a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -8,10 +8,8 @@ import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -54,7 +52,6 @@ import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.model.site.StopLocationsGroup; import org.opentripplanner.transit.model.timetable.DatedTrip; -import org.opentripplanner.transit.model.timetable.RealTimeState; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; @@ -288,47 +285,25 @@ public void addTripForId(FeedScopedId tripId, Trip trip) { transitModelIndex.getTripForId().put(tripId, trip); } + /** + * TODO This only supports realtime cancelled trips for now. + */ @Override public Collection getCanceledTrips(List feeds) { OTPRequestTimeoutException.checkForTimeout(); - List canceledTrips = new ArrayList<>(); - Map departures = new HashMap<>(); - var timetableSnapshot = lazyGetTimeTableSnapShot(); if (timetableSnapshot == null) { - return canceledTrips; - } - var calendarService = getCalendarService(); - var patternMap = transitModelIndex.getPatternForTrip(); - var trips = transitModelIndex.getTripForId(); - - for (Map.Entry entry : trips.entrySet()) { - var trip = entry.getValue(); - if (feeds != null && !feeds.contains(trip.getId().getFeedId())) { - continue; - } - Set serviceDates = calendarService.getServiceDatesForServiceId( - trip.getServiceId() - ); - var pattern = patternMap.get(trip); - for (LocalDate date : serviceDates) { - var timetable = timetableSnapshot.resolve(pattern, date); - var tripTimes = timetable.getTripTimes(trip); - if (tripTimes.getRealTimeState() == RealTimeState.CANCELED) { // use UPDATED for faked testing - canceledTrips.add(new DatedTrip(trip, date)); - // store departure time from first stop - departures.put(trip, tripTimes.sortIndex()); - } - } + return List.of(); } + List canceledTrips = timetableSnapshot.getCanceledTrips(feeds); canceledTrips.sort((t1, t2) -> { if (t1.serviceDate().isBefore(t2.serviceDate())) { return -1; } else if (t2.serviceDate().isBefore(t1.serviceDate())) { return 1; } - var departure1 = departures.get(t1.trip()); - var departure2 = departures.get(t2.trip()); + var departure1 = getDepartureTime(t1); + var departure2 = getDepartureTime(t2); if (departure1 < departure2) { return -1; } else if (departure1 > departure2) { @@ -780,4 +755,10 @@ private static Stream sortByOccurrenceAndReduce(Stream input) { .sorted(Map.Entry.comparingByValue().reversed()) .map(Map.Entry::getKey); } + + private int getDepartureTime(DatedTrip datedTrip) { + var pattern = getPatternForTrip(datedTrip.trip()); + var timetable = timetableSnapshot.resolve(pattern, datedTrip.serviceDate()); + return timetable.getTripTimes(datedTrip.trip()).getDepartureTime(0); + } } From bedee96dd764c458844df0ff849721fcfeea2cf3 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 9 Sep 2024 16:03:15 +0300 Subject: [PATCH 20/98] Update and fix tests --- .../apis/gtfs/GraphQLIntegrationTest.java | 24 ++- .../service/DefaultTransitServiceTest.java | 9 +- .../gtfs/expectations/canceled-trips.json | 14 +- .../apis/gtfs/expectations/patterns.json | 175 +++++++++++------- 4 files changed, 140 insertions(+), 82 deletions(-) diff --git a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java index adbb05ddcbf..25bb4f88eeb 100644 --- a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java +++ b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; +import static org.opentripplanner._support.time.ZoneIds.BERLIN; import static org.opentripplanner.model.plan.PlanTestConstants.D10m; import static org.opentripplanner.model.plan.PlanTestConstants.T11_00; import static org.opentripplanner.model.plan.PlanTestConstants.T11_01; @@ -36,7 +37,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.locationtech.jts.geom.Coordinate; import org.opentripplanner._support.text.I18NStrings; -import org.opentripplanner._support.time.ZoneIds; import org.opentripplanner.ext.fares.FaresToItineraryMapper; import org.opentripplanner.ext.fares.impl.DefaultFareService; import org.opentripplanner.framework.collection.ListUtils; @@ -175,6 +175,15 @@ static void setup() { var tripTimes = TripTimesFactory.tripTimes(trip, stopTimes, DEDUPLICATOR); pattern.add(tripTimes); + var trip2 = TransitModelForTest + .trip("321Canceled") + .withHeadsign(I18NString.of("Trip Headsign")) + .withServiceId(cal_id) + .build(); + var stopTimes2 = TEST_MODEL.stopTimesEvery5Minutes(3, trip2, T11_30); + var tripTimes2 = TripTimesFactory.tripTimes(trip2, stopTimes2, DEDUPLICATOR); + pattern.add(tripTimes2); + transitModel.addTripPattern(id("pattern-1"), pattern); var feedId = "testfeed"; @@ -189,7 +198,7 @@ static void setup() { .build(); transitModel.addAgency(agency); - transitModel.initTimeZone(ZoneIds.BERLIN); + transitModel.initTimeZone(BERLIN); transitModel.index(); var routes = Arrays .stream(TransitMode.values()) @@ -223,19 +232,18 @@ public TransitAlertService getTransitAlertService() { // Crate a calendar (needed for testing cancelled trips) CalendarServiceData calendarServiceData = new CalendarServiceData(); + var firstDate = LocalDate.of(2024, 8, 8); + var secondDate = LocalDate.of(2024, 8, 9); calendarServiceData.putServiceDatesForServiceId( cal_id, - List.of(LocalDate.of(2024, 8, 8), LocalDate.of(2024, 8, 9)) + List.of(firstDate, secondDate) ); transitModel.getServiceCodes().put(cal_id, 0); transitModel.updateCalendarServiceData(true, calendarServiceData, DataImportIssueStore.NOOP); transitModel.initTimetableSnapshotProvider(() -> { TimetableSnapshot timetableSnapshot = new TimetableSnapshot(); - var canceledStopTimes = TEST_MODEL.stopTimesEvery5Minutes(3, trip, T11_30); - var canceledTripTimes = TripTimesFactory.tripTimes(trip, canceledStopTimes, DEDUPLICATOR); - pattern.add(canceledTripTimes); - canceledTripTimes.cancelTrip(); - timetableSnapshot.update(pattern, canceledTripTimes, LocalDate.now()); + tripTimes2.cancelTrip(); + timetableSnapshot.update(pattern, tripTimes2, secondDate); return timetableSnapshot.commit(); }); diff --git a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index 6f0591b1a2c..060632be28a 100644 --- a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -80,9 +80,11 @@ static void setup() { // Crate a calendar (needed for testing cancelled trips) CalendarServiceData calendarServiceData = new CalendarServiceData(); + var firstDate = LocalDate.of(2024, 8, 8); + var secondDate = LocalDate.of(2024, 8, 9); calendarServiceData.putServiceDatesForServiceId( CALENDAR_ID, - List.of(LocalDate.of(2024, 8, 8), LocalDate.of(2024, 8, 9)) + List.of(firstDate, secondDate) ); transitModel.getServiceCodes().put(CALENDAR_ID, 0); transitModel.updateCalendarServiceData(true, calendarServiceData, DataImportIssueStore.NOOP); @@ -98,8 +100,9 @@ static void setup() { .withDepartureTimes(new int[] { 0, 1 }) .build() ); - timetableSnapshot.update(REAL_TIME_PATTERN, tripTimes, LocalDate.now()); - timetableSnapshot.update(RAIL_PATTERN, canceledTripTimes, LocalDate.now()); + timetableSnapshot.update(REAL_TIME_PATTERN, tripTimes, firstDate); + timetableSnapshot.update(RAIL_PATTERN, canceledTripTimes, firstDate); + timetableSnapshot.update(RAIL_PATTERN, canceledTripTimes, secondDate); return timetableSnapshot.commit(); }); diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json index 98da1d79bae..5208a38fb01 100644 --- a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json +++ b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json @@ -1,11 +1,11 @@ { "data": { "canceledTrips": { - "pageInfo" : { - "hasNextPage" : false, - "hasPreviousPage" : false, - "startCursor" : "c2ltcGxlLWN1cnNvcjA=", - "endCursor" : "c2ltcGxlLWN1cnNvcjA=" + "pageInfo": { + "hasNextPage": false, + "hasPreviousPage": false, + "startCursor": "c2ltcGxlLWN1cnNvcjA=", + "endCursor": "c2ltcGxlLWN1cnNvcjA=" }, "edges": [ { @@ -29,7 +29,7 @@ "code": "F:BUS" }, "route": { - "gtfsId": "F:R123" + "gtfsId": "F:R321Canceled" }, "stops": [ { @@ -126,4 +126,4 @@ ] } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json index b23ced4f954..d1f363fea5d 100644 --- a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json +++ b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json @@ -1,92 +1,139 @@ { - "data" : { - "patterns" : [ + "data": { + "patterns": [ { - "code" : "F:BUS", - "headsign" : "Trip Headsign", - "trips" : [ + "code": "F:BUS", + "headsign": "Trip Headsign", + "trips": [ { - "gtfsId" : "F:123", - "stoptimes" : [ + "gtfsId": "F:123", + "stoptimes": [ { - "stop" : { - "gtfsId" : "F:Stop_0", - "name" : "Stop_0" + "stop": { + "gtfsId": "F:Stop_0", + "name": "Stop_0" }, - "headsign" : "Stop headsign at stop 10", - "scheduledArrival" : 39600, - "scheduledDeparture" : 39600, - "stopPosition" : 10, - "realtimeState" : "SCHEDULED", - "pickupType" : "SCHEDULED", - "dropoffType" : "SCHEDULED" + "headsign": "Stop headsign at stop 10", + "scheduledArrival": 39600, + "scheduledDeparture": 39600, + "stopPosition": 10, + "realtimeState": "SCHEDULED", + "pickupType": "SCHEDULED", + "dropoffType": "SCHEDULED" }, { - "stop" : { - "gtfsId" : "F:Stop_1", - "name" : "Stop_1" + "stop": { + "gtfsId": "F:Stop_1", + "name": "Stop_1" }, - "headsign" : "Stop headsign at stop 20", - "scheduledArrival" : 39900, - "scheduledDeparture" : 39900, - "stopPosition" : 20, - "realtimeState" : "SCHEDULED", - "pickupType" : "SCHEDULED", - "dropoffType" : "SCHEDULED" + "headsign": "Stop headsign at stop 20", + "scheduledArrival": 39900, + "scheduledDeparture": 39900, + "stopPosition": 20, + "realtimeState": "SCHEDULED", + "pickupType": "SCHEDULED", + "dropoffType": "SCHEDULED" }, { - "stop" : { - "gtfsId" : "F:Stop_2", - "name" : "Stop_2" + "stop": { + "gtfsId": "F:Stop_2", + "name": "Stop_2" }, - "headsign" : "Stop headsign at stop 30", - "scheduledArrival" : 40200, - "scheduledDeparture" : 40200, - "stopPosition" : 30, - "realtimeState" : "SCHEDULED", - "pickupType" : "SCHEDULED", - "dropoffType" : "SCHEDULED" + "headsign": "Stop headsign at stop 30", + "scheduledArrival": 40200, + "scheduledDeparture": 40200, + "stopPosition": 30, + "realtimeState": "SCHEDULED", + "pickupType": "SCHEDULED", + "dropoffType": "SCHEDULED" } ], - "occupancy" : { - "occupancyStatus" : "FEW_SEATS_AVAILABLE" + "occupancy": { + "occupancyStatus": "FEW_SEATS_AVAILABLE" + } + }, + { + "gtfsId": "F:321Canceled", + "stoptimes": [ + { + "stop": { + "gtfsId": "F:Stop_0", + "name": "Stop_0" + }, + "headsign": "Stop headsign at stop 10", + "scheduledArrival": 41400, + "scheduledDeparture": 41400, + "stopPosition": 10, + "realtimeState": "CANCELED", + "pickupType": null, + "dropoffType": null + }, + { + "stop": { + "gtfsId": "F:Stop_1", + "name": "Stop_1" + }, + "headsign": "Stop headsign at stop 20", + "scheduledArrival": 41700, + "scheduledDeparture": 41700, + "stopPosition": 20, + "realtimeState": "CANCELED", + "pickupType": null, + "dropoffType": null + }, + { + "stop": { + "gtfsId": "F:Stop_2", + "name": "Stop_2" + }, + "headsign": "Stop headsign at stop 30", + "scheduledArrival": 42000, + "scheduledDeparture": 42000, + "stopPosition": 30, + "realtimeState": "CANCELED", + "pickupType": null, + "dropoffType": null + } + ], + "occupancy": { + "occupancyStatus": "NO_DATA_AVAILABLE" } } ], - "vehiclePositions" : [ + "vehiclePositions": [ { - "vehicleId" : "F:vehicle-1", - "label" : null, - "lat" : null, - "lon" : null, - "stopRelationship" : null, - "speed" : null, - "heading" : null, - "lastUpdated" : 31556889864403199, - "trip" : { - "gtfsId" : "F:123" + "vehicleId": "F:vehicle-1", + "label": null, + "lat": null, + "lon": null, + "stopRelationship": null, + "speed": null, + "heading": null, + "lastUpdated": 31556889864403199, + "trip": { + "gtfsId": "F:123" } }, { - "vehicleId" : "F:vehicle-2", - "label" : "vehicle2", - "lat" : 60.0, - "lon" : 80.0, - "stopRelationship" : { - "status" : "IN_TRANSIT_TO", - "stop" : { - "gtfsId" : "F:Stop_0" + "vehicleId": "F:vehicle-2", + "label": "vehicle2", + "lat": 60.0, + "lon": 80.0, + "stopRelationship": { + "status": "IN_TRANSIT_TO", + "stop": { + "gtfsId": "F:Stop_0" } }, - "speed" : 10.2, - "heading" : 80.0, - "lastUpdated" : -31557014167219200, - "trip" : { - "gtfsId" : "F:123" + "speed": 10.2, + "heading": 80.0, + "lastUpdated": -31557014167219200, + "trip": { + "gtfsId": "F:123" } } ] } ] } -} \ No newline at end of file +} From c0768e07c89f6d0b1d2a8d7d18852d5d02f09fe8 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 9 Sep 2024 16:19:28 +0300 Subject: [PATCH 21/98] Create an union for dated stoptimes --- .../apis/gtfs/GtfsGraphQLIndex.java | 6 +- .../DatedStopTimeTypeResolver.java | 21 ++++ .../apis/gtfs/datafetchers/DatedTripImpl.java | 10 +- ...eImpl.java => ExactDatedStopTimeImpl.java} | 2 +- .../gtfs/generated/GraphQLDataFetchers.java | 48 ++++---- .../apis/gtfs/generated/GraphQLTypes.java | 38 +++---- .../apis/gtfs/generated/graphql-codegen.yml | 2 +- .../opentripplanner/apis/gtfs/schema.graphqls | 106 +++++++++--------- .../apis/gtfs/GraphQLIntegrationTest.java | 5 +- .../service/DefaultTransitServiceTest.java | 5 +- .../apis/gtfs/queries/canceled-trips.graphql | 42 +++---- 11 files changed, 161 insertions(+), 124 deletions(-) create mode 100644 src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeTypeResolver.java rename src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{DatedStopTimeImpl.java => ExactDatedStopTimeImpl.java} (97%) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index a160e197611..83a41e8af5c 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -35,10 +35,11 @@ import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl; import org.opentripplanner.apis.gtfs.datafetchers.CurrencyImpl; -import org.opentripplanner.apis.gtfs.datafetchers.DatedStopTimeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.DatedStopTimeTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.DatedTripImpl; import org.opentripplanner.apis.gtfs.datafetchers.DefaultFareProductImpl; import org.opentripplanner.apis.gtfs.datafetchers.DepartureRowImpl; +import org.opentripplanner.apis.gtfs.datafetchers.ExactDatedStopTimeImpl; import org.opentripplanner.apis.gtfs.datafetchers.FareProductTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.FareProductUseImpl; import org.opentripplanner.apis.gtfs.datafetchers.FeedImpl; @@ -128,6 +129,7 @@ protected static GraphQLSchema buildSchema() { .type("StopPosition", type -> type.typeResolver(new StopPosition() {})) .type("FareProduct", type -> type.typeResolver(new FareProductTypeResolver())) .type("AlertEntity", type -> type.typeResolver(new AlertEntityTypeResolver())) + .type("DatedStopTime", type -> type.typeResolver(new DatedStopTimeTypeResolver())) .type(typeWiring.build(AgencyImpl.class)) .type(typeWiring.build(AlertImpl.class)) .type(typeWiring.build(BikeParkImpl.class)) @@ -181,7 +183,7 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(FareProductUseImpl.class)) .type(typeWiring.build(DefaultFareProductImpl.class)) .type(typeWiring.build(DatedTripImpl.class)) - .type(typeWiring.build(DatedStopTimeImpl.class)) + .type(typeWiring.build(ExactDatedStopTimeImpl.class)) .type(typeWiring.build(TripOccupancyImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeTypeResolver.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeTypeResolver.java new file mode 100644 index 00000000000..10ea6056792 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeTypeResolver.java @@ -0,0 +1,21 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.TypeResolutionEnvironment; +import graphql.schema.GraphQLObjectType; +import graphql.schema.GraphQLSchema; +import graphql.schema.TypeResolver; +import org.opentripplanner.model.TripTimeOnDate; + +public class DatedStopTimeTypeResolver implements TypeResolver { + + @Override + public GraphQLObjectType getType(TypeResolutionEnvironment environment) { + Object o = environment.getObject(); + GraphQLSchema schema = environment.getSchema(); + + if (o instanceof TripTimeOnDate) { + return schema.getObjectType("ExactDatedStopTime"); + } + return null; + } +} diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java index 9046fa6807c..f33026b0e1d 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java @@ -92,8 +92,9 @@ public DataFetcher> stops() { return this::getStops; } + @SuppressWarnings("unchecked") @Override - public DataFetcher> stoptimes() { + public DataFetcher> stoptimes() { return environment -> { TransitService transitService = getTransitService(environment); Trip trip = getSource(environment).trip(); @@ -106,7 +107,12 @@ public DataFetcher> stoptimes() { if (timetable == null) { return List.of(); } - return TripTimeOnDate.fromTripTimes(timetable, trip, serviceDate, midnight); + return (Iterable) (List) TripTimeOnDate.fromTripTimes( + timetable, + trip, + serviceDate, + midnight + ); }; } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/ExactDatedStopTimeImpl.java similarity index 97% rename from src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeImpl.java rename to src/main/java/org/opentripplanner/apis/gtfs/datafetchers/ExactDatedStopTimeImpl.java index 3ed12ac4fb6..21ec9b6e92f 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/ExactDatedStopTimeImpl.java @@ -15,7 +15,7 @@ import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.transit.service.TransitService; -public class DatedStopTimeImpl implements GraphQLDataFetchers.GraphQLDatedStopTime { +public class ExactDatedStopTimeImpl implements GraphQLDataFetchers.GraphQLExactDatedStopTime { @Override public DataFetcher arrival() { diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 3f6f7df22a0..31da847eaf5 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -327,26 +327,8 @@ public interface GraphQLCurrency { public DataFetcher digits(); } - /** Stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. */ - public interface GraphQLDatedStopTime { - public DataFetcher arrival(); - - public DataFetcher departure(); - - public DataFetcher dropoffType(); - - public DataFetcher headsign(); - - public DataFetcher pickupType(); - - public DataFetcher realtimeState(); - - public DataFetcher stop(); - - public DataFetcher stopPosition(); - - public DataFetcher timepoint(); - } + /** Departure and/or arrival times to or from a stop on a specific date. */ + public interface GraphQLDatedStopTime extends TypeResolver {} /** Trip on a specific date */ public interface GraphQLDatedTrip { @@ -364,7 +346,7 @@ public interface GraphQLDatedTrip { public DataFetcher> stops(); - public DataFetcher> stoptimes(); + public DataFetcher> stoptimes(); public DataFetcher tripHeadsign(); @@ -433,6 +415,30 @@ public interface GraphQLEmissions { public DataFetcher co2(); } + /** + * Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. + * This can include realtime estimates. + */ + public interface GraphQLExactDatedStopTime { + public DataFetcher arrival(); + + public DataFetcher departure(); + + public DataFetcher dropoffType(); + + public DataFetcher headsign(); + + public DataFetcher pickupType(); + + public DataFetcher realtimeState(); + + public DataFetcher stop(); + + public DataFetcher stopPosition(); + + public DataFetcher timepoint(); + } + /** A 'medium' that a fare product applies to, for example cash, 'Oyster Card' or 'DB Navigator App'. */ public interface GraphQLFareMedium { public DataFetcher id(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 70e98ab17a0..2796cbc7cad 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -611,25 +611,6 @@ public enum GraphQLCyclingOptimizationType { SHORTEST_DURATION, } - public static class GraphQLDatedStopTimeHeadsignArgs { - - private String language; - - public GraphQLDatedStopTimeHeadsignArgs(Map args) { - if (args != null) { - this.language = (String) args.get("language"); - } - } - - public String getGraphQLLanguage() { - return this.language; - } - - public void setGraphQLLanguage(String language) { - this.language = language; - } - } - public static class GraphQLDatedTripTripHeadsignArgs { private String language; @@ -766,6 +747,25 @@ public void setGraphQLKeepingCost(org.opentripplanner.framework.model.Cost keepi } } + public static class GraphQLExactDatedStopTimeHeadsignArgs { + + private String language; + + public GraphQLExactDatedStopTimeHeadsignArgs(Map args) { + if (args != null) { + this.language = (String) args.get("language"); + } + } + + public String getGraphQLLanguage() { + return this.language; + } + + public void setGraphQLLanguage(String language) { + this.language = language; + } + } + public static class GraphQLFeedAlertsArgs { private List types; diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 1d5ebd31a4f..64effddf651 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -59,7 +59,7 @@ config: ContactInfo: org.opentripplanner.transit.model.organization.ContactInfo Cluster: Object Coordinates: org.locationtech.jts.geom.Coordinate#Coordinate - DatedStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate + ExactDatedStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate DatedTrip: org.opentripplanner.transit.model.timetable.DatedTrip#DatedTrip DatedTripConnection: graphql.relay.Connection#Connection DatedTripEdge: graphql.relay.Edge#Edge diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 3be30ece04f..e493e6ac46a 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -73,6 +73,9 @@ interface PlaceInterface { "Entity related to an alert" union AlertEntity = Agency | Pattern | Route | RouteType | Stop | StopOnRoute | StopOnTrip | Trip | Unknown +"Departure and/or arrival times to or from a stop on a specific date." +union DatedStopTime = ExactDatedStopTime + union StopPosition = PositionAtStop | PositionBetweenStops "A public transport agency" @@ -395,55 +398,6 @@ type Currency { digits: Int! } -"Stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop." -type DatedStopTime { - "Scheduled arrival time to the stop and a realtime estimate, if one exists." - arrival: ArrivalDepartureTime - "Scheduled departure time from the stop and a realtime estimate, if one exists." - departure: ArrivalDepartureTime - """ - Whether the vehicle can be disembarked at this stop. This field can also be - used to indicate if disembarkation is possible only with special arrangements. - """ - dropoffType: PickupDropoffType - """ - Vehicle headsign of the trip on this stop. Trip headsigns can change during - the trip (e.g. on routes which run on loops), so this value should be used - instead of `tripHeadsign` to display the headsign relevant to the user. - """ - headsign( - """ - If translated headsign is found from gtfs translation.txt and wanted language is not same as - feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. - """ - language: String - ): String - """ - Whether the vehicle can be boarded at this stop. This field can also be used - to indicate if boarding is possible only with special arrangements. - """ - pickupType: PickupDropoffType - "Whether stop has been updated through a realtime update and if so, how." - realtimeState: StopRealTimeState! - "The stop where this arrival/departure happens" - stop: Stop - """ - The sequence of the stop in the pattern. This is not required to start from 0 or be consecutive - any - increasing integer sequence along the stops is valid. - - The purpose of this field is to identify the stop within the pattern so it can be cross-referenced - between it and the itinerary. It is safe to cross-reference when done quickly, i.e. within seconds. - However, it should be noted that real-time updates can change the values, so don't store it for - longer amounts of time. - - Depending on the source data, this might not be the GTFS `stop_sequence` but another value, perhaps - even generated. - """ - stopPosition: Int - "true, if this stop is used as a time equalization stop. false otherwise." - timepoint: Boolean -} - "Trip on a specific date" type DatedTrip implements Node { """ @@ -467,7 +421,7 @@ type DatedTrip implements Node { "List of stops this trip passes through" stops: [Stop!]! "List of times when this trip arrives to or departs from a stop" - stoptimes: [DatedStopTime] + stoptimes: [DatedStopTime!] "Headsign of the vehicle when running on this trip" tripHeadsign( """ @@ -573,6 +527,58 @@ type Emissions { co2: Grams } +""" +Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. +This can include realtime estimates. +""" +type ExactDatedStopTime { + "Scheduled arrival time to the stop and a realtime estimate, if one exists." + arrival: ArrivalDepartureTime + "Scheduled departure time from the stop and a realtime estimate, if one exists." + departure: ArrivalDepartureTime + """ + Whether the vehicle can be disembarked at this stop. This field can also be + used to indicate if disembarkation is possible only with special arrangements. + """ + dropoffType: PickupDropoffType + """ + Vehicle headsign of the trip on this stop. Trip headsigns can change during + the trip (e.g. on routes which run on loops), so this value should be used + instead of `tripHeadsign` to display the headsign relevant to the user. + """ + headsign( + """ + If translated headsign is found from gtfs translation.txt and wanted language is not same as + feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. + """ + language: String + ): String + """ + Whether the vehicle can be boarded at this stop. This field can also be used + to indicate if boarding is possible only with special arrangements. + """ + pickupType: PickupDropoffType + "Whether stop has been updated through a realtime update and if so, how." + realtimeState: StopRealTimeState! + "The stop where this arrival/departure happens" + stop: Stop + """ + The sequence of the stop in the pattern. This is not required to start from 0 or be consecutive - any + increasing integer sequence along the stops is valid. + + The purpose of this field is to identify the stop within the pattern so it can be cross-referenced + between it and the itinerary. It is safe to cross-reference when done quickly, i.e. within seconds. + However, it should be noted that real-time updates can change the values, so don't store it for + longer amounts of time. + + Depending on the source data, this might not be the GTFS `stop_sequence` but another value, perhaps + even generated. + """ + stopPosition: Int + "true, if this stop is used as a time equalization stop. false otherwise." + timepoint: Boolean +} + "A 'medium' that a fare product applies to, for example cash, 'Oyster Card' or 'DB Navigator App'." type FareMedium { "ID of the medium" diff --git a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java index 25bb4f88eeb..594900997d9 100644 --- a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java +++ b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java @@ -234,10 +234,7 @@ public TransitAlertService getTransitAlertService() { CalendarServiceData calendarServiceData = new CalendarServiceData(); var firstDate = LocalDate.of(2024, 8, 8); var secondDate = LocalDate.of(2024, 8, 9); - calendarServiceData.putServiceDatesForServiceId( - cal_id, - List.of(firstDate, secondDate) - ); + calendarServiceData.putServiceDatesForServiceId(cal_id, List.of(firstDate, secondDate)); transitModel.getServiceCodes().put(cal_id, 0); transitModel.updateCalendarServiceData(true, calendarServiceData, DataImportIssueStore.NOOP); transitModel.initTimetableSnapshotProvider(() -> { diff --git a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index 060632be28a..bdf9bbb73f0 100644 --- a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -82,10 +82,7 @@ static void setup() { CalendarServiceData calendarServiceData = new CalendarServiceData(); var firstDate = LocalDate.of(2024, 8, 8); var secondDate = LocalDate.of(2024, 8, 9); - calendarServiceData.putServiceDatesForServiceId( - CALENDAR_ID, - List.of(firstDate, secondDate) - ); + calendarServiceData.putServiceDatesForServiceId(CALENDAR_ID, List.of(firstDate, secondDate)); transitModel.getServiceCodes().put(CALENDAR_ID, 0); transitModel.updateCalendarServiceData(true, calendarServiceData, DataImportIssueStore.NOOP); diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index a92a710c540..84452fd04b3 100644 --- a/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -35,27 +35,29 @@ tripHeadsign tripShortName stoptimes { - dropoffType - headsign - pickupType - realtimeState - stop { - gtfsId - } - stopPosition - timepoint - arrival { - scheduledTime - estimated { - delay - time + ... on ExactDatedStopTime { + dropoffType + headsign + pickupType + realtimeState + stop { + gtfsId } - } - departure { - scheduledTime - estimated { - delay - time + stopPosition + timepoint + arrival { + scheduledTime + estimated { + delay + time + } + } + departure { + scheduledTime + estimated { + delay + time + } } } } From 66100b9a0f2f092594517f1a5461c178be6fb644 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 18 Oct 2024 16:37:00 +0300 Subject: [PATCH 22/98] Use TripOnServiceDate and redesign schema --- .../apis/gtfs/GtfsGraphQLIndex.java | 12 +- .../apis/gtfs/datafetchers/DatedTripImpl.java | 189 -------------- ...eImpl.java => FixedDatedStopTimeImpl.java} | 4 +- .../FixedTripOnServiceDateImpl.java | 113 +++++++++ .../gtfs/datafetchers/NodeTypeResolver.java | 4 - .../apis/gtfs/datafetchers/QueryTypeImpl.java | 25 +- ...ava => TripOnServiceDateTypeResolver.java} | 8 +- .../gtfs/generated/GraphQLDataFetchers.java | 134 +++++----- .../apis/gtfs/generated/GraphQLTypes.java | 57 ++--- .../apis/gtfs/generated/graphql-codegen.yml | 8 +- .../model/TimetableSnapshot.java | 12 +- .../opentripplanner/model/TripTimeOnDate.java | 32 +++ .../transit/model/timetable/DatedTrip.java | 8 - .../model/timetable/TripOnServiceDate.java | 3 +- .../service/DefaultTransitService.java | 19 +- .../transit/service/TransitService.java | 3 +- .../opentripplanner/apis/gtfs/schema.graphqls | 235 ++++++++---------- .../service/DefaultTransitServiceTest.java | 8 +- .../gtfs/expectations/canceled-trips.json | 54 ++-- .../apis/gtfs/queries/canceled-trips.graphql | 64 ++--- 20 files changed, 429 insertions(+), 563 deletions(-) delete mode 100644 src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java rename src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{ExactDatedStopTimeImpl.java => FixedDatedStopTimeImpl.java} (96%) create mode 100644 src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java rename src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{DatedStopTimeTypeResolver.java => TripOnServiceDateTypeResolver.java} (63%) delete mode 100644 src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index 83a41e8af5c..c8587e5851a 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -35,14 +35,13 @@ import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl; import org.opentripplanner.apis.gtfs.datafetchers.CurrencyImpl; -import org.opentripplanner.apis.gtfs.datafetchers.DatedStopTimeTypeResolver; -import org.opentripplanner.apis.gtfs.datafetchers.DatedTripImpl; import org.opentripplanner.apis.gtfs.datafetchers.DefaultFareProductImpl; import org.opentripplanner.apis.gtfs.datafetchers.DepartureRowImpl; -import org.opentripplanner.apis.gtfs.datafetchers.ExactDatedStopTimeImpl; import org.opentripplanner.apis.gtfs.datafetchers.FareProductTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.FareProductUseImpl; import org.opentripplanner.apis.gtfs.datafetchers.FeedImpl; +import org.opentripplanner.apis.gtfs.datafetchers.FixedDatedStopTimeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.FixedTripOnServiceDateImpl; import org.opentripplanner.apis.gtfs.datafetchers.GeometryImpl; import org.opentripplanner.apis.gtfs.datafetchers.ItineraryImpl; import org.opentripplanner.apis.gtfs.datafetchers.LegImpl; @@ -73,6 +72,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.TranslatedStringImpl; import org.opentripplanner.apis.gtfs.datafetchers.TripImpl; import org.opentripplanner.apis.gtfs.datafetchers.TripOccupancyImpl; +import org.opentripplanner.apis.gtfs.datafetchers.TripOnServiceDateTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.UnknownImpl; import org.opentripplanner.apis.gtfs.datafetchers.VehicleParkingImpl; import org.opentripplanner.apis.gtfs.datafetchers.VehiclePositionImpl; @@ -129,7 +129,7 @@ protected static GraphQLSchema buildSchema() { .type("StopPosition", type -> type.typeResolver(new StopPosition() {})) .type("FareProduct", type -> type.typeResolver(new FareProductTypeResolver())) .type("AlertEntity", type -> type.typeResolver(new AlertEntityTypeResolver())) - .type("DatedStopTime", type -> type.typeResolver(new DatedStopTimeTypeResolver())) + .type("TripOnServiceDate", type -> type.typeResolver(new TripOnServiceDateTypeResolver())) .type(typeWiring.build(AgencyImpl.class)) .type(typeWiring.build(AlertImpl.class)) .type(typeWiring.build(BikeParkImpl.class)) @@ -182,8 +182,8 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(CurrencyImpl.class)) .type(typeWiring.build(FareProductUseImpl.class)) .type(typeWiring.build(DefaultFareProductImpl.class)) - .type(typeWiring.build(DatedTripImpl.class)) - .type(typeWiring.build(ExactDatedStopTimeImpl.class)) + .type(typeWiring.build(FixedTripOnServiceDateImpl.class)) + .type(typeWiring.build(FixedDatedStopTimeImpl.class)) .type(typeWiring.build(TripOccupancyImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java deleted file mode 100644 index f33026b0e1d..00000000000 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedTripImpl.java +++ /dev/null @@ -1,189 +0,0 @@ -package org.opentripplanner.apis.gtfs.datafetchers; - -import static org.opentripplanner.apis.gtfs.GraphQLUtils.stopTimeToInt; - -import graphql.relay.Relay; -import graphql.schema.DataFetcher; -import graphql.schema.DataFetchingEnvironment; -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZonedDateTime; -import java.util.List; -import javax.annotation.Nullable; -import org.opentripplanner.apis.gtfs.GraphQLRequestContext; -import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; -import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; -import org.opentripplanner.ext.restapi.mapping.LocalDateMapper; -import org.opentripplanner.framework.time.ServiceDateUtils; -import org.opentripplanner.model.Timetable; -import org.opentripplanner.model.TripTimeOnDate; -import org.opentripplanner.transit.model.network.Route; -import org.opentripplanner.transit.model.network.TripPattern; -import org.opentripplanner.transit.model.timetable.DatedTrip; -import org.opentripplanner.transit.model.timetable.Trip; -import org.opentripplanner.transit.model.timetable.TripTimes; -import org.opentripplanner.transit.service.TransitService; - -public class DatedTripImpl implements GraphQLDataFetchers.GraphQLDatedTrip { - - @Override - public DataFetcher date() { - return env -> getSource(env).serviceDate(); - } - - @Override - public DataFetcher end() { - return env -> { - var tripTimes = getTripTimes(env); - if (tripTimes == null) { - return null; - } - var stopIndex = tripTimes.getNumStops() - 1; - var scheduledTime = getZonedDateTime(env, tripTimes.getScheduledArrivalTime(stopIndex)); - if (scheduledTime == null) { - return null; - } - return tripTimes.isRealTimeUpdated(stopIndex) - ? ArrivalDepartureTime.of(scheduledTime, tripTimes.getArrivalDelay(stopIndex)) - : ArrivalDepartureTime.ofStatic(scheduledTime); - }; - } - - @Override - public DataFetcher id() { - return env -> - new Relay.ResolvedGlobalId( - "DatedTrip", - getSource(env).trip().getId().toString() + - ';' + - LocalDateMapper.mapToApi(getSource(env).serviceDate()) - ); - } - - @Override - public DataFetcher pattern() { - return this::getTripPattern; - } - - @Override - public DataFetcher route() { - return environment -> getSource(environment).trip().getRoute(); - } - - @Override - public DataFetcher start() { - return env -> { - var tripTimes = getTripTimes(env); - if (tripTimes == null) { - return null; - } - var scheduledTime = getZonedDateTime(env, tripTimes.getScheduledDepartureTime(0)); - if (scheduledTime == null) { - return null; - } - return tripTimes.isRealTimeUpdated(0) - ? ArrivalDepartureTime.of(scheduledTime, tripTimes.getDepartureDelay(0)) - : ArrivalDepartureTime.ofStatic(scheduledTime); - }; - } - - @Override - public DataFetcher> stops() { - return this::getStops; - } - - @SuppressWarnings("unchecked") - @Override - public DataFetcher> stoptimes() { - return environment -> { - TransitService transitService = getTransitService(environment); - Trip trip = getSource(environment).trip(); - var serviceDate = getSource(environment).serviceDate(); - - Instant midnight = ServiceDateUtils - .asStartOfService(serviceDate, transitService.getTimeZone()) - .toInstant(); - Timetable timetable = getTimetable(environment, trip, serviceDate); - if (timetable == null) { - return List.of(); - } - return (Iterable) (List) TripTimeOnDate.fromTripTimes( - timetable, - trip, - serviceDate, - midnight - ); - }; - } - - @Override - public DataFetcher tripHeadsign() { - return environment -> - org.opentripplanner.framework.graphql.GraphQLUtils.getTranslation( - getSource(environment).trip().getHeadsign(), - environment - ); - } - - @Override - public DataFetcher tripShortName() { - return environment -> getSource(environment).trip().getShortName(); - } - - private List getStops(DataFetchingEnvironment environment) { - TripPattern tripPattern = getTripPattern(environment); - if (tripPattern == null) { - return List.of(); - } - return List.copyOf(tripPattern.getStops()); - } - - private TripPattern getTripPattern(DataFetchingEnvironment environment) { - return getTransitService(environment).getPatternForTrip(getSource(environment).trip()); - } - - @Nullable - private Timetable getTimetable( - DataFetchingEnvironment environment, - Trip trip, - LocalDate serviceDate - ) { - TransitService transitService = getTransitService(environment); - TripPattern tripPattern = transitService.getPatternForTrip(trip, serviceDate); - // no matching pattern found - if (tripPattern == null) { - return null; - } - - return transitService.getTimetableForTripPattern(tripPattern, serviceDate); - } - - @Nullable - private TripTimes getTripTimes(DataFetchingEnvironment environment) { - Trip trip = getSource(environment).trip(); - var serviceDate = getSource(environment).serviceDate(); - var timetable = getTimetable(environment, trip, serviceDate); - if (timetable == null) { - return null; - } - return timetable.getTripTimes(trip); - } - - private ZonedDateTime getZonedDateTime(DataFetchingEnvironment environment, int time) { - var fixedTime = stopTimeToInt(time); - if (fixedTime == null) { - return null; - } - var serviceDate = getSource(environment).serviceDate(); - TransitService transitService = getTransitService(environment); - return ServiceDateUtils.toZonedDateTime(serviceDate, transitService.getTimeZone(), fixedTime); - } - - private TransitService getTransitService(DataFetchingEnvironment environment) { - return environment.getContext().transitService(); - } - - private DatedTrip getSource(DataFetchingEnvironment environment) { - return environment.getSource(); - } -} diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/ExactDatedStopTimeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java similarity index 96% rename from src/main/java/org/opentripplanner/apis/gtfs/datafetchers/ExactDatedStopTimeImpl.java rename to src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java index 21ec9b6e92f..df2864f8580 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/ExactDatedStopTimeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java @@ -15,7 +15,7 @@ import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.transit.service.TransitService; -public class ExactDatedStopTimeImpl implements GraphQLDataFetchers.GraphQLExactDatedStopTime { +public class FixedDatedStopTimeImpl implements GraphQLDataFetchers.GraphQLFixedDatedStopTime { @Override public DataFetcher arrival() { @@ -46,7 +46,7 @@ public DataFetcher departure() { } @Override - public DataFetcher dropoffType() { + public DataFetcher dropOffType() { return environment -> PickDropMapper.map(getSource(environment).getDropoffType()); } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java new file mode 100644 index 00000000000..6b78bc0d13d --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java @@ -0,0 +1,113 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.time.Instant; +import java.time.LocalDate; +import java.util.List; +import javax.annotation.Nullable; +import org.opentripplanner.apis.gtfs.GraphQLRequestContext; +import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.framework.time.ServiceDateUtils; +import org.opentripplanner.model.Timetable; +import org.opentripplanner.model.TripTimeOnDate; +import org.opentripplanner.transit.model.network.TripPattern; +import org.opentripplanner.transit.model.timetable.Trip; +import org.opentripplanner.transit.model.timetable.TripOnServiceDate; +import org.opentripplanner.transit.service.TransitService; + +public class FixedTripOnServiceDateImpl + implements GraphQLDataFetchers.GraphQLFixedTripOnServiceDate { + + @Override + public DataFetcher date() { + return env -> getSource(env).getServiceDate(); + } + + @Override + public DataFetcher end() { + return environment -> { + TransitService transitService = getTransitService(environment); + Trip trip = getTrip(environment); + var serviceDate = getSource(environment).getServiceDate(); + + Instant midnight = ServiceDateUtils + .asStartOfService(serviceDate, transitService.getTimeZone()) + .toInstant(); + Timetable timetable = getTimetable(environment, trip, serviceDate); + if (timetable == null) { + return null; + } + return TripTimeOnDate.lastFromTripTimes(timetable, trip, serviceDate, midnight); + }; + } + + @Override + public DataFetcher start() { + return environment -> { + TransitService transitService = getTransitService(environment); + Trip trip = getTrip(environment); + var serviceDate = getSource(environment).getServiceDate(); + + Instant midnight = ServiceDateUtils + .asStartOfService(serviceDate, transitService.getTimeZone()) + .toInstant(); + Timetable timetable = getTimetable(environment, trip, serviceDate); + if (timetable == null) { + return null; + } + return TripTimeOnDate.firstFromTripTimes(timetable, trip, serviceDate, midnight); + }; + } + + @Override + public DataFetcher> stoptimes() { + return environment -> { + TransitService transitService = getTransitService(environment); + Trip trip = getTrip(environment); + var serviceDate = getSource(environment).getServiceDate(); + + Instant midnight = ServiceDateUtils + .asStartOfService(serviceDate, transitService.getTimeZone()) + .toInstant(); + Timetable timetable = getTimetable(environment, trip, serviceDate); + if (timetable == null) { + return List.of(); + } + return TripTimeOnDate.fromTripTimes(timetable, trip, serviceDate, midnight); + }; + } + + @Override + public DataFetcher trip() { + return this::getTrip; + } + + @Nullable + private Timetable getTimetable( + DataFetchingEnvironment environment, + Trip trip, + LocalDate serviceDate + ) { + TransitService transitService = getTransitService(environment); + TripPattern tripPattern = transitService.getPatternForTrip(trip, serviceDate); + // no matching pattern found + if (tripPattern == null) { + return null; + } + + return transitService.getTimetableForTripPattern(tripPattern, serviceDate); + } + + private TransitService getTransitService(DataFetchingEnvironment environment) { + return environment.getContext().transitService(); + } + + private Trip getTrip(DataFetchingEnvironment environment) { + return getSource(environment).getTrip(); + } + + private TripOnServiceDate getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java index 63f80fb643f..437d75e03e9 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/NodeTypeResolver.java @@ -20,7 +20,6 @@ import org.opentripplanner.transit.model.organization.Agency; import org.opentripplanner.transit.model.site.RegularStop; import org.opentripplanner.transit.model.site.Station; -import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; public class NodeTypeResolver implements TypeResolver { @@ -86,9 +85,6 @@ public GraphQLObjectType getType(TypeResolutionEnvironment environment) { if (o instanceof Trip) { return schema.getObjectType("Trip"); } - if (o instanceof DatedTrip) { - return schema.getObjectType("DatedTrip"); - } return null; } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index 4d893802d02..83818a3094d 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -13,7 +13,6 @@ import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import graphql.schema.DataFetchingEnvironmentImpl; -import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -69,8 +68,8 @@ 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.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; +import org.opentripplanner.transit.model.timetable.TripOnServiceDate; import org.opentripplanner.transit.service.TransitService; import org.opentripplanner.updater.GtfsRealtimeFuzzyTripMatcher; @@ -193,7 +192,10 @@ public DataFetcher> bikeRentalStations() { }; } - // TODO + /** + * @deprecated Replaced by {@link #canceledTrips()}. + */ + @Deprecated @Override public DataFetcher> cancelledTripTimes() { return environment -> null; @@ -433,12 +435,6 @@ public DataFetcher node() { return new PlaceAtDistance(place, Double.parseDouble(parts[0])); } - case "DatedTrip": - { - String[] parts = id.split(";"); - var trip = transitService.getTripForId(FeedScopedId.parse(parts[0])); - return new DatedTrip(trip, LocalDate.parse(parts[1])); - } case "Route": return transitService.getRouteForId(FeedScopedId.parse(id)); case "Stop": @@ -814,14 +810,13 @@ public DataFetcher> trips() { } @Override - public DataFetcher> canceledTrips() { + public DataFetcher> canceledTrips() { return environment -> { var args = new GraphQLTypes.GraphQLQueryTypeCanceledTripsArgs(environment.getArguments()); - var datedTrips = getTransitService(environment) - .getCanceledTrips(args.getGraphQLFeeds()) - .stream() - .collect(Collectors.toList()); - return new SimpleListConnection<>(datedTrips).get(environment); + var trips = new ArrayList<>( + getTransitService(environment).getCanceledTrips(args.getGraphQLFeeds()) + ); + return new SimpleListConnection<>(trips).get(environment); }; } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeTypeResolver.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java similarity index 63% rename from src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeTypeResolver.java rename to src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java index 10ea6056792..aaf8d6dae14 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/DatedStopTimeTypeResolver.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java @@ -4,17 +4,17 @@ import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLSchema; import graphql.schema.TypeResolver; -import org.opentripplanner.model.TripTimeOnDate; +import org.opentripplanner.transit.model.timetable.TripOnServiceDate; -public class DatedStopTimeTypeResolver implements TypeResolver { +public class TripOnServiceDateTypeResolver implements TypeResolver { @Override public GraphQLObjectType getType(TypeResolutionEnvironment environment) { Object o = environment.getObject(); GraphQLSchema schema = environment.getSchema(); - if (o instanceof TripTimeOnDate) { - return schema.getObjectType("ExactDatedStopTime"); + if (o instanceof TripOnServiceDate) { + return schema.getObjectType("FixedTripOnServiceDate"); } return null; } diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 31da847eaf5..e324e4d2494 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -66,8 +66,8 @@ import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.organization.Agency; -import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; +import org.opentripplanner.transit.model.timetable.TripOnServiceDate; import org.opentripplanner.transit.model.timetable.booking.BookingInfo; import org.opentripplanner.transit.model.timetable.booking.BookingTime; @@ -327,52 +327,6 @@ public interface GraphQLCurrency { public DataFetcher digits(); } - /** Departure and/or arrival times to or from a stop on a specific date. */ - public interface GraphQLDatedStopTime extends TypeResolver {} - - /** Trip on a specific date */ - public interface GraphQLDatedTrip { - public DataFetcher date(); - - public DataFetcher end(); - - public DataFetcher id(); - - public DataFetcher pattern(); - - public DataFetcher route(); - - public DataFetcher start(); - - public DataFetcher> stops(); - - public DataFetcher> stoptimes(); - - public DataFetcher tripHeadsign(); - - public DataFetcher tripShortName(); - } - - /** - * A connection to a list of dated trips that follows - * [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). - */ - public interface GraphQLDatedTripConnection { - public DataFetcher>> edges(); - - public DataFetcher pageInfo(); - } - - /** - * An edge for DatedTrip connection. Part of the - * [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). - */ - public interface GraphQLDatedTripEdge { - public DataFetcher cursor(); - - public DataFetcher node(); - } - /** * The standard case of a fare product: it only has a single price to be paid by the passenger * and no discounts are applied. @@ -415,30 +369,6 @@ public interface GraphQLEmissions { public DataFetcher co2(); } - /** - * Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. - * This can include realtime estimates. - */ - public interface GraphQLExactDatedStopTime { - public DataFetcher arrival(); - - public DataFetcher departure(); - - public DataFetcher dropoffType(); - - public DataFetcher headsign(); - - public DataFetcher pickupType(); - - public DataFetcher realtimeState(); - - public DataFetcher stop(); - - public DataFetcher stopPosition(); - - public DataFetcher timepoint(); - } - /** A 'medium' that a fare product applies to, for example cash, 'Oyster Card' or 'DB Navigator App'. */ public interface GraphQLFareMedium { public DataFetcher id(); @@ -490,6 +420,43 @@ public interface GraphQLFeedPublisher { public DataFetcher url(); } + /** + * Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. + * This can include realtime estimates. + */ + public interface GraphQLFixedDatedStopTime { + public DataFetcher arrival(); + + public DataFetcher departure(); + + public DataFetcher dropOffType(); + + public DataFetcher headsign(); + + public DataFetcher pickupType(); + + public DataFetcher realtimeState(); + + public DataFetcher stop(); + + public DataFetcher stopPosition(); + + public DataFetcher timepoint(); + } + + /** A fixed (i.e. not flexible or frequency based) trip on a specific service date */ + public interface GraphQLFixedTripOnServiceDate { + public DataFetcher date(); + + public DataFetcher end(); + + public DataFetcher start(); + + public DataFetcher> stoptimes(); + + public DataFetcher trip(); + } + public interface GraphQLGeometry { public DataFetcher length(); @@ -846,7 +813,7 @@ public interface GraphQLQueryType { public DataFetcher> bikeRentalStations(); - public DataFetcher> canceledTrips(); + public DataFetcher> canceledTrips(); public DataFetcher> cancelledTripTimes(); @@ -1280,6 +1247,29 @@ public interface GraphQLTripOccupancy { public DataFetcher occupancyStatus(); } + /** An instance of a trip on a service date. */ + public interface GraphQLTripOnServiceDate extends TypeResolver {} + + /** + * A connection to a list of trips on service dates that follows + * [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + */ + public interface GraphQLTripOnServiceDateConnection { + public DataFetcher>> edges(); + + public DataFetcher pageInfo(); + } + + /** + * An edge for TripOnServiceDate connection. Part of the + * [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + */ + public interface GraphQLTripOnServiceDateEdge { + public DataFetcher cursor(); + + public DataFetcher node(); + } + /** This is used for alert entities that we don't explicitly handle or they are missing. */ public interface GraphQLUnknown { public DataFetcher description(); diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 2796cbc7cad..5ab7e0d4017 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -611,25 +611,6 @@ public enum GraphQLCyclingOptimizationType { SHORTEST_DURATION, } - public static class GraphQLDatedTripTripHeadsignArgs { - - private String language; - - public GraphQLDatedTripTripHeadsignArgs(Map args) { - if (args != null) { - this.language = (String) args.get("language"); - } - } - - public String getGraphQLLanguage() { - return this.language; - } - - public void setGraphQLLanguage(String language) { - this.language = language; - } - } - public static class GraphQLDepartureRowStoptimesArgs { private Integer numberOfDepartures; @@ -747,25 +728,6 @@ public void setGraphQLKeepingCost(org.opentripplanner.framework.model.Cost keepi } } - public static class GraphQLExactDatedStopTimeHeadsignArgs { - - private String language; - - public GraphQLExactDatedStopTimeHeadsignArgs(Map args) { - if (args != null) { - this.language = (String) args.get("language"); - } - } - - public String getGraphQLLanguage() { - return this.language; - } - - public void setGraphQLLanguage(String language) { - this.language = language; - } - } - public static class GraphQLFeedAlertsArgs { private List types; @@ -811,6 +773,25 @@ public enum GraphQLFilterPlaceType { VEHICLE_RENT, } + public static class GraphQLFixedDatedStopTimeHeadsignArgs { + + private String language; + + public GraphQLFixedDatedStopTimeHeadsignArgs(Map args) { + if (args != null) { + this.language = (String) args.get("language"); + } + } + + public String getGraphQLLanguage() { + return this.language; + } + + public void setGraphQLLanguage(String language) { + this.language = language; + } + } + public enum GraphQLFormFactor { BICYCLE, CAR, diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 64effddf651..28c556238f0 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -59,10 +59,10 @@ config: ContactInfo: org.opentripplanner.transit.model.organization.ContactInfo Cluster: Object Coordinates: org.locationtech.jts.geom.Coordinate#Coordinate - ExactDatedStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate - DatedTrip: org.opentripplanner.transit.model.timetable.DatedTrip#DatedTrip - DatedTripConnection: graphql.relay.Connection#Connection - DatedTripEdge: graphql.relay.Edge#Edge + FixedDatedStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate + FixedTripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate + TripOnServiceDateConnection: graphql.relay.Connection#Connection + TripOnServiceDateEdge: graphql.relay.Edge#Edge ArrivalDepartureTime: org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime#ArrivalDepartureTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop diff --git a/src/main/java/org/opentripplanner/model/TimetableSnapshot.java b/src/main/java/org/opentripplanner/model/TimetableSnapshot.java index f92a16ecc56..3dc68bb6968 100644 --- a/src/main/java/org/opentripplanner/model/TimetableSnapshot.java +++ b/src/main/java/org/opentripplanner/model/TimetableSnapshot.java @@ -26,8 +26,8 @@ import org.opentripplanner.transit.model.framework.Result; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.site.StopLocation; -import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate; +import org.opentripplanner.transit.model.timetable.TripOnServiceDate; import org.opentripplanner.transit.model.timetable.TripTimes; import org.opentripplanner.updater.spi.UpdateError; import org.opentripplanner.updater.spi.UpdateSuccess; @@ -185,7 +185,7 @@ public TripPattern getRealtimeAddedTripPattern(FeedScopedId tripId, LocalDate se * * @param feeds if not null, only return trips from these feeds */ - public ArrayList getCanceledTrips(List feeds) { + public ArrayList getCanceledTrips(List feeds) { return timetables .values() .stream() @@ -200,7 +200,13 @@ public ArrayList getCanceledTrips(List feeds) { tripTimes.isCanceled() && (feeds == null || feeds.contains(tripTimes.getTrip().getId().getFeedId())) ) - .map(tripTimes -> new DatedTrip(tripTimes.getTrip(), timetable.getServiceDate())) + .map(tripTimes -> + TripOnServiceDate + .of(tripTimes.getTrip().getId()) + .withServiceDate(timetable.getServiceDate()) + .withTrip(tripTimes.getTrip()) + .build() + ) ) ) .collect(Collectors.toCollection(ArrayList::new)); diff --git a/src/main/java/org/opentripplanner/model/TripTimeOnDate.java b/src/main/java/org/opentripplanner/model/TripTimeOnDate.java index 8128c36e4db..ef62fa23507 100644 --- a/src/main/java/org/opentripplanner/model/TripTimeOnDate.java +++ b/src/main/java/org/opentripplanner/model/TripTimeOnDate.java @@ -89,6 +89,38 @@ public static List fromTripTimes( return out; } + /** + * Get first stop TripTimeOnDate from Timetable. + */ + public static TripTimeOnDate firstFromTripTimes( + Timetable table, + Trip trip, + LocalDate serviceDate, + Instant midnight + ) { + TripTimes times = table.getTripTimes(trip); + return new TripTimeOnDate(times, 0, table.getPattern(), serviceDate, midnight); + } + + /** + * Get last stop TripTimeOnDate from Timetable. + */ + public static TripTimeOnDate lastFromTripTimes( + Timetable table, + Trip trip, + LocalDate serviceDate, + Instant midnight + ) { + TripTimes times = table.getTripTimes(trip); + return new TripTimeOnDate( + times, + times.getNumStops() - 1, + table.getPattern(), + serviceDate, + midnight + ); + } + public static Comparator compareByDeparture() { return Comparator.comparing(t -> t.getServiceDayMidnight() + t.getRealtimeDeparture()); } diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java b/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java deleted file mode 100644 index 2227421ed0e..00000000000 --- a/src/main/java/org/opentripplanner/transit/model/timetable/DatedTrip.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.opentripplanner.transit.model.timetable; - -import java.time.LocalDate; - -/** - * Class which represents a trip on a specific date - */ -public record DatedTrip(Trip trip, LocalDate serviceDate) {} diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/TripOnServiceDate.java b/src/main/java/org/opentripplanner/transit/model/timetable/TripOnServiceDate.java index 1b4ecc964cf..68b442d0f49 100644 --- a/src/main/java/org/opentripplanner/transit/model/timetable/TripOnServiceDate.java +++ b/src/main/java/org/opentripplanner/transit/model/timetable/TripOnServiceDate.java @@ -8,7 +8,8 @@ import org.opentripplanner.transit.model.framework.FeedScopedId; /** - * Class for holding data about a certain trip on a certain day. Essentially a DatedServiceJourney. + * Class for holding data about a certain trip on a certain day. Essentially a DatedServiceJourney + * or an instance of a generic trip on a certain service date. */ public class TripOnServiceDate extends AbstractTransitEntity { diff --git a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 7eb28e50c7c..d57951fdba6 100644 --- a/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -51,7 +51,6 @@ import org.opentripplanner.transit.model.site.Station; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.model.site.StopLocationsGroup; -import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; @@ -289,17 +288,17 @@ public void addTripForId(FeedScopedId tripId, Trip trip) { * TODO This only supports realtime cancelled trips for now. */ @Override - public Collection getCanceledTrips(List feeds) { + public Collection getCanceledTrips(List feeds) { OTPRequestTimeoutException.checkForTimeout(); var timetableSnapshot = lazyGetTimeTableSnapShot(); if (timetableSnapshot == null) { return List.of(); } - List canceledTrips = timetableSnapshot.getCanceledTrips(feeds); + List canceledTrips = timetableSnapshot.getCanceledTrips(feeds); canceledTrips.sort((t1, t2) -> { - if (t1.serviceDate().isBefore(t2.serviceDate())) { + if (t1.getServiceDate().isBefore(t2.getServiceDate())) { return -1; - } else if (t2.serviceDate().isBefore(t1.serviceDate())) { + } else if (t2.getServiceDate().isBefore(t1.getServiceDate())) { return 1; } var departure1 = getDepartureTime(t1); @@ -310,7 +309,7 @@ public Collection getCanceledTrips(List feeds) { return 1; } else { // identical departure day and time, so sort by unique feedscope id - return t1.trip().getId().compareTo(t2.trip().getId()); + return t1.getTrip().getId().compareTo(t2.getTrip().getId()); } }); return canceledTrips; @@ -756,9 +755,9 @@ private static Stream sortByOccurrenceAndReduce(Stream input) { .map(Map.Entry::getKey); } - private int getDepartureTime(DatedTrip datedTrip) { - var pattern = getPatternForTrip(datedTrip.trip()); - var timetable = timetableSnapshot.resolve(pattern, datedTrip.serviceDate()); - return timetable.getTripTimes(datedTrip.trip()).getDepartureTime(0); + private int getDepartureTime(TripOnServiceDate trip) { + var pattern = getPatternForTrip(trip.getTrip()); + var timetable = timetableSnapshot.resolve(pattern, trip.getServiceDate()); + return timetable.getTripTimes(trip.getTrip()).getDepartureTime(0); } } diff --git a/src/main/java/org/opentripplanner/transit/service/TransitService.java b/src/main/java/org/opentripplanner/transit/service/TransitService.java index c2edd0b2751..139df44647b 100644 --- a/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -41,7 +41,6 @@ import org.opentripplanner.transit.model.site.Station; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.model.site.StopLocationsGroup; -import org.opentripplanner.transit.model.timetable.DatedTrip; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; @@ -142,7 +141,7 @@ public interface TransitService { * * @param feeds If not null, used for filtering. */ - Collection getCanceledTrips(List feeds); + Collection getCanceledTrips(List feeds); Collection getAllRoutes(); diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index e493e6ac46a..18822b6802f 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -73,11 +73,11 @@ interface PlaceInterface { "Entity related to an alert" union AlertEntity = Agency | Pattern | Route | RouteType | Stop | StopOnRoute | StopOnTrip | Trip | Unknown -"Departure and/or arrival times to or from a stop on a specific date." -union DatedStopTime = ExactDatedStopTime - union StopPosition = PositionAtStop | PositionBetweenStops +"An instance of a trip on a service date." +union TripOnServiceDate = FixedTripOnServiceDate + "A public transport agency" type Agency implements Node { """ @@ -398,75 +398,6 @@ type Currency { digits: Int! } -"Trip on a specific date" -type DatedTrip implements Node { - """ - The service date when the trip occurs. - - **Note**: A service date is a technical term useful for transit planning purposes and might not - correspond to a how a passenger thinks of a calendar date. For example, a night bus running - on Sunday morning at 1am to 3am, might have the previous Saturday's service date. - """ - date: LocalDate! - "The time when the trip ends including real-time information, if available." - end: ArrivalDepartureTime - "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." - id: ID! - "The pattern the trip is running on" - pattern: Pattern - "The route the trip is running on" - route: Route! - "The time when the trip starts including real-time information, if available." - start: ArrivalDepartureTime - "List of stops this trip passes through" - stops: [Stop!]! - "List of times when this trip arrives to or departs from a stop" - stoptimes: [DatedStopTime!] - "Headsign of the vehicle when running on this trip" - tripHeadsign( - """ - If a translated headsign is found from GTFS translation.txt and wanted language is not same as - feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. - """ - language: String - ): String - tripShortName: String -} - -""" -A connection to a list of dated trips that follows -[GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). -""" -type DatedTripConnection { - """ - Edges which contain the trips. Part of the - [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). - """ - edges: [DatedTripEdge] - """ - Contains cursors to fetch more pages of trips. - Part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). - """ - pageInfo: PageInfo! -} - -""" -An edge for DatedTrip connection. Part of the -[GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). -""" -type DatedTripEdge { - """ - The cursor of the edge. Part of the - [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). - """ - cursor: String! - """ - Dated trip as a node. Part of the - [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). - """ - node: DatedTrip -} - """ The standard case of a fare product: it only has a single price to be paid by the passenger and no discounts are applied. @@ -527,58 +458,6 @@ type Emissions { co2: Grams } -""" -Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. -This can include realtime estimates. -""" -type ExactDatedStopTime { - "Scheduled arrival time to the stop and a realtime estimate, if one exists." - arrival: ArrivalDepartureTime - "Scheduled departure time from the stop and a realtime estimate, if one exists." - departure: ArrivalDepartureTime - """ - Whether the vehicle can be disembarked at this stop. This field can also be - used to indicate if disembarkation is possible only with special arrangements. - """ - dropoffType: PickupDropoffType - """ - Vehicle headsign of the trip on this stop. Trip headsigns can change during - the trip (e.g. on routes which run on loops), so this value should be used - instead of `tripHeadsign` to display the headsign relevant to the user. - """ - headsign( - """ - If translated headsign is found from gtfs translation.txt and wanted language is not same as - feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. - """ - language: String - ): String - """ - Whether the vehicle can be boarded at this stop. This field can also be used - to indicate if boarding is possible only with special arrangements. - """ - pickupType: PickupDropoffType - "Whether stop has been updated through a realtime update and if so, how." - realtimeState: StopRealTimeState! - "The stop where this arrival/departure happens" - stop: Stop - """ - The sequence of the stop in the pattern. This is not required to start from 0 or be consecutive - any - increasing integer sequence along the stops is valid. - - The purpose of this field is to identify the stop within the pattern so it can be cross-referenced - between it and the itinerary. It is safe to cross-reference when done quickly, i.e. within seconds. - However, it should be noted that real-time updates can change the values, so don't store it for - longer amounts of time. - - Depending on the source data, this might not be the GTFS `stop_sequence` but another value, perhaps - even generated. - """ - stopPosition: Int - "true, if this stop is used as a time equalization stop. false otherwise." - timepoint: Boolean -} - "A 'medium' that a fare product applies to, for example cash, 'Oyster Card' or 'DB Navigator App'." type FareMedium { "ID of the medium" @@ -671,6 +550,78 @@ type FeedPublisher { url: String! } +""" +Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. +This can include realtime estimates. +""" +type FixedDatedStopTime { + "Scheduled arrival time to the stop and a realtime estimate, if one exists." + arrival: ArrivalDepartureTime + "Scheduled departure time from the stop and a realtime estimate, if one exists." + departure: ArrivalDepartureTime + """ + Whether the vehicle can be disembarked at this stop. This field can also be + used to indicate if disembarkation is possible only with special arrangements. + """ + dropOffType: PickupDropoffType + """ + Vehicle headsign of the trip on this stop. Trip headsigns can change during + the trip (e.g. on routes which run on loops), so this value should be used + instead of `tripHeadsign` to display the headsign relevant to the user. + """ + headsign( + """ + If translated headsign is found from gtfs translation.txt and wanted language is not same as + feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. + """ + language: String + ): String + """ + Whether the vehicle can be boarded at this stop. This field can also be used + to indicate if boarding is possible only with special arrangements. + """ + pickupType: PickupDropoffType + "Whether stop has been updated through a realtime update and if so, how." + realtimeState: StopRealTimeState! + "The stop where this arrival/departure happens" + stop: Stop + """ + The sequence of the stop in the pattern. This is not required to start from 0 or be consecutive - any + increasing integer sequence along the stops is valid. + + The purpose of this field is to identify the stop within the pattern so it can be cross-referenced + between it and the itinerary. It is safe to cross-reference when done quickly, i.e. within seconds. + However, it should be noted that real-time updates can change the values, so don't store it for + longer amounts of time. + + Depending on the source data, this might not be the GTFS `stop_sequence` but another value, perhaps + even generated. + """ + stopPosition: Int + "true, if this stop is used as a time equalization stop. false otherwise." + timepoint: Boolean +} + +"A fixed (i.e. not flexible or frequency based) trip on a specific service date" +type FixedTripOnServiceDate { + """ + The service date when the trip occurs. + + **Note**: A service date is a technical term useful for transit planning purposes and might not + correspond to a how a passenger thinks of a calendar date. For example, a night bus running + on Sunday morning at 1am to 3am, might have the previous Saturday's service date. + """ + date: LocalDate! + "The time when the trip ends at a stop and information related to the stop." + end: FixedDatedStopTime + "The time when the trip starts from a stop and information related to the stop." + start: FixedDatedStopTime + "List of times when this trip arrives to or departs from a stop and information related to the stop" + stoptimes: [FixedDatedStopTime!] + "This trip on service date is an instance of this trip." + trip: Trip +} + type Geometry { "The number of points in the string" length: Int @@ -1239,7 +1190,7 @@ type QueryType { feeds: [String], first: Int, last: Int - ): DatedTripConnection + ): TripOnServiceDateConnection "Get canceled TripTimes." cancelledTripTimes( "Feed feedIds (e.g. [\"HSL\"])." @@ -2482,6 +2433,40 @@ type TripOccupancy { occupancyStatus: OccupancyStatus } +""" +A connection to a list of trips on service dates that follows +[GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). +""" +type TripOnServiceDateConnection { + """ + Edges which contain the trips. Part of the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ + edges: [TripOnServiceDateEdge] + """ + Contains cursors to fetch more pages of trips. + Part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ + pageInfo: PageInfo! +} + +""" +An edge for TripOnServiceDate connection. Part of the +[GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). +""" +type TripOnServiceDateEdge { + """ + The cursor of the edge. Part of the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ + cursor: String! + """ + Trip on a service date as a node. Part of the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). + """ + node: TripOnServiceDate +} + "This is used for alert entities that we don't explicitly handle or they are missing." type Unknown { "Entity's description" diff --git a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index bdf9bbb73f0..fedcb3fe884 100644 --- a/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -25,7 +25,6 @@ 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.DatedTrip; import org.opentripplanner.transit.model.timetable.RealTimeTripTimes; import org.opentripplanner.transit.model.timetable.ScheduledTripTimes; import org.opentripplanner.transit.model.timetable.Trip; @@ -149,10 +148,7 @@ void getPatternForStopsWithRealTime() { @Test void getCanceledTrips() { - Collection canceledTrips = service.getCanceledTrips(null); - assertEquals( - "[DatedTrip[trip=Trip{F:123 RR123}, serviceDate=2024-08-08], DatedTrip[trip=Trip{F:123 RR123}, serviceDate=2024-08-09]]", - canceledTrips.toString() - ); + var canceledTrips = service.getCanceledTrips(null); + assertEquals("[TripOnServiceDate{F:123}, TripOnServiceDate{F:123}]", canceledTrips.toString()); } } diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json index 5208a38fb01..1f3285d9e7d 100644 --- a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json +++ b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json @@ -12,41 +12,26 @@ "node": { "date": "2024-08-09", "end": { - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:40:00+02:00" - }, - "scheduledTime": "2024-08-09T11:40:00+02:00" + "arrival": { + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:40:00+02:00" + }, + "scheduledTime": "2024-08-09T11:40:00+02:00" + } }, "start": { - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:30:00+02:00" - }, - "scheduledTime": "2024-08-09T11:30:00+02:00" - }, - "pattern": { - "code": "F:BUS" - }, - "route": { - "gtfsId": "F:R321Canceled" - }, - "stops": [ - { - "gtfsId": "F:Stop_0" - }, - { - "gtfsId": "F:Stop_1" - }, - { - "gtfsId": "F:Stop_2" + "departure": { + "estimated": { + "delay": "PT0S", + "time": "2024-08-09T11:30:00+02:00" + }, + "scheduledTime": "2024-08-09T11:30:00+02:00" } - ], - "tripHeadsign": "Trip Headsign", - "tripShortName": null, + }, "stoptimes": [ { - "dropoffType": null, + "dropOffType": null, "headsign": "Stop headsign at stop 10", "pickupType": null, "realtimeState": "CANCELED", @@ -71,7 +56,7 @@ } }, { - "dropoffType": null, + "dropOffType": null, "headsign": "Stop headsign at stop 20", "pickupType": null, "realtimeState": "CANCELED", @@ -96,7 +81,7 @@ } }, { - "dropoffType": null, + "dropOffType": null, "headsign": "Stop headsign at stop 30", "pickupType": null, "realtimeState": "CANCELED", @@ -120,7 +105,10 @@ } } } - ] + ], + "trip": { + "gtfsId": "F:321Canceled" + } } } ] diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index 84452fd04b3..80b1dd089bd 100644 --- a/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -8,35 +8,28 @@ } edges { node { - date - end { - estimated { - delay - time + ... on FixedTripOnServiceDate { + date + end { + arrival { + estimated { + delay + time + } + scheduledTime + } } - scheduledTime - } - start { - estimated { - delay - time + start { + departure { + estimated { + delay + time + } + scheduledTime + } } - scheduledTime - } - pattern { - code - } - route { - gtfsId - } - stops { - gtfsId - } - tripHeadsign - tripShortName - stoptimes { - ... on ExactDatedStopTime { - dropoffType + stoptimes { + dropOffType headsign pickupType realtimeState @@ -60,21 +53,10 @@ } } } - } - date - start { - estimated { - time - delay - } - scheduledTime - } - end { - estimated { - time - delay + date + trip { + gtfsId } - scheduledTime } } } From 079485ed16fdd5f24c5f394f813d9d419e541249 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 25 Oct 2024 21:25:44 +0300 Subject: [PATCH 23/98] Remove stuff from new stoptime type --- .../datafetchers/FixedDatedStopTimeImpl.java | 50 ---------------- .../FixedTripOnServiceDateImpl.java | 2 +- .../gtfs/generated/GraphQLDataFetchers.java | 15 +---- .../apis/gtfs/generated/GraphQLTypes.java | 29 --------- .../apis/gtfs/generated/graphql-codegen.yml | 1 - .../opentripplanner/apis/gtfs/schema.graphqls | 60 +------------------ .../gtfs/expectations/canceled-trips.json | 20 +------ .../apis/gtfs/queries/canceled-trips.graphql | 8 +-- 8 files changed, 5 insertions(+), 180 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java index df2864f8580..ea53804298a 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java @@ -7,10 +7,7 @@ import java.time.ZonedDateTime; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; -import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; -import org.opentripplanner.apis.gtfs.mapping.PickDropMapper; import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; -import org.opentripplanner.framework.graphql.GraphQLUtils; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.transit.service.TransitService; @@ -45,58 +42,11 @@ public DataFetcher departure() { }; } - @Override - public DataFetcher dropOffType() { - return environment -> PickDropMapper.map(getSource(environment).getDropoffType()); - } - - @Override - public DataFetcher headsign() { - return environment -> - GraphQLUtils.getTranslation(getSource(environment).getHeadsign(), environment); - } - - @Override - public DataFetcher pickupType() { - return environment -> PickDropMapper.map(getSource(environment).getPickupType()); - } - - @Override - public DataFetcher realtimeState() { - return environment -> { - var tripTime = getSource(environment); - // TODO support ADDED state - if (tripTime.isCanceledEffectively()) { - return GraphQLTypes.GraphQLStopRealTimeState.CANCELED; - } - if (tripTime.isNoDataStop()) { - return GraphQLTypes.GraphQLStopRealTimeState.NO_DATA; - } - if (tripTime.isRecordedStop()) { - return GraphQLTypes.GraphQLStopRealTimeState.RECORDED; - } - if (tripTime.isRealtime()) { - return GraphQLTypes.GraphQLStopRealTimeState.UPDATED; - } - return GraphQLTypes.GraphQLStopRealTimeState.UNUPDATED; - }; - } - - @Override - public DataFetcher stopPosition() { - return environment -> getSource(environment).getGtfsSequence(); - } - @Override public DataFetcher stop() { return environment -> getSource(environment).getStop(); } - @Override - public DataFetcher timepoint() { - return environment -> getSource(environment).isTimepoint(); - } - private TransitService getTransitService(DataFetchingEnvironment environment) { return environment.getContext().transitService(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java index 6b78bc0d13d..f6923cdc394 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java @@ -61,7 +61,7 @@ public DataFetcher start() { } @Override - public DataFetcher> stoptimes() { + public DataFetcher> stopTimes() { return environment -> { TransitService transitService = getTransitService(environment); Trip trip = getTrip(environment); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index e058705442c..f57a732dadb 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -21,7 +21,6 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRealtimeState; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRelativeDirection; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; -import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLStopRealTimeState; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; import org.opentripplanner.apis.gtfs.model.FeedPublisher; @@ -430,19 +429,7 @@ public interface GraphQLFixedDatedStopTime { public DataFetcher departure(); - public DataFetcher dropOffType(); - - public DataFetcher headsign(); - - public DataFetcher pickupType(); - - public DataFetcher realtimeState(); - public DataFetcher stop(); - - public DataFetcher stopPosition(); - - public DataFetcher timepoint(); } /** A fixed (i.e. not flexible or frequency based) trip on a specific service date */ @@ -453,7 +440,7 @@ public interface GraphQLFixedTripOnServiceDate { public DataFetcher start(); - public DataFetcher> stoptimes(); + public DataFetcher> stopTimes(); public DataFetcher trip(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 693e613cea3..ee51eaa4e83 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -773,25 +773,6 @@ public enum GraphQLFilterPlaceType { VEHICLE_RENT, } - public static class GraphQLFixedDatedStopTimeHeadsignArgs { - - private String language; - - public GraphQLFixedDatedStopTimeHeadsignArgs(Map args) { - if (args != null) { - this.language = (String) args.get("language"); - } - } - - public String getGraphQLLanguage() { - return this.language; - } - - public void setGraphQLLanguage(String language) { - this.language = language; - } - } - public enum GraphQLFormFactor { BICYCLE, CAR, @@ -4623,16 +4604,6 @@ public enum GraphQLStopAlertType { TRIPS, } - /** Whether stop has been updated through a realtime update and if so, how. */ - public enum GraphQLStopRealTimeState { - ADDED, - CANCELED, - NO_DATA, - RECORDED, - UNUPDATED, - UPDATED, - } - public static class GraphQLStoptimeHeadsignArgs { private String language; diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index e3316e1d423..2c7fb9735f4 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -102,7 +102,6 @@ config: stopAtDistanceEdge: graphql.relay.Edge#Edge StopOnRoute: org.opentripplanner.apis.gtfs.model.StopOnRouteModel#StopOnRouteModel StopOnTrip: org.opentripplanner.apis.gtfs.model.StopOnTripModel#StopOnTripModel - StopRealTimeState: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLStopRealTimeState#GraphQLStopRealTimeState Stoptime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate StoptimesInPattern: org.opentripplanner.model.StopTimesInPattern#StopTimesInPattern TicketType: org.opentripplanner.ext.fares.model.FareRuleSet#FareRuleSet diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 212319455f3..2b15423fbc0 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -559,47 +559,8 @@ type FixedDatedStopTime { arrival: ArrivalDepartureTime "Scheduled departure time from the stop and a realtime estimate, if one exists." departure: ArrivalDepartureTime - """ - Whether the vehicle can be disembarked at this stop. This field can also be - used to indicate if disembarkation is possible only with special arrangements. - """ - dropOffType: PickupDropoffType - """ - Vehicle headsign of the trip on this stop. Trip headsigns can change during - the trip (e.g. on routes which run on loops), so this value should be used - instead of `tripHeadsign` to display the headsign relevant to the user. - """ - headsign( - """ - If translated headsign is found from gtfs translation.txt and wanted language is not same as - feed's language then returns wanted translation. Otherwise uses name from trip_headsign.txt. - """ - language: String - ): String - """ - Whether the vehicle can be boarded at this stop. This field can also be used - to indicate if boarding is possible only with special arrangements. - """ - pickupType: PickupDropoffType - "Whether stop has been updated through a realtime update and if so, how." - realtimeState: StopRealTimeState! "The stop where this arrival/departure happens" stop: Stop - """ - The sequence of the stop in the pattern. This is not required to start from 0 or be consecutive - any - increasing integer sequence along the stops is valid. - - The purpose of this field is to identify the stop within the pattern so it can be cross-referenced - between it and the itinerary. It is safe to cross-reference when done quickly, i.e. within seconds. - However, it should be noted that real-time updates can change the values, so don't store it for - longer amounts of time. - - Depending on the source data, this might not be the GTFS `stop_sequence` but another value, perhaps - even generated. - """ - stopPosition: Int - "true, if this stop is used as a time equalization stop. false otherwise." - timepoint: Boolean } "A fixed (i.e. not flexible or frequency based) trip on a specific service date" @@ -617,7 +578,7 @@ type FixedTripOnServiceDate { "The time when the trip starts from a stop and information related to the stop." start: FixedDatedStopTime "List of times when this trip arrives to or departs from a stop and information related to the stop" - stoptimes: [FixedDatedStopTime!] + stopTimes: [FixedDatedStopTime!] "This trip on service date is an instance of this trip." trip: Trip } @@ -3576,25 +3537,6 @@ enum StopAlertType { TRIPS } -"Whether stop has been updated through a realtime update and if so, how." -enum StopRealTimeState { - "The stop has been added through a realtime update." - ADDED - "The stop has been canceled through a realtime update." - CANCELED - "The realtime feed has indicated that there is no data available for this stop." - NO_DATA - """ - The vehicle has arrived to the stop or already visited it and the times are no longer estimates. - Note, not all realtime feeds indicate this information even if the vehicle has already passed the stop. - """ - RECORDED - "There have been no realtime updates." - UNUPDATED - "The trip's arrival and/or departure time has been updated." - UPDATED -} - """ Transit modes include modes that are used within organized transportation networks run by public transportation authorities, taxi companies etc. diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json index 1f3285d9e7d..5d60b684b76 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json @@ -29,17 +29,11 @@ "scheduledTime": "2024-08-09T11:30:00+02:00" } }, - "stoptimes": [ + "stopTimes": [ { - "dropOffType": null, - "headsign": "Stop headsign at stop 10", - "pickupType": null, - "realtimeState": "CANCELED", "stop": { "gtfsId": "F:Stop_0" }, - "stopPosition": 10, - "timepoint": false, "arrival": { "scheduledTime": "2024-08-09T11:30:00+02:00", "estimated": { @@ -56,15 +50,9 @@ } }, { - "dropOffType": null, - "headsign": "Stop headsign at stop 20", - "pickupType": null, - "realtimeState": "CANCELED", "stop": { "gtfsId": "F:Stop_1" }, - "stopPosition": 20, - "timepoint": false, "arrival": { "scheduledTime": "2024-08-09T11:35:00+02:00", "estimated": { @@ -81,15 +69,9 @@ } }, { - "dropOffType": null, - "headsign": "Stop headsign at stop 30", - "pickupType": null, - "realtimeState": "CANCELED", "stop": { "gtfsId": "F:Stop_2" }, - "stopPosition": 30, - "timepoint": false, "arrival": { "scheduledTime": "2024-08-09T11:40:00+02:00", "estimated": { diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index 80b1dd089bd..cb738d4c56b 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -28,16 +28,10 @@ scheduledTime } } - stoptimes { - dropOffType - headsign - pickupType - realtimeState + stopTimes { stop { gtfsId } - stopPosition - timepoint arrival { scheduledTime estimated { From c15a29edcb7289c8188d49b60d61c82bd15465b4 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 25 Oct 2024 21:32:33 +0300 Subject: [PATCH 24/98] Mark stopTimes as non-null --- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 2b15423fbc0..d7aaaf67002 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -578,7 +578,7 @@ type FixedTripOnServiceDate { "The time when the trip starts from a stop and information related to the stop." start: FixedDatedStopTime "List of times when this trip arrives to or departs from a stop and information related to the stop" - stopTimes: [FixedDatedStopTime!] + stopTimes: [FixedDatedStopTime!]! "This trip on service date is an instance of this trip." trip: Trip } From 65927c6e4670911c847055abfc3e5bf3fceda901 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 25 Oct 2024 21:36:32 +0300 Subject: [PATCH 25/98] Do less inside timetable snapshot provider initialization --- .../apis/gtfs/GraphQLIntegrationTest.java | 11 ++++--- .../service/DefaultTransitServiceTest.java | 29 +++++++++---------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java b/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java index 83abb6fcfdf..ec079341ad6 100644 --- a/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java +++ b/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java @@ -253,13 +253,12 @@ public Set getRoutesForStop(StopLocation stop) { calendarServiceData, DataImportIssueStore.NOOP ); - timetableRepository.initTimetableSnapshotProvider(() -> { - TimetableSnapshot timetableSnapshot = new TimetableSnapshot(); - tripTimes2.cancelTrip(); - timetableSnapshot.update(new RealTimeTripUpdate(pattern, tripTimes2, secondDate)); + TimetableSnapshot timetableSnapshot = new TimetableSnapshot(); + tripTimes2.cancelTrip(); + timetableSnapshot.update(new RealTimeTripUpdate(pattern, tripTimes2, secondDate)); - return timetableSnapshot.commit(); - }); + var snapshot = timetableSnapshot.commit(); + timetableRepository.initTimetableSnapshotProvider(() -> snapshot); var step1 = walkStep("street") .withRelativeDirection(RelativeDirection.DEPART) diff --git a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index 2268b3628e6..26317a0ea80 100644 --- a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -93,21 +93,20 @@ static void setup() { timetableRepository.addTripPattern(RAIL_PATTERN.getId(), RAIL_PATTERN); timetableRepository.index(); - timetableRepository.initTimetableSnapshotProvider(() -> { - TimetableSnapshot timetableSnapshot = new TimetableSnapshot(); - RealTimeTripTimes tripTimes = RealTimeTripTimes.of( - ScheduledTripTimes - .of() - .withTrip(TimetableRepositoryForTest.trip("REAL_TIME_TRIP").build()) - .withDepartureTimes(new int[] { 0, 1 }) - .build() - ); - timetableSnapshot.update(new RealTimeTripUpdate(REAL_TIME_PATTERN, tripTimes, firstDate)); - timetableSnapshot.update(new RealTimeTripUpdate(RAIL_PATTERN, canceledTripTimes, firstDate)); - timetableSnapshot.update(new RealTimeTripUpdate(RAIL_PATTERN, canceledTripTimes, secondDate)); - - return timetableSnapshot.commit(); - }); + TimetableSnapshot timetableSnapshot = new TimetableSnapshot(); + RealTimeTripTimes tripTimes = RealTimeTripTimes.of( + ScheduledTripTimes + .of() + .withTrip(TimetableRepositoryForTest.trip("REAL_TIME_TRIP").build()) + .withDepartureTimes(new int[] { 0, 1 }) + .build() + ); + timetableSnapshot.update(new RealTimeTripUpdate(REAL_TIME_PATTERN, tripTimes, firstDate)); + timetableSnapshot.update(new RealTimeTripUpdate(RAIL_PATTERN, canceledTripTimes, firstDate)); + timetableSnapshot.update(new RealTimeTripUpdate(RAIL_PATTERN, canceledTripTimes, secondDate)); + + var snapshot = timetableSnapshot.commit(); + timetableRepository.initTimetableSnapshotProvider(() -> snapshot); service = new DefaultTransitService(timetableRepository) { From 9c124df484601c49a5de578c5ed020d058e339bc Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 25 Oct 2024 22:08:46 +0300 Subject: [PATCH 26/98] Minor fixes --- .../apis/gtfs/datafetchers/LegImpl.java | 14 +++++++------- .../apis/gtfs/datafetchers/StoptimeImpl.java | 4 ++-- .../apis/gtfs/generated/GraphQLDataFetchers.java | 9 +++++---- .../apis/gtfs/generated/graphql-codegen.yml | 2 +- .../apis/gtfs/mapping/PickDropMapper.java | 11 ++++++----- .../apis/gtfs/model/ArrivalDepartureTime.java | 5 +---- .../org/opentripplanner/model/TripTimeOnDate.java | 4 ++-- .../street/model/vertex/StationCentroidVertex.java | 1 - .../transit/service/DefaultTransitService.java | 2 +- .../transit/service/TransitService.java | 2 +- 10 files changed, 26 insertions(+), 28 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java index 86d6d5be1a9..4db347ee784 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java @@ -10,12 +10,12 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; import org.opentripplanner.apis.gtfs.mapping.NumberMapper; +import org.opentripplanner.apis.gtfs.mapping.PickDropMapper; import org.opentripplanner.apis.gtfs.mapping.RealtimeStateMapper; import org.opentripplanner.ext.restapi.mapping.LocalDateMapper; import org.opentripplanner.ext.ridehailing.model.RideEstimate; import org.opentripplanner.ext.ridehailing.model.RideHailingLeg; import org.opentripplanner.framework.graphql.GraphQLUtils; -import org.opentripplanner.model.PickDrop; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; import org.opentripplanner.model.plan.LegTime; @@ -66,12 +66,12 @@ public DataFetcher dropOffBookingInfo() { } @Override - public DataFetcher dropoffType() { + public DataFetcher dropoffType() { return environment -> { if (getSource(environment).getAlightRule() == null) { - return PickDrop.SCHEDULED.name(); + return GraphQLTypes.GraphQLPickupDropoffType.SCHEDULED; } - return getSource(environment).getAlightRule().name(); + return PickDropMapper.map(getSource(environment).getAlightRule()); }; } @@ -177,12 +177,12 @@ public DataFetcher pickupBookingInfo() { } @Override - public DataFetcher pickupType() { + public DataFetcher pickupType() { return environment -> { if (getSource(environment).getBoardRule() == null) { - return PickDrop.SCHEDULED.name(); + return GraphQLTypes.GraphQLPickupDropoffType.SCHEDULED; } - return getSource(environment).getBoardRule().name(); + return PickDropMapper.map(getSource(environment).getBoardRule()); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java index 155c754cfa8..e6244124ba9 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StoptimeImpl.java @@ -25,7 +25,7 @@ public DataFetcher departureDelay() { } @Override - public DataFetcher dropoffType() { + public DataFetcher dropoffType() { return environment -> PickDropMapper.map(getSource(environment).getDropoffType()); } @@ -36,7 +36,7 @@ public DataFetcher headsign() { } @Override - public DataFetcher pickupType() { + public DataFetcher pickupType() { return environment -> PickDropMapper.map(getSource(environment).getPickupType()); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index f57a732dadb..eeeac1ffd0f 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -18,6 +18,7 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLBikesAllowed; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLInputField; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLOccupancyStatus; +import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLPickupDropoffType; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRealtimeState; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRelativeDirection; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; @@ -504,7 +505,7 @@ public interface GraphQLLeg { public DataFetcher dropOffBookingInfo(); - public DataFetcher dropoffType(); + public DataFetcher dropoffType(); public DataFetcher duration(); @@ -538,7 +539,7 @@ public interface GraphQLLeg { public DataFetcher pickupBookingInfo(); - public DataFetcher pickupType(); + public DataFetcher pickupType(); public DataFetcher realTime(); @@ -1110,11 +1111,11 @@ public interface GraphQLStoptime { public DataFetcher departureDelay(); - public DataFetcher dropoffType(); + public DataFetcher dropoffType(); public DataFetcher headsign(); - public DataFetcher pickupType(); + public DataFetcher pickupType(); public DataFetcher realtime(); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 2c7fb9735f4..5309310e80d 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -80,7 +80,7 @@ config: TransitMode: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode#GraphQLTransitMode PageInfo: Object Pattern: org.opentripplanner.transit.model.network.TripPattern#TripPattern - PickupDropoffType: String + PickupDropoffType: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLPickupDropoffType#GraphQLPickupDropoffType Place: org.opentripplanner.model.plan.StopArrival#StopArrival placeAtDistance: org.opentripplanner.routing.graphfinder.PlaceAtDistance#PlaceAtDistance placeAtDistanceConnection: graphql.relay.Connection#Connection diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java b/application/src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java index c8e4d212999..acb7e61cc4b 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/mapping/PickDropMapper.java @@ -1,17 +1,18 @@ package org.opentripplanner.apis.gtfs.mapping; import javax.annotation.Nullable; +import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; import org.opentripplanner.model.PickDrop; public final class PickDropMapper { @Nullable - public static String map(PickDrop pickDrop) { + public static GraphQLTypes.GraphQLPickupDropoffType map(PickDrop pickDrop) { return switch (pickDrop) { - case SCHEDULED -> "SCHEDULED"; - case NONE -> "NONE"; - case CALL_AGENCY -> "CALL_AGENCY"; - case COORDINATE_WITH_DRIVER -> "COORDINATE_WITH_DRIVER"; + case SCHEDULED -> GraphQLTypes.GraphQLPickupDropoffType.SCHEDULED; + case NONE -> GraphQLTypes.GraphQLPickupDropoffType.NONE; + case CALL_AGENCY -> GraphQLTypes.GraphQLPickupDropoffType.CALL_AGENCY; + case COORDINATE_WITH_DRIVER -> GraphQLTypes.GraphQLPickupDropoffType.COORDINATE_WITH_DRIVER; case CANCELLED -> null; }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java b/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java index 529d83c7459..3a801537dd1 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java @@ -2,7 +2,6 @@ import java.time.Duration; import java.time.ZonedDateTime; -import javax.annotation.Nonnull; import javax.annotation.Nullable; /** @@ -10,16 +9,14 @@ * if available. */ public record ArrivalDepartureTime( - @Nonnull ZonedDateTime scheduledTime, + ZonedDateTime scheduledTime, @Nullable RealTimeEstimate estimated ) { - @Nonnull public static ArrivalDepartureTime of(ZonedDateTime realtime, int delaySecs) { var delay = Duration.ofSeconds(delaySecs); return new ArrivalDepartureTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); } - @Nonnull public static ArrivalDepartureTime ofStatic(ZonedDateTime staticTime) { return new ArrivalDepartureTime(staticTime, null); } diff --git a/application/src/main/java/org/opentripplanner/model/TripTimeOnDate.java b/application/src/main/java/org/opentripplanner/model/TripTimeOnDate.java index 4c0a4eda26c..857bb42ee51 100644 --- a/application/src/main/java/org/opentripplanner/model/TripTimeOnDate.java +++ b/application/src/main/java/org/opentripplanner/model/TripTimeOnDate.java @@ -172,14 +172,14 @@ public int getRealtimeDeparture() { * Returns the actual arrival time if available. Otherwise -1 is returned. */ public int getActualArrival() { - return tripTimes.isRecordedStop(stopIndex) ? tripTimes.getArrivalTime(stopIndex) : UNDEFINED; + return isRecordedStop() ? tripTimes.getArrivalTime(stopIndex) : UNDEFINED; } /** * Returns the actual departure time if available. Otherwise -1 is returned. */ public int getActualDeparture() { - return tripTimes.isRecordedStop(stopIndex) ? tripTimes.getDepartureTime(stopIndex) : UNDEFINED; + return isRecordedStop() ? tripTimes.getDepartureTime(stopIndex) : UNDEFINED; } public int getArrivalDelay() { diff --git a/application/src/main/java/org/opentripplanner/street/model/vertex/StationCentroidVertex.java b/application/src/main/java/org/opentripplanner/street/model/vertex/StationCentroidVertex.java index f6f3b00191d..30de8e0f597 100644 --- a/application/src/main/java/org/opentripplanner/street/model/vertex/StationCentroidVertex.java +++ b/application/src/main/java/org/opentripplanner/street/model/vertex/StationCentroidVertex.java @@ -20,7 +20,6 @@ public Station getStation() { return this.station; } - @Nonnull @Override public I18NString getName() { return station.getName(); diff --git a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index c8cfbcaae4f..8270a0e06d1 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -298,7 +298,7 @@ public Trip getScheduledTripForId(FeedScopedId id) { * TODO This only supports realtime cancelled trips for now. */ @Override - public Collection getCanceledTrips(List feeds) { + public Collection getCanceledTrips(@Nullable List feeds) { OTPRequestTimeoutException.checkForTimeout(); var timetableSnapshot = lazyGetTimeTableSnapShot(); if (timetableSnapshot == null) { diff --git a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java index d74401c0def..c8b1cc21e63 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -174,7 +174,7 @@ public interface TransitService { * * @param feeds If not null, used for filtering. */ - Collection getCanceledTrips(List feeds); + Collection getCanceledTrips(@Nullable List feeds); /** * Return all routes, including those created by real-time updates. From 9e5eb1489819ca82f58fd91544492597367e2ef7 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 25 Oct 2024 22:17:43 +0300 Subject: [PATCH 27/98] Rename FixedDatedStopTime -> FixedStopTimeOnServiceDate --- .../org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java | 4 ++-- ...pTimeImpl.java => FixedStopTimeOnServiceDateImpl.java} | 3 ++- .../apis/gtfs/generated/graphql-codegen.yml | 2 +- .../org/opentripplanner/apis/gtfs/schema.graphqls | 8 ++++---- 4 files changed, 9 insertions(+), 8 deletions(-) rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{FixedDatedStopTimeImpl.java => FixedStopTimeOnServiceDateImpl.java} (95%) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index c8587e5851a..9aeed1e9472 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -40,7 +40,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.FareProductTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.FareProductUseImpl; import org.opentripplanner.apis.gtfs.datafetchers.FeedImpl; -import org.opentripplanner.apis.gtfs.datafetchers.FixedDatedStopTimeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.FixedStopTimeOnServiceDateImpl; import org.opentripplanner.apis.gtfs.datafetchers.FixedTripOnServiceDateImpl; import org.opentripplanner.apis.gtfs.datafetchers.GeometryImpl; import org.opentripplanner.apis.gtfs.datafetchers.ItineraryImpl; @@ -183,7 +183,7 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(FareProductUseImpl.class)) .type(typeWiring.build(DefaultFareProductImpl.class)) .type(typeWiring.build(FixedTripOnServiceDateImpl.class)) - .type(typeWiring.build(FixedDatedStopTimeImpl.class)) + .type(typeWiring.build(FixedStopTimeOnServiceDateImpl.class)) .type(typeWiring.build(TripOccupancyImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java similarity index 95% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java index ea53804298a..50cdb002a3e 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedDatedStopTimeImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java @@ -12,7 +12,8 @@ import org.opentripplanner.model.TripTimeOnDate; import org.opentripplanner.transit.service.TransitService; -public class FixedDatedStopTimeImpl implements GraphQLDataFetchers.GraphQLFixedDatedStopTime { +public class FixedStopTimeOnServiceDateImpl + implements GraphQLDataFetchers.GraphQLFixedDatedStopTime { @Override public DataFetcher arrival() { diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 5309310e80d..66b701c5e01 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -59,7 +59,7 @@ config: ContactInfo: org.opentripplanner.transit.model.organization.ContactInfo Cluster: Object Coordinates: org.locationtech.jts.geom.Coordinate#Coordinate - FixedDatedStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate + FixedStopTimeOnServiceDate: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate FixedTripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate TripOnServiceDateConnection: graphql.relay.Connection#Connection TripOnServiceDateEdge: graphql.relay.Edge#Edge diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index d7aaaf67002..00aa6ab71b4 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -554,7 +554,7 @@ type FeedPublisher { Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. This can include realtime estimates. """ -type FixedDatedStopTime { +type FixedStopTimeOnServiceDate { "Scheduled arrival time to the stop and a realtime estimate, if one exists." arrival: ArrivalDepartureTime "Scheduled departure time from the stop and a realtime estimate, if one exists." @@ -574,11 +574,11 @@ type FixedTripOnServiceDate { """ date: LocalDate! "The time when the trip ends at a stop and information related to the stop." - end: FixedDatedStopTime + end: FixedStopTimeOnServiceDate "The time when the trip starts from a stop and information related to the stop." - start: FixedDatedStopTime + start: FixedStopTimeOnServiceDate "List of times when this trip arrives to or departs from a stop and information related to the stop" - stopTimes: [FixedDatedStopTime!]! + stopTimes: [FixedStopTimeOnServiceDate!]! "This trip on service date is an instance of this trip." trip: Trip } From 7f1948e4c8d4011732f19a5cb9c0cea40cf97641 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 25 Oct 2024 22:33:21 +0300 Subject: [PATCH 28/98] Run codegen --- .../apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java | 2 +- .../apis/gtfs/generated/GraphQLDataFetchers.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java index 50cdb002a3e..f6e8c62b223 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java @@ -13,7 +13,7 @@ import org.opentripplanner.transit.service.TransitService; public class FixedStopTimeOnServiceDateImpl - implements GraphQLDataFetchers.GraphQLFixedDatedStopTime { + implements GraphQLDataFetchers.GraphQLFixedStopTimeOnServiceDate { @Override public DataFetcher arrival() { diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index eeeac1ffd0f..9dc3fa6662f 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -425,7 +425,7 @@ public interface GraphQLFeedPublisher { * Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. * This can include realtime estimates. */ - public interface GraphQLFixedDatedStopTime { + public interface GraphQLFixedStopTimeOnServiceDate { public DataFetcher arrival(); public DataFetcher departure(); From 7ed48c3d556ab37bb375f8c23eb34018c30d5b39 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Thu, 31 Oct 2024 15:11:20 +0200 Subject: [PATCH 29/98] Improve schema doc and mark some fields as non-null --- .../opentripplanner/apis/gtfs/schema.graphqls | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 4f51c0e3085..2853164008c 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -165,7 +165,7 @@ type ArrivalDepartureTime { "The estimated time of the event. If no real-time information is available, this is null." estimated: RealTimeEstimate "The scheduled time of the event." - scheduledTime: OffsetDateTime + scheduledTime: OffsetDateTime! } "Bike park represents a location where bicycles can be parked." @@ -573,10 +573,10 @@ type FixedTripOnServiceDate { on Sunday morning at 1am to 3am, might have the previous Saturday's service date. """ date: LocalDate! - "The time when the trip ends at a stop and information related to the stop." - end: FixedStopTimeOnServiceDate - "The time when the trip starts from a stop and information related to the stop." - start: FixedStopTimeOnServiceDate + "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." + end: FixedStopTimeOnServiceDate! + "Information related to trip's scheduled departure from the first stop. Can contain realtime information." + start: FixedStopTimeOnServiceDate! "List of times when this trip arrives to or departs from a stop and information related to the stop" stopTimes: [FixedStopTimeOnServiceDate!]! "This trip on service date is an instance of this trip." @@ -1146,15 +1146,32 @@ type QueryType { ids: [String] ): [BikeRentalStation] @deprecated(reason : "Use rentalVehicles or vehicleRentalStations instead") """ - Get pages of canceled Trips. Follows the + Get pages of canceled Trips. Planned cancellations are not currently supported. Follows the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). """ canceledTrips( + """ + This parameter is part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm) + and should be used together with the `first` parameter. + """ after: String, + """ + This parameter is part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm) + and should be used together with the `last` parameter. + """ before: String, "Feed feedIds (e.g. [\"HSL\"])." feeds: [String], + """ + Limits how many trips are returned. This parameter is part of the + [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm) and can be used together with + the `after` parameter. + """ first: Int, + """ + This parameter is part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm) + and should be used together with the `before` parameter. + """ last: Int ): TripOnServiceDateConnection "Get canceled TripTimes." @@ -1191,7 +1208,7 @@ type QueryType { routes: [String], "Trip gtfsIds (e.g. [\"HSL:1098_20190405_Ma_2_1455\"])." trips: [String] - ): [Stoptime] @deprecated(reason : "`cancelledTripTimes` is deprecated. Use `canceledTrips` instead.") + ): [Stoptime] @deprecated(reason : "`cancelledTripTimes` is not implemented. Use `canceledTrips` instead.") "Get a single car park based on its ID, i.e. value of field `carParkId`" carPark(id: String!): CarPark @deprecated(reason : "carPark is deprecated. Use vehicleParking instead.") "Get all car parks" From 2797fa53f4d1f2faeff9ae2b0704c0069046b7c6 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 1 Nov 2024 13:44:40 +0200 Subject: [PATCH 30/98] Slightly refactor methods to fetch cancelled trips --- .../apis/gtfs/datafetchers/QueryTypeImpl.java | 12 ++- .../model/TimetableSnapshot.java | 75 ++++++++++++------- .../service/DefaultTransitService.java | 65 +++++++++++----- .../transit/service/TransitService.java | 11 ++- .../service/DefaultTransitServiceTest.java | 22 +++++- 5 files changed, 131 insertions(+), 54 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index 5b9c151557b..784dd5f51bf 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -833,9 +833,15 @@ public DataFetcher> trips() { public DataFetcher> canceledTrips() { return environment -> { var args = new GraphQLTypes.GraphQLQueryTypeCanceledTripsArgs(environment.getArguments()); - var trips = new ArrayList<>( - getTransitService(environment).getCanceledTrips(args.getGraphQLFeeds()) - ); + if (args.getGraphQLFeeds() != null && args.getGraphQLFeeds().isEmpty()) { + throw new IllegalArgumentException( + "Feeds need to be either not specified or contain elements." + ); + } + + var trips = args.getGraphQLFeeds() != null + ? getTransitService(environment).findCanceledTrips(args.getGraphQLFeeds()) + : getTransitService(environment).listCanceledTrips(); return new SimpleListConnection<>(trips).get(environment); }; } diff --git a/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java b/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java index f8365ef025a..b8aace7feb0 100644 --- a/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java +++ b/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java @@ -20,6 +20,7 @@ import java.util.Map.Entry; import java.util.SortedSet; import java.util.TreeSet; +import java.util.function.Predicate; import java.util.stream.Collectors; import javax.annotation.Nullable; import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.TransitLayerUpdater; @@ -226,35 +227,24 @@ public TripPattern getNewTripPatternForModifiedTrip(FeedScopedId tripId, LocalDa } /** - * Get trips which have been canceled. + * Find trips which have been canceled. * - * @param feeds if not null, only return trips from these feeds + * @param feeds only return trips from these feeds. Empty list is not allowed. */ - public ArrayList getCanceledTrips(List feeds) { - return timetables - .values() - .stream() - .flatMap(timetables -> - timetables - .stream() - .flatMap(timetable -> - timetable - .getTripTimes() - .stream() - .filter(tripTimes -> - tripTimes.isCanceled() && - (feeds == null || feeds.contains(tripTimes.getTrip().getId().getFeedId())) - ) - .map(tripTimes -> - TripOnServiceDate - .of(tripTimes.getTrip().getId()) - .withServiceDate(timetable.getServiceDate()) - .withTrip(tripTimes.getTrip()) - .build() - ) - ) - ) - .collect(Collectors.toCollection(ArrayList::new)); + public List findCanceledTrips(List feeds) { + if (feeds == null || feeds.isEmpty()) { + throw new IllegalArgumentException("Feeds list cannot be null or empty"); + } + return findTripsOnServiceDates(tripTimes -> + tripTimes.isCanceled() && feeds.contains(tripTimes.getTrip().getId().getFeedId()) + ); + } + + /** + * List trips which have been canceled. + */ + public List listCanceledTrips() { + return findTripsOnServiceDates(TripTimes::isCanceled); } /** @@ -679,6 +669,37 @@ private void validateNotReadOnly() { } } + private TripOnServiceDate mapToTripOnServiceDate(TripTimes tripTimes, Timetable timetable) { + return TripOnServiceDate + .of(tripTimes.getTrip().getId()) + .withServiceDate(timetable.getServiceDate()) + .withTrip(tripTimes.getTrip()) + .build(); + } + + /** + * Find trips from timetables based on filter criteria. + * + * @param filter used to filter {@link TripTimes}. + */ + private List findTripsOnServiceDates(Predicate filter) { + return timetables + .values() + .stream() + .flatMap(timetables -> + timetables + .stream() + .flatMap(timetable -> + timetable + .getTripTimes() + .stream() + .filter(filter) + .map(tripTimes -> mapToTripOnServiceDate(tripTimes, timetable)) + ) + ) + .collect(Collectors.toCollection(ArrayList::new)); + } + protected static class SortedTimetableComparator implements Comparator { @Override diff --git a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 98f73d5afcb..114414210ce 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -10,6 +10,7 @@ import java.time.ZonedDateTime; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -298,30 +299,34 @@ public Trip getScheduledTripForId(FeedScopedId id) { * TODO This only supports realtime cancelled trips for now. */ @Override - public Collection getCanceledTrips(@Nullable List feeds) { + public List findCanceledTrips(List feeds) { + if (feeds == null || feeds.isEmpty()) { + throw new IllegalArgumentException( + "Feeds list cannot be empty or null. It needs to have elements." + ); + } OTPRequestTimeoutException.checkForTimeout(); var timetableSnapshot = lazyGetTimeTableSnapShot(); if (timetableSnapshot == null) { return List.of(); } - List canceledTrips = timetableSnapshot.getCanceledTrips(feeds); - canceledTrips.sort((t1, t2) -> { - if (t1.getServiceDate().isBefore(t2.getServiceDate())) { - return -1; - } else if (t2.getServiceDate().isBefore(t1.getServiceDate())) { - return 1; - } - var departure1 = getDepartureTime(t1); - var departure2 = getDepartureTime(t2); - if (departure1 < departure2) { - return -1; - } else if (departure1 > departure2) { - return 1; - } else { - // identical departure day and time, so sort by unique feedscope id - return t1.getTrip().getId().compareTo(t2.getTrip().getId()); - } - }); + List canceledTrips = timetableSnapshot.findCanceledTrips(feeds); + canceledTrips.sort(new TripOnServiceDateComparator()); + return canceledTrips; + } + + /** + * TODO This only supports realtime cancelled trips for now. + */ + @Override + public List listCanceledTrips() { + OTPRequestTimeoutException.checkForTimeout(); + var timetableSnapshot = lazyGetTimeTableSnapShot(); + if (timetableSnapshot == null) { + return List.of(); + } + List canceledTrips = timetableSnapshot.listCanceledTrips(); + canceledTrips.sort(new TripOnServiceDateComparator()); return canceledTrips; } @@ -799,4 +804,26 @@ private int getDepartureTime(TripOnServiceDate trip) { var timetable = timetableSnapshot.resolve(pattern, trip.getServiceDate()); return timetable.getTripTimes(trip.getTrip()).getDepartureTime(0); } + + private class TripOnServiceDateComparator implements Comparator { + + @Override + public int compare(TripOnServiceDate t1, TripOnServiceDate t2) { + if (t1.getServiceDate().isBefore(t2.getServiceDate())) { + return -1; + } else if (t2.getServiceDate().isBefore(t1.getServiceDate())) { + return 1; + } + var departure1 = getDepartureTime(t1); + var departure2 = getDepartureTime(t2); + if (departure1 < departure2) { + return -1; + } else if (departure1 > departure2) { + return 1; + } else { + // identical departure day and time, so sort by unique feedscope id + return t1.getTrip().getId().compareTo(t2.getTrip().getId()); + } + } + } } diff --git a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java index c8b1cc21e63..4e0b49d559f 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -170,11 +170,16 @@ public interface TransitService { Collection getAllTrips(); /** - * Get canceled trips. + * Find canceled trips. * - * @param feeds If not null, used for filtering. + * @param feeds used for filtering. Empty list is not allowed. */ - Collection getCanceledTrips(@Nullable List feeds); + List findCanceledTrips(List feeds); + + /** + * List all canceled trips. + */ + List listCanceledTrips(); /** * Return all routes, including those created by real-time updates. diff --git a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index 1d463955bad..534b0103854 100644 --- a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -1,5 +1,6 @@ package org.opentripplanner.transit.service; +import static org.junit.Assert.assertThrows; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.opentripplanner.model.plan.PlanTestConstants.T11_30; import static org.opentripplanner.transit.model.basic.TransitMode.BUS; @@ -152,8 +153,25 @@ void getPatternForStopsWithRealTime() { } @Test - void getCanceledTrips() { - var canceledTrips = service.getCanceledTrips(null); + void listCanceledTrips() { + var canceledTrips = service.listCanceledTrips(); assertEquals("[TripOnServiceDate{F:123}, TripOnServiceDate{F:123}]", canceledTrips.toString()); } + + @Test + void findCanceledTrips() { + var canceledTripsForFeedWithCancellations = service.findCanceledTrips(List.of("F", "G")); + assertEquals( + "[TripOnServiceDate{F:123}, TripOnServiceDate{F:123}]", + canceledTripsForFeedWithCancellations.toString() + ); + + var canceledTripsForFeedWithoutCancellations = service.findCanceledTrips(List.of("G")); + assertEquals("[]", canceledTripsForFeedWithoutCancellations.toString()); + } + + @Test + void findCanceledTripsWithEmptyFeeds() { + assertThrows(IllegalArgumentException.class, () -> service.findCanceledTrips(List.of())); + } } From a2b30f865258b48e5fb66cde8fb5ff95a0211d06 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 1 Nov 2024 13:57:00 +0200 Subject: [PATCH 31/98] Improve schema doc --- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 2853164008c..1d970162390 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1146,7 +1146,9 @@ type QueryType { ids: [String] ): [BikeRentalStation] @deprecated(reason : "Use rentalVehicles or vehicleRentalStations instead") """ - Get pages of canceled Trips. Planned cancellations are not currently supported. Follows the + Get pages of canceled trips. Planned cancellations are not currently supported. Limiting the number of + returned trips with either `first` or `last` is highly recommended since the number of returned trips + can be really high when there is a strike affecting the transit services, for example. Follows the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). """ canceledTrips( From 6eaef7a9c345c80c6d5f422db6e1d01a96ed18b3 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 1 Nov 2024 14:02:26 +0200 Subject: [PATCH 32/98] Rename date -> serviceDate --- .../apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java | 2 +- .../apis/gtfs/generated/GraphQLDataFetchers.java | 4 ++-- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 2 +- .../apis/gtfs/expectations/canceled-trips.json | 2 +- .../opentripplanner/apis/gtfs/queries/canceled-trips.graphql | 3 +-- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java index f6923cdc394..c34c25e3f1d 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java @@ -20,7 +20,7 @@ public class FixedTripOnServiceDateImpl implements GraphQLDataFetchers.GraphQLFixedTripOnServiceDate { @Override - public DataFetcher date() { + public DataFetcher serviceDate() { return env -> getSource(env).getServiceDate(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 9dc3fa6662f..60e0b1e3fbc 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -435,10 +435,10 @@ public interface GraphQLFixedStopTimeOnServiceDate { /** A fixed (i.e. not flexible or frequency based) trip on a specific service date */ public interface GraphQLFixedTripOnServiceDate { - public DataFetcher date(); - public DataFetcher end(); + public DataFetcher serviceDate(); + public DataFetcher start(); public DataFetcher> stopTimes(); diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 1d970162390..4cfe9fa6fd0 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -572,7 +572,7 @@ type FixedTripOnServiceDate { correspond to a how a passenger thinks of a calendar date. For example, a night bus running on Sunday morning at 1am to 3am, might have the previous Saturday's service date. """ - date: LocalDate! + serviceDate: LocalDate! "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." end: FixedStopTimeOnServiceDate! "Information related to trip's scheduled departure from the first stop. Can contain realtime information." diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json index 5d60b684b76..b3facd3da1f 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json @@ -10,7 +10,7 @@ "edges": [ { "node": { - "date": "2024-08-09", + "serviceDate": "2024-08-09", "end": { "arrival": { "estimated": { diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index cb738d4c56b..a29950f7b0e 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -9,7 +9,7 @@ edges { node { ... on FixedTripOnServiceDate { - date + serviceDate end { arrival { estimated { @@ -47,7 +47,6 @@ } } } - date trip { gtfsId } From 396c43c83e7faaf6f709fcb518f73a913bdf18a5 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 1 Nov 2024 14:36:09 +0200 Subject: [PATCH 33/98] Rename ArrivalDepartureTime -> FixedArrivalDepartureTime and LegTime -> FixedArrivalDepartureTime --- .../impl/CombinedInterlinedTransitLeg.java | 6 ++-- .../ext/flex/FlexibleTransitLeg.java | 10 +++--- .../FixedStopTimeOnServiceDateImpl.java | 14 ++++---- .../apis/gtfs/datafetchers/LegImpl.java | 6 ++-- .../apis/gtfs/datafetchers/PlaceImpl.java | 6 ++-- .../gtfs/generated/GraphQLDataFetchers.java | 35 +++++++++---------- .../apis/gtfs/generated/graphql-codegen.yml | 4 +-- .../apis/gtfs/model/ArrivalDepartureTime.java | 29 --------------- ...me.java => FixedArrivalDepartureTime.java} | 21 +++++++---- .../model/plan/FrequencyTransitLeg.java | 8 +++-- .../org/opentripplanner/model/plan/Leg.java | 4 +-- .../model/plan/ScheduledTransitLeg.java | 12 +++---- .../model/plan/StopArrival.java | 8 ++--- .../model/plan/StopArrivalMapper.java | 8 ++--- .../opentripplanner/model/plan/StreetLeg.java | 8 ++--- .../model/plan/UnknownTransitPathLeg.java | 8 ++--- .../opentripplanner/apis/gtfs/schema.graphqls | 30 ++++++++-------- 17 files changed, 99 insertions(+), 118 deletions(-) delete mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java rename application/src/main/java/org/opentripplanner/model/plan/{LegTime.java => FixedArrivalDepartureTime.java} (61%) diff --git a/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java b/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java index d3608ccf8d9..5d27ea650ed 100644 --- a/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java +++ b/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java @@ -10,7 +10,7 @@ import org.opentripplanner.framework.collection.ListUtils; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.LegTime; +import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.TransitLeg; @@ -55,12 +55,12 @@ public Trip getTrip() { } @Override - public LegTime start() { + public FixedArrivalDepartureTime start() { return first.start(); } @Override - public LegTime end() { + public FixedArrivalDepartureTime end() { return second.end(); } diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java index cf6c229c46f..14988f4cdc2 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java @@ -15,7 +15,7 @@ import org.opentripplanner.model.PickDrop; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.LegTime; +import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.TransitLeg; @@ -87,13 +87,13 @@ public Accessibility getTripWheelchairAccessibility() { } @Override - public LegTime start() { - return LegTime.ofStatic(startTime); + public FixedArrivalDepartureTime start() { + return FixedArrivalDepartureTime.ofStatic(startTime); } @Override - public LegTime end() { - return LegTime.ofStatic(endTime); + public FixedArrivalDepartureTime end() { + return FixedArrivalDepartureTime.ofStatic(endTime); } @Override diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java index f6e8c62b223..a7551e487f5 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java @@ -7,16 +7,16 @@ import java.time.ZonedDateTime; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; -import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.TripTimeOnDate; +import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.transit.service.TransitService; public class FixedStopTimeOnServiceDateImpl implements GraphQLDataFetchers.GraphQLFixedStopTimeOnServiceDate { @Override - public DataFetcher arrival() { + public DataFetcher arrival() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledArrival()); @@ -24,13 +24,13 @@ public DataFetcher arrival() { return null; } return tripTime.isRealtime() - ? ArrivalDepartureTime.of(scheduledTime, tripTime.getArrivalDelay()) - : ArrivalDepartureTime.ofStatic(scheduledTime); + ? FixedArrivalDepartureTime.of(scheduledTime, tripTime.getArrivalDelay()) + : FixedArrivalDepartureTime.ofStatic(scheduledTime); }; } @Override - public DataFetcher departure() { + public DataFetcher departure() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledDeparture()); @@ -38,8 +38,8 @@ public DataFetcher departure() { return null; } return tripTime.isRealtime() - ? ArrivalDepartureTime.of(scheduledTime, tripTime.getDepartureDelay()) - : ArrivalDepartureTime.ofStatic(scheduledTime); + ? FixedArrivalDepartureTime.of(scheduledTime, tripTime.getDepartureDelay()) + : FixedArrivalDepartureTime.ofStatic(scheduledTime); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java index 4db347ee784..59fc154a7c4 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java @@ -17,8 +17,8 @@ import org.opentripplanner.ext.ridehailing.model.RideHailingLeg; import org.opentripplanner.framework.graphql.GraphQLUtils; import org.opentripplanner.model.fare.FareProductUse; +import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.LegTime; import org.opentripplanner.model.plan.ScheduledTransitLeg; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.StreetLeg; @@ -81,7 +81,7 @@ public DataFetcher duration() { } @Override - public DataFetcher end() { + public DataFetcher end() { return environment -> getSource(environment).end(); } @@ -227,7 +227,7 @@ public DataFetcher serviceDate() { } @Override - public DataFetcher start() { + public DataFetcher start() { return environment -> getSource(environment).start(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java index 145321f809c..5c8cc44147a 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java @@ -7,7 +7,7 @@ import org.opentripplanner.apis.gtfs.model.StopPosition; import org.opentripplanner.apis.gtfs.model.StopPosition.PositionAtStop; import org.opentripplanner.framework.graphql.GraphQLUtils; -import org.opentripplanner.model.plan.LegTime; +import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.VertexType; @@ -19,7 +19,7 @@ public class PlaceImpl implements GraphQLDataFetchers.GraphQLPlace { @Override - public DataFetcher arrival() { + public DataFetcher arrival() { return environment -> getSource(environment).arrival; } @@ -58,7 +58,7 @@ public DataFetcher carPark() { @Deprecated @Override - public DataFetcher departure() { + public DataFetcher departure() { return environment -> getSource(environment).departure; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 60e0b1e3fbc..7053e185d70 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -23,7 +23,6 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRelativeDirection; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; -import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; import org.opentripplanner.apis.gtfs.model.FeedPublisher; import org.opentripplanner.apis.gtfs.model.PlanPageInfo; import org.opentripplanner.apis.gtfs.model.RideHailingProvider; @@ -40,9 +39,9 @@ import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.fare.RiderCategory; import org.opentripplanner.model.plan.Emissions; +import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.LegTime; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.WalkStep; import org.opentripplanner.routing.alertpatch.TransitAlert; @@ -143,16 +142,6 @@ public interface GraphQLAlert { /** Entity related to an alert */ public interface GraphQLAlertEntity extends TypeResolver {} - /** - * Timing of an arrival or a departure to or from a stop. May contain real-time information if - * available. - */ - public interface GraphQLArrivalDepartureTime { - public DataFetcher estimated(); - - public DataFetcher scheduledTime(); - } - /** Bike park represents a location where bicycles can be parked. */ public interface GraphQLBikePark { public DataFetcher bikeParkId(); @@ -421,14 +410,24 @@ public interface GraphQLFeedPublisher { public DataFetcher url(); } + /** + * Timing of an arrival or a departure to or from a stop. May contain real-time information if + * available. This is used when there is a known scheduled time. + */ + public interface GraphQLFixedArrivalDepartureTime { + public DataFetcher estimated(); + + public DataFetcher scheduledTime(); + } + /** * Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. * This can include realtime estimates. */ public interface GraphQLFixedStopTimeOnServiceDate { - public DataFetcher arrival(); + public DataFetcher arrival(); - public DataFetcher departure(); + public DataFetcher departure(); public DataFetcher stop(); } @@ -509,7 +508,7 @@ public interface GraphQLLeg { public DataFetcher duration(); - public DataFetcher end(); + public DataFetcher end(); public DataFetcher endTime(); @@ -553,7 +552,7 @@ public interface GraphQLLeg { public DataFetcher serviceDate(); - public DataFetcher start(); + public DataFetcher start(); public DataFetcher startTime(); @@ -661,7 +660,7 @@ public interface GraphQLPattern { } public interface GraphQLPlace { - public DataFetcher arrival(); + public DataFetcher arrival(); public DataFetcher arrivalTime(); @@ -671,7 +670,7 @@ public interface GraphQLPlace { public DataFetcher carPark(); - public DataFetcher departure(); + public DataFetcher departure(); public DataFetcher departureTime(); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 66b701c5e01..5b02cd86f89 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -63,7 +63,7 @@ config: FixedTripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate TripOnServiceDateConnection: graphql.relay.Connection#Connection TripOnServiceDateEdge: graphql.relay.Edge#Edge - ArrivalDepartureTime: org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime#ArrivalDepartureTime + FixedArrivalDepartureTime: org.opentripplanner.model.plan.FixedArrivalDepartureTime#FixedArrivalDepartureTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step @@ -74,7 +74,7 @@ config: InputField: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLInputField#GraphQLInputField Itinerary: org.opentripplanner.model.plan.Itinerary#Itinerary Leg: org.opentripplanner.model.plan.Leg#Leg - LegTime: org.opentripplanner.model.plan.LegTime#LegTime + LegTime: org.opentripplanner.model.plan.FixedArrivalDepartureTime#FixedArrivalDepartureTime Mode: String OccupancyStatus: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLOccupancyStatus#GraphQLOccupancyStatus TransitMode: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode#GraphQLTransitMode diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java b/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java deleted file mode 100644 index 3a801537dd1..00000000000 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.opentripplanner.apis.gtfs.model; - -import java.time.Duration; -import java.time.ZonedDateTime; -import javax.annotation.Nullable; - -/** - * Timing of an arrival or a departure to or from a stop. May contain real-time information - * if available. - */ -public record ArrivalDepartureTime( - ZonedDateTime scheduledTime, - @Nullable RealTimeEstimate estimated -) { - public static ArrivalDepartureTime of(ZonedDateTime realtime, int delaySecs) { - var delay = Duration.ofSeconds(delaySecs); - return new ArrivalDepartureTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); - } - - public static ArrivalDepartureTime ofStatic(ZonedDateTime staticTime) { - return new ArrivalDepartureTime(staticTime, null); - } - - /** - * Realtime information about a vehicle at a certain place. - * @param delay Delay or "earliness" of a vehicle. Earliness is expressed as a negative number. - */ - record RealTimeEstimate(ZonedDateTime time, Duration delay) {} -} diff --git a/application/src/main/java/org/opentripplanner/model/plan/LegTime.java b/application/src/main/java/org/opentripplanner/model/plan/FixedArrivalDepartureTime.java similarity index 61% rename from application/src/main/java/org/opentripplanner/model/plan/LegTime.java rename to application/src/main/java/org/opentripplanner/model/plan/FixedArrivalDepartureTime.java index 71ced95942a..f27644b59a6 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/LegTime.java +++ b/application/src/main/java/org/opentripplanner/model/plan/FixedArrivalDepartureTime.java @@ -6,20 +6,27 @@ import javax.annotation.Nullable; /** - * A scheduled time of a transit vehicle at a certain location with a optional realtime information. + * A scheduled time of a transit vehicle at a certain location with an optional realtime + * information. */ -public record LegTime(ZonedDateTime scheduledTime, @Nullable RealTimeEstimate estimated) { - public LegTime { +public record FixedArrivalDepartureTime( + ZonedDateTime scheduledTime, + @Nullable RealTimeEstimate estimated +) { + public FixedArrivalDepartureTime { Objects.requireNonNull(scheduledTime); } - public static LegTime of(ZonedDateTime realtime, int delaySecs) { + public static FixedArrivalDepartureTime of(ZonedDateTime realtime, int delaySecs) { var delay = Duration.ofSeconds(delaySecs); - return new LegTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); + return new FixedArrivalDepartureTime( + realtime.minus(delay), + new RealTimeEstimate(realtime, delay) + ); } - public static LegTime ofStatic(ZonedDateTime staticTime) { - return new LegTime(staticTime, null); + public static FixedArrivalDepartureTime ofStatic(ZonedDateTime staticTime) { + return new FixedArrivalDepartureTime(staticTime, null); } /** diff --git a/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java b/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java index 48c4b1b7b87..19a2ce2c491 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java @@ -55,8 +55,12 @@ public List getIntermediateStops() { StopArrival visit = new StopArrival( Place.forStop(stop), - LegTime.ofStatic(ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, arrivalTime)), - LegTime.ofStatic(ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, departureTime)), + FixedArrivalDepartureTime.ofStatic( + ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, arrivalTime) + ), + FixedArrivalDepartureTime.ofStatic( + ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, departureTime) + ), i, tripTimes.gtfsSequenceOfStopIndex(i) ); diff --git a/application/src/main/java/org/opentripplanner/model/plan/Leg.java b/application/src/main/java/org/opentripplanner/model/plan/Leg.java index 2a4483d7cd2..718b3ba5360 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/Leg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/Leg.java @@ -209,12 +209,12 @@ default Accessibility getTripWheelchairAccessibility() { /** * The time (including realtime information) when the leg starts. */ - LegTime start(); + FixedArrivalDepartureTime start(); /** * The time (including realtime information) when the leg ends. */ - LegTime end(); + FixedArrivalDepartureTime end(); /** * The date and time this leg begins. diff --git a/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java b/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java index 068d6675eec..784232a5060 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java @@ -161,20 +161,20 @@ public Accessibility getTripWheelchairAccessibility() { } @Override - public LegTime start() { + public FixedArrivalDepartureTime start() { if (isRealTimeUpdated()) { - return LegTime.of(startTime, getDepartureDelay()); + return FixedArrivalDepartureTime.of(startTime, getDepartureDelay()); } else { - return LegTime.ofStatic(startTime); + return FixedArrivalDepartureTime.ofStatic(startTime); } } @Override - public LegTime end() { + public FixedArrivalDepartureTime end() { if (isRealTimeUpdated()) { - return LegTime.of(endTime, getArrivalDelay()); + return FixedArrivalDepartureTime.of(endTime, getArrivalDelay()); } else { - return LegTime.ofStatic(endTime); + return FixedArrivalDepartureTime.ofStatic(endTime); } } diff --git a/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java b/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java index 489b122da09..bd0bc52cd6e 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java @@ -9,8 +9,8 @@ public final class StopArrival { public final Place place; - public final LegTime arrival; - public final LegTime departure; + public final FixedArrivalDepartureTime arrival; + public final FixedArrivalDepartureTime departure; public final Integer stopPosInPattern; public final Integer gtfsStopSequence; @@ -24,8 +24,8 @@ public final class StopArrival { */ public StopArrival( Place place, - LegTime arrival, - LegTime departure, + FixedArrivalDepartureTime arrival, + FixedArrivalDepartureTime departure, Integer stopPosInPattern, Integer gtfsStopSequence ) { diff --git a/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java b/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java index 25bab2a7c3f..23d75df357c 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java @@ -34,12 +34,12 @@ StopArrival map(int i, StopLocation stop, boolean realTime) { tripTimes.getDepartureTime(i) ); - var arrival = LegTime.ofStatic(arrivalTime); - var departure = LegTime.ofStatic(departureTime); + var arrival = FixedArrivalDepartureTime.ofStatic(arrivalTime); + var departure = FixedArrivalDepartureTime.ofStatic(departureTime); if (realTime) { - arrival = LegTime.of(arrivalTime, tripTimes.getArrivalDelay(i)); - departure = LegTime.of(departureTime, tripTimes.getDepartureDelay(i)); + arrival = FixedArrivalDepartureTime.of(arrivalTime, tripTimes.getArrivalDelay(i)); + departure = FixedArrivalDepartureTime.of(departureTime, tripTimes.getDepartureDelay(i)); } return new StopArrival( diff --git a/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java b/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java index 6384159a4ec..15dfda93079 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java @@ -157,13 +157,13 @@ public boolean hasSameMode(Leg other) { } @Override - public LegTime start() { - return LegTime.ofStatic(startTime); + public FixedArrivalDepartureTime start() { + return FixedArrivalDepartureTime.ofStatic(startTime); } @Override - public LegTime end() { - return LegTime.ofStatic(endTime); + public FixedArrivalDepartureTime end() { + return FixedArrivalDepartureTime.ofStatic(endTime); } @Override diff --git a/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java b/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java index 76179a8ee7c..c6ec7f8c45b 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java @@ -70,13 +70,13 @@ public boolean hasSameMode(Leg other) { } @Override - public LegTime start() { - return LegTime.ofStatic(startTime); + public FixedArrivalDepartureTime start() { + return FixedArrivalDepartureTime.ofStatic(startTime); } @Override - public LegTime end() { - return LegTime.ofStatic(endTime); + public FixedArrivalDepartureTime end() { + return FixedArrivalDepartureTime.ofStatic(endTime); } @Override diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 4cfe9fa6fd0..da7bec99199 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -157,17 +157,6 @@ type Alert implements Node { trip: Trip @deprecated(reason : "Alert can have multiple affected entities now instead of there being duplicate alerts\nfor different entities. This will return only one of the affected trips.\nUse entities instead.") } -""" -Timing of an arrival or a departure to or from a stop. May contain real-time information if -available. -""" -type ArrivalDepartureTime { - "The estimated time of the event. If no real-time information is available, this is null." - estimated: RealTimeEstimate - "The scheduled time of the event." - scheduledTime: OffsetDateTime! -} - "Bike park represents a location where bicycles can be parked." type BikePark implements Node & PlaceInterface { "ID of the bike park" @@ -550,21 +539,34 @@ type FeedPublisher { url: String! } +""" +Timing of an arrival or a departure to or from a stop. May contain real-time information if +available. This is used when there is a known scheduled time. +""" +type FixedArrivalDepartureTime { + "The estimated time of the event. If no real-time information is available, this is null." + estimated: RealTimeEstimate + "The scheduled time of the event." + scheduledTime: OffsetDateTime! +} + """ Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. This can include realtime estimates. """ type FixedStopTimeOnServiceDate { "Scheduled arrival time to the stop and a realtime estimate, if one exists." - arrival: ArrivalDepartureTime + arrival: FixedArrivalDepartureTime "Scheduled departure time from the stop and a realtime estimate, if one exists." - departure: ArrivalDepartureTime + departure: FixedArrivalDepartureTime "The stop where this arrival/departure happens" stop: Stop } "A fixed (i.e. not flexible or frequency based) trip on a specific service date" type FixedTripOnServiceDate { + "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." + end: FixedStopTimeOnServiceDate! """ The service date when the trip occurs. @@ -573,8 +575,6 @@ type FixedTripOnServiceDate { on Sunday morning at 1am to 3am, might have the previous Saturday's service date. """ serviceDate: LocalDate! - "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." - end: FixedStopTimeOnServiceDate! "Information related to trip's scheduled departure from the first stop. Can contain realtime information." start: FixedStopTimeOnServiceDate! "List of times when this trip arrives to or departs from a stop and information related to the stop" From 672a96830d0614f198334460bc52f58e29ee902c Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Wed, 13 Nov 2024 15:17:02 +0200 Subject: [PATCH 34/98] Make TripOnServiceDate an interface and rename some types --- .../impl/CombinedInterlinedTransitLeg.java | 6 +- .../ext/flex/FlexibleTransitLeg.java | 10 +- .../apis/gtfs/GtfsGraphQLIndex.java | 8 +- .../apis/gtfs/datafetchers/LegImpl.java | 6 +- .../apis/gtfs/datafetchers/PlaceImpl.java | 6 +- ....java => RegularRealTimeStopTimeImpl.java} | 18 +-- ...java => RegularTripOnServiceDateImpl.java} | 4 +- .../TripOnServiceDateTypeResolver.java | 2 +- .../gtfs/generated/GraphQLDataFetchers.java | 86 ++++++++------- .../apis/gtfs/generated/graphql-codegen.yml | 8 +- .../model/plan/FrequencyTransitLeg.java | 4 +- .../org/opentripplanner/model/plan/Leg.java | 4 +- ....java => RegularArrivalDepartureTime.java} | 12 +- .../model/plan/ScheduledTransitLeg.java | 12 +- .../model/plan/StopArrival.java | 8 +- .../model/plan/StopArrivalMapper.java | 8 +- .../opentripplanner/model/plan/StreetLeg.java | 8 +- .../model/plan/UnknownTransitPathLeg.java | 8 +- .../opentripplanner/apis/gtfs/schema.graphqls | 103 ++++++++++-------- .../apis/gtfs/queries/canceled-trips.graphql | 2 +- 20 files changed, 168 insertions(+), 155 deletions(-) rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{FixedStopTimeOnServiceDateImpl.java => RegularRealTimeStopTimeImpl.java} (76%) rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{FixedTripOnServiceDateImpl.java => RegularTripOnServiceDateImpl.java} (97%) rename application/src/main/java/org/opentripplanner/model/plan/{FixedArrivalDepartureTime.java => RegularArrivalDepartureTime.java} (74%) diff --git a/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java b/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java index 5d27ea650ed..a53c3a689c2 100644 --- a/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java +++ b/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java @@ -10,7 +10,7 @@ import org.opentripplanner.framework.collection.ListUtils; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.FixedArrivalDepartureTime; +import org.opentripplanner.model.plan.RegularArrivalDepartureTime; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.TransitLeg; @@ -55,12 +55,12 @@ public Trip getTrip() { } @Override - public FixedArrivalDepartureTime start() { + public RegularArrivalDepartureTime start() { return first.start(); } @Override - public FixedArrivalDepartureTime end() { + public RegularArrivalDepartureTime end() { return second.end(); } diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java index 14988f4cdc2..9c59da7d39f 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java @@ -15,7 +15,7 @@ import org.opentripplanner.model.PickDrop; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.FixedArrivalDepartureTime; +import org.opentripplanner.model.plan.RegularArrivalDepartureTime; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.TransitLeg; @@ -87,13 +87,13 @@ public Accessibility getTripWheelchairAccessibility() { } @Override - public FixedArrivalDepartureTime start() { - return FixedArrivalDepartureTime.ofStatic(startTime); + public RegularArrivalDepartureTime start() { + return RegularArrivalDepartureTime.ofStatic(startTime); } @Override - public FixedArrivalDepartureTime end() { - return FixedArrivalDepartureTime.ofStatic(endTime); + public RegularArrivalDepartureTime end() { + return RegularArrivalDepartureTime.ofStatic(endTime); } @Override diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index 9aeed1e9472..014acb97398 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -40,8 +40,6 @@ import org.opentripplanner.apis.gtfs.datafetchers.FareProductTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.FareProductUseImpl; import org.opentripplanner.apis.gtfs.datafetchers.FeedImpl; -import org.opentripplanner.apis.gtfs.datafetchers.FixedStopTimeOnServiceDateImpl; -import org.opentripplanner.apis.gtfs.datafetchers.FixedTripOnServiceDateImpl; import org.opentripplanner.apis.gtfs.datafetchers.GeometryImpl; import org.opentripplanner.apis.gtfs.datafetchers.ItineraryImpl; import org.opentripplanner.apis.gtfs.datafetchers.LegImpl; @@ -54,6 +52,8 @@ import org.opentripplanner.apis.gtfs.datafetchers.PlanConnectionImpl; import org.opentripplanner.apis.gtfs.datafetchers.PlanImpl; import org.opentripplanner.apis.gtfs.datafetchers.QueryTypeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.RegularRealTimeStopTimeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.RegularTripOnServiceDateImpl; import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleImpl; import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleTypeImpl; import org.opentripplanner.apis.gtfs.datafetchers.RideHailingEstimateImpl; @@ -182,8 +182,8 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(CurrencyImpl.class)) .type(typeWiring.build(FareProductUseImpl.class)) .type(typeWiring.build(DefaultFareProductImpl.class)) - .type(typeWiring.build(FixedTripOnServiceDateImpl.class)) - .type(typeWiring.build(FixedStopTimeOnServiceDateImpl.class)) + .type(typeWiring.build(RegularTripOnServiceDateImpl.class)) + .type(typeWiring.build(RegularRealTimeStopTimeImpl.class)) .type(typeWiring.build(TripOccupancyImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java index 59fc154a7c4..c90339f1016 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java @@ -17,8 +17,8 @@ import org.opentripplanner.ext.ridehailing.model.RideHailingLeg; import org.opentripplanner.framework.graphql.GraphQLUtils; import org.opentripplanner.model.fare.FareProductUse; -import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Leg; +import org.opentripplanner.model.plan.RegularArrivalDepartureTime; import org.opentripplanner.model.plan.ScheduledTransitLeg; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.StreetLeg; @@ -81,7 +81,7 @@ public DataFetcher duration() { } @Override - public DataFetcher end() { + public DataFetcher end() { return environment -> getSource(environment).end(); } @@ -227,7 +227,7 @@ public DataFetcher serviceDate() { } @Override - public DataFetcher start() { + public DataFetcher start() { return environment -> getSource(environment).start(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java index 5c8cc44147a..b732bb14887 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java @@ -7,8 +7,8 @@ import org.opentripplanner.apis.gtfs.model.StopPosition; import org.opentripplanner.apis.gtfs.model.StopPosition.PositionAtStop; import org.opentripplanner.framework.graphql.GraphQLUtils; -import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Place; +import org.opentripplanner.model.plan.RegularArrivalDepartureTime; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.VertexType; import org.opentripplanner.routing.vehicle_parking.VehicleParking; @@ -19,7 +19,7 @@ public class PlaceImpl implements GraphQLDataFetchers.GraphQLPlace { @Override - public DataFetcher arrival() { + public DataFetcher arrival() { return environment -> getSource(environment).arrival; } @@ -58,7 +58,7 @@ public DataFetcher carPark() { @Deprecated @Override - public DataFetcher departure() { + public DataFetcher departure() { return environment -> getSource(environment).departure; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java similarity index 76% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java index a7551e487f5..2f524bdea34 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedStopTimeOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java @@ -9,14 +9,14 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.TripTimeOnDate; -import org.opentripplanner.model.plan.FixedArrivalDepartureTime; +import org.opentripplanner.model.plan.RegularArrivalDepartureTime; import org.opentripplanner.transit.service.TransitService; -public class FixedStopTimeOnServiceDateImpl - implements GraphQLDataFetchers.GraphQLFixedStopTimeOnServiceDate { +public class RegularRealTimeStopTimeImpl + implements GraphQLDataFetchers.GraphQLRegularRealTimeStopTime { @Override - public DataFetcher arrival() { + public DataFetcher arrival() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledArrival()); @@ -24,13 +24,13 @@ public DataFetcher arrival() { return null; } return tripTime.isRealtime() - ? FixedArrivalDepartureTime.of(scheduledTime, tripTime.getArrivalDelay()) - : FixedArrivalDepartureTime.ofStatic(scheduledTime); + ? RegularArrivalDepartureTime.of(scheduledTime, tripTime.getArrivalDelay()) + : RegularArrivalDepartureTime.ofStatic(scheduledTime); }; } @Override - public DataFetcher departure() { + public DataFetcher departure() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledDeparture()); @@ -38,8 +38,8 @@ public DataFetcher departure() { return null; } return tripTime.isRealtime() - ? FixedArrivalDepartureTime.of(scheduledTime, tripTime.getDepartureDelay()) - : FixedArrivalDepartureTime.ofStatic(scheduledTime); + ? RegularArrivalDepartureTime.of(scheduledTime, tripTime.getDepartureDelay()) + : RegularArrivalDepartureTime.ofStatic(scheduledTime); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularTripOnServiceDateImpl.java similarity index 97% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularTripOnServiceDateImpl.java index c34c25e3f1d..54cda759fd4 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FixedTripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularTripOnServiceDateImpl.java @@ -16,8 +16,8 @@ import org.opentripplanner.transit.model.timetable.TripOnServiceDate; import org.opentripplanner.transit.service.TransitService; -public class FixedTripOnServiceDateImpl - implements GraphQLDataFetchers.GraphQLFixedTripOnServiceDate { +public class RegularTripOnServiceDateImpl + implements GraphQLDataFetchers.GraphQLRegularTripOnServiceDate { @Override public DataFetcher serviceDate() { diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java index aaf8d6dae14..570177768f0 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java @@ -14,7 +14,7 @@ public GraphQLObjectType getType(TypeResolutionEnvironment environment) { GraphQLSchema schema = environment.getSchema(); if (o instanceof TripOnServiceDate) { - return schema.getObjectType("FixedTripOnServiceDate"); + return schema.getObjectType("RegularTripOnServiceDate"); } return null; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 7053e185d70..f89a94f7a31 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -39,9 +39,9 @@ import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.fare.RiderCategory; import org.opentripplanner.model.plan.Emissions; -import org.opentripplanner.model.plan.FixedArrivalDepartureTime; import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.Leg; +import org.opentripplanner.model.plan.RegularArrivalDepartureTime; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.WalkStep; import org.opentripplanner.routing.alertpatch.TransitAlert; @@ -410,41 +410,6 @@ public interface GraphQLFeedPublisher { public DataFetcher url(); } - /** - * Timing of an arrival or a departure to or from a stop. May contain real-time information if - * available. This is used when there is a known scheduled time. - */ - public interface GraphQLFixedArrivalDepartureTime { - public DataFetcher estimated(); - - public DataFetcher scheduledTime(); - } - - /** - * Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. - * This can include realtime estimates. - */ - public interface GraphQLFixedStopTimeOnServiceDate { - public DataFetcher arrival(); - - public DataFetcher departure(); - - public DataFetcher stop(); - } - - /** A fixed (i.e. not flexible or frequency based) trip on a specific service date */ - public interface GraphQLFixedTripOnServiceDate { - public DataFetcher end(); - - public DataFetcher serviceDate(); - - public DataFetcher start(); - - public DataFetcher> stopTimes(); - - public DataFetcher trip(); - } - public interface GraphQLGeometry { public DataFetcher length(); @@ -508,7 +473,7 @@ public interface GraphQLLeg { public DataFetcher duration(); - public DataFetcher end(); + public DataFetcher end(); public DataFetcher endTime(); @@ -552,7 +517,7 @@ public interface GraphQLLeg { public DataFetcher serviceDate(); - public DataFetcher start(); + public DataFetcher start(); public DataFetcher startTime(); @@ -660,7 +625,7 @@ public interface GraphQLPattern { } public interface GraphQLPlace { - public DataFetcher arrival(); + public DataFetcher arrival(); public DataFetcher arrivalTime(); @@ -670,7 +635,7 @@ public interface GraphQLPlace { public DataFetcher carPark(); - public DataFetcher departure(); + public DataFetcher departure(); public DataFetcher departureTime(); @@ -881,6 +846,41 @@ public interface GraphQLRealTimeEstimate { public DataFetcher time(); } + /** + * Timing of an arrival or a departure to or from a stop. May contain real-time information if + * available. This is used when there is a known scheduled time. + */ + public interface GraphQLRegularRealTimeArrivalDepartureTime { + public DataFetcher estimated(); + + public DataFetcher scheduledTime(); + } + + /** + * Regular real-time stop time represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. + * This can include real-time estimates. + */ + public interface GraphQLRegularRealTimeStopTime { + public DataFetcher arrival(); + + public DataFetcher departure(); + + public DataFetcher stop(); + } + + /** A regular (i.e. not flexible) trip on a specific service date */ + public interface GraphQLRegularTripOnServiceDate { + public DataFetcher end(); + + public DataFetcher serviceDate(); + + public DataFetcher start(); + + public DataFetcher> stopTimes(); + + public DataFetcher trip(); + } + /** Rental vehicle represents a vehicle that belongs to a rental network. */ public interface GraphQLRentalVehicle { public DataFetcher allowPickupNow(); @@ -1240,7 +1240,11 @@ public interface GraphQLTripOccupancy { } /** An instance of a trip on a service date. */ - public interface GraphQLTripOnServiceDate extends TypeResolver {} + public interface GraphQLTripOnServiceDate extends TypeResolver { + public default DataFetcher serviceDate() { + return null; + } + } /** * A connection to a list of trips on service dates that follows diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 5b02cd86f89..1df05e0fb5a 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -59,11 +59,11 @@ config: ContactInfo: org.opentripplanner.transit.model.organization.ContactInfo Cluster: Object Coordinates: org.locationtech.jts.geom.Coordinate#Coordinate - FixedStopTimeOnServiceDate: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate - FixedTripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate + RegularRealTimeStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate + RegularTripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate TripOnServiceDateConnection: graphql.relay.Connection#Connection TripOnServiceDateEdge: graphql.relay.Edge#Edge - FixedArrivalDepartureTime: org.opentripplanner.model.plan.FixedArrivalDepartureTime#FixedArrivalDepartureTime + RegularRealTimeArrivalDepartureTime: org.opentripplanner.model.plan.RegularArrivalDepartureTime#RegularArrivalDepartureTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step @@ -74,7 +74,7 @@ config: InputField: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLInputField#GraphQLInputField Itinerary: org.opentripplanner.model.plan.Itinerary#Itinerary Leg: org.opentripplanner.model.plan.Leg#Leg - LegTime: org.opentripplanner.model.plan.FixedArrivalDepartureTime#FixedArrivalDepartureTime + LegTime: org.opentripplanner.model.plan.RegularArrivalDepartureTime#RegularArrivalDepartureTime Mode: String OccupancyStatus: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLOccupancyStatus#GraphQLOccupancyStatus TransitMode: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode#GraphQLTransitMode diff --git a/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java b/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java index 19a2ce2c491..042cb3ccb87 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java @@ -55,10 +55,10 @@ public List getIntermediateStops() { StopArrival visit = new StopArrival( Place.forStop(stop), - FixedArrivalDepartureTime.ofStatic( + RegularArrivalDepartureTime.ofStatic( ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, arrivalTime) ), - FixedArrivalDepartureTime.ofStatic( + RegularArrivalDepartureTime.ofStatic( ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, departureTime) ), i, diff --git a/application/src/main/java/org/opentripplanner/model/plan/Leg.java b/application/src/main/java/org/opentripplanner/model/plan/Leg.java index 718b3ba5360..18b4c04fc1f 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/Leg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/Leg.java @@ -209,12 +209,12 @@ default Accessibility getTripWheelchairAccessibility() { /** * The time (including realtime information) when the leg starts. */ - FixedArrivalDepartureTime start(); + RegularArrivalDepartureTime start(); /** * The time (including realtime information) when the leg ends. */ - FixedArrivalDepartureTime end(); + RegularArrivalDepartureTime end(); /** * The date and time this leg begins. diff --git a/application/src/main/java/org/opentripplanner/model/plan/FixedArrivalDepartureTime.java b/application/src/main/java/org/opentripplanner/model/plan/RegularArrivalDepartureTime.java similarity index 74% rename from application/src/main/java/org/opentripplanner/model/plan/FixedArrivalDepartureTime.java rename to application/src/main/java/org/opentripplanner/model/plan/RegularArrivalDepartureTime.java index f27644b59a6..370e91934e1 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/FixedArrivalDepartureTime.java +++ b/application/src/main/java/org/opentripplanner/model/plan/RegularArrivalDepartureTime.java @@ -9,24 +9,24 @@ * A scheduled time of a transit vehicle at a certain location with an optional realtime * information. */ -public record FixedArrivalDepartureTime( +public record RegularArrivalDepartureTime( ZonedDateTime scheduledTime, @Nullable RealTimeEstimate estimated ) { - public FixedArrivalDepartureTime { + public RegularArrivalDepartureTime { Objects.requireNonNull(scheduledTime); } - public static FixedArrivalDepartureTime of(ZonedDateTime realtime, int delaySecs) { + public static RegularArrivalDepartureTime of(ZonedDateTime realtime, int delaySecs) { var delay = Duration.ofSeconds(delaySecs); - return new FixedArrivalDepartureTime( + return new RegularArrivalDepartureTime( realtime.minus(delay), new RealTimeEstimate(realtime, delay) ); } - public static FixedArrivalDepartureTime ofStatic(ZonedDateTime staticTime) { - return new FixedArrivalDepartureTime(staticTime, null); + public static RegularArrivalDepartureTime ofStatic(ZonedDateTime staticTime) { + return new RegularArrivalDepartureTime(staticTime, null); } /** diff --git a/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java b/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java index 784232a5060..07c69765af7 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java @@ -161,20 +161,20 @@ public Accessibility getTripWheelchairAccessibility() { } @Override - public FixedArrivalDepartureTime start() { + public RegularArrivalDepartureTime start() { if (isRealTimeUpdated()) { - return FixedArrivalDepartureTime.of(startTime, getDepartureDelay()); + return RegularArrivalDepartureTime.of(startTime, getDepartureDelay()); } else { - return FixedArrivalDepartureTime.ofStatic(startTime); + return RegularArrivalDepartureTime.ofStatic(startTime); } } @Override - public FixedArrivalDepartureTime end() { + public RegularArrivalDepartureTime end() { if (isRealTimeUpdated()) { - return FixedArrivalDepartureTime.of(endTime, getArrivalDelay()); + return RegularArrivalDepartureTime.of(endTime, getArrivalDelay()); } else { - return FixedArrivalDepartureTime.ofStatic(endTime); + return RegularArrivalDepartureTime.ofStatic(endTime); } } diff --git a/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java b/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java index bd0bc52cd6e..d4914b0691b 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java @@ -9,8 +9,8 @@ public final class StopArrival { public final Place place; - public final FixedArrivalDepartureTime arrival; - public final FixedArrivalDepartureTime departure; + public final RegularArrivalDepartureTime arrival; + public final RegularArrivalDepartureTime departure; public final Integer stopPosInPattern; public final Integer gtfsStopSequence; @@ -24,8 +24,8 @@ public final class StopArrival { */ public StopArrival( Place place, - FixedArrivalDepartureTime arrival, - FixedArrivalDepartureTime departure, + RegularArrivalDepartureTime arrival, + RegularArrivalDepartureTime departure, Integer stopPosInPattern, Integer gtfsStopSequence ) { diff --git a/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java b/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java index 23d75df357c..5377ee809b3 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java @@ -34,12 +34,12 @@ StopArrival map(int i, StopLocation stop, boolean realTime) { tripTimes.getDepartureTime(i) ); - var arrival = FixedArrivalDepartureTime.ofStatic(arrivalTime); - var departure = FixedArrivalDepartureTime.ofStatic(departureTime); + var arrival = RegularArrivalDepartureTime.ofStatic(arrivalTime); + var departure = RegularArrivalDepartureTime.ofStatic(departureTime); if (realTime) { - arrival = FixedArrivalDepartureTime.of(arrivalTime, tripTimes.getArrivalDelay(i)); - departure = FixedArrivalDepartureTime.of(departureTime, tripTimes.getDepartureDelay(i)); + arrival = RegularArrivalDepartureTime.of(arrivalTime, tripTimes.getArrivalDelay(i)); + departure = RegularArrivalDepartureTime.of(departureTime, tripTimes.getDepartureDelay(i)); } return new StopArrival( diff --git a/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java b/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java index 15dfda93079..62e03ee0acb 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java @@ -157,13 +157,13 @@ public boolean hasSameMode(Leg other) { } @Override - public FixedArrivalDepartureTime start() { - return FixedArrivalDepartureTime.ofStatic(startTime); + public RegularArrivalDepartureTime start() { + return RegularArrivalDepartureTime.ofStatic(startTime); } @Override - public FixedArrivalDepartureTime end() { - return FixedArrivalDepartureTime.ofStatic(endTime); + public RegularArrivalDepartureTime end() { + return RegularArrivalDepartureTime.ofStatic(endTime); } @Override diff --git a/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java b/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java index c6ec7f8c45b..358cfd9fe05 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java @@ -70,13 +70,13 @@ public boolean hasSameMode(Leg other) { } @Override - public FixedArrivalDepartureTime start() { - return FixedArrivalDepartureTime.ofStatic(startTime); + public RegularArrivalDepartureTime start() { + return RegularArrivalDepartureTime.ofStatic(startTime); } @Override - public FixedArrivalDepartureTime end() { - return FixedArrivalDepartureTime.ofStatic(endTime); + public RegularArrivalDepartureTime end() { + return RegularArrivalDepartureTime.ofStatic(endTime); } @Override diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 0496bd4448c..8cbf5fb91fa 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -70,14 +70,23 @@ interface PlaceInterface { lon: Float } +"An instance of a trip on a service date." +interface TripOnServiceDate { + """ + The service date when the trip occurs. + + **Note**: A service date is a technical term useful for transit planning purposes and might not + correspond to a how a passenger thinks of a calendar date. For example, a night bus running + on Sunday morning at 1am to 3am, might have the previous Saturday's service date. + """ + serviceDate: LocalDate! +} + "Entity related to an alert" union AlertEntity = Agency | Pattern | Route | RouteType | Stop | StopOnRoute | StopOnTrip | Trip | Unknown union StopPosition = PositionAtStop | PositionBetweenStops -"An instance of a trip on a service date." -union TripOnServiceDate = FixedTripOnServiceDate - "A public transport agency" type Agency implements Node { """ @@ -539,50 +548,6 @@ type FeedPublisher { url: String! } -""" -Timing of an arrival or a departure to or from a stop. May contain real-time information if -available. This is used when there is a known scheduled time. -""" -type FixedArrivalDepartureTime { - "The estimated time of the event. If no real-time information is available, this is null." - estimated: RealTimeEstimate - "The scheduled time of the event." - scheduledTime: OffsetDateTime! -} - -""" -Exact dated stoptime represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. -This can include realtime estimates. -""" -type FixedStopTimeOnServiceDate { - "Scheduled arrival time to the stop and a realtime estimate, if one exists." - arrival: FixedArrivalDepartureTime - "Scheduled departure time from the stop and a realtime estimate, if one exists." - departure: FixedArrivalDepartureTime - "The stop where this arrival/departure happens" - stop: Stop -} - -"A fixed (i.e. not flexible or frequency based) trip on a specific service date" -type FixedTripOnServiceDate { - "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." - end: FixedStopTimeOnServiceDate! - """ - The service date when the trip occurs. - - **Note**: A service date is a technical term useful for transit planning purposes and might not - correspond to a how a passenger thinks of a calendar date. For example, a night bus running - on Sunday morning at 1am to 3am, might have the previous Saturday's service date. - """ - serviceDate: LocalDate! - "Information related to trip's scheduled departure from the first stop. Can contain realtime information." - start: FixedStopTimeOnServiceDate! - "List of times when this trip arrives to or departs from a stop and information related to the stop" - stopTimes: [FixedStopTimeOnServiceDate!]! - "This trip on service date is an instance of this trip." - trip: Trip -} - type Geometry { "The number of points in the string" length: Int @@ -1824,6 +1789,50 @@ type RealTimeEstimate { time: OffsetDateTime! } +""" +Timing of an arrival or a departure to or from a stop. May contain real-time information if +available. This is used when there is a known scheduled time. +""" +type RegularRealTimeArrivalDepartureTime { + "The estimated time of the event. If no real-time information is available, this is null." + estimated: RealTimeEstimate + "The scheduled time of the event." + scheduledTime: OffsetDateTime! +} + +""" +Regular real-time stop time represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. +This can include real-time estimates. +""" +type RegularRealTimeStopTime { + "Scheduled arrival time to the stop and a real-time estimate, if one exists." + arrival: RegularRealTimeArrivalDepartureTime + "Scheduled departure time from the stop and a real-time estimate, if one exists." + departure: RegularRealTimeArrivalDepartureTime + "The stop where this arrival/departure happens" + stop: Stop +} + +"A regular (i.e. not flexible) trip on a specific service date" +type RegularTripOnServiceDate implements TripOnServiceDate { + "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." + end: RegularRealTimeStopTime! + """ + The service date when the trip occurs. + + **Note**: A service date is a technical term useful for transit planning purposes and might not + correspond to a how a passenger thinks of a calendar date. For example, a night bus running + on Sunday morning at 1am to 3am, might have the previous Saturday's service date. + """ + serviceDate: LocalDate! + "Information related to trip's scheduled departure from the first stop. Can contain realtime information." + start: RegularRealTimeStopTime! + "List of times when this trip arrives to or departs from a stop and information related to the stop" + stopTimes: [RegularRealTimeStopTime!]! + "This trip on service date is an instance of this trip." + trip: Trip +} + "Rental vehicle represents a vehicle that belongs to a rental network." type RentalVehicle implements Node & PlaceInterface { "If true, vehicle is currently available for renting." diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index a29950f7b0e..9629c4ae418 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -8,7 +8,7 @@ } edges { node { - ... on FixedTripOnServiceDate { + ... on RegularTripOnServiceDate { serviceDate end { arrival { From 8885c193c6778ead7ad75728e2bae5c5859e27db Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Sun, 17 Nov 2024 23:46:45 +0200 Subject: [PATCH 35/98] Rename RegularArrivalDepartureTime -> LegCallTime --- .../impl/CombinedInterlinedTransitLeg.java | 6 +++--- .../ext/flex/FlexibleTransitLeg.java | 10 +++++----- .../apis/gtfs/datafetchers/LegImpl.java | 6 +++--- .../apis/gtfs/datafetchers/PlaceImpl.java | 6 +++--- .../RegularRealTimeStopTimeImpl.java | 14 ++++++------- .../gtfs/generated/GraphQLDataFetchers.java | 14 ++++++------- .../apis/gtfs/generated/graphql-codegen.yml | 4 ++-- .../model/plan/FrequencyTransitLeg.java | 8 ++------ .../org/opentripplanner/model/plan/Leg.java | 4 ++-- ...valDepartureTime.java => LegCallTime.java} | 20 +++++++------------ .../model/plan/ScheduledTransitLeg.java | 12 +++++------ .../model/plan/StopArrival.java | 8 ++++---- .../model/plan/StopArrivalMapper.java | 8 ++++---- .../opentripplanner/model/plan/StreetLeg.java | 8 ++++---- .../model/plan/UnknownTransitPathLeg.java | 8 ++++---- 15 files changed, 63 insertions(+), 73 deletions(-) rename application/src/main/java/org/opentripplanner/model/plan/{RegularArrivalDepartureTime.java => LegCallTime.java} (62%) diff --git a/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java b/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java index f41126a6a60..60d03e484df 100644 --- a/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java +++ b/application/src/ext/java/org/opentripplanner/ext/fares/impl/CombinedInterlinedTransitLeg.java @@ -9,7 +9,7 @@ import org.locationtech.jts.geom.LineString; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.RegularArrivalDepartureTime; +import org.opentripplanner.model.plan.LegCallTime; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.TransitLeg; @@ -55,12 +55,12 @@ public Trip getTrip() { } @Override - public RegularArrivalDepartureTime start() { + public LegCallTime start() { return first.start(); } @Override - public RegularArrivalDepartureTime end() { + public LegCallTime end() { return second.end(); } diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java index 39a9d0375d6..769407aa05a 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexibleTransitLeg.java @@ -13,7 +13,7 @@ import org.opentripplanner.model.PickDrop; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.RegularArrivalDepartureTime; +import org.opentripplanner.model.plan.LegCallTime; import org.opentripplanner.model.plan.Place; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.TransitLeg; @@ -87,13 +87,13 @@ public Accessibility getTripWheelchairAccessibility() { } @Override - public RegularArrivalDepartureTime start() { - return RegularArrivalDepartureTime.ofStatic(startTime); + public LegCallTime start() { + return LegCallTime.ofStatic(startTime); } @Override - public RegularArrivalDepartureTime end() { - return RegularArrivalDepartureTime.ofStatic(endTime); + public LegCallTime end() { + return LegCallTime.ofStatic(endTime); } @Override diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java index c90339f1016..fdd2609e17a 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegImpl.java @@ -18,7 +18,7 @@ import org.opentripplanner.framework.graphql.GraphQLUtils; import org.opentripplanner.model.fare.FareProductUse; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.RegularArrivalDepartureTime; +import org.opentripplanner.model.plan.LegCallTime; import org.opentripplanner.model.plan.ScheduledTransitLeg; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.StreetLeg; @@ -81,7 +81,7 @@ public DataFetcher duration() { } @Override - public DataFetcher end() { + public DataFetcher end() { return environment -> getSource(environment).end(); } @@ -227,7 +227,7 @@ public DataFetcher serviceDate() { } @Override - public DataFetcher start() { + public DataFetcher start() { return environment -> getSource(environment).start(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java index b732bb14887..e1924101b1b 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/PlaceImpl.java @@ -7,8 +7,8 @@ import org.opentripplanner.apis.gtfs.model.StopPosition; import org.opentripplanner.apis.gtfs.model.StopPosition.PositionAtStop; import org.opentripplanner.framework.graphql.GraphQLUtils; +import org.opentripplanner.model.plan.LegCallTime; import org.opentripplanner.model.plan.Place; -import org.opentripplanner.model.plan.RegularArrivalDepartureTime; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.VertexType; import org.opentripplanner.routing.vehicle_parking.VehicleParking; @@ -19,7 +19,7 @@ public class PlaceImpl implements GraphQLDataFetchers.GraphQLPlace { @Override - public DataFetcher arrival() { + public DataFetcher arrival() { return environment -> getSource(environment).arrival; } @@ -58,7 +58,7 @@ public DataFetcher carPark() { @Deprecated @Override - public DataFetcher departure() { + public DataFetcher departure() { return environment -> getSource(environment).departure; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java index 54f99b828a1..de4476f6651 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java @@ -8,7 +8,7 @@ import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.model.TripTimeOnDate; -import org.opentripplanner.model.plan.RegularArrivalDepartureTime; +import org.opentripplanner.model.plan.LegCallTime; import org.opentripplanner.transit.service.TransitService; import org.opentripplanner.utils.time.ServiceDateUtils; @@ -16,7 +16,7 @@ public class RegularRealTimeStopTimeImpl implements GraphQLDataFetchers.GraphQLRegularRealTimeStopTime { @Override - public DataFetcher arrival() { + public DataFetcher arrival() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledArrival()); @@ -24,13 +24,13 @@ public DataFetcher arrival() { return null; } return tripTime.isRealtime() - ? RegularArrivalDepartureTime.of(scheduledTime, tripTime.getArrivalDelay()) - : RegularArrivalDepartureTime.ofStatic(scheduledTime); + ? LegCallTime.of(scheduledTime, tripTime.getArrivalDelay()) + : LegCallTime.ofStatic(scheduledTime); }; } @Override - public DataFetcher departure() { + public DataFetcher departure() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledDeparture()); @@ -38,8 +38,8 @@ public DataFetcher departure() { return null; } return tripTime.isRealtime() - ? RegularArrivalDepartureTime.of(scheduledTime, tripTime.getDepartureDelay()) - : RegularArrivalDepartureTime.ofStatic(scheduledTime); + ? LegCallTime.of(scheduledTime, tripTime.getDepartureDelay()) + : LegCallTime.ofStatic(scheduledTime); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 0d06737b4e3..c2f2d236b41 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -41,7 +41,7 @@ import org.opentripplanner.model.plan.Emissions; import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.model.plan.RegularArrivalDepartureTime; +import org.opentripplanner.model.plan.LegCallTime; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.WalkStep; import org.opentripplanner.routing.alertpatch.TransitAlert; @@ -473,7 +473,7 @@ public interface GraphQLLeg { public DataFetcher duration(); - public DataFetcher end(); + public DataFetcher end(); public DataFetcher endTime(); @@ -517,7 +517,7 @@ public interface GraphQLLeg { public DataFetcher serviceDate(); - public DataFetcher start(); + public DataFetcher start(); public DataFetcher startTime(); @@ -625,7 +625,7 @@ public interface GraphQLPattern { } public interface GraphQLPlace { - public DataFetcher arrival(); + public DataFetcher arrival(); public DataFetcher arrivalTime(); @@ -635,7 +635,7 @@ public interface GraphQLPlace { public DataFetcher carPark(); - public DataFetcher departure(); + public DataFetcher departure(); public DataFetcher departureTime(); @@ -861,9 +861,9 @@ public interface GraphQLRegularRealTimeArrivalDepartureTime { * This can include real-time estimates. */ public interface GraphQLRegularRealTimeStopTime { - public DataFetcher arrival(); + public DataFetcher arrival(); - public DataFetcher departure(); + public DataFetcher departure(); public DataFetcher stop(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 1df05e0fb5a..156053ad5dc 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -63,7 +63,7 @@ config: RegularTripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate TripOnServiceDateConnection: graphql.relay.Connection#Connection TripOnServiceDateEdge: graphql.relay.Edge#Edge - RegularRealTimeArrivalDepartureTime: org.opentripplanner.model.plan.RegularArrivalDepartureTime#RegularArrivalDepartureTime + RegularRealTimeArrivalDepartureTime: org.opentripplanner.model.plan.LegCallTime#LegCallTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step @@ -74,7 +74,7 @@ config: InputField: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLInputField#GraphQLInputField Itinerary: org.opentripplanner.model.plan.Itinerary#Itinerary Leg: org.opentripplanner.model.plan.Leg#Leg - LegTime: org.opentripplanner.model.plan.RegularArrivalDepartureTime#RegularArrivalDepartureTime + LegTime: org.opentripplanner.model.plan.LegCallTime#LegCallTime Mode: String OccupancyStatus: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLOccupancyStatus#GraphQLOccupancyStatus TransitMode: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode#GraphQLTransitMode diff --git a/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java b/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java index a26b6c88951..6226b0d2b01 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/FrequencyTransitLeg.java @@ -55,12 +55,8 @@ public List getIntermediateStops() { StopArrival visit = new StopArrival( Place.forStop(stop), - RegularArrivalDepartureTime.ofStatic( - ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, arrivalTime) - ), - RegularArrivalDepartureTime.ofStatic( - ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, departureTime) - ), + LegCallTime.ofStatic(ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, arrivalTime)), + LegCallTime.ofStatic(ServiceDateUtils.toZonedDateTime(serviceDate, zoneId, departureTime)), i, tripTimes.gtfsSequenceOfStopIndex(i) ); diff --git a/application/src/main/java/org/opentripplanner/model/plan/Leg.java b/application/src/main/java/org/opentripplanner/model/plan/Leg.java index 00f1516a875..27e67400daf 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/Leg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/Leg.java @@ -209,12 +209,12 @@ default Accessibility getTripWheelchairAccessibility() { /** * The time (including realtime information) when the leg starts. */ - RegularArrivalDepartureTime start(); + LegCallTime start(); /** * The time (including realtime information) when the leg ends. */ - RegularArrivalDepartureTime end(); + LegCallTime end(); /** * The date and time this leg begins. diff --git a/application/src/main/java/org/opentripplanner/model/plan/RegularArrivalDepartureTime.java b/application/src/main/java/org/opentripplanner/model/plan/LegCallTime.java similarity index 62% rename from application/src/main/java/org/opentripplanner/model/plan/RegularArrivalDepartureTime.java rename to application/src/main/java/org/opentripplanner/model/plan/LegCallTime.java index 370e91934e1..78a6eb37694 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/RegularArrivalDepartureTime.java +++ b/application/src/main/java/org/opentripplanner/model/plan/LegCallTime.java @@ -7,26 +7,20 @@ /** * A scheduled time of a transit vehicle at a certain location with an optional realtime - * information. + * information. This is meant to be used in transit legs. */ -public record RegularArrivalDepartureTime( - ZonedDateTime scheduledTime, - @Nullable RealTimeEstimate estimated -) { - public RegularArrivalDepartureTime { +public record LegCallTime(ZonedDateTime scheduledTime, @Nullable RealTimeEstimate estimated) { + public LegCallTime { Objects.requireNonNull(scheduledTime); } - public static RegularArrivalDepartureTime of(ZonedDateTime realtime, int delaySecs) { + public static LegCallTime of(ZonedDateTime realtime, int delaySecs) { var delay = Duration.ofSeconds(delaySecs); - return new RegularArrivalDepartureTime( - realtime.minus(delay), - new RealTimeEstimate(realtime, delay) - ); + return new LegCallTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); } - public static RegularArrivalDepartureTime ofStatic(ZonedDateTime staticTime) { - return new RegularArrivalDepartureTime(staticTime, null); + public static LegCallTime ofStatic(ZonedDateTime staticTime) { + return new LegCallTime(staticTime, null); } /** diff --git a/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java b/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java index 635f9ca07d7..55e4bccfdec 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/ScheduledTransitLeg.java @@ -161,20 +161,20 @@ public Accessibility getTripWheelchairAccessibility() { } @Override - public RegularArrivalDepartureTime start() { + public LegCallTime start() { if (isRealTimeUpdated()) { - return RegularArrivalDepartureTime.of(startTime, getDepartureDelay()); + return LegCallTime.of(startTime, getDepartureDelay()); } else { - return RegularArrivalDepartureTime.ofStatic(startTime); + return LegCallTime.ofStatic(startTime); } } @Override - public RegularArrivalDepartureTime end() { + public LegCallTime end() { if (isRealTimeUpdated()) { - return RegularArrivalDepartureTime.of(endTime, getArrivalDelay()); + return LegCallTime.of(endTime, getArrivalDelay()); } else { - return RegularArrivalDepartureTime.ofStatic(endTime); + return LegCallTime.ofStatic(endTime); } } diff --git a/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java b/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java index 6d1314ad8b4..478c8eea379 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StopArrival.java @@ -9,8 +9,8 @@ public final class StopArrival { public final Place place; - public final RegularArrivalDepartureTime arrival; - public final RegularArrivalDepartureTime departure; + public final LegCallTime arrival; + public final LegCallTime departure; public final Integer stopPosInPattern; public final Integer gtfsStopSequence; @@ -24,8 +24,8 @@ public final class StopArrival { */ public StopArrival( Place place, - RegularArrivalDepartureTime arrival, - RegularArrivalDepartureTime departure, + LegCallTime arrival, + LegCallTime departure, Integer stopPosInPattern, Integer gtfsStopSequence ) { diff --git a/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java b/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java index 80f2de3de80..a4c83e10901 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StopArrivalMapper.java @@ -34,12 +34,12 @@ StopArrival map(int i, StopLocation stop, boolean realTime) { tripTimes.getDepartureTime(i) ); - var arrival = RegularArrivalDepartureTime.ofStatic(arrivalTime); - var departure = RegularArrivalDepartureTime.ofStatic(departureTime); + var arrival = LegCallTime.ofStatic(arrivalTime); + var departure = LegCallTime.ofStatic(departureTime); if (realTime) { - arrival = RegularArrivalDepartureTime.of(arrivalTime, tripTimes.getArrivalDelay(i)); - departure = RegularArrivalDepartureTime.of(departureTime, tripTimes.getDepartureDelay(i)); + arrival = LegCallTime.of(arrivalTime, tripTimes.getArrivalDelay(i)); + departure = LegCallTime.of(departureTime, tripTimes.getDepartureDelay(i)); } return new StopArrival( diff --git a/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java b/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java index fbf2114da38..cb577b9ec49 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/StreetLeg.java @@ -157,13 +157,13 @@ public boolean hasSameMode(Leg other) { } @Override - public RegularArrivalDepartureTime start() { - return RegularArrivalDepartureTime.ofStatic(startTime); + public LegCallTime start() { + return LegCallTime.ofStatic(startTime); } @Override - public RegularArrivalDepartureTime end() { - return RegularArrivalDepartureTime.ofStatic(endTime); + public LegCallTime end() { + return LegCallTime.ofStatic(endTime); } @Override diff --git a/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java b/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java index ea07d97cb16..443621b750a 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java +++ b/application/src/main/java/org/opentripplanner/model/plan/UnknownTransitPathLeg.java @@ -70,13 +70,13 @@ public boolean hasSameMode(Leg other) { } @Override - public RegularArrivalDepartureTime start() { - return RegularArrivalDepartureTime.ofStatic(startTime); + public LegCallTime start() { + return LegCallTime.ofStatic(startTime); } @Override - public RegularArrivalDepartureTime end() { - return RegularArrivalDepartureTime.ofStatic(endTime); + public LegCallTime end() { + return LegCallTime.ofStatic(endTime); } @Override From c7d6d4359c32438efbebde82383bc8363a936951 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 18 Nov 2024 00:32:16 +0200 Subject: [PATCH 36/98] Refactor LegCallTime --- .../model/plan/LegCallTime.java | 31 ++++++++++++------- .../model/plan/LegRealTimeEstimate.java | 30 ++++++++++++++++++ 2 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 application/src/main/java/org/opentripplanner/model/plan/LegRealTimeEstimate.java diff --git a/application/src/main/java/org/opentripplanner/model/plan/LegCallTime.java b/application/src/main/java/org/opentripplanner/model/plan/LegCallTime.java index 78a6eb37694..676b45c8f92 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/LegCallTime.java +++ b/application/src/main/java/org/opentripplanner/model/plan/LegCallTime.java @@ -9,20 +9,35 @@ * A scheduled time of a transit vehicle at a certain location with an optional realtime * information. This is meant to be used in transit legs. */ -public record LegCallTime(ZonedDateTime scheduledTime, @Nullable RealTimeEstimate estimated) { - public LegCallTime { - Objects.requireNonNull(scheduledTime); +public class LegCallTime { + + private final ZonedDateTime scheduledTime; + + @Nullable + private final LegRealTimeEstimate estimated; + + private LegCallTime(ZonedDateTime scheduledTime, @Nullable LegRealTimeEstimate estimated) { + this.scheduledTime = Objects.requireNonNull(scheduledTime); + this.estimated = estimated; } public static LegCallTime of(ZonedDateTime realtime, int delaySecs) { var delay = Duration.ofSeconds(delaySecs); - return new LegCallTime(realtime.minus(delay), new RealTimeEstimate(realtime, delay)); + return new LegCallTime(realtime.minus(delay), new LegRealTimeEstimate(realtime, delay)); } public static LegCallTime ofStatic(ZonedDateTime staticTime) { return new LegCallTime(staticTime, null); } + public ZonedDateTime scheduledTime() { + return scheduledTime; + } + + public LegRealTimeEstimate estimated() { + return estimated; + } + /** * The most up-to-date time available: if realtime data is available it is returned, if not then * the scheduled one is. @@ -31,13 +46,7 @@ public ZonedDateTime time() { if (estimated == null) { return scheduledTime; } else { - return estimated.time; + return estimated.time(); } } - - /** - * Realtime information about a vehicle at a certain place. - * @param delay Delay or "earliness" of a vehicle. Earliness is expressed as a negative number. - */ - record RealTimeEstimate(ZonedDateTime time, Duration delay) {} } diff --git a/application/src/main/java/org/opentripplanner/model/plan/LegRealTimeEstimate.java b/application/src/main/java/org/opentripplanner/model/plan/LegRealTimeEstimate.java new file mode 100644 index 00000000000..a924b0c22ae --- /dev/null +++ b/application/src/main/java/org/opentripplanner/model/plan/LegRealTimeEstimate.java @@ -0,0 +1,30 @@ +package org.opentripplanner.model.plan; + +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Objects; + +/** + * Realtime information about a vehicle at a certain place. Meant to be used in transit legs. + */ +public class LegRealTimeEstimate { + + private final ZonedDateTime time; + private final Duration delay; + + /** + * @param delay Delay or "earliness" of a vehicle. Earliness is expressed as a negative number. + */ + public LegRealTimeEstimate(ZonedDateTime time, Duration delay) { + this.time = Objects.requireNonNull(time); + this.delay = Objects.requireNonNull(delay); + } + + public ZonedDateTime time() { + return time; + } + + public Duration delay() { + return delay; + } +} From 178c150725b78c2ebb4e3b3c089cc6b1d33bf16d Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 18 Nov 2024 12:20:10 +0200 Subject: [PATCH 37/98] Rename StopTime -> StopCall etc. and create own model for its times --- .../apis/gtfs/GtfsGraphQLIndex.java | 15 ++- ...ellableTripOnServiceDateTypeResolver.java} | 4 +- ...imeStopTimeImpl.java => StopCallImpl.java} | 17 ++- ...teImpl.java => TripOnServiceDateImpl.java} | 5 +- .../gtfs/generated/GraphQLDataFetchers.java | 84 +++++++------ .../apis/gtfs/generated/graphql-codegen.yml | 6 +- .../model/timetable/CallRealTimeEstimate.java | 31 +++++ .../transit/model/timetable/CallTime.java | 40 ++++++ .../opentripplanner/apis/gtfs/schema.graphqls | 116 +++++++++--------- .../gtfs/expectations/canceled-trips.json | 2 +- .../apis/gtfs/queries/canceled-trips.graphql | 4 +- 11 files changed, 201 insertions(+), 123 deletions(-) rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{TripOnServiceDateTypeResolver.java => CancellableTripOnServiceDateTypeResolver.java} (79%) rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{RegularRealTimeStopTimeImpl.java => StopCallImpl.java} (79%) rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{RegularTripOnServiceDateImpl.java => TripOnServiceDateImpl.java} (95%) create mode 100644 application/src/main/java/org/opentripplanner/transit/model/timetable/CallRealTimeEstimate.java create mode 100644 application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index 014acb97398..2a7599ecfd7 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -31,6 +31,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.BikeRentalStationImpl; import org.opentripplanner.apis.gtfs.datafetchers.BookingInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.BookingTimeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.CancellableTripOnServiceDateTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.CarParkImpl; import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl; @@ -52,14 +53,13 @@ import org.opentripplanner.apis.gtfs.datafetchers.PlanConnectionImpl; import org.opentripplanner.apis.gtfs.datafetchers.PlanImpl; import org.opentripplanner.apis.gtfs.datafetchers.QueryTypeImpl; -import org.opentripplanner.apis.gtfs.datafetchers.RegularRealTimeStopTimeImpl; -import org.opentripplanner.apis.gtfs.datafetchers.RegularTripOnServiceDateImpl; import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleImpl; import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleTypeImpl; import org.opentripplanner.apis.gtfs.datafetchers.RideHailingEstimateImpl; import org.opentripplanner.apis.gtfs.datafetchers.RouteImpl; import org.opentripplanner.apis.gtfs.datafetchers.RouteTypeImpl; import org.opentripplanner.apis.gtfs.datafetchers.RoutingErrorImpl; +import org.opentripplanner.apis.gtfs.datafetchers.StopCallImpl; import org.opentripplanner.apis.gtfs.datafetchers.StopGeometriesImpl; import org.opentripplanner.apis.gtfs.datafetchers.StopImpl; import org.opentripplanner.apis.gtfs.datafetchers.StopOnRouteImpl; @@ -72,7 +72,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.TranslatedStringImpl; import org.opentripplanner.apis.gtfs.datafetchers.TripImpl; import org.opentripplanner.apis.gtfs.datafetchers.TripOccupancyImpl; -import org.opentripplanner.apis.gtfs.datafetchers.TripOnServiceDateTypeResolver; +import org.opentripplanner.apis.gtfs.datafetchers.TripOnServiceDateImpl; import org.opentripplanner.apis.gtfs.datafetchers.UnknownImpl; import org.opentripplanner.apis.gtfs.datafetchers.VehicleParkingImpl; import org.opentripplanner.apis.gtfs.datafetchers.VehiclePositionImpl; @@ -129,7 +129,10 @@ protected static GraphQLSchema buildSchema() { .type("StopPosition", type -> type.typeResolver(new StopPosition() {})) .type("FareProduct", type -> type.typeResolver(new FareProductTypeResolver())) .type("AlertEntity", type -> type.typeResolver(new AlertEntityTypeResolver())) - .type("TripOnServiceDate", type -> type.typeResolver(new TripOnServiceDateTypeResolver())) + .type( + "CancellableTripOnServiceDate", + type -> type.typeResolver(new CancellableTripOnServiceDateTypeResolver()) + ) .type(typeWiring.build(AgencyImpl.class)) .type(typeWiring.build(AlertImpl.class)) .type(typeWiring.build(BikeParkImpl.class)) @@ -182,8 +185,8 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(CurrencyImpl.class)) .type(typeWiring.build(FareProductUseImpl.class)) .type(typeWiring.build(DefaultFareProductImpl.class)) - .type(typeWiring.build(RegularTripOnServiceDateImpl.class)) - .type(typeWiring.build(RegularRealTimeStopTimeImpl.class)) + .type(typeWiring.build(TripOnServiceDateImpl.class)) + .type(typeWiring.build(StopCallImpl.class)) .type(typeWiring.build(TripOccupancyImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CancellableTripOnServiceDateTypeResolver.java similarity index 79% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CancellableTripOnServiceDateTypeResolver.java index 570177768f0..4c9af823767 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateTypeResolver.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CancellableTripOnServiceDateTypeResolver.java @@ -6,7 +6,7 @@ import graphql.schema.TypeResolver; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; -public class TripOnServiceDateTypeResolver implements TypeResolver { +public class CancellableTripOnServiceDateTypeResolver implements TypeResolver { @Override public GraphQLObjectType getType(TypeResolutionEnvironment environment) { @@ -14,7 +14,7 @@ public GraphQLObjectType getType(TypeResolutionEnvironment environment) { GraphQLSchema schema = environment.getSchema(); if (o instanceof TripOnServiceDate) { - return schema.getObjectType("RegularTripOnServiceDate"); + return schema.getObjectType("TripOnServiceDate"); } return null; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StopCallImpl.java similarity index 79% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StopCallImpl.java index de4476f6651..cb5ec7e15a5 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularRealTimeStopTimeImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StopCallImpl.java @@ -8,15 +8,14 @@ import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.model.TripTimeOnDate; -import org.opentripplanner.model.plan.LegCallTime; +import org.opentripplanner.transit.model.timetable.CallTime; import org.opentripplanner.transit.service.TransitService; import org.opentripplanner.utils.time.ServiceDateUtils; -public class RegularRealTimeStopTimeImpl - implements GraphQLDataFetchers.GraphQLRegularRealTimeStopTime { +public class StopCallImpl implements GraphQLDataFetchers.GraphQLStopCall { @Override - public DataFetcher arrival() { + public DataFetcher arrival() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledArrival()); @@ -24,13 +23,13 @@ public DataFetcher arrival() { return null; } return tripTime.isRealtime() - ? LegCallTime.of(scheduledTime, tripTime.getArrivalDelay()) - : LegCallTime.ofStatic(scheduledTime); + ? CallTime.of(scheduledTime, tripTime.getArrivalDelay()) + : CallTime.ofStatic(scheduledTime); }; } @Override - public DataFetcher departure() { + public DataFetcher departure() { return environment -> { var tripTime = getSource(environment); var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledDeparture()); @@ -38,8 +37,8 @@ public DataFetcher departure() { return null; } return tripTime.isRealtime() - ? LegCallTime.of(scheduledTime, tripTime.getDepartureDelay()) - : LegCallTime.ofStatic(scheduledTime); + ? CallTime.of(scheduledTime, tripTime.getDepartureDelay()) + : CallTime.ofStatic(scheduledTime); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularTripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java similarity index 95% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularTripOnServiceDateImpl.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java index f6b7107aded..22e45a9afda 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RegularTripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java @@ -16,8 +16,7 @@ import org.opentripplanner.transit.service.TransitService; import org.opentripplanner.utils.time.ServiceDateUtils; -public class RegularTripOnServiceDateImpl - implements GraphQLDataFetchers.GraphQLRegularTripOnServiceDate { +public class TripOnServiceDateImpl implements GraphQLDataFetchers.GraphQLTripOnServiceDate { @Override public DataFetcher serviceDate() { @@ -61,7 +60,7 @@ public DataFetcher start() { } @Override - public DataFetcher> stopTimes() { + public DataFetcher> stopCalls() { return environment -> { TransitService transitService = getTransitService(environment); Trip trip = getTrip(environment); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index c2f2d236b41..f4843a31ecf 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -66,6 +66,7 @@ import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.organization.Agency; +import org.opentripplanner.transit.model.timetable.CallTime; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; import org.opentripplanner.transit.model.timetable.booking.BookingInfo; @@ -239,6 +240,26 @@ public interface GraphQLBookingTime { public DataFetcher time(); } + /** Real-time estimates for an arrival or departure at a certain place. */ + public interface GraphQLCallRealTimeEstimate { + public DataFetcher delay(); + + public DataFetcher time(); + } + + /** + * Timing of an arrival or a departure to or from a stop. May contain real-time information if + * available. This is used when there is a known scheduled time. + */ + public interface GraphQLCallTime { + public DataFetcher estimated(); + + public DataFetcher scheduledTime(); + } + + /** An instance of a trip, which can be cancelled, on a service date. */ + public interface GraphQLCancellableTripOnServiceDate extends TypeResolver {} + /** Car park represents a location where cars can be parked. */ public interface GraphQLCarPark { public DataFetcher carParkId(); @@ -846,41 +867,6 @@ public interface GraphQLRealTimeEstimate { public DataFetcher time(); } - /** - * Timing of an arrival or a departure to or from a stop. May contain real-time information if - * available. This is used when there is a known scheduled time. - */ - public interface GraphQLRegularRealTimeArrivalDepartureTime { - public DataFetcher estimated(); - - public DataFetcher scheduledTime(); - } - - /** - * Regular real-time stop time represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. - * This can include real-time estimates. - */ - public interface GraphQLRegularRealTimeStopTime { - public DataFetcher arrival(); - - public DataFetcher departure(); - - public DataFetcher stop(); - } - - /** A regular (i.e. not flexible) trip on a specific service date */ - public interface GraphQLRegularTripOnServiceDate { - public DataFetcher end(); - - public DataFetcher serviceDate(); - - public DataFetcher start(); - - public DataFetcher> stopTimes(); - - public DataFetcher trip(); - } - /** Rental vehicle represents a vehicle that belongs to a rental network. */ public interface GraphQLRentalVehicle { public DataFetcher allowPickupNow(); @@ -1075,6 +1061,18 @@ public interface GraphQLStop { public DataFetcher zoneId(); } + /** + * Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. + * This can include real-time estimates. + */ + public interface GraphQLStopCall { + public DataFetcher arrival(); + + public DataFetcher departure(); + + public DataFetcher stop(); + } + public interface GraphQLStopGeometries { public DataFetcher geoJson(); @@ -1241,11 +1239,17 @@ public interface GraphQLTripOccupancy { public DataFetcher occupancyStatus(); } - /** An instance of a trip on a service date. */ - public interface GraphQLTripOnServiceDate extends TypeResolver { - public default DataFetcher serviceDate() { - return null; - } + /** A regular (i.e. not flexible) trip on a specific service date */ + public interface GraphQLTripOnServiceDate { + public DataFetcher end(); + + public DataFetcher serviceDate(); + + public DataFetcher start(); + + public DataFetcher> stopCalls(); + + public DataFetcher trip(); } /** diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 156053ad5dc..1f2733ee34b 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -59,11 +59,11 @@ config: ContactInfo: org.opentripplanner.transit.model.organization.ContactInfo Cluster: Object Coordinates: org.locationtech.jts.geom.Coordinate#Coordinate - RegularRealTimeStopTime: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate - RegularTripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate + StopCall: org.opentripplanner.model.TripTimeOnDate#TripTimeOnDate + TripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate TripOnServiceDateConnection: graphql.relay.Connection#Connection TripOnServiceDateEdge: graphql.relay.Edge#Edge - RegularRealTimeArrivalDepartureTime: org.opentripplanner.model.plan.LegCallTime#LegCallTime + CallTime: org.opentripplanner.transit.model.timetable.CallTime#CallTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step diff --git a/application/src/main/java/org/opentripplanner/transit/model/timetable/CallRealTimeEstimate.java b/application/src/main/java/org/opentripplanner/transit/model/timetable/CallRealTimeEstimate.java new file mode 100644 index 00000000000..eeac4a321c4 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/transit/model/timetable/CallRealTimeEstimate.java @@ -0,0 +1,31 @@ +package org.opentripplanner.transit.model.timetable; + +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Objects; + +/** + * Realtime information about a vehicle at a certain place. This is meant to be used in timetables + * (not in transit legs). + */ +public class CallRealTimeEstimate { + + private final ZonedDateTime time; + private final Duration delay; + + /** + * @param delay Delay or "earliness" of a vehicle. Earliness is expressed as a negative number. + */ + public CallRealTimeEstimate(ZonedDateTime time, Duration delay) { + this.time = Objects.requireNonNull(time); + this.delay = Objects.requireNonNull(delay); + } + + public ZonedDateTime time() { + return time; + } + + public Duration delay() { + return delay; + } +} diff --git a/application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java b/application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java new file mode 100644 index 00000000000..4a7df9fb217 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java @@ -0,0 +1,40 @@ +package org.opentripplanner.transit.model.timetable; + +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Objects; +import javax.annotation.Nullable; + +/** + * A scheduled time of a transit vehicle at a certain location with an optional realtime + * information. This is meant to be used in timetables (not in transit legs). + */ +public class CallTime { + + private final ZonedDateTime scheduledTime; + + @Nullable + private final CallRealTimeEstimate estimated; + + private CallTime(ZonedDateTime scheduledTime, @Nullable CallRealTimeEstimate estimated) { + this.scheduledTime = Objects.requireNonNull(scheduledTime); + this.estimated = estimated; + } + + public static CallTime of(ZonedDateTime realtime, int delaySecs) { + var delay = Duration.ofSeconds(delaySecs); + return new CallTime(realtime.minus(delay), new CallRealTimeEstimate(realtime, delay)); + } + + public static CallTime ofStatic(ZonedDateTime staticTime) { + return new CallTime(staticTime, null); + } + + public ZonedDateTime scheduledTime() { + return scheduledTime; + } + + public CallRealTimeEstimate estimated() { + return estimated; + } +} diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 25f7a757131..07a89270370 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -70,21 +70,12 @@ interface PlaceInterface { lon: Float } -"An instance of a trip on a service date." -interface TripOnServiceDate { - """ - The service date when the trip occurs. - - **Note**: A service date is a technical term useful for transit planning purposes and might not - correspond to a how a passenger thinks of a calendar date. For example, a night bus running - on Sunday morning at 1am to 3am, might have the previous Saturday's service date. - """ - serviceDate: LocalDate! -} - "Entity related to an alert" union AlertEntity = Agency | Pattern | Route | RouteType | Stop | StopOnRoute | StopOnTrip | Trip | Unknown +"An instance of a trip, which can be cancelled, on a service date." +union CancellableTripOnServiceDate = TripOnServiceDate + union StopPosition = PositionAtStop | PositionBetweenStops "A public transport agency" @@ -306,6 +297,28 @@ type BookingTime { time: String } +"Real-time estimates for an arrival or departure at a certain place." +type CallRealTimeEstimate { + """ + The delay or "earliness" of the vehicle at a certain place. + + If the vehicle is early then this is a negative duration. + """ + delay: Duration! + time: OffsetDateTime! +} + +""" +Timing of an arrival or a departure to or from a stop. May contain real-time information if +available. This is used when there is a known scheduled time. +""" +type CallTime { + "The estimated time of the event. If no real-time information is available, this is null." + estimated: CallRealTimeEstimate + "The scheduled time of the event." + scheduledTime: OffsetDateTime! +} + "Car park represents a location where cars can be parked." type CarPark implements Node & PlaceInterface { "ID of the car park" @@ -1808,50 +1821,6 @@ type RealTimeEstimate { time: OffsetDateTime! } -""" -Timing of an arrival or a departure to or from a stop. May contain real-time information if -available. This is used when there is a known scheduled time. -""" -type RegularRealTimeArrivalDepartureTime { - "The estimated time of the event. If no real-time information is available, this is null." - estimated: RealTimeEstimate - "The scheduled time of the event." - scheduledTime: OffsetDateTime! -} - -""" -Regular real-time stop time represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. -This can include real-time estimates. -""" -type RegularRealTimeStopTime { - "Scheduled arrival time to the stop and a real-time estimate, if one exists." - arrival: RegularRealTimeArrivalDepartureTime - "Scheduled departure time from the stop and a real-time estimate, if one exists." - departure: RegularRealTimeArrivalDepartureTime - "The stop where this arrival/departure happens" - stop: Stop -} - -"A regular (i.e. not flexible) trip on a specific service date" -type RegularTripOnServiceDate implements TripOnServiceDate { - "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." - end: RegularRealTimeStopTime! - """ - The service date when the trip occurs. - - **Note**: A service date is a technical term useful for transit planning purposes and might not - correspond to a how a passenger thinks of a calendar date. For example, a night bus running - on Sunday morning at 1am to 3am, might have the previous Saturday's service date. - """ - serviceDate: LocalDate! - "Information related to trip's scheduled departure from the first stop. Can contain realtime information." - start: RegularRealTimeStopTime! - "List of times when this trip arrives to or departs from a stop and information related to the stop" - stopTimes: [RegularRealTimeStopTime!]! - "This trip on service date is an instance of this trip." - trip: Trip -} - "Rental vehicle represents a vehicle that belongs to a rental network." type RentalVehicle implements Node & PlaceInterface { "If true, vehicle is currently available for renting." @@ -2214,6 +2183,19 @@ type Stop implements Node & PlaceInterface { zoneId: String } +""" +Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. +This can include real-time estimates. +""" +type StopCall { + "Scheduled arrival time to the stop and a real-time estimate, if one exists." + arrival: CallTime + "Scheduled departure time from the stop and a real-time estimate, if one exists." + departure: CallTime + "The stop where this arrival/departure happens" + stop: Stop +} + type StopGeometries { "Representation of the stop geometries as GeoJSON (https://geojson.org/)" geoJson: GeoJson @@ -2469,6 +2451,26 @@ type TripOccupancy { occupancyStatus: OccupancyStatus } +"A regular (i.e. not flexible) trip on a specific service date" +type TripOnServiceDate { + "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." + end: StopCall! + """ + The service date when the trip occurs. + + **Note**: A service date is a technical term useful for transit planning purposes and might not + correspond to a how a passenger thinks of a calendar date. For example, a night bus running + on Sunday morning at 1am to 3am, might have the previous Saturday's service date. + """ + serviceDate: LocalDate! + "Information related to trip's scheduled departure from the first stop. Can contain realtime information." + start: StopCall! + "List of times when this trip arrives to or departs from a stop and information related to the stop" + stopCalls: [StopCall!]! + "This trip on service date is an instance of this trip." + trip: Trip +} + """ A connection to a list of trips on service dates that follows [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). @@ -2500,7 +2502,7 @@ type TripOnServiceDateEdge { Trip on a service date as a node. Part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). """ - node: TripOnServiceDate + node: CancellableTripOnServiceDate } "This is used for alert entities that we don't explicitly handle or they are missing." diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json index b3facd3da1f..5e32b67fc4e 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json @@ -29,7 +29,7 @@ "scheduledTime": "2024-08-09T11:30:00+02:00" } }, - "stopTimes": [ + "stopCalls": [ { "stop": { "gtfsId": "F:Stop_0" diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index 9629c4ae418..8d5685a06ba 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -8,7 +8,7 @@ } edges { node { - ... on RegularTripOnServiceDate { + ... on TripOnServiceDate { serviceDate end { arrival { @@ -28,7 +28,7 @@ scheduledTime } } - stopTimes { + stopCalls { stop { gtfsId } From 349efb66083bc7041aa563d42c1cd34e260cb432 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 18 Nov 2024 14:38:46 +0200 Subject: [PATCH 38/98] Create implementations for call times --- .../apis/gtfs/GtfsGraphQLIndex.java | 8 ++++++ .../CallRealTimeEstimateImpl.java | 25 +++++++++++++++++++ .../apis/gtfs/datafetchers/CallTimeImpl.java | 25 +++++++++++++++++++ .../apis/gtfs/datafetchers/LegTimeImpl.java | 25 +++++++++++++++++++ .../datafetchers/RealTimeEstimateImpl.java | 25 +++++++++++++++++++ .../gtfs/generated/GraphQLDataFetchers.java | 6 +++-- .../apis/gtfs/generated/graphql-codegen.yml | 2 ++ 7 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallRealTimeEstimateImpl.java create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegTimeImpl.java create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RealTimeEstimateImpl.java diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index 2a7599ecfd7..ddf251ea833 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -31,6 +31,8 @@ import org.opentripplanner.apis.gtfs.datafetchers.BikeRentalStationImpl; import org.opentripplanner.apis.gtfs.datafetchers.BookingInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.BookingTimeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.CallRealTimeEstimateImpl; +import org.opentripplanner.apis.gtfs.datafetchers.CallTimeImpl; import org.opentripplanner.apis.gtfs.datafetchers.CancellableTripOnServiceDateTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.CarParkImpl; import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; @@ -44,6 +46,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.GeometryImpl; import org.opentripplanner.apis.gtfs.datafetchers.ItineraryImpl; import org.opentripplanner.apis.gtfs.datafetchers.LegImpl; +import org.opentripplanner.apis.gtfs.datafetchers.LegTimeImpl; import org.opentripplanner.apis.gtfs.datafetchers.MoneyImpl; import org.opentripplanner.apis.gtfs.datafetchers.NodeTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.OpeningHoursImpl; @@ -53,6 +56,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.PlanConnectionImpl; import org.opentripplanner.apis.gtfs.datafetchers.PlanImpl; import org.opentripplanner.apis.gtfs.datafetchers.QueryTypeImpl; +import org.opentripplanner.apis.gtfs.datafetchers.RealTimeEstimateImpl; import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleImpl; import org.opentripplanner.apis.gtfs.datafetchers.RentalVehicleTypeImpl; import org.opentripplanner.apis.gtfs.datafetchers.RideHailingEstimateImpl; @@ -188,6 +192,10 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(TripOnServiceDateImpl.class)) .type(typeWiring.build(StopCallImpl.class)) .type(typeWiring.build(TripOccupancyImpl.class)) + .type(typeWiring.build(LegTimeImpl.class)) + .type(typeWiring.build(RealTimeEstimateImpl.class)) + .type(typeWiring.build(CallTimeImpl.class)) + .type(typeWiring.build(CallRealTimeEstimateImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallRealTimeEstimateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallRealTimeEstimateImpl.java new file mode 100644 index 00000000000..09439c6e916 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallRealTimeEstimateImpl.java @@ -0,0 +1,25 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.time.Duration; +import java.time.OffsetDateTime; +import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.transit.model.timetable.CallRealTimeEstimate; + +public class CallRealTimeEstimateImpl implements GraphQLDataFetchers.GraphQLCallRealTimeEstimate { + + @Override + public DataFetcher delay() { + return environment -> getSource(environment).delay(); + } + + @Override + public DataFetcher time() { + return environment -> getSource(environment).time().toOffsetDateTime(); + } + + private CallRealTimeEstimate getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java new file mode 100644 index 00000000000..5a2da2c2d82 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java @@ -0,0 +1,25 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.time.OffsetDateTime; +import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.transit.model.timetable.CallRealTimeEstimate; +import org.opentripplanner.transit.model.timetable.CallTime; + +public class CallTimeImpl implements GraphQLDataFetchers.GraphQLCallTime { + + @Override + public DataFetcher estimated() { + return environment -> getSource(environment).estimated(); + } + + @Override + public DataFetcher scheduledTime() { + return environment -> getSource(environment).scheduledTime().toOffsetDateTime(); + } + + private CallTime getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegTimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegTimeImpl.java new file mode 100644 index 00000000000..571c0f2f38c --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegTimeImpl.java @@ -0,0 +1,25 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.time.OffsetDateTime; +import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.model.plan.LegCallTime; +import org.opentripplanner.model.plan.LegRealTimeEstimate; + +public class LegTimeImpl implements GraphQLDataFetchers.GraphQLLegTime { + + @Override + public DataFetcher estimated() { + return environment -> getSource(environment).estimated(); + } + + @Override + public DataFetcher scheduledTime() { + return environment -> getSource(environment).scheduledTime().toOffsetDateTime(); + } + + private LegCallTime getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RealTimeEstimateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RealTimeEstimateImpl.java new file mode 100644 index 00000000000..fbbf5226691 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RealTimeEstimateImpl.java @@ -0,0 +1,25 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import java.time.Duration; +import java.time.OffsetDateTime; +import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.model.plan.LegRealTimeEstimate; + +public class RealTimeEstimateImpl implements GraphQLDataFetchers.GraphQLRealTimeEstimate { + + @Override + public DataFetcher delay() { + return environment -> getSource(environment).delay(); + } + + @Override + public DataFetcher time() { + return environment -> getSource(environment).time().toOffsetDateTime(); + } + + private LegRealTimeEstimate getSource(DataFetchingEnvironment environment) { + return environment.getSource(); + } +} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index f4843a31ecf..0210a5708dc 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -42,6 +42,7 @@ import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.Leg; import org.opentripplanner.model.plan.LegCallTime; +import org.opentripplanner.model.plan.LegRealTimeEstimate; import org.opentripplanner.model.plan.StopArrival; import org.opentripplanner.model.plan.WalkStep; import org.opentripplanner.routing.alertpatch.TransitAlert; @@ -66,6 +67,7 @@ import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.organization.Agency; +import org.opentripplanner.transit.model.timetable.CallRealTimeEstimate; import org.opentripplanner.transit.model.timetable.CallTime; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; @@ -252,7 +254,7 @@ public interface GraphQLCallRealTimeEstimate { * available. This is used when there is a known scheduled time. */ public interface GraphQLCallTime { - public DataFetcher estimated(); + public DataFetcher estimated(); public DataFetcher scheduledTime(); } @@ -558,7 +560,7 @@ public interface GraphQLLeg { * available. */ public interface GraphQLLegTime { - public DataFetcher estimated(); + public DataFetcher estimated(); public DataFetcher scheduledTime(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 1f2733ee34b..d5059311cac 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -130,4 +130,6 @@ config: FareMedium: org.opentripplanner.model.fare.FareMedium#FareMedium RiderCategory: org.opentripplanner.model.fare.RiderCategory#RiderCategory StopPosition: org.opentripplanner.apis.gtfs.model.StopPosition#StopPosition + RealTimeEstimate: org.opentripplanner.model.plan.LegRealTimeEstimate#LegRealTimeEstimate + CallRealTimeEstimate: org.opentripplanner.transit.model.timetable.CallRealTimeEstimate#CallRealTimeEstimate From 405f580ec1d1ca7e0df3f8fa2fe5d27aa9ae19cb Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Tue, 19 Nov 2024 17:19:18 +0200 Subject: [PATCH 39/98] Remove support for feeds argument --- .../apis/gtfs/datafetchers/QueryTypeImpl.java | 11 +--------- .../apis/gtfs/generated/GraphQLTypes.java | 10 ---------- .../model/TimetableSnapshot.java | 14 ------------- .../service/DefaultTransitService.java | 20 ------------------- .../transit/service/TransitService.java | 7 ------- .../opentripplanner/apis/gtfs/schema.graphqls | 2 -- .../service/DefaultTransitServiceTest.java | 18 ----------------- .../apis/gtfs/queries/canceled-trips.graphql | 2 +- 8 files changed, 2 insertions(+), 82 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java index 2f886f81734..b36cb0a46ba 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/QueryTypeImpl.java @@ -833,16 +833,7 @@ public DataFetcher> trips() { @Override public DataFetcher> canceledTrips() { return environment -> { - var args = new GraphQLTypes.GraphQLQueryTypeCanceledTripsArgs(environment.getArguments()); - if (args.getGraphQLFeeds() != null && args.getGraphQLFeeds().isEmpty()) { - throw new IllegalArgumentException( - "Feeds need to be either not specified or contain elements." - ); - } - - var trips = args.getGraphQLFeeds() != null - ? getTransitService(environment).findCanceledTrips(args.getGraphQLFeeds()) - : getTransitService(environment).listCanceledTrips(); + var trips = getTransitService(environment).listCanceledTrips(); return new SimpleListConnection<>(trips).get(environment); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java index 37d5ff674dd..32e78eef231 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLTypes.java @@ -2410,7 +2410,6 @@ public static class GraphQLQueryTypeCanceledTripsArgs { private String after; private String before; - private List feeds; private Integer first; private Integer last; @@ -2418,7 +2417,6 @@ public GraphQLQueryTypeCanceledTripsArgs(Map args) { if (args != null) { this.after = (String) args.get("after"); this.before = (String) args.get("before"); - this.feeds = (List) args.get("feeds"); this.first = (Integer) args.get("first"); this.last = (Integer) args.get("last"); } @@ -2432,10 +2430,6 @@ public String getGraphQLBefore() { return this.before; } - public List getGraphQLFeeds() { - return this.feeds; - } - public Integer getGraphQLFirst() { return this.first; } @@ -2452,10 +2446,6 @@ public void setGraphQLBefore(String before) { this.before = before; } - public void setGraphQLFeeds(List feeds) { - this.feeds = feeds; - } - public void setGraphQLFirst(Integer first) { this.first = first; } diff --git a/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java b/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java index 77e5d1f6fbb..44ce1e5cb18 100644 --- a/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java +++ b/application/src/main/java/org/opentripplanner/model/TimetableSnapshot.java @@ -226,20 +226,6 @@ public TripPattern getNewTripPatternForModifiedTrip(FeedScopedId tripId, LocalDa return realTimeNewTripPatternsForModifiedTrips.get(tripIdAndServiceDate); } - /** - * Find trips which have been canceled. - * - * @param feeds only return trips from these feeds. Empty list is not allowed. - */ - public List findCanceledTrips(List feeds) { - if (feeds == null || feeds.isEmpty()) { - throw new IllegalArgumentException("Feeds list cannot be null or empty"); - } - return findTripsOnServiceDates(tripTimes -> - tripTimes.isCanceled() && feeds.contains(tripTimes.getTrip().getId().getFeedId()) - ); - } - /** * List trips which have been canceled. */ diff --git a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java index 2dd31e93da3..8b9e473d193 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/DefaultTransitService.java @@ -295,26 +295,6 @@ public Trip getScheduledTripForId(FeedScopedId id) { return this.timetableRepositoryIndex.getTripForId(id); } - /** - * TODO This only supports realtime cancelled trips for now. - */ - @Override - public List findCanceledTrips(List feeds) { - if (feeds == null || feeds.isEmpty()) { - throw new IllegalArgumentException( - "Feeds list cannot be empty or null. It needs to have elements." - ); - } - OTPRequestTimeoutException.checkForTimeout(); - var timetableSnapshot = lazyGetTimeTableSnapShot(); - if (timetableSnapshot == null) { - return List.of(); - } - List canceledTrips = timetableSnapshot.findCanceledTrips(feeds); - canceledTrips.sort(new TripOnServiceDateComparator()); - return canceledTrips; - } - /** * TODO This only supports realtime cancelled trips for now. */ diff --git a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java index 4e0b49d559f..e534b154dd0 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TransitService.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TransitService.java @@ -169,13 +169,6 @@ public interface TransitService { */ Collection getAllTrips(); - /** - * Find canceled trips. - * - * @param feeds used for filtering. Empty list is not allowed. - */ - List findCanceledTrips(List feeds); - /** * List all canceled trips. */ diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 07a89270370..2bd7d42a451 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1151,8 +1151,6 @@ type QueryType { and should be used together with the `last` parameter. """ before: String, - "Feed feedIds (e.g. [\"HSL\"])." - feeds: [String], """ Limits how many trips are returned. This parameter is part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm) and can be used together with diff --git a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java index 534b0103854..868d89d61d7 100644 --- a/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java +++ b/application/src/test/java/org/opentripplanner/transit/service/DefaultTransitServiceTest.java @@ -1,6 +1,5 @@ package org.opentripplanner.transit.service; -import static org.junit.Assert.assertThrows; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.opentripplanner.model.plan.PlanTestConstants.T11_30; import static org.opentripplanner.transit.model.basic.TransitMode.BUS; @@ -157,21 +156,4 @@ void listCanceledTrips() { var canceledTrips = service.listCanceledTrips(); assertEquals("[TripOnServiceDate{F:123}, TripOnServiceDate{F:123}]", canceledTrips.toString()); } - - @Test - void findCanceledTrips() { - var canceledTripsForFeedWithCancellations = service.findCanceledTrips(List.of("F", "G")); - assertEquals( - "[TripOnServiceDate{F:123}, TripOnServiceDate{F:123}]", - canceledTripsForFeedWithCancellations.toString() - ); - - var canceledTripsForFeedWithoutCancellations = service.findCanceledTrips(List.of("G")); - assertEquals("[]", canceledTripsForFeedWithoutCancellations.toString()); - } - - @Test - void findCanceledTripsWithEmptyFeeds() { - assertThrows(IllegalArgumentException.class, () -> service.findCanceledTrips(List.of())); - } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index 8d5685a06ba..cf767d81f10 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -1,5 +1,5 @@ { - canceledTrips(feeds: "F") { + canceledTrips(first: 2) { pageInfo { hasNextPage hasPreviousPage From ac21d8a099ea751d55ab1b0c6216e5273c8ef82e Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Thu, 21 Nov 2024 14:14:29 +0200 Subject: [PATCH 40/98] Improve doc --- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 2bd7d42a451..15a877e3ed4 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -300,11 +300,12 @@ type BookingTime { "Real-time estimates for an arrival or departure at a certain place." type CallRealTimeEstimate { """ - The delay or "earliness" of the vehicle at a certain place. + The delay or "earliness" of the vehicle at a certain place. This estimate can change quite often. If the vehicle is early then this is a negative duration. """ delay: Duration! + "The estimate for a call event (such as arrival or departure) at a certain place. This estimate can change quite often." time: OffsetDateTime! } From ca5310034416fae6c6a6907cd91f8b97e12f7b4f Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Fri, 22 Nov 2024 13:03:57 +0200 Subject: [PATCH 41/98] Redesign schema --- .../apis/gtfs/GtfsGraphQLIndex.java | 7 ++----- ...ypeResolver.java => CallTypeResolver.java} | 8 +++---- .../datafetchers/TripOnServiceDateImpl.java | 12 +++++++---- .../gtfs/generated/GraphQLDataFetchers.java | 21 +++++++++++-------- .../opentripplanner/apis/gtfs/schema.graphqls | 19 ++++++++++------- .../apis/gtfs/queries/canceled-trips.graphql | 20 +++++++++++------- 6 files changed, 49 insertions(+), 38 deletions(-) rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{CancellableTripOnServiceDateTypeResolver.java => CallTypeResolver.java} (62%) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index ddf251ea833..10e33c0f777 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -33,7 +33,7 @@ import org.opentripplanner.apis.gtfs.datafetchers.BookingTimeImpl; import org.opentripplanner.apis.gtfs.datafetchers.CallRealTimeEstimateImpl; import org.opentripplanner.apis.gtfs.datafetchers.CallTimeImpl; -import org.opentripplanner.apis.gtfs.datafetchers.CancellableTripOnServiceDateTypeResolver; +import org.opentripplanner.apis.gtfs.datafetchers.CallTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.CarParkImpl; import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl; @@ -133,10 +133,7 @@ protected static GraphQLSchema buildSchema() { .type("StopPosition", type -> type.typeResolver(new StopPosition() {})) .type("FareProduct", type -> type.typeResolver(new FareProductTypeResolver())) .type("AlertEntity", type -> type.typeResolver(new AlertEntityTypeResolver())) - .type( - "CancellableTripOnServiceDate", - type -> type.typeResolver(new CancellableTripOnServiceDateTypeResolver()) - ) + .type("Call", type -> type.typeResolver(new CallTypeResolver())) .type(typeWiring.build(AgencyImpl.class)) .type(typeWiring.build(AlertImpl.class)) .type(typeWiring.build(BikeParkImpl.class)) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CancellableTripOnServiceDateTypeResolver.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTypeResolver.java similarity index 62% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CancellableTripOnServiceDateTypeResolver.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTypeResolver.java index 4c9af823767..02ee6784073 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CancellableTripOnServiceDateTypeResolver.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTypeResolver.java @@ -4,17 +4,17 @@ import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLSchema; import graphql.schema.TypeResolver; -import org.opentripplanner.transit.model.timetable.TripOnServiceDate; +import org.opentripplanner.model.TripTimeOnDate; -public class CancellableTripOnServiceDateTypeResolver implements TypeResolver { +public class CallTypeResolver implements TypeResolver { @Override public GraphQLObjectType getType(TypeResolutionEnvironment environment) { Object o = environment.getObject(); GraphQLSchema schema = environment.getSchema(); - if (o instanceof TripOnServiceDate) { - return schema.getObjectType("TripOnServiceDate"); + if (o instanceof TripTimeOnDate) { + return schema.getObjectType("StopCall"); } return null; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java index 22e45a9afda..b85f63a9d17 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java @@ -24,7 +24,7 @@ public DataFetcher serviceDate() { } @Override - public DataFetcher end() { + public DataFetcher end() { return environment -> { TransitService transitService = getTransitService(environment); Trip trip = getTrip(environment); @@ -42,7 +42,7 @@ public DataFetcher end() { } @Override - public DataFetcher start() { + public DataFetcher start() { return environment -> { TransitService transitService = getTransitService(environment); Trip trip = getTrip(environment); @@ -60,7 +60,7 @@ public DataFetcher start() { } @Override - public DataFetcher> stopCalls() { + public DataFetcher> stopCalls() { return environment -> { TransitService transitService = getTransitService(environment); Trip trip = getTrip(environment); @@ -73,7 +73,11 @@ public DataFetcher> stopCalls() { if (timetable == null) { return List.of(); } - return TripTimeOnDate.fromTripTimes(timetable, trip, serviceDate, midnight); + return TripTimeOnDate + .fromTripTimes(timetable, trip, serviceDate, midnight) + .stream() + .map(Object.class::cast) + .toList(); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 0210a5708dc..375525b1a1f 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -242,6 +242,12 @@ public interface GraphQLBookingTime { public DataFetcher time(); } + /** + * Call is a visit to a location (a stop or an area) in a trip on service date. It can contain + * exact arrival and departure times and/or a scheduled time window. + */ + public interface GraphQLCall extends TypeResolver {} + /** Real-time estimates for an arrival or departure at a certain place. */ public interface GraphQLCallRealTimeEstimate { public DataFetcher delay(); @@ -259,9 +265,6 @@ public interface GraphQLCallTime { public DataFetcher scheduledTime(); } - /** An instance of a trip, which can be cancelled, on a service date. */ - public interface GraphQLCancellableTripOnServiceDate extends TypeResolver {} - /** Car park represents a location where cars can be parked. */ public interface GraphQLCarPark { public DataFetcher carParkId(); @@ -1065,7 +1068,7 @@ public interface GraphQLStop { /** * Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. - * This can include real-time estimates. + * The times are exact (although can be changed by real-time updates), not time windows. */ public interface GraphQLStopCall { public DataFetcher arrival(); @@ -1241,15 +1244,15 @@ public interface GraphQLTripOccupancy { public DataFetcher occupancyStatus(); } - /** A regular (i.e. not flexible) trip on a specific service date */ + /** A trip on a specific service date. */ public interface GraphQLTripOnServiceDate { - public DataFetcher end(); + public DataFetcher end(); public DataFetcher serviceDate(); - public DataFetcher start(); + public DataFetcher start(); - public DataFetcher> stopCalls(); + public DataFetcher> stopCalls(); public DataFetcher trip(); } @@ -1271,7 +1274,7 @@ public interface GraphQLTripOnServiceDateConnection { public interface GraphQLTripOnServiceDateEdge { public DataFetcher cursor(); - public DataFetcher node(); + public DataFetcher node(); } /** This is used for alert entities that we don't explicitly handle or they are missing. */ diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 15a877e3ed4..b3152a71dd4 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -73,8 +73,11 @@ interface PlaceInterface { "Entity related to an alert" union AlertEntity = Agency | Pattern | Route | RouteType | Stop | StopOnRoute | StopOnTrip | Trip | Unknown -"An instance of a trip, which can be cancelled, on a service date." -union CancellableTripOnServiceDate = TripOnServiceDate +""" +Call is a visit to a location (a stop or an area) in a trip on service date. It can contain +exact arrival and departure times and/or a scheduled time window. +""" +union Call = StopCall union StopPosition = PositionAtStop | PositionBetweenStops @@ -2184,7 +2187,7 @@ type Stop implements Node & PlaceInterface { """ Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. -This can include real-time estimates. +The times are exact (although can be changed by real-time updates), not time windows. """ type StopCall { "Scheduled arrival time to the stop and a real-time estimate, if one exists." @@ -2450,10 +2453,10 @@ type TripOccupancy { occupancyStatus: OccupancyStatus } -"A regular (i.e. not flexible) trip on a specific service date" +"A trip on a specific service date." type TripOnServiceDate { "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." - end: StopCall! + end: Call! """ The service date when the trip occurs. @@ -2463,9 +2466,9 @@ type TripOnServiceDate { """ serviceDate: LocalDate! "Information related to trip's scheduled departure from the first stop. Can contain realtime information." - start: StopCall! + start: Call! "List of times when this trip arrives to or departs from a stop and information related to the stop" - stopCalls: [StopCall!]! + stopCalls: [Call!]! "This trip on service date is an instance of this trip." trip: Trip } @@ -2501,7 +2504,7 @@ type TripOnServiceDateEdge { Trip on a service date as a node. Part of the [GraphQL Cursor Connections Specification](https://relay.dev/graphql/connections.htm). """ - node: CancellableTripOnServiceDate + node: TripOnServiceDate } "This is used for alert entities that we don't explicitly handle or they are missing." diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index cf767d81f10..b3817605f37 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -8,9 +8,9 @@ } edges { node { - ... on TripOnServiceDate { - serviceDate - end { + serviceDate + end { + ... on StopCall { arrival { estimated { delay @@ -19,7 +19,9 @@ scheduledTime } } - start { + } + start { + ... on StopCall { departure { estimated { delay @@ -28,7 +30,9 @@ scheduledTime } } - stopCalls { + } + stopCalls { + ... on StopCall { stop { gtfsId } @@ -47,9 +51,9 @@ } } } - trip { - gtfsId - } + } + trip { + gtfsId } } } From de5758b7b502168df8e882c602d6553d145b3be0 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Mon, 25 Nov 2024 12:39:34 +0100 Subject: [PATCH 42/98] Add module test for listing canceled trips --- .../cancellation/CanceledTripTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 application/src/test/java/org/opentripplanner/updater/trip/moduletests/cancellation/CanceledTripTest.java diff --git a/application/src/test/java/org/opentripplanner/updater/trip/moduletests/cancellation/CanceledTripTest.java b/application/src/test/java/org/opentripplanner/updater/trip/moduletests/cancellation/CanceledTripTest.java new file mode 100644 index 00000000000..75c8d5caa46 --- /dev/null +++ b/application/src/test/java/org/opentripplanner/updater/trip/moduletests/cancellation/CanceledTripTest.java @@ -0,0 +1,41 @@ +package org.opentripplanner.updater.trip.moduletests.cancellation; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.transit.realtime.GtfsRealtime.TripDescriptor.ScheduleRelationship.CANCELED; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opentripplanner.transit.model._data.TimetableRepositoryForTest.id; +import static org.opentripplanner.updater.spi.UpdateResultAssertions.assertSuccess; + +import org.junit.jupiter.api.Test; +import org.opentripplanner.updater.trip.RealtimeTestConstants; +import org.opentripplanner.updater.trip.RealtimeTestEnvironment; +import org.opentripplanner.updater.trip.TripInput; +import org.opentripplanner.updater.trip.TripUpdateBuilder; + +public class CanceledTripTest implements RealtimeTestConstants { + + @Test + void listCanceledTrips() { + var env = RealtimeTestEnvironment + .gtfs() + .addTrip( + TripInput + .of(TRIP_1_ID) + .addStop(STOP_A1, "0:00:10", "0:00:11") + .addStop(STOP_B1, "0:00:20", "0:00:21") + .build() + ) + .build(); + + assertThat(env.getTransitService().listCanceledTrips()).isEmpty(); + + var update = new TripUpdateBuilder(TRIP_1_ID, SERVICE_DATE, CANCELED, TIME_ZONE).build(); + assertSuccess(env.applyTripUpdate(update)); + + var canceled = env.getTransitService().listCanceledTrips(); + assertThat(canceled).hasSize(1); + var trip = canceled.getFirst(); + assertEquals(id(TRIP_1_ID), trip.getTrip().getId()); + assertEquals(SERVICE_DATE, trip.getServiceDate()); + } +} From e6c003678c86007917c460e17431c7e03ac1daf8 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Mon, 25 Nov 2024 13:12:51 +0100 Subject: [PATCH 43/98] Remove duplication --- .../datafetchers/TripOnServiceDateImpl.java | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java index b85f63a9d17..ad419f0c228 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java @@ -26,55 +26,49 @@ public DataFetcher serviceDate() { @Override public DataFetcher end() { return environment -> { - TransitService transitService = getTransitService(environment); - Trip trip = getTrip(environment); - var serviceDate = getSource(environment).getServiceDate(); - - Instant midnight = ServiceDateUtils - .asStartOfService(serviceDate, transitService.getTimeZone()) - .toInstant(); - Timetable timetable = getTimetable(environment, trip, serviceDate); - if (timetable == null) { + final Result result = getResult(environment); + if (result.timetable() == null) { return null; } - return TripTimeOnDate.lastFromTripTimes(timetable, trip, serviceDate, midnight); + return TripTimeOnDate.lastFromTripTimes(result.timetable(), result.trip(), result.serviceDate(), result.midnight()); }; } + private Result getResult(DataFetchingEnvironment environment) { + TransitService transitService = getTransitService(environment); + Trip trip = getTrip(environment); + var serviceDate = getSource(environment).getServiceDate(); + + Instant midnight = ServiceDateUtils + .asStartOfService(serviceDate, transitService.getTimeZone()) + .toInstant(); + Timetable timetable = getTimetable(environment, trip, serviceDate); + return new Result(trip, serviceDate, midnight, timetable); + } + + private record Result(Trip trip, LocalDate serviceDate, Instant midnight, @Nullable Timetable timetable) { + } + @Override public DataFetcher start() { return environment -> { - TransitService transitService = getTransitService(environment); - Trip trip = getTrip(environment); - var serviceDate = getSource(environment).getServiceDate(); - - Instant midnight = ServiceDateUtils - .asStartOfService(serviceDate, transitService.getTimeZone()) - .toInstant(); - Timetable timetable = getTimetable(environment, trip, serviceDate); - if (timetable == null) { + var result = getResult(environment); + if (result.timetable() == null) { return null; } - return TripTimeOnDate.firstFromTripTimes(timetable, trip, serviceDate, midnight); + return TripTimeOnDate.firstFromTripTimes(result.timetable, result.trip, result.serviceDate, result.midnight); }; } @Override public DataFetcher> stopCalls() { return environment -> { - TransitService transitService = getTransitService(environment); - Trip trip = getTrip(environment); - var serviceDate = getSource(environment).getServiceDate(); - - Instant midnight = ServiceDateUtils - .asStartOfService(serviceDate, transitService.getTimeZone()) - .toInstant(); - Timetable timetable = getTimetable(environment, trip, serviceDate); - if (timetable == null) { + var result = getResult(environment); + if (result.timetable == null) { return List.of(); } return TripTimeOnDate - .fromTripTimes(timetable, trip, serviceDate, midnight) + .fromTripTimes(result.timetable, result.trip, result.serviceDate, result.midnight) .stream() .map(Object.class::cast) .toList(); From bee85dee2f4991da17b4b07788fda9ae79f4c0da Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 25 Nov 2024 14:47:06 +0200 Subject: [PATCH 44/98] Renaming or ordering --- .../datafetchers/TripOnServiceDateImpl.java | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java index ad419f0c228..aae18085cc1 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java @@ -26,49 +26,49 @@ public DataFetcher serviceDate() { @Override public DataFetcher end() { return environment -> { - final Result result = getResult(environment); - if (result.timetable() == null) { + var arguments = getFromTripTimesArguments(environment); + if (arguments.timetable() == null) { return null; } - return TripTimeOnDate.lastFromTripTimes(result.timetable(), result.trip(), result.serviceDate(), result.midnight()); + return TripTimeOnDate.lastFromTripTimes( + arguments.timetable(), + arguments.trip(), + arguments.serviceDate(), + arguments.midnight() + ); }; } - private Result getResult(DataFetchingEnvironment environment) { - TransitService transitService = getTransitService(environment); - Trip trip = getTrip(environment); - var serviceDate = getSource(environment).getServiceDate(); - - Instant midnight = ServiceDateUtils - .asStartOfService(serviceDate, transitService.getTimeZone()) - .toInstant(); - Timetable timetable = getTimetable(environment, trip, serviceDate); - return new Result(trip, serviceDate, midnight, timetable); - } - - private record Result(Trip trip, LocalDate serviceDate, Instant midnight, @Nullable Timetable timetable) { - } - @Override public DataFetcher start() { return environment -> { - var result = getResult(environment); - if (result.timetable() == null) { + var arguments = getFromTripTimesArguments(environment); + if (arguments.timetable() == null) { return null; } - return TripTimeOnDate.firstFromTripTimes(result.timetable, result.trip, result.serviceDate, result.midnight); + return TripTimeOnDate.firstFromTripTimes( + arguments.timetable(), + arguments.trip(), + arguments.serviceDate(), + arguments.midnight() + ); }; } @Override public DataFetcher> stopCalls() { return environment -> { - var result = getResult(environment); - if (result.timetable == null) { + var arguments = getFromTripTimesArguments(environment); + if (arguments.timetable() == null) { return List.of(); } return TripTimeOnDate - .fromTripTimes(result.timetable, result.trip, result.serviceDate, result.midnight) + .fromTripTimes( + arguments.timetable(), + arguments.trip(), + arguments.serviceDate(), + arguments.midnight() + ) .stream() .map(Object.class::cast) .toList(); @@ -107,4 +107,23 @@ private Trip getTrip(DataFetchingEnvironment environment) { private TripOnServiceDate getSource(DataFetchingEnvironment environment) { return environment.getSource(); } + + private FromTripTimesArguments getFromTripTimesArguments(DataFetchingEnvironment environment) { + TransitService transitService = getTransitService(environment); + Trip trip = getTrip(environment); + var serviceDate = getSource(environment).getServiceDate(); + + Instant midnight = ServiceDateUtils + .asStartOfService(serviceDate, transitService.getTimeZone()) + .toInstant(); + Timetable timetable = getTimetable(environment, trip, serviceDate); + return new FromTripTimesArguments(trip, serviceDate, midnight, timetable); + } + + private record FromTripTimesArguments( + Trip trip, + LocalDate serviceDate, + Instant midnight, + @Nullable Timetable timetable + ) {} } From dba65b0cbb564e0b703e1fe732522e1475f76024 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Tue, 26 Nov 2024 11:47:26 +0200 Subject: [PATCH 45/98] Update application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls --- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index fb8baa0eb9a..d7e540e1a1b 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -323,7 +323,7 @@ type CallTime { "The estimated time of the event. If no real-time information is available, this is null." estimated: CallRealTimeEstimate "The scheduled time of the event." - scheduledTime: OffsetDateTime! + scheduledTime: OffsetDateTime } "Car park represents a location where cars can be parked." From 33189c22fd4fc74407f9c5b3f20d7425ed9ea580 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Tue, 26 Nov 2024 11:09:33 +0200 Subject: [PATCH 46/98] Rename 'transferByStopIndex' variable to 'transfersByStopIndex'. --- .../raptoradapter/transit/mappers/TransfersMapper.java | 6 +++--- .../raptoradapter/transit/mappers/TransitLayerMapper.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java index ff47cb3ea74..3de07da9e19 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java @@ -18,7 +18,7 @@ static List> mapTransfers( SiteRepository siteRepository, TransitService transitService ) { - List> transferByStopIndex = new ArrayList<>(); + List> transfersByStopIndex = new ArrayList<>(); for (int i = 0; i < siteRepository.stopIndexSize(); ++i) { var stop = siteRepository.stopByIndex(i); @@ -45,10 +45,10 @@ static List> mapTransfers( } // Create a copy to compact and make the inner lists immutable - transferByStopIndex.add(List.copyOf(list)); + transfersByStopIndex.add(List.copyOf(list)); } // Return an immutable copy - return List.copyOf(transferByStopIndex); + return List.copyOf(transfersByStopIndex); } } diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransitLayerMapper.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransitLayerMapper.java index d6f9c0709c5..edcfa3f9dc8 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransitLayerMapper.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransitLayerMapper.java @@ -62,7 +62,7 @@ public static TransitLayer map( private TransitLayer map(TransitTuningParameters tuningParameters) { HashMap> tripPatternsByStopByDate; - List> transferByStopIndex; + List> transfersByStopIndex; ConstrainedTransfersForPatterns constrainedTransfers = null; LOG.info("Mapping transitLayer from TimetableRepository..."); @@ -71,7 +71,7 @@ private TransitLayer map(TransitTuningParameters tuningParameters) { tripPatternsByStopByDate = mapTripPatterns(allTripPatterns); - transferByStopIndex = mapTransfers(siteRepository, transitService); + transfersByStopIndex = mapTransfers(siteRepository, transitService); TransferIndexGenerator transferIndexGenerator = null; if (OTPFeature.TransferConstraints.isOn()) { @@ -86,7 +86,7 @@ private TransitLayer map(TransitTuningParameters tuningParameters) { return new TransitLayer( tripPatternsByStopByDate, - transferByStopIndex, + transfersByStopIndex, transitService.getTransferService(), siteRepository, transferCache, From aa4927ed83734c9af78df7caacb6235aa647db3f Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Fri, 29 Nov 2024 15:09:43 +0200 Subject: [PATCH 47/98] Add changes for CAR transfers. --- .../api/parameter/QualifiedModeSet.java | 7 ++++--- .../mapping/RaptorPathToItineraryMapper.java | 2 +- ...treetModeToTransferTraverseModeMapper.java | 21 +++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StreetModeToTransferTraverseModeMapper.java diff --git a/application/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java b/application/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java index c6f1a3d74ec..98ce58c6d21 100644 --- a/application/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java +++ b/application/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java @@ -126,9 +126,10 @@ public RequestModes getRequestModes() { mBuilder.withEgressMode(StreetMode.CAR_HAILING); mBuilder.withDirectMode(StreetMode.WALK); } else { - mBuilder.withAccessMode(StreetMode.WALK); - mBuilder.withTransferMode(StreetMode.WALK); - mBuilder.withEgressMode(StreetMode.WALK); + // This is necessary for transfer calculations. + mBuilder.withAccessMode(StreetMode.CAR); + mBuilder.withTransferMode(StreetMode.CAR); + mBuilder.withEgressMode(StreetMode.CAR); mBuilder.withDirectMode(StreetMode.CAR); } } diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java index 64c59b71603..15e3307b4e9 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapper.java @@ -126,7 +126,7 @@ else if (pathLeg.isTransferLeg()) { legs.addAll( mapTransferLeg( pathLeg.asTransferLeg(), - transferMode == StreetMode.BIKE ? TraverseMode.BICYCLE : TraverseMode.WALK + StreetModeToTransferTraverseModeMapper.map(transferMode) ) ); } diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StreetModeToTransferTraverseModeMapper.java b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StreetModeToTransferTraverseModeMapper.java new file mode 100644 index 00000000000..65db8e87832 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StreetModeToTransferTraverseModeMapper.java @@ -0,0 +1,21 @@ +package org.opentripplanner.routing.algorithm.mapping; + +import org.opentripplanner.routing.api.request.StreetMode; +import org.opentripplanner.street.search.TraverseMode; + +/** + * Maps street mode to transfer traverse mode. + */ +public class StreetModeToTransferTraverseModeMapper { + + public static TraverseMode map(StreetMode mode) { + return switch (mode) { + case WALK -> TraverseMode.WALK; + case BIKE -> TraverseMode.BICYCLE; + case CAR -> TraverseMode.CAR; + default -> throw new IllegalArgumentException( + String.format("StreetMode %s can not be mapped to a TraverseMode for transfers.", mode) + ); + }; + } +} From 4c882f42b22c20c582ca67438171b725523ff7d4 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Fri, 29 Nov 2024 15:13:10 +0200 Subject: [PATCH 48/98] Add EnumSet of StreetModes to PathTransfers and implement mode-specific transfers. --- .../opentripplanner/ext/flex/FlexIndex.java | 14 ++++++- .../opentripplanner/ext/flex/FlexRouter.java | 2 +- .../module/DirectTransferGenerator.java | 42 +++++++++++++++---- .../opentripplanner/model/PathTransfer.java | 25 +++++++++-- .../transit/RaptorTransferIndex.java | 3 ++ .../raptoradapter/transit/Transfer.java | 13 +++++- .../transit/mappers/TransfersMapper.java | 9 +++- .../RaptorPathToItineraryMapperTest.java | 4 +- .../raptoradapter/transit/TransferTest.java | 14 ++++--- 9 files changed, 101 insertions(+), 25 deletions(-) diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java index cd047de6d04..ccc4f7fe554 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java @@ -5,9 +5,11 @@ import com.google.common.collect.Multimap; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.opentripplanner.ext.flex.trip.FlexTrip; import org.opentripplanner.model.PathTransfer; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.site.GroupStop; @@ -18,6 +20,8 @@ public class FlexIndex { private final Multimap transfersToStop = ArrayListMultimap.create(); + private final Multimap transfersFromStop = ArrayListMultimap.create(); + private final Multimap> flexTripsByStop = HashMultimap.create(); private final Map routeById = new HashMap<>(); @@ -25,8 +29,12 @@ public class FlexIndex { private final Map> tripById = new HashMap<>(); public FlexIndex(TimetableRepository timetableRepository) { - for (PathTransfer transfer : timetableRepository.getAllPathTransfers()) { + // Flex transfers should only use WALK mode transfers. + StreetMode mode = StreetMode.WALK; + List filteredPathTransfers = timetableRepository.getAllPathTransfers().stream().filter(pathTransfer -> pathTransfer.getModes().contains(mode)).toList(); + for (PathTransfer transfer : filteredPathTransfers) { transfersToStop.put(transfer.to, transfer); + transfersFromStop.put(transfer.from, transfer); } for (FlexTrip flexTrip : timetableRepository.getAllFlexTrips()) { routeById.put(flexTrip.getTrip().getRoute().getId(), flexTrip.getTrip().getRoute()); @@ -47,6 +55,10 @@ public Collection getTransfersToStop(StopLocation stopLocation) { return transfersToStop.get(stopLocation); } + public Collection getTransfersFromStop(StopLocation stopLocation) { + return transfersFromStop.get(stopLocation); + } + public Collection> getFlexTripsByStop(StopLocation stopLocation) { return flexTripsByStop.get(stopLocation); } diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexRouter.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexRouter.java index 46d9e527980..e7f3d3544ab 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexRouter.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexRouter.java @@ -192,7 +192,7 @@ public TransitStopVertex getStopVertexForStopId(FeedScopedId stopId) { @Override public Collection getTransfersFromStop(StopLocation stop) { - return transitService.findPathTransfers(stop); + return transitService.getFlexIndex().getTransfersFromStop(stop); } @Override diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index c0deb932418..4c26808ab80 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -3,9 +3,12 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimaps; import java.time.Duration; +import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; @@ -17,6 +20,7 @@ import org.opentripplanner.graph_builder.module.nearbystops.StreetNearbyStopFinder; import org.opentripplanner.model.PathTransfer; import org.opentripplanner.routing.api.request.RouteRequest; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graphfinder.NearbyStop; import org.opentripplanner.street.model.edge.Edge; @@ -102,6 +106,7 @@ public void buildGraph() { LOG.debug("Linking stop '{}' {}", stop, ts0); for (RouteRequest transferProfile : transferRequests) { + StreetMode mode = transferProfile.journey().transfer().mode(); for (NearbyStop sd : nearbyStopFinder.findNearbyStops( ts0, transferProfile, @@ -115,12 +120,12 @@ public void buildGraph() { if (sd.stop.transfersNotAllowed()) { continue; } - distinctTransfers.put( - new TransferKey(stop, sd.stop, sd.edges), - new PathTransfer(stop, sd.stop, sd.distance, sd.edges) - ); + createPathTransfer(distinctTransfers, sd, stop, mode); } - if (OTPFeature.FlexRouting.isOn()) { + } + if (OTPFeature.FlexRouting.isOn()) { + for (RouteRequest transferProfile : transferRequests) { + StreetMode mode = transferProfile.journey().transfer().mode(); // This code is for finding transfers from AreaStops to Stops, transfers // from Stops to AreaStops and between Stops are already covered above. for (NearbyStop sd : nearbyStopFinder.findNearbyStops( @@ -136,10 +141,7 @@ public void buildGraph() { if (sd.stop instanceof RegularStop) { continue; } - distinctTransfers.put( - new TransferKey(sd.stop, stop, sd.edges), - new PathTransfer(sd.stop, stop, sd.distance, sd.edges) - ); + createPathTransfer(distinctTransfers, sd, stop, mode); } } } @@ -174,6 +176,28 @@ public void buildGraph() { ); } + /** + * Factory method for creating a PathTransfer. + */ + private void createPathTransfer( + Map distinctTransfers, + NearbyStop sd, + RegularStop stop, + StreetMode mode + ) { + TransferKey transferKey = new TransferKey(stop, sd.stop, sd.edges); + PathTransfer pathTransfer = distinctTransfers.get(transferKey); + if (pathTransfer == null) { + EnumSet modes = EnumSet.of(mode); + distinctTransfers.put( + transferKey, + new PathTransfer(stop, sd.stop, sd.distance, sd.edges, modes) + ); + } else { + pathTransfer.addMode(mode); + } + } + /** * Factory method for creating a NearbyStopFinder. Will create different finders depending on * whether the graph has a street network and if ConsiderPatternsForDirectTransfers feature is diff --git a/application/src/main/java/org/opentripplanner/model/PathTransfer.java b/application/src/main/java/org/opentripplanner/model/PathTransfer.java index 5b42a8149e3..ed4696ab11c 100644 --- a/application/src/main/java/org/opentripplanner/model/PathTransfer.java +++ b/application/src/main/java/org/opentripplanner/model/PathTransfer.java @@ -1,19 +1,20 @@ package org.opentripplanner.model; import java.io.Serializable; +import java.util.EnumSet; import java.util.List; import org.opentripplanner.model.transfer.ConstrainedTransfer; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.street.model.edge.Edge; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.utils.tostring.ToStringBuilder; /** - * Represents a transfer between stops with the street network path attatched to it. + * Represents a transfer for a set of modes between stops with the street network path attached to it. *

* Do not confuse this with {@link ConstrainedTransfer}. * *

- * TODO these should really have a set of valid modes in case bike vs. walk transfers are different * TODO Should we just store the NearbyStop as a field here, or even switch to using it instead * where this class is used */ @@ -27,11 +28,20 @@ public class PathTransfer implements Serializable { private final List edges; - public PathTransfer(StopLocation from, StopLocation to, double distanceMeters, List edges) { + private EnumSet modes; + + public PathTransfer( + StopLocation from, + StopLocation to, + double distanceMeters, + List edges, + EnumSet modes + ) { this.from = from; this.to = to; this.distanceMeters = distanceMeters; this.edges = edges; + this.modes = modes; } public String getName() { @@ -46,6 +56,14 @@ public List getEdges() { return this.edges; } + public EnumSet getModes() { + return this.modes; + } + + public boolean addMode(StreetMode mode) { + return this.modes.add(mode); + } + @Override public String toString() { return ToStringBuilder @@ -54,6 +72,7 @@ public String toString() { .addObj("to", to) .addNum("distance", distanceMeters) .addColSize("edges", edges) + .addColSize("modes", modes) .toString(); } } diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java index 1d9b804067c..941e1296838 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.function.Function; import org.opentripplanner.raptor.api.model.RaptorTransfer; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.street.search.request.StreetSearchRequest; public class RaptorTransferIndex { @@ -29,6 +30,7 @@ public static RaptorTransferIndex create( ) { var forwardTransfers = new ArrayList>(transfersByStopIndex.size()); var reversedTransfers = new ArrayList>(transfersByStopIndex.size()); + StreetMode mode = request.mode(); for (int i = 0; i < transfersByStopIndex.size(); i++) { forwardTransfers.add(new ArrayList<>()); @@ -41,6 +43,7 @@ public static RaptorTransferIndex create( var transfers = transfersByStopIndex .get(fromStop) .stream() + .filter(transfer -> transfer.getModes().contains(mode)) .flatMap(s -> s.asRaptorTransfer(request).stream()) .collect( toMap(RaptorTransfer::stop, Function.identity(), (a, b) -> a.c1() < b.c1() ? a : b) diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java index 32d54787e6f..c0c923228bf 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java @@ -8,6 +8,7 @@ import org.locationtech.jts.geom.Coordinate; import org.opentripplanner.raptor.api.model.RaptorCostConverter; import org.opentripplanner.raptor.api.model.RaptorTransfer; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.routing.api.request.preference.WalkPreferences; import org.opentripplanner.street.model.edge.Edge; import org.opentripplanner.street.search.request.StreetSearchRequest; @@ -31,16 +32,20 @@ public class Transfer { private final List edges; - public Transfer(int toStop, List edges) { + private final Set modes; + + public Transfer(int toStop, List edges, Set modes) { this.toStop = toStop; this.edges = edges; this.distanceMeters = (int) edges.stream().mapToDouble(Edge::getDistanceMeters).sum(); + this.modes = modes; } - public Transfer(int toStopIndex, int distanceMeters) { + public Transfer(int toStopIndex, int distanceMeters, Set modes) { this.toStop = toStopIndex; this.distanceMeters = distanceMeters; this.edges = null; + this.modes = modes; } public List getCoordinates() { @@ -68,6 +73,10 @@ public List getEdges() { return edges; } + public Set getModes() { + return modes; + } + public Optional asRaptorTransfer(StreetSearchRequest request) { WalkPreferences walkPreferences = request.preferences().walk(); if (edges == null || edges.isEmpty()) { diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java index 3de07da9e19..9fc49c5c5e1 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/mappers/TransfersMapper.java @@ -34,10 +34,15 @@ static List> mapTransfers( int toStopIndex = pathTransfer.to.getIndex(); Transfer newTransfer; if (pathTransfer.getEdges() != null) { - newTransfer = new Transfer(toStopIndex, pathTransfer.getEdges()); + newTransfer = + new Transfer(toStopIndex, pathTransfer.getEdges(), pathTransfer.getModes()); } else { newTransfer = - new Transfer(toStopIndex, (int) Math.ceil(pathTransfer.getDistanceMeters())); + new Transfer( + toStopIndex, + (int) Math.ceil(pathTransfer.getDistanceMeters()), + pathTransfer.getModes() + ); } list.add(newTransfer); diff --git a/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java b/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java index 8f2fc45b875..c397cc74877 100644 --- a/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java +++ b/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Set; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -54,6 +55,7 @@ import org.opentripplanner.routing.algorithm.raptoradapter.transit.TransitLayer; import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.DefaultCostCalculator; import org.opentripplanner.routing.api.request.RouteRequest; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.street.search.state.State; import org.opentripplanner.street.search.state.TestStateBuilder; @@ -199,7 +201,7 @@ void createItineraryWithOnBoardFlexAccess() { flexAccessEgress, AccessEgressType.ACCESS ); - Transfer transfer = new Transfer(S2.getIndex(), 0); + Transfer transfer = new Transfer(S2.getIndex(), 0, Set.of(StreetMode.WALK)); RaptorTransfer raptorTransfer = new DefaultRaptorTransfer(S1.getIndex(), 0, 0, transfer); RaptorAccessEgress egress = new DefaultAccessEgress(S2.getIndex(), state); PathLeg egressLeg = new EgressPathLeg<>(egress, 0, 0, 0); diff --git a/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java b/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java index 8dc4d548c18..ca846148dea 100644 --- a/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java +++ b/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java @@ -6,11 +6,13 @@ import java.util.List; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.opentripplanner._support.geometry.Coordinates; import org.opentripplanner.raptor.api.model.RaptorCostConverter; import org.opentripplanner.raptor.api.model.RaptorTransfer; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.street.model._data.StreetModelForTest; import org.opentripplanner.street.model.vertex.IntersectionVertex; import org.opentripplanner.street.search.request.StreetSearchRequest; @@ -34,7 +36,7 @@ void limitMaxCost() { // very long edge from Berlin to Boston that has of course a huge cost to traverse var edge = StreetModelForTest.streetEdge(BERLIN_V, BOSTON_V); - var veryLongTransfer = new Transfer(0, List.of(edge)); + var veryLongTransfer = new Transfer(0, List.of(edge), Set.of(StreetMode.WALK)); assertTrue(veryLongTransfer.getDistanceMeters() > 1_000_000); // cost would be too high, so it should be capped to a maximum value assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); @@ -43,7 +45,7 @@ void limitMaxCost() { @Test void allowLowCost() { var edge = StreetModelForTest.streetEdge(BERLIN_V, BRANDENBURG_GATE_V); - var transfer = new Transfer(0, List.of(edge)); + var transfer = new Transfer(0, List.of(edge), Set.of(StreetMode.WALK)); assertTrue(transfer.getDistanceMeters() < 4000); final Optional raptorTransfer = transfer.asRaptorTransfer( StreetSearchRequest.of().build() @@ -58,26 +60,26 @@ class WithoutEdges { @Test void overflow() { - var veryLongTransfer = new Transfer(0, Integer.MAX_VALUE); + var veryLongTransfer = new Transfer(0, Integer.MAX_VALUE, Set.of(StreetMode.WALK)); assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); } @Test void negativeCost() { - var veryLongTransfer = new Transfer(0, -5); + var veryLongTransfer = new Transfer(0, -5, Set.of(StreetMode.WALK)); assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); } @Test void limitMaxCost() { - var veryLongTransfer = new Transfer(0, 8_000_000); + var veryLongTransfer = new Transfer(0, 8_000_000, Set.of(StreetMode.WALK)); // cost would be too high, so it will be capped before passing to RAPTOR assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); } @Test void allowLowCost() { - var transfer = new Transfer(0, 200); + var transfer = new Transfer(0, 200, Set.of(StreetMode.WALK)); final Optional raptorTransfer = transfer.asRaptorTransfer( StreetSearchRequest.of().build() ); From 44e4d31e0f7d7945513c2d465035eb173e482f57 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Fri, 29 Nov 2024 15:13:55 +0200 Subject: [PATCH 49/98] Add test for mode-specific transfers. --- .../module/DirectTransferGeneratorTest.java | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java b/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java index 8a17e5258d8..310e474ae99 100644 --- a/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java +++ b/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java @@ -196,7 +196,7 @@ public void testMultipleRequestsWithoutPatterns() { reqWalk.journey().transfer().setMode(StreetMode.WALK); var reqBike = new RouteRequest(); - reqWalk.journey().transfer().setMode(StreetMode.BIKE); + reqBike.journey().transfer().setMode(StreetMode.BIKE); var transferRequests = List.of(reqWalk, reqBike); @@ -223,7 +223,7 @@ public void testMultipleRequestsWithPatterns() { reqWalk.journey().transfer().setMode(StreetMode.WALK); var reqBike = new RouteRequest(); - reqWalk.journey().transfer().setMode(StreetMode.BIKE); + reqBike.journey().transfer().setMode(StreetMode.BIKE); var transferRequests = List.of(reqWalk, reqBike); @@ -250,6 +250,61 @@ public void testMultipleRequestsWithPatterns() { ); } + @Test + public void testPathTransfersWithModesForMultipleRequestsWithPatterns() { + var reqWalk = new RouteRequest(); + reqWalk.journey().transfer().setMode(StreetMode.WALK); + + var reqBike = new RouteRequest(); + reqBike.journey().transfer().setMode(StreetMode.BIKE); + + var transferRequests = List.of(reqWalk, reqBike); + + TestOtpModel model = model(true); + var graph = model.graph(); + graph.hasStreets = true; + var timetableRepository = model.timetableRepository(); + + new DirectTransferGenerator( + graph, + timetableRepository, + DataImportIssueStore.NOOP, + MAX_TRANSFER_DURATION, + transferRequests + ) + .buildGraph(); + + var walkTransfers = timetableRepository + .getAllPathTransfers() + .stream() + .filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.WALK)) + .toList(); + var bikeTransfers = timetableRepository + .getAllPathTransfers() + .stream() + .filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.BIKE)) + .toList(); + var carTransfers = timetableRepository + .getAllPathTransfers() + .stream() + .filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.CAR)) + .toList(); + + assertTransfers( + walkTransfers, + tr(S0, 100, List.of(V0, V11), S11), + tr(S0, 100, List.of(V0, V21), S21), + tr(S11, 100, List.of(V11, V21), S21) + ); + assertTransfers( + bikeTransfers, + tr(S0, 100, List.of(V0, V11), S11), + tr(S0, 100, List.of(V0, V21), S21), + tr(S11, 110, List.of(V11, V22), S22) + ); + assertTransfers(carTransfers); + } + @Test public void testTransferOnIsolatedStations() { var otpModel = model(true, false, true); From 8448e6e91539ae9015269cc8de1ecef453dbc64e Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Fri, 29 Nov 2024 16:25:55 +0200 Subject: [PATCH 50/98] Remove unused imports and small changes. --- .../module/DirectTransferGenerator.java | 2 -- .../algorithm/raptoradapter/transit/Transfer.java | 9 +++++---- .../mapping/RaptorPathToItineraryMapperTest.java | 4 ++-- .../raptoradapter/transit/TransferTest.java | 13 +++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index 4c26808ab80..27fc87d9fff 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -5,10 +5,8 @@ import java.time.Duration; import java.util.EnumSet; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java index c0c923228bf..6ee0dee83c0 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -32,16 +33,16 @@ public class Transfer { private final List edges; - private final Set modes; + private final EnumSet modes; - public Transfer(int toStop, List edges, Set modes) { + public Transfer(int toStop, List edges, EnumSet modes) { this.toStop = toStop; this.edges = edges; this.distanceMeters = (int) edges.stream().mapToDouble(Edge::getDistanceMeters).sum(); this.modes = modes; } - public Transfer(int toStopIndex, int distanceMeters, Set modes) { + public Transfer(int toStopIndex, int distanceMeters, EnumSet modes) { this.toStop = toStopIndex; this.distanceMeters = distanceMeters; this.edges = null; @@ -73,7 +74,7 @@ public List getEdges() { return edges; } - public Set getModes() { + public EnumSet getModes() { return modes; } diff --git a/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java b/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java index c397cc74877..1c43234bd4d 100644 --- a/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java +++ b/application/src/test/java/org/opentripplanner/routing/algorithm/mapping/RaptorPathToItineraryMapperTest.java @@ -12,9 +12,9 @@ import java.time.LocalDateTime; import java.time.Month; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; import java.util.List; -import java.util.Set; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -201,7 +201,7 @@ void createItineraryWithOnBoardFlexAccess() { flexAccessEgress, AccessEgressType.ACCESS ); - Transfer transfer = new Transfer(S2.getIndex(), 0, Set.of(StreetMode.WALK)); + Transfer transfer = new Transfer(S2.getIndex(), 0, EnumSet.of(StreetMode.WALK)); RaptorTransfer raptorTransfer = new DefaultRaptorTransfer(S1.getIndex(), 0, 0, transfer); RaptorAccessEgress egress = new DefaultAccessEgress(S2.getIndex(), state); PathLeg egressLeg = new EgressPathLeg<>(egress, 0, 0, 0); diff --git a/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java b/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java index ca846148dea..7edda8fba9c 100644 --- a/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java +++ b/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opentripplanner.street.model._data.StreetModelForTest.intersectionVertex; +import java.util.EnumSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -36,7 +37,7 @@ void limitMaxCost() { // very long edge from Berlin to Boston that has of course a huge cost to traverse var edge = StreetModelForTest.streetEdge(BERLIN_V, BOSTON_V); - var veryLongTransfer = new Transfer(0, List.of(edge), Set.of(StreetMode.WALK)); + var veryLongTransfer = new Transfer(0, List.of(edge), EnumSet.of(StreetMode.WALK)); assertTrue(veryLongTransfer.getDistanceMeters() > 1_000_000); // cost would be too high, so it should be capped to a maximum value assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); @@ -45,7 +46,7 @@ void limitMaxCost() { @Test void allowLowCost() { var edge = StreetModelForTest.streetEdge(BERLIN_V, BRANDENBURG_GATE_V); - var transfer = new Transfer(0, List.of(edge), Set.of(StreetMode.WALK)); + var transfer = new Transfer(0, List.of(edge), EnumSet.of(StreetMode.WALK)); assertTrue(transfer.getDistanceMeters() < 4000); final Optional raptorTransfer = transfer.asRaptorTransfer( StreetSearchRequest.of().build() @@ -60,26 +61,26 @@ class WithoutEdges { @Test void overflow() { - var veryLongTransfer = new Transfer(0, Integer.MAX_VALUE, Set.of(StreetMode.WALK)); + var veryLongTransfer = new Transfer(0, Integer.MAX_VALUE, EnumSet.of(StreetMode.WALK)); assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); } @Test void negativeCost() { - var veryLongTransfer = new Transfer(0, -5, Set.of(StreetMode.WALK)); + var veryLongTransfer = new Transfer(0, -5, EnumSet.of(StreetMode.WALK)); assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); } @Test void limitMaxCost() { - var veryLongTransfer = new Transfer(0, 8_000_000, Set.of(StreetMode.WALK)); + var veryLongTransfer = new Transfer(0, 8_000_000, EnumSet.of(StreetMode.WALK)); // cost would be too high, so it will be capped before passing to RAPTOR assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get()); } @Test void allowLowCost() { - var transfer = new Transfer(0, 200, Set.of(StreetMode.WALK)); + var transfer = new Transfer(0, 200, EnumSet.of(StreetMode.WALK)); final Optional raptorTransfer = transfer.asRaptorTransfer( StreetSearchRequest.of().build() ); From b3bad269596f10f452c4e8a208f34b2ea10cd407 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 2 Dec 2024 10:24:07 +0200 Subject: [PATCH 51/98] Implement new schema design --- .../apis/gtfs/GtfsGraphQLIndex.java | 12 +- .../CallScheduledTimeTypeResolver.java | 21 +++ ...java => CallStopLocationTypeResolver.java} | 8 +- .../apis/gtfs/datafetchers/CallTimeImpl.java | 25 --- ...timateImpl.java => EstimatedTimeImpl.java} | 6 +- .../apis/gtfs/datafetchers/StopCallImpl.java | 41 +++-- .../datafetchers/TripOnServiceDateImpl.java | 22 +-- .../gtfs/generated/GraphQLDataFetchers.java | 65 ++++---- .../apis/gtfs/generated/graphql-codegen.yml | 5 +- .../apis/gtfs/model/ArrivalDepartureTime.java | 9 + .../apis/gtfs/model/CallRealTime.java | 6 + .../apis/gtfs/model/CallSchedule.java | 3 + .../transit/model/timetable/CallTime.java | 40 ----- ...alTimeEstimate.java => EstimatedTime.java} | 9 +- .../opentripplanner/apis/gtfs/schema.graphqls | 86 +++++----- .../gtfs/expectations/canceled-trips.json | 154 ++++++++++-------- .../apis/gtfs/queries/canceled-trips.graphql | 72 +++++--- 17 files changed, 313 insertions(+), 271 deletions(-) create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallScheduledTimeTypeResolver.java rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{CallTypeResolver.java => CallStopLocationTypeResolver.java} (66%) delete mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java rename application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/{CallRealTimeEstimateImpl.java => EstimatedTimeImpl.java} (69%) create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/model/CallRealTime.java create mode 100644 application/src/main/java/org/opentripplanner/apis/gtfs/model/CallSchedule.java delete mode 100644 application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java rename application/src/main/java/org/opentripplanner/transit/model/timetable/{CallRealTimeEstimate.java => EstimatedTime.java} (69%) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index 28194b21856..302458ac656 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -31,15 +31,15 @@ import org.opentripplanner.apis.gtfs.datafetchers.BikeRentalStationImpl; import org.opentripplanner.apis.gtfs.datafetchers.BookingInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.BookingTimeImpl; -import org.opentripplanner.apis.gtfs.datafetchers.CallRealTimeEstimateImpl; -import org.opentripplanner.apis.gtfs.datafetchers.CallTimeImpl; -import org.opentripplanner.apis.gtfs.datafetchers.CallTypeResolver; +import org.opentripplanner.apis.gtfs.datafetchers.CallScheduledTimeTypeResolver; +import org.opentripplanner.apis.gtfs.datafetchers.CallStopLocationTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.CarParkImpl; import org.opentripplanner.apis.gtfs.datafetchers.ContactInfoImpl; import org.opentripplanner.apis.gtfs.datafetchers.CoordinatesImpl; import org.opentripplanner.apis.gtfs.datafetchers.CurrencyImpl; import org.opentripplanner.apis.gtfs.datafetchers.DefaultFareProductImpl; import org.opentripplanner.apis.gtfs.datafetchers.DepartureRowImpl; +import org.opentripplanner.apis.gtfs.datafetchers.EstimatedTimeImpl; import org.opentripplanner.apis.gtfs.datafetchers.FareProductTypeResolver; import org.opentripplanner.apis.gtfs.datafetchers.FareProductUseImpl; import org.opentripplanner.apis.gtfs.datafetchers.FeedImpl; @@ -135,7 +135,8 @@ protected static GraphQLSchema buildSchema() { .type("StopPosition", type -> type.typeResolver(new StopPosition() {})) .type("FareProduct", type -> type.typeResolver(new FareProductTypeResolver())) .type("AlertEntity", type -> type.typeResolver(new AlertEntityTypeResolver())) - .type("Call", type -> type.typeResolver(new CallTypeResolver())) + .type("CallStopLocation", type -> type.typeResolver(new CallStopLocationTypeResolver())) + .type("CallScheduledTime", type -> type.typeResolver(new CallScheduledTimeTypeResolver())) .type(typeWiring.build(AgencyImpl.class)) .type(typeWiring.build(AlertImpl.class)) .type(typeWiring.build(BikeParkImpl.class)) @@ -193,8 +194,7 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(TripOccupancyImpl.class)) .type(typeWiring.build(LegTimeImpl.class)) .type(typeWiring.build(RealTimeEstimateImpl.class)) - .type(typeWiring.build(CallTimeImpl.class)) - .type(typeWiring.build(CallRealTimeEstimateImpl.class)) + .type(typeWiring.build(EstimatedTimeImpl.class)) .build(); SchemaGenerator schemaGenerator = new SchemaGenerator(); return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallScheduledTimeTypeResolver.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallScheduledTimeTypeResolver.java new file mode 100644 index 00000000000..ac45b3766b6 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallScheduledTimeTypeResolver.java @@ -0,0 +1,21 @@ +package org.opentripplanner.apis.gtfs.datafetchers; + +import graphql.TypeResolutionEnvironment; +import graphql.schema.GraphQLObjectType; +import graphql.schema.GraphQLSchema; +import graphql.schema.TypeResolver; +import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; + +public class CallScheduledTimeTypeResolver implements TypeResolver { + + @Override + public GraphQLObjectType getType(TypeResolutionEnvironment environment) { + Object o = environment.getObject(); + GraphQLSchema schema = environment.getSchema(); + + if (o instanceof ArrivalDepartureTime) { + return schema.getObjectType("ArrivalDepartureTime"); + } + return null; + } +} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTypeResolver.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallStopLocationTypeResolver.java similarity index 66% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTypeResolver.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallStopLocationTypeResolver.java index 02ee6784073..5a7b02320a3 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTypeResolver.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallStopLocationTypeResolver.java @@ -4,17 +4,17 @@ import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLSchema; import graphql.schema.TypeResolver; -import org.opentripplanner.model.TripTimeOnDate; +import org.opentripplanner.transit.model.site.StopLocation; -public class CallTypeResolver implements TypeResolver { +public class CallStopLocationTypeResolver implements TypeResolver { @Override public GraphQLObjectType getType(TypeResolutionEnvironment environment) { Object o = environment.getObject(); GraphQLSchema schema = environment.getSchema(); - if (o instanceof TripTimeOnDate) { - return schema.getObjectType("StopCall"); + if (o instanceof StopLocation) { + return schema.getObjectType("Stop"); } return null; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java deleted file mode 100644 index 5a2da2c2d82..00000000000 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallTimeImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.opentripplanner.apis.gtfs.datafetchers; - -import graphql.schema.DataFetcher; -import graphql.schema.DataFetchingEnvironment; -import java.time.OffsetDateTime; -import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; -import org.opentripplanner.transit.model.timetable.CallRealTimeEstimate; -import org.opentripplanner.transit.model.timetable.CallTime; - -public class CallTimeImpl implements GraphQLDataFetchers.GraphQLCallTime { - - @Override - public DataFetcher estimated() { - return environment -> getSource(environment).estimated(); - } - - @Override - public DataFetcher scheduledTime() { - return environment -> getSource(environment).scheduledTime().toOffsetDateTime(); - } - - private CallTime getSource(DataFetchingEnvironment environment) { - return environment.getSource(); - } -} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallRealTimeEstimateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/EstimatedTimeImpl.java similarity index 69% rename from application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallRealTimeEstimateImpl.java rename to application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/EstimatedTimeImpl.java index 09439c6e916..eebb64ee625 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/CallRealTimeEstimateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/EstimatedTimeImpl.java @@ -5,9 +5,9 @@ import java.time.Duration; import java.time.OffsetDateTime; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; -import org.opentripplanner.transit.model.timetable.CallRealTimeEstimate; +import org.opentripplanner.transit.model.timetable.EstimatedTime; -public class CallRealTimeEstimateImpl implements GraphQLDataFetchers.GraphQLCallRealTimeEstimate { +public class EstimatedTimeImpl implements GraphQLDataFetchers.GraphQLEstimatedTime { @Override public DataFetcher delay() { @@ -19,7 +19,7 @@ public DataFetcher time() { return environment -> getSource(environment).time().toOffsetDateTime(); } - private CallRealTimeEstimate getSource(DataFetchingEnvironment environment) { + private EstimatedTime getSource(DataFetchingEnvironment environment) { return environment.getSource(); } } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StopCallImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StopCallImpl.java index cb5ec7e15a5..4d3ede74c76 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StopCallImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StopCallImpl.java @@ -7,43 +7,52 @@ import java.time.ZonedDateTime; import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.apis.gtfs.model.ArrivalDepartureTime; +import org.opentripplanner.apis.gtfs.model.CallRealTime; +import org.opentripplanner.apis.gtfs.model.CallSchedule; import org.opentripplanner.model.TripTimeOnDate; -import org.opentripplanner.transit.model.timetable.CallTime; +import org.opentripplanner.transit.model.timetable.EstimatedTime; import org.opentripplanner.transit.service.TransitService; import org.opentripplanner.utils.time.ServiceDateUtils; public class StopCallImpl implements GraphQLDataFetchers.GraphQLStopCall { @Override - public DataFetcher arrival() { + public DataFetcher realTime() { return environment -> { var tripTime = getSource(environment); - var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledArrival()); - if (scheduledTime == null) { + if (!tripTime.isRealtime()) { return null; } - return tripTime.isRealtime() - ? CallTime.of(scheduledTime, tripTime.getArrivalDelay()) - : CallTime.ofStatic(scheduledTime); + var scheduledArrival = getZonedDateTime(environment, tripTime.getScheduledArrival()); + var estimatedArrival = scheduledArrival == null + ? null + : EstimatedTime.of(scheduledArrival, tripTime.getArrivalDelay()); + var scheduledDeparture = getZonedDateTime(environment, tripTime.getScheduledDeparture()); + var estimatedDeparture = scheduledDeparture == null + ? null + : EstimatedTime.of(scheduledDeparture, tripTime.getDepartureDelay()); + return new CallRealTime(estimatedArrival, estimatedDeparture); }; } @Override - public DataFetcher departure() { + public DataFetcher schedule() { return environment -> { var tripTime = getSource(environment); - var scheduledTime = getZonedDateTime(environment, tripTime.getScheduledDeparture()); - if (scheduledTime == null) { - return null; - } - return tripTime.isRealtime() - ? CallTime.of(scheduledTime, tripTime.getDepartureDelay()) - : CallTime.ofStatic(scheduledTime); + var scheduledArrival = getZonedDateTime(environment, tripTime.getScheduledArrival()); + var scheduledDeparture = getZonedDateTime(environment, tripTime.getScheduledDeparture()); + return new CallSchedule( + new ArrivalDepartureTime( + scheduledArrival == null ? null : scheduledArrival.toOffsetDateTime(), + scheduledDeparture == null ? null : scheduledDeparture.toOffsetDateTime() + ) + ); }; } @Override - public DataFetcher stop() { + public DataFetcher stopLocation() { return environment -> getSource(environment).getStop(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java index aae18085cc1..3b00551835e 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/TripOnServiceDateImpl.java @@ -24,7 +24,7 @@ public DataFetcher serviceDate() { } @Override - public DataFetcher end() { + public DataFetcher end() { return environment -> { var arguments = getFromTripTimesArguments(environment); if (arguments.timetable() == null) { @@ -40,7 +40,7 @@ public DataFetcher end() { } @Override - public DataFetcher start() { + public DataFetcher start() { return environment -> { var arguments = getFromTripTimesArguments(environment); if (arguments.timetable() == null) { @@ -56,22 +56,18 @@ public DataFetcher start() { } @Override - public DataFetcher> stopCalls() { + public DataFetcher> stopCalls() { return environment -> { var arguments = getFromTripTimesArguments(environment); if (arguments.timetable() == null) { return List.of(); } - return TripTimeOnDate - .fromTripTimes( - arguments.timetable(), - arguments.trip(), - arguments.serviceDate(), - arguments.midnight() - ) - .stream() - .map(Object.class::cast) - .toList(); + return TripTimeOnDate.fromTripTimes( + arguments.timetable(), + arguments.trip(), + arguments.serviceDate(), + arguments.midnight() + ); }; } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 986fb9b8318..fb3c0ddbb41 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -23,6 +23,8 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRelativeDirection; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; +import org.opentripplanner.apis.gtfs.model.CallRealTime; +import org.opentripplanner.apis.gtfs.model.CallSchedule; import org.opentripplanner.apis.gtfs.model.FeedPublisher; import org.opentripplanner.apis.gtfs.model.PlanPageInfo; import org.opentripplanner.apis.gtfs.model.RideHailingProvider; @@ -67,8 +69,7 @@ import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.network.TripPattern; import org.opentripplanner.transit.model.organization.Agency; -import org.opentripplanner.transit.model.timetable.CallRealTimeEstimate; -import org.opentripplanner.transit.model.timetable.CallTime; +import org.opentripplanner.transit.model.timetable.EstimatedTime; import org.opentripplanner.transit.model.timetable.Trip; import org.opentripplanner.transit.model.timetable.TripOnServiceDate; import org.opentripplanner.transit.model.timetable.booking.BookingInfo; @@ -145,6 +146,13 @@ public interface GraphQLAlert { /** Entity related to an alert */ public interface GraphQLAlertEntity extends TypeResolver {} + /** Arrival and departure time (not relative to midnight). */ + public interface GraphQLArrivalDepartureTime { + public DataFetcher arrival(); + + public DataFetcher departure(); + } + /** Bike park represents a location where bicycles can be parked. */ public interface GraphQLBikePark { public DataFetcher bikeParkId(); @@ -242,28 +250,23 @@ public interface GraphQLBookingTime { public DataFetcher time(); } - /** - * Call is a visit to a location (a stop or an area) in a trip on service date. It can contain - * exact arrival and departure times and/or a scheduled time window. - */ - public interface GraphQLCall extends TypeResolver {} + /** Real-time estimates for arrival and departure times for a stop location. */ + public interface GraphQLCallRealTime { + public DataFetcher arrival(); - /** Real-time estimates for an arrival or departure at a certain place. */ - public interface GraphQLCallRealTimeEstimate { - public DataFetcher delay(); + public DataFetcher departure(); + } - public DataFetcher time(); + /** What is scheduled for a trip on a service date for a stop location. */ + public interface GraphQLCallSchedule { + public DataFetcher time(); } - /** - * Timing of an arrival or a departure to or from a stop. May contain real-time information if - * available. This is used when there is a known scheduled time. - */ - public interface GraphQLCallTime { - public DataFetcher estimated(); + /** Scheduled times for a trip on a service date for a stop location. */ + public interface GraphQLCallScheduledTime extends TypeResolver {} - public DataFetcher scheduledTime(); - } + /** Location where a transit vehicle stops at. */ + public interface GraphQLCallStopLocation extends TypeResolver {} /** Car park represents a location where cars can be parked. */ public interface GraphQLCarPark { @@ -385,6 +388,13 @@ public interface GraphQLEmissions { public DataFetcher co2(); } + /** Real-time estimates for an arrival or departure at a certain place. */ + public interface GraphQLEstimatedTime { + public DataFetcher delay(); + + public DataFetcher time(); + } + /** A 'medium' that a fare product applies to, for example cash, 'Oyster Card' or 'DB Navigator App'. */ public interface GraphQLFareMedium { public DataFetcher id(); @@ -1073,16 +1083,13 @@ public interface GraphQLStop { public DataFetcher zoneId(); } - /** - * Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. - * The times are exact (although can be changed by real-time updates), not time windows. - */ + /** Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop location. */ public interface GraphQLStopCall { - public DataFetcher arrival(); + public DataFetcher realTime(); - public DataFetcher departure(); + public DataFetcher schedule(); - public DataFetcher stop(); + public DataFetcher stopLocation(); } public interface GraphQLStopGeometries { @@ -1253,13 +1260,13 @@ public interface GraphQLTripOccupancy { /** A trip on a specific service date. */ public interface GraphQLTripOnServiceDate { - public DataFetcher end(); + public DataFetcher end(); public DataFetcher serviceDate(); - public DataFetcher start(); + public DataFetcher start(); - public DataFetcher> stopCalls(); + public DataFetcher> stopCalls(); public DataFetcher trip(); } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 117744d314a..a12f9ff2c64 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -63,7 +63,6 @@ config: TripOnServiceDate: org.opentripplanner.transit.model.timetable.TripOnServiceDate#TripOnServiceDate TripOnServiceDateConnection: graphql.relay.Connection#Connection TripOnServiceDateEdge: graphql.relay.Edge#Edge - CallTime: org.opentripplanner.transit.model.timetable.CallTime#CallTime debugOutput: org.opentripplanner.api.resource.DebugOutput#DebugOutput DepartureRow: org.opentripplanner.routing.graphfinder.PatternAtStop#PatternAtStop elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step @@ -131,6 +130,8 @@ config: RiderCategory: org.opentripplanner.model.fare.RiderCategory#RiderCategory StopPosition: org.opentripplanner.apis.gtfs.model.StopPosition#StopPosition RealTimeEstimate: org.opentripplanner.model.plan.LegRealTimeEstimate#LegRealTimeEstimate - CallRealTimeEstimate: org.opentripplanner.transit.model.timetable.CallRealTimeEstimate#CallRealTimeEstimate + EstimatedTime: org.opentripplanner.transit.model.timetable.EstimatedTime#EstimatedTime + CallRealTime: org.opentripplanner.apis.gtfs.model.CallRealTime#CallRealTime RentalPlace: org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace#VehicleRentalPlace + CallSchedule: org.opentripplanner.apis.gtfs.model.CallSchedule#CallSchedule diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java b/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java new file mode 100644 index 00000000000..f72bdd0b3e9 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/model/ArrivalDepartureTime.java @@ -0,0 +1,9 @@ +package org.opentripplanner.apis.gtfs.model; + +import java.time.OffsetDateTime; +import javax.annotation.Nullable; + +public record ArrivalDepartureTime( + @Nullable OffsetDateTime arrival, + @Nullable OffsetDateTime departure +) {} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/model/CallRealTime.java b/application/src/main/java/org/opentripplanner/apis/gtfs/model/CallRealTime.java new file mode 100644 index 00000000000..94caf731627 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/model/CallRealTime.java @@ -0,0 +1,6 @@ +package org.opentripplanner.apis.gtfs.model; + +import javax.annotation.Nullable; +import org.opentripplanner.transit.model.timetable.EstimatedTime; + +public record CallRealTime(@Nullable EstimatedTime arrival, @Nullable EstimatedTime departure) {} diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/model/CallSchedule.java b/application/src/main/java/org/opentripplanner/apis/gtfs/model/CallSchedule.java new file mode 100644 index 00000000000..6b35d2ed425 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/model/CallSchedule.java @@ -0,0 +1,3 @@ +package org.opentripplanner.apis.gtfs.model; + +public record CallSchedule(ArrivalDepartureTime time) {} diff --git a/application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java b/application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java deleted file mode 100644 index 4a7df9fb217..00000000000 --- a/application/src/main/java/org/opentripplanner/transit/model/timetable/CallTime.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.opentripplanner.transit.model.timetable; - -import java.time.Duration; -import java.time.ZonedDateTime; -import java.util.Objects; -import javax.annotation.Nullable; - -/** - * A scheduled time of a transit vehicle at a certain location with an optional realtime - * information. This is meant to be used in timetables (not in transit legs). - */ -public class CallTime { - - private final ZonedDateTime scheduledTime; - - @Nullable - private final CallRealTimeEstimate estimated; - - private CallTime(ZonedDateTime scheduledTime, @Nullable CallRealTimeEstimate estimated) { - this.scheduledTime = Objects.requireNonNull(scheduledTime); - this.estimated = estimated; - } - - public static CallTime of(ZonedDateTime realtime, int delaySecs) { - var delay = Duration.ofSeconds(delaySecs); - return new CallTime(realtime.minus(delay), new CallRealTimeEstimate(realtime, delay)); - } - - public static CallTime ofStatic(ZonedDateTime staticTime) { - return new CallTime(staticTime, null); - } - - public ZonedDateTime scheduledTime() { - return scheduledTime; - } - - public CallRealTimeEstimate estimated() { - return estimated; - } -} diff --git a/application/src/main/java/org/opentripplanner/transit/model/timetable/CallRealTimeEstimate.java b/application/src/main/java/org/opentripplanner/transit/model/timetable/EstimatedTime.java similarity index 69% rename from application/src/main/java/org/opentripplanner/transit/model/timetable/CallRealTimeEstimate.java rename to application/src/main/java/org/opentripplanner/transit/model/timetable/EstimatedTime.java index eeac4a321c4..359a8c7de6a 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/timetable/CallRealTimeEstimate.java +++ b/application/src/main/java/org/opentripplanner/transit/model/timetable/EstimatedTime.java @@ -8,7 +8,7 @@ * Realtime information about a vehicle at a certain place. This is meant to be used in timetables * (not in transit legs). */ -public class CallRealTimeEstimate { +public class EstimatedTime { private final ZonedDateTime time; private final Duration delay; @@ -16,11 +16,16 @@ public class CallRealTimeEstimate { /** * @param delay Delay or "earliness" of a vehicle. Earliness is expressed as a negative number. */ - public CallRealTimeEstimate(ZonedDateTime time, Duration delay) { + private EstimatedTime(ZonedDateTime time, Duration delay) { this.time = Objects.requireNonNull(time); this.delay = Objects.requireNonNull(delay); } + public static EstimatedTime of(ZonedDateTime scheduledTime, int delaySecs) { + var delay = Duration.ofSeconds(delaySecs); + return new EstimatedTime(scheduledTime.minus(delay), delay); + } + public ZonedDateTime time() { return time; } diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index d7e540e1a1b..10aa3f8c524 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -73,11 +73,11 @@ interface PlaceInterface { "Entity related to an alert" union AlertEntity = Agency | Pattern | Route | RouteType | Stop | StopOnRoute | StopOnTrip | Trip | Unknown -""" -Call is a visit to a location (a stop or an area) in a trip on service date. It can contain -exact arrival and departure times and/or a scheduled time window. -""" -union Call = StopCall +"Scheduled times for a trip on a service date for a stop location." +union CallScheduledTime = ArrivalDepartureTime + +"Location where a transit vehicle stops at." +union CallStopLocation = Stop "Rental place union that represents either a VehicleRentalStation or a RentalVehicle" union RentalPlace = RentalVehicle | VehicleRentalStation @@ -172,6 +172,14 @@ type Alert implements Node { trip: Trip @deprecated(reason : "Alert can have multiple affected entities now instead of there being duplicate alerts\nfor different entities. This will return only one of the affected trips.\nUse entities instead.") } +"Arrival and departure time (not relative to midnight)." +type ArrivalDepartureTime { + "Arrival time as an ISO-8601-formatted datetime." + arrival: OffsetDateTime + "Departure time as an ISO-8601-formatted datetime." + departure: OffsetDateTime +} + "Bike park represents a location where bicycles can be parked." type BikePark implements Node & PlaceInterface { "ID of the bike park" @@ -303,27 +311,18 @@ type BookingTime { time: String } -"Real-time estimates for an arrival or departure at a certain place." -type CallRealTimeEstimate { - """ - The delay or "earliness" of the vehicle at a certain place. This estimate can change quite often. - - If the vehicle is early then this is a negative duration. - """ - delay: Duration! - "The estimate for a call event (such as arrival or departure) at a certain place. This estimate can change quite often." - time: OffsetDateTime! +"Real-time estimates for arrival and departure times for a stop location." +type CallRealTime { + "Real-time estimates for the arrival." + arrival: EstimatedTime + "Real-time estimates for the departure." + departure: EstimatedTime } -""" -Timing of an arrival or a departure to or from a stop. May contain real-time information if -available. This is used when there is a known scheduled time. -""" -type CallTime { - "The estimated time of the event. If no real-time information is available, this is null." - estimated: CallRealTimeEstimate - "The scheduled time of the event." - scheduledTime: OffsetDateTime +"What is scheduled for a trip on a service date for a stop location." +type CallSchedule { + "Scheduled time for a trip on a service date for a stop location." + time: CallScheduledTime } "Car park represents a location where cars can be parked." @@ -485,6 +484,18 @@ type Emissions { co2: Grams } +"Real-time estimates for an arrival or departure at a certain place." +type EstimatedTime { + """ + The delay or "earliness" of the vehicle at a certain place. This estimate can change quite often. + + If the vehicle is early then this is a negative duration. + """ + delay: Duration! + "The estimate for a call event (such as arrival or departure) at a certain place. This estimate can change quite often." + time: OffsetDateTime! +} + "A 'medium' that a fare product applies to, for example cash, 'Oyster Card' or 'DB Navigator App'." type FareMedium { "ID of the medium" @@ -2217,17 +2228,14 @@ type Stop implements Node & PlaceInterface { zoneId: String } -""" -Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop. -The times are exact (although can be changed by real-time updates), not time windows. -""" +"Stop call represents the time when a specific trip on a specific date arrives to and/or departs from a specific stop location." type StopCall { - "Scheduled arrival time to the stop and a real-time estimate, if one exists." - arrival: CallTime - "Scheduled departure time from the stop and a real-time estimate, if one exists." - departure: CallTime + "Real-time estimates for arrival and departure times for this stop location." + realTime: CallRealTime + "Scheduled arrival and departure times for this stop location." + schedule: CallSchedule "The stop where this arrival/departure happens" - stop: Stop + stopLocation: CallStopLocation! } type StopGeometries { @@ -2487,8 +2495,8 @@ type TripOccupancy { "A trip on a specific service date." type TripOnServiceDate { - "Information related to trip's scheduled arrival to the final stop. Can contain realtime information." - end: Call! + "Information related to trip's scheduled arrival to the final stop location. Can contain realtime information." + end: StopCall! """ The service date when the trip occurs. @@ -2497,10 +2505,10 @@ type TripOnServiceDate { on Sunday morning at 1am to 3am, might have the previous Saturday's service date. """ serviceDate: LocalDate! - "Information related to trip's scheduled departure from the first stop. Can contain realtime information." - start: Call! - "List of times when this trip arrives to or departs from a stop and information related to the stop" - stopCalls: [Call!]! + "Information related to trip's scheduled departure from the first stop location. Can contain realtime information." + start: StopCall! + "List of times when this trip arrives to or departs from a stop location and information related to the visit to the stop location." + stopCalls: [StopCall!]! "This trip on service date is an instance of this trip." trip: Trip } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json index 5e32b67fc4e..1e2b4d39a3f 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/canceled-trips.json @@ -1,99 +1,119 @@ { - "data": { - "canceledTrips": { - "pageInfo": { - "hasNextPage": false, - "hasPreviousPage": false, - "startCursor": "c2ltcGxlLWN1cnNvcjA=", - "endCursor": "c2ltcGxlLWN1cnNvcjA=" + "data" : { + "canceledTrips" : { + "pageInfo" : { + "hasNextPage" : false, + "hasPreviousPage" : false, + "startCursor" : "c2ltcGxlLWN1cnNvcjA=", + "endCursor" : "c2ltcGxlLWN1cnNvcjA=" }, - "edges": [ + "edges" : [ { - "node": { - "serviceDate": "2024-08-09", - "end": { - "arrival": { - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:40:00+02:00" - }, - "scheduledTime": "2024-08-09T11:40:00+02:00" + "node" : { + "serviceDate" : "2024-08-09", + "end" : { + "schedule" : { + "time" : { + "arrival" : "2024-08-09T11:40:00+02:00" + } + }, + "realTime" : { + "arrival" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:40:00+02:00" + } + }, + "stopLocation" : { + "gtfsId" : "F:Stop_2" } }, - "start": { - "departure": { - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:30:00+02:00" - }, - "scheduledTime": "2024-08-09T11:30:00+02:00" + "start" : { + "schedule" : { + "time" : { + "departure" : "2024-08-09T11:30:00+02:00" + } + }, + "realTime" : { + "departure" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:30:00+02:00" + } + }, + "stopLocation" : { + "gtfsId" : "F:Stop_0" } }, - "stopCalls": [ + "stopCalls" : [ { - "stop": { - "gtfsId": "F:Stop_0" - }, - "arrival": { - "scheduledTime": "2024-08-09T11:30:00+02:00", - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:30:00+02:00" + "schedule" : { + "time" : { + "arrival" : "2024-08-09T11:30:00+02:00", + "departure" : "2024-08-09T11:30:00+02:00" } }, - "departure": { - "scheduledTime": "2024-08-09T11:30:00+02:00", - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:30:00+02:00" + "realTime" : { + "arrival" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:30:00+02:00" + }, + "departure" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:30:00+02:00" } + }, + "stopLocation" : { + "gtfsId" : "F:Stop_0" } }, { - "stop": { - "gtfsId": "F:Stop_1" - }, - "arrival": { - "scheduledTime": "2024-08-09T11:35:00+02:00", - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:35:00+02:00" + "schedule" : { + "time" : { + "arrival" : "2024-08-09T11:35:00+02:00", + "departure" : "2024-08-09T11:35:00+02:00" } }, - "departure": { - "scheduledTime": "2024-08-09T11:35:00+02:00", - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:35:00+02:00" + "realTime" : { + "arrival" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:35:00+02:00" + }, + "departure" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:35:00+02:00" } + }, + "stopLocation" : { + "gtfsId" : "F:Stop_1" } }, { - "stop": { - "gtfsId": "F:Stop_2" - }, - "arrival": { - "scheduledTime": "2024-08-09T11:40:00+02:00", - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:40:00+02:00" + "schedule" : { + "time" : { + "arrival" : "2024-08-09T11:40:00+02:00", + "departure" : "2024-08-09T11:40:00+02:00" } }, - "departure": { - "scheduledTime": "2024-08-09T11:40:00+02:00", - "estimated": { - "delay": "PT0S", - "time": "2024-08-09T11:40:00+02:00" + "realTime" : { + "arrival" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:40:00+02:00" + }, + "departure" : { + "delay" : "PT0S", + "time" : "2024-08-09T11:40:00+02:00" } + }, + "stopLocation" : { + "gtfsId" : "F:Stop_2" } } ], - "trip": { - "gtfsId": "F:321Canceled" + "trip" : { + "gtfsId" : "F:321Canceled" } } } ] } } -} +} \ No newline at end of file diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql index b3817605f37..988a1e62cd9 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/canceled-trips.graphql @@ -10,45 +10,67 @@ node { serviceDate end { - ... on StopCall { - arrival { - estimated { - delay - time + schedule { + time { + ... on ArrivalDepartureTime { + arrival } - scheduledTime + } + } + realTime { + arrival { + delay + time + } + } + stopLocation { + ... on Stop { + gtfsId } } } start { - ... on StopCall { - departure { - estimated { - delay - time + schedule { + time { + ... on ArrivalDepartureTime { + departure } - scheduledTime + } + } + realTime { + departure { + delay + time + } + } + stopLocation { + ... on Stop { + gtfsId } } } stopCalls { - ... on StopCall { - stop { - gtfsId + schedule { + time { + ... on ArrivalDepartureTime { + arrival + departure + } } + } + realTime { arrival { - scheduledTime - estimated { - delay - time - } + delay + time } departure { - scheduledTime - estimated { - delay - time - } + delay + time + } + } + stopLocation { + ... on Stop { + gtfsId } } } From 6a485a35c7282c915be8e491af863be450cc787c Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 2 Dec 2024 11:05:02 +0200 Subject: [PATCH 52/98] Minor schema doc fixes --- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 10aa3f8c524..04fd2220283 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -2234,7 +2234,7 @@ type StopCall { realTime: CallRealTime "Scheduled arrival and departure times for this stop location." schedule: CallSchedule - "The stop where this arrival/departure happens" + "The stop where this arrival/departure happens." stopLocation: CallStopLocation! } @@ -2495,7 +2495,7 @@ type TripOccupancy { "A trip on a specific service date." type TripOnServiceDate { - "Information related to trip's scheduled arrival to the final stop location. Can contain realtime information." + "Information related to trip's scheduled arrival to the final stop location. Can contain real-time information." end: StopCall! """ The service date when the trip occurs. @@ -2505,7 +2505,7 @@ type TripOnServiceDate { on Sunday morning at 1am to 3am, might have the previous Saturday's service date. """ serviceDate: LocalDate! - "Information related to trip's scheduled departure from the first stop location. Can contain realtime information." + "Information related to trip's scheduled departure from the first stop location. Can contain real-time information." start: StopCall! "List of times when this trip arrives to or departs from a stop location and information related to the visit to the stop location." stopCalls: [StopCall!]! From 5217ce51f2c66c978b33f1f71a89d8f54a41dcaa Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Mon, 2 Dec 2024 11:05:09 +0200 Subject: [PATCH 53/98] Formatting --- .../apis/gtfs/expectations/patterns.json | 208 +++++++++--------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json index e9882981a13..4aac9295cc9 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/patterns.json @@ -1,145 +1,145 @@ { - "data" : { - "patterns" : [ + "data": { + "patterns": [ { - "code" : "F:BUS", - "headsign" : "Trip Headsign", - "trips" : [ + "code": "F:BUS", + "headsign": "Trip Headsign", + "trips": [ { - "gtfsId" : "F:123", - "stoptimes" : [ + "gtfsId": "F:123", + "stoptimes": [ { - "stop" : { - "gtfsId" : "F:Stop_0", - "name" : "Stop_0" + "stop": { + "gtfsId": "F:Stop_0", + "name": "Stop_0" }, - "headsign" : "Stop headsign at stop 10", - "scheduledArrival" : 39600, - "scheduledDeparture" : 39600, - "stopPosition" : 10, - "stopPositionInPattern" : 0, - "realtimeState" : "SCHEDULED", - "pickupType" : "SCHEDULED", - "dropoffType" : "SCHEDULED" + "headsign": "Stop headsign at stop 10", + "scheduledArrival": 39600, + "scheduledDeparture": 39600, + "stopPosition": 10, + "stopPositionInPattern": 0, + "realtimeState": "SCHEDULED", + "pickupType": "SCHEDULED", + "dropoffType": "SCHEDULED" }, { - "stop" : { - "gtfsId" : "F:Stop_1", - "name" : "Stop_1" + "stop": { + "gtfsId": "F:Stop_1", + "name": "Stop_1" }, - "headsign" : "Stop headsign at stop 20", - "scheduledArrival" : 39900, - "scheduledDeparture" : 39900, - "stopPosition" : 20, - "stopPositionInPattern" : 1, - "realtimeState" : "SCHEDULED", - "pickupType" : "SCHEDULED", - "dropoffType" : "SCHEDULED" + "headsign": "Stop headsign at stop 20", + "scheduledArrival": 39900, + "scheduledDeparture": 39900, + "stopPosition": 20, + "stopPositionInPattern": 1, + "realtimeState": "SCHEDULED", + "pickupType": "SCHEDULED", + "dropoffType": "SCHEDULED" }, { - "stop" : { - "gtfsId" : "F:Stop_2", - "name" : "Stop_2" + "stop": { + "gtfsId": "F:Stop_2", + "name": "Stop_2" }, - "headsign" : "Stop headsign at stop 30", - "scheduledArrival" : 40200, - "scheduledDeparture" : 40200, - "stopPosition" : 30, - "stopPositionInPattern" : 2, - "realtimeState" : "SCHEDULED", - "pickupType" : "SCHEDULED", - "dropoffType" : "SCHEDULED" + "headsign": "Stop headsign at stop 30", + "scheduledArrival": 40200, + "scheduledDeparture": 40200, + "stopPosition": 30, + "stopPositionInPattern": 2, + "realtimeState": "SCHEDULED", + "pickupType": "SCHEDULED", + "dropoffType": "SCHEDULED" } ], - "occupancy" : { - "occupancyStatus" : "FEW_SEATS_AVAILABLE" + "occupancy": { + "occupancyStatus": "FEW_SEATS_AVAILABLE" } }, { - "gtfsId" : "F:321Canceled", - "stoptimes" : [ + "gtfsId": "F:321Canceled", + "stoptimes": [ { - "stop" : { - "gtfsId" : "F:Stop_0", - "name" : "Stop_0" + "stop": { + "gtfsId": "F:Stop_0", + "name": "Stop_0" }, - "headsign" : "Stop headsign at stop 10", - "scheduledArrival" : 41400, - "scheduledDeparture" : 41400, - "stopPosition" : 10, - "stopPositionInPattern" : 0, - "realtimeState" : "CANCELED", - "pickupType" : null, - "dropoffType" : null + "headsign": "Stop headsign at stop 10", + "scheduledArrival": 41400, + "scheduledDeparture": 41400, + "stopPosition": 10, + "stopPositionInPattern": 0, + "realtimeState": "CANCELED", + "pickupType": null, + "dropoffType": null }, { - "stop" : { - "gtfsId" : "F:Stop_1", - "name" : "Stop_1" + "stop": { + "gtfsId": "F:Stop_1", + "name": "Stop_1" }, - "headsign" : "Stop headsign at stop 20", - "scheduledArrival" : 41700, - "scheduledDeparture" : 41700, - "stopPosition" : 20, - "stopPositionInPattern" : 1, - "realtimeState" : "CANCELED", - "pickupType" : null, - "dropoffType" : null + "headsign": "Stop headsign at stop 20", + "scheduledArrival": 41700, + "scheduledDeparture": 41700, + "stopPosition": 20, + "stopPositionInPattern": 1, + "realtimeState": "CANCELED", + "pickupType": null, + "dropoffType": null }, { - "stop" : { - "gtfsId" : "F:Stop_2", - "name" : "Stop_2" + "stop": { + "gtfsId": "F:Stop_2", + "name": "Stop_2" }, - "headsign" : "Stop headsign at stop 30", - "scheduledArrival" : 42000, - "scheduledDeparture" : 42000, - "stopPosition" : 30, - "stopPositionInPattern" : 2, - "realtimeState" : "CANCELED", - "pickupType" : null, - "dropoffType" : null + "headsign": "Stop headsign at stop 30", + "scheduledArrival": 42000, + "scheduledDeparture": 42000, + "stopPosition": 30, + "stopPositionInPattern": 2, + "realtimeState": "CANCELED", + "pickupType": null, + "dropoffType": null } ], - "occupancy" : { - "occupancyStatus" : "NO_DATA_AVAILABLE" + "occupancy": { + "occupancyStatus": "NO_DATA_AVAILABLE" } } ], - "vehiclePositions" : [ + "vehiclePositions": [ { - "vehicleId" : "F:vehicle-1", - "label" : null, - "lat" : null, - "lon" : null, - "stopRelationship" : null, - "speed" : null, - "heading" : null, - "lastUpdated" : 31556889864403199, - "trip" : { - "gtfsId" : "F:123" + "vehicleId": "F:vehicle-1", + "label": null, + "lat": null, + "lon": null, + "stopRelationship": null, + "speed": null, + "heading": null, + "lastUpdated": 31556889864403199, + "trip": { + "gtfsId": "F:123" } }, { - "vehicleId" : "F:vehicle-2", - "label" : "vehicle2", - "lat" : 60.0, - "lon" : 80.0, - "stopRelationship" : { - "status" : "IN_TRANSIT_TO", - "stop" : { - "gtfsId" : "F:Stop_0" + "vehicleId": "F:vehicle-2", + "label": "vehicle2", + "lat": 60.0, + "lon": 80.0, + "stopRelationship": { + "status": "IN_TRANSIT_TO", + "stop": { + "gtfsId": "F:Stop_0" } }, - "speed" : 10.2, - "heading" : 80.0, - "lastUpdated" : -31557014167219200, - "trip" : { - "gtfsId" : "F:123" + "speed": 10.2, + "heading": 80.0, + "lastUpdated": -31557014167219200, + "trip": { + "gtfsId": "F:123" } } ] } ] } -} \ No newline at end of file +} From 3c46be363a6912f6f221eba1aebf9a9ebbbf1a39 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Tue, 3 Dec 2024 08:10:56 +0200 Subject: [PATCH 54/98] Add logging for mode-specific transfers. --- .../module/DirectTransferGenerator.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index 27fc87d9fff..0219445bb3d 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import org.opentripplanner.framework.application.OTPFeature; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; import org.opentripplanner.graph_builder.issues.StopNotLinkedForTransfers; @@ -172,6 +173,20 @@ public void buildGraph() { nTransfersTotal, nLinkedStops ); + for (StreetMode mode : transferRequests + .stream() + .map(transferProfile -> transferProfile.journey().transfer().mode()) + .collect(Collectors.toSet())) { + LOG.info( + "Created {} transfers for mode {}.", + transfersByStop + .values() + .stream() + .filter(pathTransfer -> pathTransfer.getModes().contains(mode)) + .count(), + mode + ); + } } /** From a682d98b51c9212d788c80532fa67147fd66697b Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Tue, 3 Dec 2024 01:22:09 +0100 Subject: [PATCH 55/98] fix: Add default penalty to all car api modes. The CAR & CAR_PICKUP can be used in access/egress, but no penalty was set. --- .../preference/AccessEgressPreferences.java | 33 ++++++++++--------- .../apis/transmodel/schema.graphql | 2 +- .../preference/StreetPreferencesTest.java | 9 +++-- doc/user/RouteRequest.md | 2 ++ 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java b/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java index 42925339fd1..635c4c6c7b0 100644 --- a/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java +++ b/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java @@ -21,21 +21,7 @@ */ public final class AccessEgressPreferences implements Serializable { - private static final TimeAndCostPenalty DEFAULT_PENALTY = TimeAndCostPenalty.of( - TimePenalty.of(ofMinutes(20), 2f), - 1.5 - ); - private static final TimeAndCostPenalty FLEX_DEFAULT_PENALTY = TimeAndCostPenalty.of( - TimePenalty.of(ofMinutes(10), 1.3f), - 1.3 - ); - private static final TimeAndCostPenaltyForEnum DEFAULT_TIME_AND_COST = TimeAndCostPenaltyForEnum - .of(StreetMode.class) - .with(StreetMode.CAR_TO_PARK, DEFAULT_PENALTY) - .with(StreetMode.CAR_HAILING, DEFAULT_PENALTY) - .with(StreetMode.CAR_RENTAL, DEFAULT_PENALTY) - .with(StreetMode.FLEXIBLE, FLEX_DEFAULT_PENALTY) - .build(); + private static final TimeAndCostPenaltyForEnum DEFAULT_TIME_AND_COST = createDefaultCarPenalty(); public static final AccessEgressPreferences DEFAULT = new AccessEgressPreferences(); @@ -159,4 +145,21 @@ AccessEgressPreferences build() { private static DurationForEnum durationForStreetModeOf(Duration defaultValue) { return DurationForEnum.of(StreetMode.class).withDefault(defaultValue).build(); } + + private static TimeAndCostPenaltyForEnum createDefaultCarPenalty() { + var penaltyrBuilder = TimeAndCostPenaltyForEnum.of(StreetMode.class); + + var flexDefaultPenalty = TimeAndCostPenalty.of(TimePenalty.of(ofMinutes(10), 1.3f), 1.3); + penaltyrBuilder.with(StreetMode.FLEXIBLE, flexDefaultPenalty); + + // Add penalty to all car variants with access and/or egress. + var carPenalty = TimeAndCostPenalty.of(TimePenalty.of(ofMinutes(20), 2f), 1.5); + for (var it : StreetMode.values()) { + if (it.includesDriving() && (it.accessAllowed() || it.egressAllowed())) { + penaltyrBuilder.with(it, carPenalty); + } + } + + return penaltyrBuilder.build(); + } } diff --git a/application/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql b/application/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql index ed182473bb6..8468a127878 100644 --- a/application/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql +++ b/application/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql @@ -775,7 +775,7 @@ type QueryType { "Input type for executing a travel search for a trip between two locations. Returns trip patterns describing suggested alternatives for the trip." trip( "Time and cost penalty on access/egress modes." - accessEgressPenalty: [PenaltyForStreetMode!] = [{streetMode : car_park, timePenalty : "20m + 2.0 t", costFactor : 1.5}, {streetMode : car_rental, timePenalty : "20m + 2.0 t", costFactor : 1.5}, {streetMode : flexible, timePenalty : "10m + 1.30 t", costFactor : 1.3}], + accessEgressPenalty: [PenaltyForStreetMode!] = [{streetMode : car, timePenalty : "20m + 2.0 t", costFactor : 1.5}, {streetMode : car_park, timePenalty : "20m + 2.0 t", costFactor : 1.5}, {streetMode : car_pickup, timePenalty : "20m + 2.0 t", costFactor : 1.5}, {streetMode : car_rental, timePenalty : "20m + 2.0 t", costFactor : 1.5}, {streetMode : flexible, timePenalty : "10m + 1.30 t", costFactor : 1.3}], "The alightSlack is the minimum extra time after exiting a public transport vehicle. This is the default value used, if not overridden by the 'alightSlackList'." alightSlackDefault: Int = 0, "List of alightSlack for a given set of modes. Defaults: []" diff --git a/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java b/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java index a318474eab7..77875c44fa1 100644 --- a/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java +++ b/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java @@ -109,9 +109,14 @@ void testToString() { "routingTimeout: 3s, " + "elevator: ElevatorPreferences{boardTime: 2m}, " + "intersectionTraversalModel: CONSTANT, " + - "accessEgress: AccessEgressPreferences{penalty: TimeAndCostPenaltyForEnum{CAR_TO_PARK: " + + "accessEgress: AccessEgressPreferences{penalty: TimeAndCostPenaltyForEnum{" + + "CAR: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + + "CAR_TO_PARK: " + CAR_PENALTY + - ", CAR_RENTAL: (timePenalty: 20m + 2.0 t, costFactor: 1.50), CAR_HAILING: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + + ", " + + "CAR_PICKUP: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + + "CAR_RENTAL: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + + "CAR_HAILING: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + "FLEXIBLE: (timePenalty: 10m + 1.30 t, costFactor: 1.30)}, " + "maxDuration: DurationForStreetMode{default:5m}" + "}, " + diff --git a/doc/user/RouteRequest.md b/doc/user/RouteRequest.md index ea3d0d12c74..0faf1a07b00 100644 --- a/doc/user/RouteRequest.md +++ b/doc/user/RouteRequest.md @@ -445,7 +445,9 @@ performance will be better. The default values are +- `car` = (timePenalty: 20m + 2.0 t, costFactor: 1.50) - `car-to-park` = (timePenalty: 20m + 2.0 t, costFactor: 1.50) +- `car-pickup` = (timePenalty: 20m + 2.0 t, costFactor: 1.50) - `car-rental` = (timePenalty: 20m + 2.0 t, costFactor: 1.50) - `car-hailing` = (timePenalty: 20m + 2.0 t, costFactor: 1.50) - `flexible` = (timePenalty: 10m + 1.30 t, costFactor: 1.30) From 244c5371bc8319981906afc8ce5cca97ebd57829 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Wed, 4 Dec 2024 10:42:54 +0200 Subject: [PATCH 56/98] Fix flex routing transfer calculations and only calculate flex transfer requests for WALK mode. --- .../module/DirectTransferGenerator.java | 95 +++++++++++-------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index 0219445bb3d..19e2c8227d0 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -3,6 +3,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimaps; import java.time.Duration; +import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -89,6 +90,17 @@ public void buildGraph() { HashMultimap.create() ); + List flexTransferRequests = new ArrayList<>(); + // Flex transfer requests only use the WALK mode. + if (OTPFeature.FlexRouting.isOn()) { + flexTransferRequests.addAll( + transferRequests + .stream() + .filter(transferProfile -> transferProfile.journey().transfer().mode() == StreetMode.WALK) + .toList() + ); + } + stops .stream() .parallel() @@ -104,6 +116,7 @@ public void buildGraph() { LOG.debug("Linking stop '{}' {}", stop, ts0); + // Calculate default transfers. for (RouteRequest transferProfile : transferRequests) { StreetMode mode = transferProfile.journey().transfer().mode(); for (NearbyStop sd : nearbyStopFinder.findNearbyStops( @@ -119,28 +132,48 @@ public void buildGraph() { if (sd.stop.transfersNotAllowed()) { continue; } - createPathTransfer(distinctTransfers, sd, stop, mode); + TransferKey transferKey = new TransferKey(stop, sd.stop, sd.edges); + PathTransfer pathTransfer = distinctTransfers.get(transferKey); + if (pathTransfer == null) { + EnumSet modes = EnumSet.of(mode); + distinctTransfers.put( + transferKey, + new PathTransfer(stop, sd.stop, sd.distance, sd.edges, modes) + ); + } else { + pathTransfer.addMode(mode); + } } } - if (OTPFeature.FlexRouting.isOn()) { - for (RouteRequest transferProfile : transferRequests) { - StreetMode mode = transferProfile.journey().transfer().mode(); - // This code is for finding transfers from AreaStops to Stops, transfers - // from Stops to AreaStops and between Stops are already covered above. - for (NearbyStop sd : nearbyStopFinder.findNearbyStops( - ts0, - transferProfile, - transferProfile.journey().transfer(), - true - )) { - // Skip the origin stop, loop transfers are not needed. - if (sd.stop == stop) { - continue; - } - if (sd.stop instanceof RegularStop) { - continue; - } - createPathTransfer(distinctTransfers, sd, stop, mode); + // Calculate flex transfers if flex routing is enabled. + for (RouteRequest transferProfile : flexTransferRequests) { + StreetMode mode = transferProfile.journey().transfer().mode(); + // This code is for finding transfers from AreaStops to Stops, transfers + // from Stops to AreaStops and between Stops are already covered above. + for (NearbyStop sd : nearbyStopFinder.findNearbyStops( + ts0, + transferProfile, + transferProfile.journey().transfer(), + true + )) { + // Skip the origin stop, loop transfers are not needed. + if (sd.stop == stop) { + continue; + } + if (sd.stop instanceof RegularStop) { + continue; + } + // The TransferKey and PathTransfer are created differently for flex routing. + TransferKey transferKey = new TransferKey(sd.stop, stop, sd.edges); + PathTransfer pathTransfer = distinctTransfers.get(transferKey); + if (pathTransfer == null) { + EnumSet modes = EnumSet.of(mode); + distinctTransfers.put( + transferKey, + new PathTransfer(sd.stop, stop, sd.distance, sd.edges, modes) + ); + } else { + pathTransfer.addMode(mode); } } } @@ -189,28 +222,6 @@ public void buildGraph() { } } - /** - * Factory method for creating a PathTransfer. - */ - private void createPathTransfer( - Map distinctTransfers, - NearbyStop sd, - RegularStop stop, - StreetMode mode - ) { - TransferKey transferKey = new TransferKey(stop, sd.stop, sd.edges); - PathTransfer pathTransfer = distinctTransfers.get(transferKey); - if (pathTransfer == null) { - EnumSet modes = EnumSet.of(mode); - distinctTransfers.put( - transferKey, - new PathTransfer(stop, sd.stop, sd.distance, sd.edges, modes) - ); - } else { - pathTransfer.addMode(mode); - } - } - /** * Factory method for creating a NearbyStopFinder. Will create different finders depending on * whether the graph has a street network and if ConsiderPatternsForDirectTransfers feature is From 15656d586aae8ab56f225b2937cfe823ff90e2ff Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Wed, 4 Dec 2024 15:41:33 +0100 Subject: [PATCH 57/98] Add fallback names for corridors --- .../osm/tagmapping/OsmTagMapper.java | 3 ++- .../main/resources/WayProperties.properties | 1 + .../main/resources/WayProperties_de.properties | 1 + .../osm/tagmapping/OsmTagMapperTest.java | 18 +++++++++++++++--- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java b/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java index 55bc87f5cad..e2debf79916 100644 --- a/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java +++ b/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java @@ -624,7 +624,7 @@ public void populateProperties(WayPropertySet props) { props.setSlopeOverride(new BestMatchSpecifier("indoor=yes"), true); } - public void populateNotesAndNames(WayPropertySet props) { + static void populateNotesAndNames(WayPropertySet props) { /* and the notes */ // TODO: The curly brackets in the string below mean that the CreativeNamer should substitute in OSM tag values. // However they are not taken into account when passed to the translation function. @@ -667,6 +667,7 @@ public void populateNotesAndNames(WayPropertySet props) { props.createNames("highway=footway", "name.pedestrian_path"); props.createNames("highway=bridleway", "name.bridleway"); props.createNames("highway=footway;bicycle=no", "name.pedestrian_path"); + props.createNames("highway=corridor", "name.corridor"); // Platforms props.createNames("otp:route_ref=*", "name.otp_route_ref"); diff --git a/application/src/main/resources/WayProperties.properties b/application/src/main/resources/WayProperties.properties index a7e7d73fc34..8ff0590e0d4 100644 --- a/application/src/main/resources/WayProperties.properties +++ b/application/src/main/resources/WayProperties.properties @@ -8,6 +8,7 @@ name.pedestrian_path=path name.pedestrian_area=open area name.path=path name.bridleway=bridleway +name.corridor=corridor name.otp_route_ref=Route {otp:route_ref} name.platform_ref=Platform {ref} diff --git a/application/src/main/resources/WayProperties_de.properties b/application/src/main/resources/WayProperties_de.properties index c741c8dc991..ecb537a5186 100644 --- a/application/src/main/resources/WayProperties_de.properties +++ b/application/src/main/resources/WayProperties_de.properties @@ -9,6 +9,7 @@ name.pedestrian_path=Fu\u00dfweg name.pedestrian_area=Fu\u00dfg\u00e4ngerzone name.path=Weg name.bridleway=Reitweg +name.corridor=Korridor name.otp_route_ref=Route {otp:route_ref} name.platform_ref=Plattform {ref} diff --git a/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java b/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java index 5448f84294d..8d699e38843 100644 --- a/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java +++ b/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java @@ -184,9 +184,7 @@ public static List roadCases() { @ParameterizedTest @MethodSource("roadCases") void motorroad(OsmWithTags way) { - OsmTagMapper osmTagMapper = new OsmTagMapper(); - WayPropertySet wps = new WayPropertySet(); - osmTagMapper.populateProperties(wps); + final WayPropertySet wps = wayProperySet(); assertEquals(ALL, wps.getDataForWay(way).getPermission()); @@ -194,9 +192,23 @@ void motorroad(OsmWithTags way) { assertEquals(CAR, wps.getDataForWay(way).getPermission()); } + @Test + void corridorName() { + final WayPropertySet wps = wayProperySet(); + var way = way("highway", "corridor"); + assertEquals("corridor", wps.getCreativeNameForWay(way).toString()); + } + public OsmWithTags way(String key, String value) { var way = new OsmWithTags(); way.addTag(key, value); return way; } + + private static WayPropertySet wayProperySet() { + OsmTagMapper osmTagMapper = new OsmTagMapper(); + WayPropertySet wps = new WayPropertySet(); + osmTagMapper.populateProperties(wps); + return wps; + } } From d7fd1d85050fe5c1708aaa6a26fb6ae34e5aa56c Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Wed, 4 Dec 2024 21:57:41 +0100 Subject: [PATCH 58/98] Add translations for all languages --- application/src/main/resources/WayProperties_fi.properties | 1 + application/src/main/resources/WayProperties_fr.properties | 1 + application/src/main/resources/WayProperties_hu.properties | 1 + application/src/main/resources/WayProperties_nl.properties | 1 + application/src/main/resources/WayProperties_no.properties | 1 + application/src/main/resources/WayProperties_sv.properties | 1 + .../org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java | 3 +++ 7 files changed, 9 insertions(+) diff --git a/application/src/main/resources/WayProperties_fi.properties b/application/src/main/resources/WayProperties_fi.properties index b4f7330b737..725580c6c1a 100644 --- a/application/src/main/resources/WayProperties_fi.properties +++ b/application/src/main/resources/WayProperties_fi.properties @@ -8,6 +8,7 @@ name.pedestrian_path=polku name.pedestrian_area=aukio name.path=polku name.bridleway=ratsupolku +name.corridor=käytävä name.otp_route_ref=linja {otp:route_ref} name.platform_ref=laituri {ref} diff --git a/application/src/main/resources/WayProperties_fr.properties b/application/src/main/resources/WayProperties_fr.properties index 0c926a8c357..566ba586e18 100644 --- a/application/src/main/resources/WayProperties_fr.properties +++ b/application/src/main/resources/WayProperties_fr.properties @@ -9,6 +9,7 @@ name.pedestrian_path=chemin pi\u00e9tonnier name.pedestrian_area=plateau pi\u00e9tonnier name.path=chemin name.bridleway=sentier \u00e9questre +name.corridor=couloir name.otp_route_ref=Ligne {otp:route_ref} name.platform_ref=Plate-forme {ref} diff --git a/application/src/main/resources/WayProperties_hu.properties b/application/src/main/resources/WayProperties_hu.properties index 13539374eb2..e61bc8dbf1a 100644 --- a/application/src/main/resources/WayProperties_hu.properties +++ b/application/src/main/resources/WayProperties_hu.properties @@ -8,6 +8,7 @@ name.pedestrian_path=gyalog\u00FAt name.pedestrian_area=t\u00E9r name.path=path name.bridleway=nyomvonal +name.corridor=folyoso name.otp_route_ref={otp:route_ref} name.platform_ref={ref} diff --git a/application/src/main/resources/WayProperties_nl.properties b/application/src/main/resources/WayProperties_nl.properties index 501287506d2..dc7597c898e 100644 --- a/application/src/main/resources/WayProperties_nl.properties +++ b/application/src/main/resources/WayProperties_nl.properties @@ -9,6 +9,7 @@ name.pedestrian_path=voetpad name.pedestrian_area=open ruimte name.path=pad name.bridleway=ruiterpad +name.corridor=gang name.otp_route_ref=Lijn {otp:route_ref} name.platform_ref=Spoor {ref} diff --git a/application/src/main/resources/WayProperties_no.properties b/application/src/main/resources/WayProperties_no.properties index 95883c60af3..3cb19cdac76 100644 --- a/application/src/main/resources/WayProperties_no.properties +++ b/application/src/main/resources/WayProperties_no.properties @@ -8,6 +8,7 @@ name.pedestrian_path=gangvei name.pedestrian_area=plass name.path=sti name.bridleway=bridleway +name.corridor=korridor name.otp_route_ref=Rute {otp:route_ref} name.platform_ref=Plattform {ref} diff --git a/application/src/main/resources/WayProperties_sv.properties b/application/src/main/resources/WayProperties_sv.properties index 31529e1416b..3ba8bda6849 100644 --- a/application/src/main/resources/WayProperties_sv.properties +++ b/application/src/main/resources/WayProperties_sv.properties @@ -8,6 +8,7 @@ name.pedestrian_path=gångbanan name.pedestrian_area=torget name.path=stigen name.bridleway=ridvägem +name.corridor=korridor name.otp_route_ref=linje {otp:route_ref} name.platform_ref=plattform {ref} diff --git a/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java b/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java index 8d699e38843..0c8583c02db 100644 --- a/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java +++ b/application/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java @@ -7,6 +7,7 @@ import static org.opentripplanner.street.model.StreetTraversalPermission.CAR; import java.util.List; +import java.util.Locale; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -197,6 +198,8 @@ void corridorName() { final WayPropertySet wps = wayProperySet(); var way = way("highway", "corridor"); assertEquals("corridor", wps.getCreativeNameForWay(way).toString()); + assertEquals("Korridor", wps.getCreativeNameForWay(way).toString(Locale.GERMANY)); + assertEquals("käytävä", wps.getCreativeNameForWay(way).toString(Locale.of("FI"))); } public OsmWithTags way(String key, String value) { From e1bb7d6be66eb65d698db7ccea643814ce5345dc Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Fri, 6 Dec 2024 09:32:00 +0100 Subject: [PATCH 59/98] Make flex linking work together with boarding locations --- .../module/StreetLinkerModule.java | 20 ++++++- .../model/vertex/TransitStopVertex.java | 26 +++++++++ .../module/StreetLinkerModuleTest.java | 56 ++++++++++++++++++- 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java b/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java index 83a6f282204..bfd35c2f025 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java @@ -103,7 +103,7 @@ public void linkTransitStops(Graph graph, TimetableRepository timetableRepositor continue; } // check if stop is already linked, to allow multiple idempotent linking cycles - if (tStop.isConnectedToGraph()) { + if (isAlreadyLinked(tStop, stopLocationsUsedForFlexTrips)) { continue; } @@ -127,6 +127,24 @@ public void linkTransitStops(Graph graph, TimetableRepository timetableRepositor LOG.info(progress.completeMessage()); } + /** + * Determines if a given transit stop vertex is already linked to the street network, taking into + * account that flex stop need special linking to both a walkable and drivable edge. + * + * @param stopVertex The transit stop vertex to be checked. + * @param stopLocationsUsedForFlexTrips A set of stop locations that are used for flexible trips. + */ + private static boolean isAlreadyLinked( + TransitStopVertex stopVertex, + Set stopLocationsUsedForFlexTrips + ) { + if (stopLocationsUsedForFlexTrips.contains(stopVertex.getStop())) { + return stopVertex.isLinkedToDrivableEdge() && stopVertex.isLinkedToWalkableEdge(); + } else { + return stopVertex.isConnectedToGraph(); + } + } + /** * Link a stop to the nearest "relevant" edges. *

diff --git a/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java b/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java index 82c977902b0..d43f587280c 100644 --- a/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java +++ b/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java @@ -1,9 +1,14 @@ package org.opentripplanner.street.model.vertex; +import static org.opentripplanner.street.search.TraverseMode.CAR; +import static org.opentripplanner.street.search.TraverseMode.WALK; + import java.util.HashSet; import java.util.Set; import org.opentripplanner.street.model.edge.Edge; import org.opentripplanner.street.model.edge.PathwayEdge; +import org.opentripplanner.street.model.edge.StreetTransitEntityLink; +import org.opentripplanner.street.search.TraverseMode; import org.opentripplanner.transit.model.basic.Accessibility; import org.opentripplanner.transit.model.basic.TransitMode; import org.opentripplanner.transit.model.site.RegularStop; @@ -94,4 +99,25 @@ public StationElement getStationElement() { public boolean isConnectedToGraph() { return getDegreeOut() + getDegreeIn() > 0; } + + public boolean isLinkedToDrivableEdge() { + return isLinkedToEdgeWhichAllows(CAR); + } + + public boolean isLinkedToWalkableEdge() { + return isLinkedToEdgeWhichAllows(WALK); + } + + private boolean isLinkedToEdgeWhichAllows(TraverseMode traverseMode) { + return getOutgoing() + .stream() + .anyMatch(edge -> + edge instanceof StreetTransitEntityLink link && + link + .getToVertex() + .getOutgoingStreetEdges() + .stream() + .anyMatch(se -> se.canTraverse(traverseMode)) + ); + } } diff --git a/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java b/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java index 4f54581fdb8..3a9452e022a 100644 --- a/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java +++ b/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java @@ -11,6 +11,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Set; import org.junit.jupiter.api.Test; import org.opentripplanner.ext.flex.trip.UnscheduledTrip; import org.opentripplanner.framework.application.OTPFeature; @@ -20,8 +21,10 @@ import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.service.vehicleparking.internal.DefaultVehicleParkingRepository; import org.opentripplanner.street.model._data.StreetModelForTest; +import org.opentripplanner.street.model.edge.BoardingLocationToStopLink; import org.opentripplanner.street.model.edge.Edge; import org.opentripplanner.street.model.edge.StreetTransitStopLink; +import org.opentripplanner.street.model.vertex.OsmBoardingLocationVertex; import org.opentripplanner.street.model.vertex.SplitterVertex; import org.opentripplanner.street.model.vertex.TransitStopVertex; import org.opentripplanner.transit.model._data.TimetableRepositoryForTest; @@ -103,6 +106,38 @@ void linkFlexStop() { }); } + @Test + void linkFlexStopWithBoardingLocation() { + OTPFeature.FlexRouting.testOn(() -> { + var model = new TestModel().withStopLinkedToBoardingLocation(); + var flexTrip = TimetableRepositoryForTest.of().unscheduledTrip("flex", model.stop()); + model.withFlexTrip(flexTrip); + + var module = model.streetLinkerModule(); + + module.buildGraph(); + + assertTrue(model.stopVertex().isConnectedToGraph()); + + // stop is used by a flex trip, needs to be linked to both the walk and car edge, + // also linked to the boarding location + assertThat(model.stopVertex().getOutgoing()).hasSize(3); + var links = model.outgoingLinks(); + assertInstanceOf(BoardingLocationToStopLink.class, links.getFirst()); + var linkToWalk = links.get(1); + SplitterVertex walkSplit = (SplitterVertex) linkToWalk.getToVertex(); + + assertTrue(walkSplit.isConnectedToWalkingEdge()); + assertFalse(walkSplit.isConnectedToDriveableEdge()); + + var linkToCar = links.getLast(); + SplitterVertex carSplit = (SplitterVertex) linkToCar.getToVertex(); + + assertFalse(carSplit.isConnectedToWalkingEdge()); + assertTrue(carSplit.isConnectedToDriveableEdge()); + }); + } + @Test void linkCarsAllowedStop() { var model = new TestModel(); @@ -140,6 +175,7 @@ private static class TestModel { private final StreetLinkerModule module; private final RegularStop stop; private final TimetableRepository timetableRepository; + private final Graph graph; public TestModel() { var from = StreetModelForTest.intersectionVertex( @@ -151,7 +187,7 @@ public TestModel() { KONGSBERG_PLATFORM_1.x + DELTA ); - Graph graph = new Graph(); + this.graph = new Graph(); graph.addVertex(from); graph.addVertex(to); @@ -232,5 +268,23 @@ public void withCarsAllowedTrip(Trip trip, StopLocation... stops) { timetableRepository.addTripPattern(tripPattern.getId(), tripPattern); } + + /** + * Links the stop to a boarding location as can happen during regular graph build. + */ + public TestModel withStopLinkedToBoardingLocation() { + var boardingLocation = new OsmBoardingLocationVertex( + "boarding-location", + KONGSBERG_PLATFORM_1.x - 0.0001, + KONGSBERG_PLATFORM_1.y - 0.0001, + null, + Set.of(stop.getId().getId()) + ); + graph.addVertex(boardingLocation); + + BoardingLocationToStopLink.createBoardingLocationToStopLink(boardingLocation, stopVertex); + BoardingLocationToStopLink.createBoardingLocationToStopLink(stopVertex, boardingLocation); + return this; + } } } From 22a414cc9f445448df663d5be7e06deed31f22be Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Fri, 6 Dec 2024 09:53:50 +0100 Subject: [PATCH 60/98] Add javadoc --- .../street/model/vertex/TransitStopVertex.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java b/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java index d43f587280c..7d5d52f02b3 100644 --- a/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java +++ b/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java @@ -100,10 +100,18 @@ public boolean isConnectedToGraph() { return getDegreeOut() + getDegreeIn() > 0; } + /** + * Determines if this vertex is linked (via a {@link StreetTransitEntityLink}) to a drivable edge + * in the street network. + */ public boolean isLinkedToDrivableEdge() { return isLinkedToEdgeWhichAllows(CAR); } + /** + * Determines if this vertex is linked (via a {@link StreetTransitEntityLink}) to a walkable edge + * in the street network. + */ public boolean isLinkedToWalkableEdge() { return isLinkedToEdgeWhichAllows(WALK); } From 47d444165dcd0f911314071d73f8f3ae55d24c0d Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Fri, 6 Dec 2024 15:02:26 +0100 Subject: [PATCH 61/98] Add warnings --- .../street/model/vertex/TransitStopVertex.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java b/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java index 7d5d52f02b3..5b1b1dfa6a8 100644 --- a/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java +++ b/application/src/main/java/org/opentripplanner/street/model/vertex/TransitStopVertex.java @@ -103,6 +103,8 @@ public boolean isConnectedToGraph() { /** * Determines if this vertex is linked (via a {@link StreetTransitEntityLink}) to a drivable edge * in the street network. + *

+ * This method is slow: only use this during graph build. */ public boolean isLinkedToDrivableEdge() { return isLinkedToEdgeWhichAllows(CAR); @@ -111,6 +113,8 @@ public boolean isLinkedToDrivableEdge() { /** * Determines if this vertex is linked (via a {@link StreetTransitEntityLink}) to a walkable edge * in the street network. + *

+ * This method is slow: only use this during graph build. */ public boolean isLinkedToWalkableEdge() { return isLinkedToEdgeWhichAllows(WALK); From ee5b8421309be1c674ecf08e82ca5341409c8e64 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Mon, 9 Dec 2024 08:11:44 +0100 Subject: [PATCH 62/98] Improve comment --- .../graph_builder/module/StreetLinkerModule.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java b/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java index bfd35c2f025..b59b2aee20f 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java @@ -129,7 +129,9 @@ public void linkTransitStops(Graph graph, TimetableRepository timetableRepositor /** * Determines if a given transit stop vertex is already linked to the street network, taking into - * account that flex stop need special linking to both a walkable and drivable edge. + * account that flex stop need special linking to both a walkable and drivable edge. For example, + * the {@link OsmBoardingLocationsModule}, which runs before this one, links stops often to + * walkable edges only. * * @param stopVertex The transit stop vertex to be checked. * @param stopLocationsUsedForFlexTrips A set of stop locations that are used for flexible trips. From 012f149376eb5ae5453a3c33e852665224bff1b5 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Mon, 9 Dec 2024 13:55:57 +0200 Subject: [PATCH 63/98] Add changes based on review comments. --- .../module/DirectTransferGenerator.java | 20 +++++++++++-------- .../opentripplanner/model/PathTransfer.java | 12 ++++++----- .../raptoradapter/transit/Transfer.java | 2 +- .../transit/service/TimetableRepository.java | 9 +++++++++ .../module/DirectTransferGeneratorTest.java | 18 +++-------------- .../raptoradapter/transit/TransferTest.java | 1 - 6 files changed, 32 insertions(+), 30 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index 19e2c8227d0..626c85312a7 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -135,19 +135,21 @@ public void buildGraph() { TransferKey transferKey = new TransferKey(stop, sd.stop, sd.edges); PathTransfer pathTransfer = distinctTransfers.get(transferKey); if (pathTransfer == null) { - EnumSet modes = EnumSet.of(mode); + // If the PathTransfer can't be found, it is created. distinctTransfers.put( transferKey, - new PathTransfer(stop, sd.stop, sd.distance, sd.edges, modes) + new PathTransfer(stop, sd.stop, sd.distance, sd.edges, EnumSet.of(mode)) ); } else { - pathTransfer.addMode(mode); + // If the PathTransfer is found, a new PathTransfer with the added mode is created. + distinctTransfers.put(transferKey, pathTransfer.withAddedMode(mode)); } } } // Calculate flex transfers if flex routing is enabled. for (RouteRequest transferProfile : flexTransferRequests) { - StreetMode mode = transferProfile.journey().transfer().mode(); + // Flex transfer requests only use the WALK mode. + StreetMode mode = StreetMode.WALK; // This code is for finding transfers from AreaStops to Stops, transfers // from Stops to AreaStops and between Stops are already covered above. for (NearbyStop sd : nearbyStopFinder.findNearbyStops( @@ -167,13 +169,14 @@ public void buildGraph() { TransferKey transferKey = new TransferKey(sd.stop, stop, sd.edges); PathTransfer pathTransfer = distinctTransfers.get(transferKey); if (pathTransfer == null) { - EnumSet modes = EnumSet.of(mode); + // If the PathTransfer can't be found, it is created. distinctTransfers.put( transferKey, - new PathTransfer(sd.stop, stop, sd.distance, sd.edges, modes) + new PathTransfer(sd.stop, stop, sd.distance, sd.edges, EnumSet.of(mode)) ); } else { - pathTransfer.addMode(mode); + // If the PathTransfer is found, a new PathTransfer with the added mode is created. + distinctTransfers.put(transferKey, pathTransfer.withAddedMode(mode)); } } } @@ -209,7 +212,8 @@ public void buildGraph() { for (StreetMode mode : transferRequests .stream() .map(transferProfile -> transferProfile.journey().transfer().mode()) - .collect(Collectors.toSet())) { + .distinct() + .toList()) { LOG.info( "Created {} transfers for mode {}.", transfersByStop diff --git a/application/src/main/java/org/opentripplanner/model/PathTransfer.java b/application/src/main/java/org/opentripplanner/model/PathTransfer.java index ed4696ab11c..a6b66548e64 100644 --- a/application/src/main/java/org/opentripplanner/model/PathTransfer.java +++ b/application/src/main/java/org/opentripplanner/model/PathTransfer.java @@ -28,7 +28,7 @@ public class PathTransfer implements Serializable { private final List edges; - private EnumSet modes; + private final EnumSet modes; public PathTransfer( StopLocation from, @@ -53,15 +53,17 @@ public double getDistanceMeters() { } public List getEdges() { - return this.edges; + return edges; } public EnumSet getModes() { - return this.modes; + return modes.clone(); } - public boolean addMode(StreetMode mode) { - return this.modes.add(mode); + public PathTransfer withAddedMode(StreetMode mode) { + EnumSet newModes = EnumSet.copyOf(modes); + newModes.add(mode); + return new PathTransfer(from, to, distanceMeters, edges, newModes); } @Override diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java index 6ee0dee83c0..2440321ab1f 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java @@ -75,7 +75,7 @@ public List getEdges() { } public EnumSet getModes() { - return modes; + return modes.clone(); } public Optional asRaptorTransfer(StreetSearchRequest request) { diff --git a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java index b81dd7d4f14..d83c3f9b996 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java @@ -35,6 +35,7 @@ import org.opentripplanner.model.transfer.DefaultTransferService; import org.opentripplanner.routing.algorithm.raptoradapter.transit.TransitLayer; import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.TransitLayerUpdater; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.routing.impl.DelegatingTransitAlertServiceImpl; import org.opentripplanner.routing.services.TransitAlertService; import org.opentripplanner.routing.util.ConcurrentPublished; @@ -433,6 +434,14 @@ public Collection getTransfersByStop(StopLocation stop) { return transfersByStop.get(stop); } + public Collection getTransfersByMode(StreetMode mode) { + return transfersByStop + .values() + .stream() + .filter(pathTransfer -> pathTransfer.getModes().contains(mode)) + .toList(); + } + public SiteRepository getSiteRepository() { return siteRepository; } diff --git a/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java b/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java index 310e474ae99..482cb0afd13 100644 --- a/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java +++ b/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java @@ -274,21 +274,9 @@ public void testPathTransfersWithModesForMultipleRequestsWithPatterns() { ) .buildGraph(); - var walkTransfers = timetableRepository - .getAllPathTransfers() - .stream() - .filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.WALK)) - .toList(); - var bikeTransfers = timetableRepository - .getAllPathTransfers() - .stream() - .filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.BIKE)) - .toList(); - var carTransfers = timetableRepository - .getAllPathTransfers() - .stream() - .filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.CAR)) - .toList(); + var walkTransfers = timetableRepository.getTransfersByMode(StreetMode.WALK); + var bikeTransfers = timetableRepository.getTransfersByMode(StreetMode.BIKE); + var carTransfers = timetableRepository.getTransfersByMode(StreetMode.CAR); assertTransfers( walkTransfers, diff --git a/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java b/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java index 7edda8fba9c..ebae06f5063 100644 --- a/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java +++ b/application/src/test/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/TransferTest.java @@ -7,7 +7,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Optional; -import java.util.Set; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.opentripplanner._support.geometry.Coordinates; From 984d34eeebfdacb8469e89705b83bfb10fd9965a Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Mon, 9 Dec 2024 14:33:37 +0200 Subject: [PATCH 64/98] Change how EnumSet is copied and make EnumSet immutable in Transfer. --- .../java/org/opentripplanner/model/PathTransfer.java | 2 +- .../algorithm/raptoradapter/transit/Transfer.java | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/model/PathTransfer.java b/application/src/main/java/org/opentripplanner/model/PathTransfer.java index a6b66548e64..01aa9af02f5 100644 --- a/application/src/main/java/org/opentripplanner/model/PathTransfer.java +++ b/application/src/main/java/org/opentripplanner/model/PathTransfer.java @@ -57,7 +57,7 @@ public List getEdges() { } public EnumSet getModes() { - return modes.clone(); + return EnumSet.copyOf(modes); } public PathTransfer withAddedMode(StreetMode mode) { diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java index 2440321ab1f..648343b9b0f 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java @@ -1,5 +1,7 @@ package org.opentripplanner.routing.algorithm.raptoradapter.transit; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; @@ -33,20 +35,20 @@ public class Transfer { private final List edges; - private final EnumSet modes; + private final ImmutableSet modes; public Transfer(int toStop, List edges, EnumSet modes) { this.toStop = toStop; this.edges = edges; this.distanceMeters = (int) edges.stream().mapToDouble(Edge::getDistanceMeters).sum(); - this.modes = modes; + this.modes = Sets.immutableEnumSet(modes); } public Transfer(int toStopIndex, int distanceMeters, EnumSet modes) { this.toStop = toStopIndex; this.distanceMeters = distanceMeters; this.edges = null; - this.modes = modes; + this.modes = Sets.immutableEnumSet(modes); } public List getCoordinates() { @@ -74,8 +76,8 @@ public List getEdges() { return edges; } - public EnumSet getModes() { - return modes.clone(); + public ImmutableSet getModes() { + return modes; } public Optional asRaptorTransfer(StreetSearchRequest request) { From ebbba525dd2d40d550a7e1ffb2d3f664b9cdfd06 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Mon, 9 Dec 2024 16:20:42 +0100 Subject: [PATCH 65/98] Apply review feedback --- .../graph_builder/module/StreetLinkerModule.java | 4 ++-- .../graph_builder/module/StreetLinkerModuleTest.java | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java b/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java index b59b2aee20f..d50659f275c 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/StreetLinkerModule.java @@ -129,8 +129,8 @@ public void linkTransitStops(Graph graph, TimetableRepository timetableRepositor /** * Determines if a given transit stop vertex is already linked to the street network, taking into - * account that flex stop need special linking to both a walkable and drivable edge. For example, - * the {@link OsmBoardingLocationsModule}, which runs before this one, links stops often to + * account that flex stops need special linking to both a walkable and drivable edge. For example, + * the {@link OsmBoardingLocationsModule}, which runs before this one, often links stops to * walkable edges only. * * @param stopVertex The transit stop vertex to be checked. diff --git a/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java b/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java index 3a9452e022a..10427812ac2 100644 --- a/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java +++ b/application/src/test/java/org/opentripplanner/graph_builder/module/StreetLinkerModuleTest.java @@ -122,14 +122,23 @@ void linkFlexStopWithBoardingLocation() { // stop is used by a flex trip, needs to be linked to both the walk and car edge, // also linked to the boarding location assertThat(model.stopVertex().getOutgoing()).hasSize(3); + + // while the order of the link doesn't matter, it _is_ deterministic. + // first we have the link to the boarding location where the passengers are expected + // to wait. var links = model.outgoingLinks(); assertInstanceOf(BoardingLocationToStopLink.class, links.getFirst()); + + // the second link is the link to the walkable street network. this is not really necessary + // because the boarding location is walkable. this will be refactored away in the future. var linkToWalk = links.get(1); SplitterVertex walkSplit = (SplitterVertex) linkToWalk.getToVertex(); assertTrue(walkSplit.isConnectedToWalkingEdge()); assertFalse(walkSplit.isConnectedToDriveableEdge()); + // lastly we have the link to the drivable street network because vehicles also need to + // reach the stop if it's part of a flex trip. var linkToCar = links.getLast(); SplitterVertex carSplit = (SplitterVertex) linkToCar.getToVertex(); From 15c7da207b008bff83c16cc902e15c2160d01a52 Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Tue, 10 Dec 2024 16:34:29 +0100 Subject: [PATCH 66/98] refactor: Delete old comments/config in shaded-jar pom.xml The removed section was commented out by @abyrd in May 2014, and replaced later the same year with the current filter configuration (see filter config above the removed code). --- shaded-jar/pom.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/shaded-jar/pom.xml b/shaded-jar/pom.xml index 5709ef8245f..cf48c89271c 100644 --- a/shaded-jar/pom.xml +++ b/shaded-jar/pom.xml @@ -77,14 +77,6 @@ true false - - From c90aea1344534daa82f93a9abe65a31a74769757 Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Tue, 10 Dec 2024 19:15:49 +0100 Subject: [PATCH 67/98] feature: Add 'otp-shaded.jar' as an Maven published artifact. --- {shaded-jar => otp-shaded}/pom.xml | 87 +++++++++++++++++------------- pom.xml | 8 ++- 2 files changed, 55 insertions(+), 40 deletions(-) rename {shaded-jar => otp-shaded}/pom.xml (57%) diff --git a/shaded-jar/pom.xml b/otp-shaded/pom.xml similarity index 57% rename from shaded-jar/pom.xml rename to otp-shaded/pom.xml index cf48c89271c..1758813b3c5 100644 --- a/shaded-jar/pom.xml +++ b/otp-shaded/pom.xml @@ -8,12 +8,10 @@ otp-root 2.7.0-SNAPSHOT - shaded-jar - pom + otp-shaded OpenTripPlanner - Shaded Jar - skip false @@ -27,39 +25,25 @@ - - - - org.apache.maven.plugins + maven-shade-plugin - - ${project.build.directory}/otp-${project.version}-shaded.jar + ${skipShadeJar} + false + false @@ -71,12 +55,6 @@ - ${skipShadeJar} - - true - - false @@ -107,6 +85,39 @@ + + + + + + + com.hubspot.maven.plugins + prettier-maven-plugin + + true + + diff --git a/pom.xml b/pom.xml index edc1ab5efd7..b3166900806 100644 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ raptor gtfs-realtime-protobuf application - shaded-jar + otp-shaded @@ -110,6 +110,11 @@ maven-shade-plugin 3.6.0 + + com.hubspot.maven.plugins + prettier-maven-plugin + ${plugin.prettier.version} + @@ -290,7 +295,6 @@ com.hubspot.maven.plugins prettier-maven-plugin - ${plugin.prettier.version} ${plugin.prettier.skip} 2.0.0 From f85cf52e094920a5acb53d6a7b3bae9ee7a5aca8 Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Tue, 10 Dec 2024 20:31:15 +0100 Subject: [PATCH 68/98] doc: Fix references to the otp-shaded jar in doc. --- .github/workflows/performance-test.yml | 2 +- README.md | 15 ++++++++++----- doc/user/Basic-Tutorial.md | 18 +++++++++--------- doc/user/Developers-Guide.md | 2 +- doc/user/Getting-OTP.md | 25 +++++++++++-------------- script/otp | 2 +- script/run-and-test-otp | 5 +++-- 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/.github/workflows/performance-test.yml b/.github/workflows/performance-test.yml index 1ec537a0b4f..5e55e158a6f 100644 --- a/.github/workflows/performance-test.yml +++ b/.github/workflows/performance-test.yml @@ -88,7 +88,7 @@ jobs: - name: Build graph if: matrix.profile == 'core' || github.ref == 'refs/heads/dev-2.x' run: | - cp shaded-jar/target/otp-*-SNAPSHOT-shaded.jar otp.jar + cp otp-shaded/target/otp-shaded-*-SNAPSHOT.jar otp.jar java -Xmx32G -jar otp.jar --build --save test/performance/${{ matrix.location }}/ - name: Run speed test diff --git a/README.md b/README.md index ec66e694e8c..4ee4e02e69b 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,11 @@ We run a speed test (included in the code) to measure the performance for every ## Repository layout -The main Java server code is in `application/src/main/`. OTP also includes a Javascript client based on the -MapLibre mapping library in `client/src/`. This client is now used for testing, with most major -deployments building custom clients from reusable components. The Maven build produces a unified ("shaded") -JAR file at `shaded-jar/target/otp-VERSION.jar` containing all necessary code and dependencies to run OpenTripPlanner. +The main Java server code is in `application/src/main/`. OTP also includes a Javascript client +based on the MapLibre mapping library in `client/src/`. This client is now used for testing, with +most major deployments building custom clients from reusable components. The Maven build produces a +unified ("shaded") JAR file at `otp-shaded/target/otp-shaded-VERSION.jar` containing all necessary +code and dependencies to run OpenTripPlanner. Additional information and instructions are available in the [main documentation](http://docs.opentripplanner.org/en/dev-2.x/), including a @@ -59,7 +60,11 @@ the world. ## Getting in touch -The fastest way to get help is to use our [Gitter chat room](https://gitter.im/opentripplanner/OpenTripPlanner) where most of the core developers are. Bug reports may be filed via the Github [issue tracker](https://github.com/openplans/OpenTripPlanner/issues). The OpenTripPlanner [mailing list](http://groups.google.com/group/opentripplanner-users) is used almost exclusively for project announcements. The mailing list and issue tracker are not intended for support questions or discussions. Please use the chat for this purpose. Other details of [project governance](http://docs.opentripplanner.org/en/dev-2.x/Governance/) can be found in the main documentation. +The fastest way to get help is to use our [Gitter chat room](https://gitter.im/opentripplanner/OpenTripPlanner) where most of the core developers +are. Bug reports may be filed via the Github [issue tracker](https://github.com/openplans/OpenTripPlanner/issues). The OpenTripPlanner [mailing list](http://groups.google.com/group/opentripplanner-users) +is used almost exclusively for project announcements. The mailing list and issue tracker are not +intended for support questions or discussions. Please use the chat for this purpose. Other details +of [project governance](http://docs.opentripplanner.org/en/dev-2.x/Governance/) can be found in the main documentation. ## OTP Ecosystem diff --git a/doc/user/Basic-Tutorial.md b/doc/user/Basic-Tutorial.md index 64eeded6b01..e51ab44232a 100644 --- a/doc/user/Basic-Tutorial.md +++ b/doc/user/Basic-Tutorial.md @@ -18,9 +18,9 @@ JAR containing all other libraries needed for OTP to work, and is available from repository. You will be able to go to [the OTP directory at Maven Central](https://repo1.maven.org/maven2/org/opentripplanner/otp/), navigate to -the [directory of releases](https://repo1.maven.org/maven2/org/opentripplanner/otp/2.6.0/), +the [directory of releases](https://repo1.maven.org/maven2/org/opentripplanner/otp-shaded/2.7.0/), and download -the [file with `shaded.jar` suffix](https://repo1.maven.org/maven2/org/opentripplanner/otp/2.6.0/otp-2.6.0-shaded.jar) +the [file with `otp-shaded` artifactId](https://repo1.maven.org/maven2/org/opentripplanner/otp-shaded/2.7.0/otp-shaded-2.7.0.jar) . You may also want to get your own copy of the OTP source code @@ -95,7 +95,7 @@ for cropping and filtering OSM data. ## Starting OTP -A typical command to start OTP looks like `java -Xmx2G -jar otp.shaded.jar `. The +A typical command to start OTP looks like `java -Xmx2G -jar otp-shaded-VERSION.jar `. The `-Xmx` parameter sets the limit on how much memory OTP is allowed to consume. GTFS and OSM data sets are often very large, and OTP is relatively memory-hungry. You will need at least 1GB of memory when working with the Portland TriMet data set, and several gigabytes for larger inputs. @@ -129,7 +129,7 @@ below and in other tutorials. The simplest way to use OTP is to build a graph in a single step and start a server immediately, without saving it to disk. The command to do so is: - $ java -Xmx2G -jar otp-2.6.0-shaded.jar --build --serve /home/username/otp + $ java -Xmx2G -jar otp-shaded-2.7.0.jar --build --serve /home/username/otp where `/home/username/otp` should be the directory where you put your configuration and input files. @@ -154,13 +154,13 @@ build a graph from street and transit data then save it to a file using the `--b command line parameters together. If for example your current working directory (`.`) contains the input files and the OTP JAR file, you can use this command: - $ java -Xmx2G -jar otp-2.6.0-shaded.jar --build --save . + $ java -Xmx2G -jar otp-shaded-2.7.0.jar --build --save . This will produce a file called `graph.obj` in the same directory as the inputs. The server can then be started later using the `--load` parameter, and will read this file instead of building the graph from scratch: - $ java -Xmx2G -jar otp-2.6.0-shaded.jar --load . + $ java -Xmx2G -jar otp-shaded-2.7.0.jar --load . Another reason to perform these two phases separately is that the building process loads the entire GTFS and OSM data sets into memory, so can require significantly more memory than just running a @@ -177,16 +177,16 @@ graph once, and then layer transit data on top of the streets to make the final Again assuming the input files and OTP JAR file are in the current working directory, you can build a street graph with OSM and elevation data only (ignoring transit input files) with this command: - $ java -Xmx2G -jar otp-2.6.0-shaded.jar --buildStreet . + $ java -Xmx2G -jar otp-shaded-2.7.0.jar --buildStreet . Then, to build a graph layering transit data on top of the saved street graph (built using the previous command): - $ java -Xmx2G -jar otp-2.6.0-shaded.jar --loadStreet --save . + $ java -Xmx2G -jar otp-shaded-2.7.0.jar --loadStreet --save . Finally, the server can be started using the `--load` parameter: - $ java -Xmx2G -jar otp-2.6.0-shaded.jar --load . + $ java -Xmx2G -jar otp-shaded-2.7.0.jar --load . ## Command Line Switches diff --git a/doc/user/Developers-Guide.md b/doc/user/Developers-Guide.md index f5633ff17b1..d109f7a9170 100644 --- a/doc/user/Developers-Guide.md +++ b/doc/user/Developers-Guide.md @@ -232,7 +232,7 @@ Releases are performed off the master branch, and are tagged with git annotated OpenTripPlanner is currently configured such that builds including releases upload JAR files to GitHub Packages. This is not the most convenient place for end users to find and download the files. -Therefore we also attach a stand-alone "shaded" JAR to the GitHub tag/release page, and have +Therefore, we also attach a stand-alone "shaded" JAR to the GitHub tag/release page. We have historically also uploaded Maven artifacts to Maven Central including compiled and source code JARs as well as the "shaded" JAR containing all dependencies, allowing stand-alone usage. This release process is handled by the Sonatype Nexus Staging plugin, which is no longer configured in the diff --git a/doc/user/Getting-OTP.md b/doc/user/Getting-OTP.md index ea0bac0df90..c9585a9caf5 100644 --- a/doc/user/Getting-OTP.md +++ b/doc/user/Getting-OTP.md @@ -6,8 +6,8 @@ OpenTripPlanner is distributed as a single stand-alone runnable JAR file. We cre release page on GitHub for each release version, and also deploy them to the Maven Central repository. You can go to the [release pages on GitHub](https://github.com/opentripplanner/OpenTripPlanner/releases) -or [the OTP directory at Maven Central](https://repo1.maven.org/maven2/org/opentripplanner/otp/), -navigate to the highest version number, and download the file whose name ends with `shaded.jar`. +or [the OTP directory at Maven Central](https://repo1.maven.org/maven2/org/opentripplanner/otp-shaded/), +navigate to the highest version number, and download the jar file `otp-shaded-VERSION.jar`. Note that version numbers like `v2.1.0-rc1` or `v2.6.0-SNAPSHOT` refer to development builds _ before_ the release version `v2.6.0`. The existence of a build `vX.Y.Z-SNAPSHOT` does not mean @@ -64,8 +64,8 @@ OTP. If all goes well you should see a success message like the following: [INFO] ------------------------------------------------------------------------ ``` -This build process should produce a JAR file called `otp-x.y.z-shaded.jar` in the -`shaded-jar/target/` directory which contains all the compiled OTP classes and their dependencies +This build process should produce a JAR file called `otp-shaded-x.y.z.jar` in the +`otp-shaded/target/` directory which contains all the compiled OTP classes and their dependencies (the external libraries they use). The shell script called 'otp' in the root of the cloned repository will start the main class of that JAR file under a Java virtual machine, so after the Maven build completes you should be able to run `./otp --help` and see an OTP help message including command line @@ -92,14 +92,11 @@ git clean -df mvn clean package -DskipTests ``` -Please note that the build process creates two distinct versions of the OTP JAR file. The one ending -in `-shaded.jar` -is much bigger because it contains copies of all the external libraries that OTP uses. It serves as -a stand-alone runnable distribution of OTP. The one with a version number but without the -word `shaded` -contains only OTP itself, without any external dependencies. This JAR is useful when OTP is included -as a component in some other project, where we want the dependency management system to gather all -the external libraries automatically. +Please note that the build process multiple jar files. The `otp-shaded-VERSION.jar` is much bigger +because it contains copies of all the external libraries that OTP uses. It serves as a stand-alone +runnable distribution of OTP. The other jar files are regular Java jar files. These JAR files are +useful when OTP is included as a component in some other project, where we want the dependency +management system to gather all the external libraries automatically. ## Maven Repository @@ -110,8 +107,8 @@ file) to the Maven repository, from which it can be automatically included in ot This repository is machine-readable (by Maven or other build systems) and also provides human readable directory listings via HTTP. You can fetch an OTP JAR from this repository by constructing -the proper URL for the release you want. For example, release 2.6.0 will be found -at `https://repo1.maven.org/maven2/org/opentripplanner/otp/2.6.0/otp-2.6.0-shaded.jar`. +the proper URL for the release you want. For example, release 2.7.0 will be found +at `https://repo1.maven.org/maven2/org/opentripplanner/otp-shaded/2.7.0/otp-shaded-2.7.0-shaded.jar`. To make use of OTP in another Maven project, you must specify it as a dependency in that project's `pom.xml`: diff --git a/script/otp b/script/otp index 58e7c7b65fa..5dae485f663 100755 --- a/script/otp +++ b/script/otp @@ -3,6 +3,6 @@ # Standalone OTP can build a graph, run an OTP API server, # or any combination of these. -JAR_FILE="$(dirname $0)/target/${project.build.finalName}-shaded.jar" +JAR_FILE="$(dirname $0)/../otp-shaded/target/otp-shaded-2.7.0-SNAPSHOT.jar" java -Xmx8G -jar "${JAR_FILE}" "$@" diff --git a/script/run-and-test-otp b/script/run-and-test-otp index 0fc322e3a86..d1c7c9bdbe1 100755 --- a/script/run-and-test-otp +++ b/script/run-and-test-otp @@ -58,6 +58,7 @@ fi # is not working as expected. OTP_LOG=target/otp.log RESPONSE_FILE=target/response.json +SHADED_TARGET=otp-shaded/target if [ "$1" != "--skipCompile" ] && [ "$1" != "-c" ]; then @@ -66,8 +67,8 @@ if [ "$1" != "--skipCompile" ] && [ "$1" != "-c" ]; then fi echo "Start OTP, output: $OTP_LOG" -mv target/otp-*-shaded.jar target/otp-shaded.jar -java -Xmx16G -jar target/otp-shaded.jar ${DATA_DIR} --build --save --serve > ${OTP_LOG} & +mv ${SHADED_TARGET}/otp-shaded-*.jar ${SHADED_TARGET}/otp-shaded.jar +java -Xmx16G -jar ${SHADED_TARGET}/otp-shaded.jar ${DATA_DIR} --build --save --serve > ${OTP_LOG} & OTP_PID=$! tail -F ${OTP_LOG} & From 3ae6eedf3c2b006cbbb3bcd9ceb07a46e5c677f2 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Wed, 11 Dec 2024 16:40:38 +0200 Subject: [PATCH 69/98] Change logging in transfer calculations. --- .../module/DirectTransferGenerator.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index 626c85312a7..dcd56822a09 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -209,21 +209,17 @@ public void buildGraph() { nTransfersTotal, nLinkedStops ); - for (StreetMode mode : transferRequests + transferRequests .stream() .map(transferProfile -> transferProfile.journey().transfer().mode()) .distinct() - .toList()) { - LOG.info( - "Created {} transfers for mode {}.", - transfersByStop - .values() - .stream() - .filter(pathTransfer -> pathTransfer.getModes().contains(mode)) - .count(), - mode + .forEach(mode -> + LOG.info( + "Created {} transfers for mode {}.", + timetableRepository.getTransfersByMode(mode).size(), + mode + ) ); - } } /** From 4a01328ab31f1c49060d3df33c4b390d90cc3a01 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Thu, 12 Dec 2024 12:34:11 +0200 Subject: [PATCH 70/98] Refactor to use method. --- .../src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java | 4 +--- .../opentripplanner/transit/service/TimetableRepository.java | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java index ccc4f7fe554..73259fbc80e 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java @@ -30,9 +30,7 @@ public class FlexIndex { public FlexIndex(TimetableRepository timetableRepository) { // Flex transfers should only use WALK mode transfers. - StreetMode mode = StreetMode.WALK; - List filteredPathTransfers = timetableRepository.getAllPathTransfers().stream().filter(pathTransfer -> pathTransfer.getModes().contains(mode)).toList(); - for (PathTransfer transfer : filteredPathTransfers) { + for (PathTransfer transfer : timetableRepository.getTransfersByMode(StreetMode.WALK)) { transfersToStop.put(transfer.to, transfer); transfersFromStop.put(transfer.from, transfer); } diff --git a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java index d83c3f9b996..7ef6da379f1 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -434,7 +435,7 @@ public Collection getTransfersByStop(StopLocation stop) { return transfersByStop.get(stop); } - public Collection getTransfersByMode(StreetMode mode) { + public List getTransfersByMode(StreetMode mode) { return transfersByStop .values() .stream() From 95e9ca770bac8f0751f951f3223ffb669d66baa4 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Thu, 12 Dec 2024 13:43:09 +0200 Subject: [PATCH 71/98] Rename getTransfersByMode to findTransfers. --- .../ext/java/org/opentripplanner/ext/flex/FlexIndex.java | 2 +- .../graph_builder/module/DirectTransferGenerator.java | 2 +- .../transit/service/TimetableRepository.java | 2 +- .../graph_builder/module/DirectTransferGeneratorTest.java | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java index 73259fbc80e..86d9766178f 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java @@ -30,7 +30,7 @@ public class FlexIndex { public FlexIndex(TimetableRepository timetableRepository) { // Flex transfers should only use WALK mode transfers. - for (PathTransfer transfer : timetableRepository.getTransfersByMode(StreetMode.WALK)) { + for (PathTransfer transfer : timetableRepository.findTransfers(StreetMode.WALK)) { transfersToStop.put(transfer.to, transfer); transfersFromStop.put(transfer.from, transfer); } diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java index dcd56822a09..37ac69d88ff 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java @@ -216,7 +216,7 @@ public void buildGraph() { .forEach(mode -> LOG.info( "Created {} transfers for mode {}.", - timetableRepository.getTransfersByMode(mode).size(), + timetableRepository.findTransfers(mode).size(), mode ) ); diff --git a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java index 7ef6da379f1..5c57724d90d 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java @@ -435,7 +435,7 @@ public Collection getTransfersByStop(StopLocation stop) { return transfersByStop.get(stop); } - public List getTransfersByMode(StreetMode mode) { + public List findTransfers(StreetMode mode) { return transfersByStop .values() .stream() diff --git a/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java b/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java index 482cb0afd13..39d2f4b5684 100644 --- a/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java +++ b/application/src/test/java/org/opentripplanner/graph_builder/module/DirectTransferGeneratorTest.java @@ -274,9 +274,9 @@ public void testPathTransfersWithModesForMultipleRequestsWithPatterns() { ) .buildGraph(); - var walkTransfers = timetableRepository.getTransfersByMode(StreetMode.WALK); - var bikeTransfers = timetableRepository.getTransfersByMode(StreetMode.BIKE); - var carTransfers = timetableRepository.getTransfersByMode(StreetMode.CAR); + var walkTransfers = timetableRepository.findTransfers(StreetMode.WALK); + var bikeTransfers = timetableRepository.findTransfers(StreetMode.BIKE); + var carTransfers = timetableRepository.findTransfers(StreetMode.CAR); assertTransfers( walkTransfers, From fbd1ff17fd92510bc3ea50d44842c8b51deae889 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Thu, 12 Dec 2024 22:36:14 +0100 Subject: [PATCH 72/98] Rename 'bogusName' to 'nameIsDerived' --- .../ext/restapi/mapping/WalkStepMapper.java | 2 +- .../apis/gtfs/datafetchers/stepImpl.java | 2 +- .../transmodel/model/plan/PathGuidanceType.java | 2 +- .../module/osm/naming/PortlandCustomNamer.java | 6 +++--- .../inspector/raster/PathwayEdgeRenderer.java | 2 +- .../vector/edge/EdgePropertyMapper.java | 2 +- .../opentripplanner/model/plan/WalkStep.java | 11 ++++++----- .../model/plan/WalkStepBuilder.java | 15 +++++++++------ .../mapping/StatesToWalkStepsMapper.java | 4 ++-- .../opentripplanner/street/model/edge/Edge.java | 2 +- .../street/model/edge/ElevatorAlightEdge.java | 2 +- .../street/model/edge/ElevatorBoardEdge.java | 2 +- .../street/model/edge/PathwayEdge.java | 2 +- .../street/model/edge/StreetEdge.java | 17 +++++++++++------ .../street/model/edge/StreetEdgeBuilder.java | 4 ++-- .../module/osm/naming/SidewalkNamerTest.java | 2 +- .../model/edge/StreetEdgeBuilderTest.java | 6 +++--- .../street/model/edge/StreetEdgeTest.java | 4 ++-- 18 files changed, 48 insertions(+), 39 deletions(-) diff --git a/application/src/ext/java/org/opentripplanner/ext/restapi/mapping/WalkStepMapper.java b/application/src/ext/java/org/opentripplanner/ext/restapi/mapping/WalkStepMapper.java index c5c59e4dc37..8767abe7478 100644 --- a/application/src/ext/java/org/opentripplanner/ext/restapi/mapping/WalkStepMapper.java +++ b/application/src/ext/java/org/opentripplanner/ext/restapi/mapping/WalkStepMapper.java @@ -42,7 +42,7 @@ public ApiWalkStep mapWalkStep(WalkStep domain) { api.exit = domain.getExit(); api.stayOn = domain.isStayOn(); api.area = domain.getArea(); - api.bogusName = domain.getBogusName(); + api.bogusName = domain.nameIsDerived(); if (domain.getStartLocation() != null) { api.lon = domain.getStartLocation().longitude(); api.lat = domain.getStartLocation().latitude(); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java index 6bd51ae5f29..f14db6f213f 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/stepImpl.java @@ -35,7 +35,7 @@ public DataFetcher area() { @Override public DataFetcher bogusName() { - return environment -> getSource(environment).getBogusName(); + return environment -> getSource(environment).nameIsDerived(); } @Override diff --git a/application/src/main/java/org/opentripplanner/apis/transmodel/model/plan/PathGuidanceType.java b/application/src/main/java/org/opentripplanner/apis/transmodel/model/plan/PathGuidanceType.java index c52baa0be4c..68406f57d54 100644 --- a/application/src/main/java/org/opentripplanner/apis/transmodel/model/plan/PathGuidanceType.java +++ b/application/src/main/java/org/opentripplanner/apis/transmodel/model/plan/PathGuidanceType.java @@ -96,7 +96,7 @@ public static GraphQLObjectType create(GraphQLObjectType elevationStepType) { "The name of this street was generated by the system, so we should only display it once, and generally just display right/left directions" ) .type(Scalars.GraphQLBoolean) - .dataFetcher(environment -> ((WalkStep) environment.getSource()).getBogusName()) + .dataFetcher(environment -> ((WalkStep) environment.getSource()).nameIsDerived()) .build() ) .field( diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/naming/PortlandCustomNamer.java b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/naming/PortlandCustomNamer.java index e05bc736cbb..42bd57ca13c 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/naming/PortlandCustomNamer.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/naming/PortlandCustomNamer.java @@ -76,7 +76,7 @@ public void recordEdges(OsmWithTags way, StreetEdgePair edgePair) { edgePair .asIterable() .forEach(edge -> { - if (!edge.hasBogusName()) { + if (!edge.nameIsDerived()) { return; // this edge already has a real name so there is nothing to do } if (isHighwayLink) { @@ -149,7 +149,7 @@ private static String nameAccordingToDestination(StreetEdge e, int maxDepth) { return null; } for (StreetEdge out : e.getToVertex().getOutgoingStreetEdges()) { - if (out.hasBogusName()) { + if (out.nameIsDerived()) { String name = nameAccordingToDestination(out, maxDepth - 1); if (name == null) { continue; @@ -170,7 +170,7 @@ private static String nameAccordingToOrigin(StreetEdge e, int maxDepth) { return null; } for (StreetEdge in : e.getFromVertex().getIncomingStreetEdges()) { - if (in.hasBogusName()) { + if (in.nameIsDerived()) { String name = nameAccordingToOrigin(in, maxDepth - 1); if (name == null) { continue; diff --git a/application/src/main/java/org/opentripplanner/inspector/raster/PathwayEdgeRenderer.java b/application/src/main/java/org/opentripplanner/inspector/raster/PathwayEdgeRenderer.java index 0da19670264..27328b1ba1f 100644 --- a/application/src/main/java/org/opentripplanner/inspector/raster/PathwayEdgeRenderer.java +++ b/application/src/main/java/org/opentripplanner/inspector/raster/PathwayEdgeRenderer.java @@ -22,7 +22,7 @@ public Optional renderEdge(Edge e) { StringBuilder sb = new StringBuilder(); - if (!pwe.hasBogusName()) { + if (!pwe.nameIsDerived()) { sb.append("name=").append(pwe.getName()).append(", "); } diff --git a/application/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java b/application/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java index 83b677a62ce..1363ba7e6be 100644 --- a/application/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java +++ b/application/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java @@ -38,7 +38,7 @@ private static List mapStreetEdge(StreetEdge se) { kv("noThruTraffic", noThruTrafficAsString(se)), kv("wheelchairAccessible", se.isWheelchairAccessible()) ); - if (se.hasBogusName()) { + if (se.nameIsDerived()) { props.addFirst(kv("name", "%s (generated)".formatted(se.getName().toString()))); } else { props.addFirst(kv("name", se.getName().toString())); diff --git a/application/src/main/java/org/opentripplanner/model/plan/WalkStep.java b/application/src/main/java/org/opentripplanner/model/plan/WalkStep.java index 45f2b5da701..c2c2b2c609e 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/WalkStep.java +++ b/application/src/main/java/org/opentripplanner/model/plan/WalkStep.java @@ -39,7 +39,7 @@ public final class WalkStep { private final Set streetNotes; private final boolean area; - private final boolean bogusName; + private final boolean nameIsDerived; private final double angle; private final boolean walkingBike; @@ -57,7 +57,7 @@ public final class WalkStep { Set streetNotes, String exit, ElevationProfile elevationProfile, - boolean bogusName, + boolean nameIsDerived, boolean walkingBike, boolean area, boolean stayOn, @@ -71,7 +71,7 @@ public final class WalkStep { this.directionText = directionText; this.streetNotes = Set.copyOf(Objects.requireNonNull(streetNotes)); this.startLocation = Objects.requireNonNull(startLocation); - this.bogusName = bogusName; + this.nameIsDerived = nameIsDerived; this.angle = DoubleUtils.roundTo2Decimals(angle); this.walkingBike = walkingBike; this.area = area; @@ -148,9 +148,10 @@ public boolean getArea() { /** * The name of this street was generated by the system, so we should only display it once, and * generally just display right/left directions + * @see Edge#nameIsDerived() */ - public boolean getBogusName() { - return bogusName; + public boolean nameIsDerived() { + return nameIsDerived; } /** diff --git a/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java b/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java index 8d4df6634fd..a972e62e709 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java +++ b/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java @@ -17,7 +17,7 @@ public class WalkStepBuilder { private final Set streetNotes = new HashSet<>(); private I18NString directionText; private WgsCoordinate startLocation; - private boolean bogusName = false; + private boolean nameIsDerived = false; private double angle; private boolean walkingBike = false; private boolean area = false; @@ -44,8 +44,8 @@ public WalkStepBuilder withStartLocation(WgsCoordinate startLocation) { return this; } - public WalkStepBuilder withBogusName(boolean bogusName) { - this.bogusName = bogusName; + public WalkStepBuilder withBogusName(boolean nameIsDerived) { + this.nameIsDerived = nameIsDerived; return this; } @@ -140,8 +140,11 @@ public I18NString directionText() { return directionText; } - public boolean bogusName() { - return bogusName; + /** + * @see Edge#nameIsDerived() + */ + public boolean nameIsDerived() { + return nameIsDerived; } public RelativeDirection relativeDirection() { @@ -157,7 +160,7 @@ public WalkStep build() { streetNotes, exit, elevationProfile, - bogusName, + nameIsDerived, walkingBike, area, stayOn, diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java index 32f5ccf533b..bf140dfbc53 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java @@ -430,7 +430,7 @@ private boolean continueOnSameStreet(Edge edge, String streetNameNoParens) { return !( current.directionText().toString() != null && !(java.util.Objects.equals(current.directionTextNoParens(), streetNameNoParens)) && - (!current.bogusName() || !edge.hasBogusName()) + (!current.nameIsDerived() || !edge.nameIsDerived()) ); } @@ -543,7 +543,7 @@ private WalkStepBuilder createWalkStep(State forwardState, State backState) { .builder() .withDirectionText(en.getName()) .withStartLocation(new WgsCoordinate(backState.getVertex().getCoordinate())) - .withBogusName(en.hasBogusName()) + .withBogusName(en.nameIsDerived()) .withAngle(DirectionUtils.getFirstAngle(forwardState.getBackEdge().getGeometry())) .withWalkingBike(forwardState.isBackWalkingBike()) .withArea(forwardState.getBackEdge() instanceof AreaEdge) diff --git a/application/src/main/java/org/opentripplanner/street/model/edge/Edge.java b/application/src/main/java/org/opentripplanner/street/model/edge/Edge.java index 8e4126b4e59..b24dbb2e36e 100644 --- a/application/src/main/java/org/opentripplanner/street/model/edge/Edge.java +++ b/application/src/main/java/org/opentripplanner/street/model/edge/Edge.java @@ -152,7 +152,7 @@ public String getDefaultName() { * Returns false if the field reflects the real world name, like "Fifth Avenue", * "Hauptstraße" or "Øvre Holmegate". */ - public boolean hasBogusName() { + public boolean nameIsDerived() { return false; } diff --git a/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorAlightEdge.java b/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorAlightEdge.java index ca3b0b4b0f7..8fa88009b73 100644 --- a/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorAlightEdge.java +++ b/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorAlightEdge.java @@ -76,7 +76,7 @@ public I18NString getName() { * @author mattwigway */ @Override - public boolean hasBogusName() { + public boolean nameIsDerived() { return false; } diff --git a/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorBoardEdge.java b/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorBoardEdge.java index 9bf0d67afa5..cacc97fc2f1 100644 --- a/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorBoardEdge.java +++ b/application/src/main/java/org/opentripplanner/street/model/edge/ElevatorBoardEdge.java @@ -65,7 +65,7 @@ public I18NString getName() { * never included in plans. */ @Override - public boolean hasBogusName() { + public boolean nameIsDerived() { return true; } diff --git a/application/src/main/java/org/opentripplanner/street/model/edge/PathwayEdge.java b/application/src/main/java/org/opentripplanner/street/model/edge/PathwayEdge.java index 703658fdda4..cfa82ba85b5 100644 --- a/application/src/main/java/org/opentripplanner/street/model/edge/PathwayEdge.java +++ b/application/src/main/java/org/opentripplanner/street/model/edge/PathwayEdge.java @@ -167,7 +167,7 @@ public I18NString getName() { } @Override - public boolean hasBogusName() { + public boolean nameIsDerived() { return signpostedAs == null; } diff --git a/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java b/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java index 468da359e0a..02675b1202c 100644 --- a/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java +++ b/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java @@ -55,7 +55,10 @@ public class StreetEdge /** If you have more than 16 flags, increase flags to short or int */ static final int BACK_FLAG_INDEX = 0; static final int ROUNDABOUT_FLAG_INDEX = 1; - static final int HASBOGUSNAME_FLAG_INDEX = 2; + /** + * @see Edge#nameIsDerived() + */ + static final int NAME_IS_DERIVED_FLAG_INDEX = 2; static final int MOTOR_VEHICLE_NOTHRUTRAFFIC = 3; static final int STAIRS_FLAG_INDEX = 4; static final int SLOPEOVERRIDE_FLAG_INDEX = 5; @@ -444,20 +447,22 @@ public I18NString getName() { } /** - * Update the name of the edge after it has been constructed. This method also sets the bogusName + * Update the name of the edge after it has been constructed. This method also sets the nameIsDerived * property to false, indicating to the code that maps from edges to steps that this is a real * street name. - * @see Edge#hasBogusName() + * @see Edge#nameIsDerived() */ public void setName(I18NString name) { this.name = name; - this.flags = BitSetUtils.set(flags, HASBOGUSNAME_FLAG_INDEX, false); + this.flags = BitSetUtils.set(flags, NAME_IS_DERIVED_FLAG_INDEX, false); } - public boolean hasBogusName() { - return BitSetUtils.get(flags, HASBOGUSNAME_FLAG_INDEX); + @Override + public boolean nameIsDerived() { + return BitSetUtils.get(flags, NAME_IS_DERIVED_FLAG_INDEX); } + @Override public LineString getGeometry() { return CompactLineStringUtils.uncompactLineString( fromv.getLon(), diff --git a/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java b/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java index 99a02205eb6..f189cb68f14 100644 --- a/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java +++ b/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java @@ -3,7 +3,7 @@ import static org.opentripplanner.street.model.edge.StreetEdge.BACK_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.BICYCLE_NOTHRUTRAFFIC; import static org.opentripplanner.street.model.edge.StreetEdge.CLASS_LINK; -import static org.opentripplanner.street.model.edge.StreetEdge.HASBOGUSNAME_FLAG_INDEX; +import static org.opentripplanner.street.model.edge.StreetEdge.NAME_IS_DERIVED_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.MOTOR_VEHICLE_NOTHRUTRAFFIC; import static org.opentripplanner.street.model.edge.StreetEdge.ROUNDABOUT_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.SLOPEOVERRIDE_FLAG_INDEX; @@ -175,7 +175,7 @@ public B withLink(boolean link) { } public B withBogusName(boolean hasBogusName) { - flags = BitSetUtils.set(flags, HASBOGUSNAME_FLAG_INDEX, hasBogusName); + flags = BitSetUtils.set(flags, NAME_IS_DERIVED_FLAG_INDEX, hasBogusName); return instance(); } diff --git a/application/src/test/java/org/opentripplanner/graph_builder/module/osm/naming/SidewalkNamerTest.java b/application/src/test/java/org/opentripplanner/graph_builder/module/osm/naming/SidewalkNamerTest.java index cbfb7b76c6f..851a71620bf 100644 --- a/application/src/test/java/org/opentripplanner/graph_builder/module/osm/naming/SidewalkNamerTest.java +++ b/application/src/test/java/org/opentripplanner/graph_builder/module/osm/naming/SidewalkNamerTest.java @@ -58,7 +58,7 @@ void postprocess() { assertNotEquals(sidewalk.edge.getName(), pryorStreet.edge.getName()); builder.postProcess(new SidewalkNamer()); assertEquals(sidewalk.edge.getName(), pryorStreet.edge.getName()); - assertFalse(sidewalk.edge.hasBogusName()); + assertFalse(sidewalk.edge.nameIsDerived()); } private static class ModelBuilder { diff --git a/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeBuilderTest.java b/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeBuilderTest.java index d447916d21d..aeddb9221c9 100644 --- a/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeBuilderTest.java +++ b/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeBuilderTest.java @@ -32,7 +32,7 @@ class StreetEdgeBuilderTest { private static final float WALK_SAFETY_FACTOR = 0.5f; private static final float BICYCLE_SAFETY_FACTOR = 0.4f; private static final boolean SLOPE_OVERRIDE = false; - private static final boolean BOGUS_NAME = true; + private static final boolean NAME_IS_DERIVED = true; private static final boolean BICYCLE_NO_THRU_TRAFFIC = true; private static final boolean MOTOR_VEHICLE_NO_THRU_TRAFFIC = true; private static final boolean WALK_NO_THRU_TRAFFIC = true; @@ -82,7 +82,7 @@ private static StreetEdge buildStreetEdge() { .withBack(BACK) .withStairs(STAIRS) .withSlopeOverride(SLOPE_OVERRIDE) - .withBogusName(BOGUS_NAME) + .withBogusName(NAME_IS_DERIVED) .withWalkNoThruTraffic(WALK_NO_THRU_TRAFFIC) .withBicycleNoThruTraffic(BICYCLE_NO_THRU_TRAFFIC) .withMotorVehicleNoThruTraffic(MOTOR_VEHICLE_NO_THRU_TRAFFIC) @@ -100,7 +100,7 @@ private static void assertAllProperties(StreetEdge streetEdge) { assertEquals(WALK_SAFETY_FACTOR, streetEdge.getWalkSafetyFactor()); assertEquals(BICYCLE_SAFETY_FACTOR, streetEdge.getBicycleSafetyFactor()); assertEquals(SLOPE_OVERRIDE, streetEdge.isSlopeOverride()); - assertEquals(BOGUS_NAME, streetEdge.hasBogusName()); + assertEquals(NAME_IS_DERIVED, streetEdge.nameIsDerived()); assertEquals(WALK_NO_THRU_TRAFFIC, streetEdge.isWalkNoThruTraffic()); assertEquals(BICYCLE_NO_THRU_TRAFFIC, streetEdge.isBicycleNoThruTraffic()); assertEquals(MOTOR_VEHICLE_NO_THRU_TRAFFIC, streetEdge.isMotorVehicleNoThruTraffic()); diff --git a/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java b/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java index ef2bacb91dd..bbc77656a23 100644 --- a/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java +++ b/application/src/test/java/org/opentripplanner/street/model/edge/StreetEdgeTest.java @@ -413,11 +413,11 @@ void setName() { .buildAndConnect(); assertEquals(path, edge.getName()); - assertTrue(edge.hasBogusName()); + assertTrue(edge.nameIsDerived()); var mainStreet = I18NString.of("Main Street"); edge.setName(mainStreet); assertEquals(mainStreet, edge.getName()); - assertFalse(edge.hasBogusName()); + assertFalse(edge.nameIsDerived()); } } From 4c6db7fa912eebce17adcc8ae06ae184b49bd67c Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Fri, 13 Dec 2024 08:04:25 +0100 Subject: [PATCH 73/98] Rename missing method --- .../java/org/opentripplanner/model/plan/WalkStepBuilder.java | 2 +- .../routing/algorithm/mapping/StatesToWalkStepsMapper.java | 4 ++-- .../opentripplanner/street/model/edge/StreetEdgeBuilder.java | 2 +- .../java/org/opentripplanner/model/plan/WalkStepTest.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java b/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java index a972e62e709..b2f9e1f7510 100644 --- a/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java +++ b/application/src/main/java/org/opentripplanner/model/plan/WalkStepBuilder.java @@ -44,7 +44,7 @@ public WalkStepBuilder withStartLocation(WgsCoordinate startLocation) { return this; } - public WalkStepBuilder withBogusName(boolean nameIsDerived) { + public WalkStepBuilder withNameIsDerived(boolean nameIsDerived) { this.nameIsDerived = nameIsDerived; return this; } diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java index bf140dfbc53..4ce1c616e65 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java @@ -525,7 +525,7 @@ private void createAndSaveStep( addStep( createWalkStep(forwardState, backState) .withDirectionText(name) - .withBogusName(false) + .withNameIsDerived(false) .withDirections(lastAngle, DirectionUtils.getFirstAngle(edge.getGeometry()), false) .withRelativeDirection(direction) .addDistance(edge.getDistanceMeters()) @@ -543,7 +543,7 @@ private WalkStepBuilder createWalkStep(State forwardState, State backState) { .builder() .withDirectionText(en.getName()) .withStartLocation(new WgsCoordinate(backState.getVertex().getCoordinate())) - .withBogusName(en.nameIsDerived()) + .withNameIsDerived(en.nameIsDerived()) .withAngle(DirectionUtils.getFirstAngle(forwardState.getBackEdge().getGeometry())) .withWalkingBike(forwardState.isBackWalkingBike()) .withArea(forwardState.getBackEdge() instanceof AreaEdge) diff --git a/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java b/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java index f189cb68f14..aa168b1453d 100644 --- a/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java +++ b/application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeBuilder.java @@ -3,8 +3,8 @@ import static org.opentripplanner.street.model.edge.StreetEdge.BACK_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.BICYCLE_NOTHRUTRAFFIC; import static org.opentripplanner.street.model.edge.StreetEdge.CLASS_LINK; -import static org.opentripplanner.street.model.edge.StreetEdge.NAME_IS_DERIVED_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.MOTOR_VEHICLE_NOTHRUTRAFFIC; +import static org.opentripplanner.street.model.edge.StreetEdge.NAME_IS_DERIVED_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.ROUNDABOUT_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.SLOPEOVERRIDE_FLAG_INDEX; import static org.opentripplanner.street.model.edge.StreetEdge.STAIRS_FLAG_INDEX; diff --git a/application/src/test/java/org/opentripplanner/model/plan/WalkStepTest.java b/application/src/test/java/org/opentripplanner/model/plan/WalkStepTest.java index 7199c7bea60..4556cb90de0 100644 --- a/application/src/test/java/org/opentripplanner/model/plan/WalkStepTest.java +++ b/application/src/test/java/org/opentripplanner/model/plan/WalkStepTest.java @@ -17,7 +17,7 @@ public void testRelativeDirection() { WalkStepBuilder builder = new WalkStepBuilder() .withDirectionText(new NonLocalizedString("Any")) .withStartLocation(new WgsCoordinate(3.0, 4.0)) - .withBogusName(false) + .withNameIsDerived(false) .withAngle(0.0) .withWalkingBike(false) .withArea(false); From f384f07e2b41d1f14973114790f617bc0a97d093 Mon Sep 17 00:00:00 2001 From: OTP Changelog Bot Date: Fri, 13 Dec 2024 12:44:42 +0000 Subject: [PATCH 74/98] Add changelog entry for #6331 [ci skip] --- doc/user/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/Changelog.md b/doc/user/Changelog.md index fde54b3c21a..414e99d69ec 100644 --- a/doc/user/Changelog.md +++ b/doc/user/Changelog.md @@ -62,6 +62,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Better escalator duration control: specific duration from OSM duration tag, default speed from build-config.json [#6268](https://github.com/opentripplanner/OpenTripPlanner/pull/6268) - Detect JSON array in addition to JSON objects when including a file in the config. [#6307](https://github.com/opentripplanner/OpenTripPlanner/pull/6307) - Use WCAG recommendation to fill in GTFS route text color if it is missing [#6308](https://github.com/opentripplanner/OpenTripPlanner/pull/6308) +- Add shaded jar artifact [#6331](https://github.com/opentripplanner/OpenTripPlanner/pull/6331) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.6.0 (2024-09-18) From 2592135227598b50d5faf23a86520811a38f4af1 Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Fri, 13 Dec 2024 13:59:35 +0100 Subject: [PATCH 75/98] doc: Improve changelog name for PR: #6331 Rename `otp-shaded-jar` artifact and fix deployment to Maven Central --- doc/user/Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/Changelog.md b/doc/user/Changelog.md index 414e99d69ec..e652c7600d9 100644 --- a/doc/user/Changelog.md +++ b/doc/user/Changelog.md @@ -62,7 +62,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Better escalator duration control: specific duration from OSM duration tag, default speed from build-config.json [#6268](https://github.com/opentripplanner/OpenTripPlanner/pull/6268) - Detect JSON array in addition to JSON objects when including a file in the config. [#6307](https://github.com/opentripplanner/OpenTripPlanner/pull/6307) - Use WCAG recommendation to fill in GTFS route text color if it is missing [#6308](https://github.com/opentripplanner/OpenTripPlanner/pull/6308) -- Add shaded jar artifact [#6331](https://github.com/opentripplanner/OpenTripPlanner/pull/6331) +- Rename `otp-shaded-jar` artifact and fix deployment to Maven Central [#6331](https://github.com/opentripplanner/OpenTripPlanner/pull/6331) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.6.0 (2024-09-18) From f9b33c5b23dfdadbeca8dc3c445d69db298bb40d Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Fri, 13 Dec 2024 14:41:42 +0100 Subject: [PATCH 76/98] Also exclude container build from shaded jar --- otp-shaded/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/otp-shaded/pom.xml b/otp-shaded/pom.xml index 1758813b3c5..129f108e1af 100644 --- a/otp-shaded/pom.xml +++ b/otp-shaded/pom.xml @@ -118,6 +118,13 @@ true + + com.google.cloud.tools + jib-maven-plugin + + true + + From df64c5a7f5ffc4453db5f74d21536770c27cb3ff Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Fri, 13 Dec 2024 16:03:01 +0200 Subject: [PATCH 77/98] Changes based on review comments and small optimization. --- .../org/opentripplanner/ext/flex/FlexIndex.java | 1 - .../raptoradapter/transit/RaptorTransferIndex.java | 5 ++--- .../algorithm/raptoradapter/transit/Transfer.java | 13 ++++++------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java index 86d9766178f..8097bd05c6e 100644 --- a/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java +++ b/application/src/ext/java/org/opentripplanner/ext/flex/FlexIndex.java @@ -5,7 +5,6 @@ import com.google.common.collect.Multimap; import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.opentripplanner.ext.flex.trip.FlexTrip; import org.opentripplanner.model.PathTransfer; diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java index 941e1296838..8676e863911 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/RaptorTransferIndex.java @@ -33,7 +33,6 @@ public static RaptorTransferIndex create( StreetMode mode = request.mode(); for (int i = 0; i < transfersByStopIndex.size(); i++) { - forwardTransfers.add(new ArrayList<>()); reversedTransfers.add(new ArrayList<>()); } @@ -43,14 +42,14 @@ public static RaptorTransferIndex create( var transfers = transfersByStopIndex .get(fromStop) .stream() - .filter(transfer -> transfer.getModes().contains(mode)) + .filter(transfer -> transfer.allowsMode(mode)) .flatMap(s -> s.asRaptorTransfer(request).stream()) .collect( toMap(RaptorTransfer::stop, Function.identity(), (a, b) -> a.c1() < b.c1() ? a : b) ) .values(); - forwardTransfers.get(fromStop).addAll(transfers); + forwardTransfers.add(new ArrayList<>(transfers)); for (RaptorTransfer forwardTransfer : transfers) { reversedTransfers diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java index 648343b9b0f..7e66498f349 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java @@ -1,9 +1,8 @@ package org.opentripplanner.routing.algorithm.raptoradapter.transit; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Optional; @@ -35,20 +34,20 @@ public class Transfer { private final List edges; - private final ImmutableSet modes; + private final Set modes; public Transfer(int toStop, List edges, EnumSet modes) { this.toStop = toStop; this.edges = edges; this.distanceMeters = (int) edges.stream().mapToDouble(Edge::getDistanceMeters).sum(); - this.modes = Sets.immutableEnumSet(modes); + this.modes = Collections.unmodifiableSet(modes); } public Transfer(int toStopIndex, int distanceMeters, EnumSet modes) { this.toStop = toStopIndex; this.distanceMeters = distanceMeters; this.edges = null; - this.modes = Sets.immutableEnumSet(modes); + this.modes = Collections.unmodifiableSet(modes); } public List getCoordinates() { @@ -76,8 +75,8 @@ public List getEdges() { return edges; } - public ImmutableSet getModes() { - return modes; + public boolean allowsMode(StreetMode mode) { + return modes.contains(mode); } public Optional asRaptorTransfer(StreetSearchRequest request) { From 9b44df082e097cd13f591c89bbfc1633983a837a Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Fri, 13 Dec 2024 16:12:23 +0200 Subject: [PATCH 78/98] Add comments. --- .../src/main/java/org/opentripplanner/model/PathTransfer.java | 1 + .../org/opentripplanner/transit/service/TimetableRepository.java | 1 + 2 files changed, 2 insertions(+) diff --git a/application/src/main/java/org/opentripplanner/model/PathTransfer.java b/application/src/main/java/org/opentripplanner/model/PathTransfer.java index 01aa9af02f5..c4676fdf06f 100644 --- a/application/src/main/java/org/opentripplanner/model/PathTransfer.java +++ b/application/src/main/java/org/opentripplanner/model/PathTransfer.java @@ -60,6 +60,7 @@ public EnumSet getModes() { return EnumSet.copyOf(modes); } + /** Create a new PathTransfer based on the current one with the mode added to the valid modes. */ public PathTransfer withAddedMode(StreetMode mode) { EnumSet newModes = EnumSet.copyOf(modes); newModes.add(mode); diff --git a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java index 5c57724d90d..004391602ae 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java @@ -435,6 +435,7 @@ public Collection getTransfersByStop(StopLocation stop) { return transfersByStop.get(stop); } + /** Pre-generated transfers between all stops filtered based on the modes in the PathTransfer's mode field. */ public List findTransfers(StreetMode mode) { return transfersByStop .values() From c75b0a2dee17484a99bc8dc4fe2c3eeb86dbace2 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Fri, 13 Dec 2024 16:14:39 +0200 Subject: [PATCH 79/98] Fix spelling. --- .../opentripplanner/transit/service/TimetableRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java index 004391602ae..ff8607f3818 100644 --- a/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java +++ b/application/src/main/java/org/opentripplanner/transit/service/TimetableRepository.java @@ -435,7 +435,7 @@ public Collection getTransfersByStop(StopLocation stop) { return transfersByStop.get(stop); } - /** Pre-generated transfers between all stops filtered based on the modes in the PathTransfer's mode field. */ + /** Pre-generated transfers between all stops filtered based on the modes in the PathTransfer. */ public List findTransfers(StreetMode mode) { return transfersByStop .values() From 6dc9a4ee878a78d8f7edd9a8095a61ef51c5ec29 Mon Sep 17 00:00:00 2001 From: Thomas Gran Date: Fri, 13 Dec 2024 13:49:40 +0100 Subject: [PATCH 80/98] review: Apply fixes from review --- .../request/preference/AccessEgressPreferences.java | 8 ++++---- .../api/request/preference/StreetPreferencesTest.java | 11 +++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java b/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java index 635c4c6c7b0..289e06e6e02 100644 --- a/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java +++ b/application/src/main/java/org/opentripplanner/routing/api/request/preference/AccessEgressPreferences.java @@ -147,19 +147,19 @@ private static DurationForEnum durationForStreetModeOf(Duration defa } private static TimeAndCostPenaltyForEnum createDefaultCarPenalty() { - var penaltyrBuilder = TimeAndCostPenaltyForEnum.of(StreetMode.class); + var penaltyBuilder = TimeAndCostPenaltyForEnum.of(StreetMode.class); var flexDefaultPenalty = TimeAndCostPenalty.of(TimePenalty.of(ofMinutes(10), 1.3f), 1.3); - penaltyrBuilder.with(StreetMode.FLEXIBLE, flexDefaultPenalty); + penaltyBuilder.with(StreetMode.FLEXIBLE, flexDefaultPenalty); // Add penalty to all car variants with access and/or egress. var carPenalty = TimeAndCostPenalty.of(TimePenalty.of(ofMinutes(20), 2f), 1.5); for (var it : StreetMode.values()) { if (it.includesDriving() && (it.accessAllowed() || it.egressAllowed())) { - penaltyrBuilder.with(it, carPenalty); + penaltyBuilder.with(it, carPenalty); } } - return penaltyrBuilder.build(); + return penaltyBuilder.build(); } } diff --git a/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java b/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java index 77875c44fa1..2f2bdd9a5b5 100644 --- a/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java +++ b/application/src/test/java/org/opentripplanner/routing/api/request/preference/StreetPreferencesTest.java @@ -23,7 +23,7 @@ class StreetPreferencesTest { private static final int ELEVATOR_BOARD_TIME = (int) Duration.ofMinutes(2).toSeconds(); private static final IntersectionTraversalModel INTERSECTION_TRAVERSAL_MODEL = IntersectionTraversalModel.CONSTANT; - private static final TimeAndCostPenalty CAR_PENALTY = TimeAndCostPenalty.of( + private static final TimeAndCostPenalty CAR_TO_PARK_PENALTY = TimeAndCostPenalty.of( TimePenalty.of("2m + 1.5t"), 3.5 ); @@ -34,7 +34,7 @@ class StreetPreferencesTest { .withTurnReluctance(TURN_RELUCTANCE) .withElevator(it -> it.withBoardTime(ELEVATOR_BOARD_TIME)) .withIntersectionTraversalModel(INTERSECTION_TRAVERSAL_MODEL) - .withAccessEgress(it -> it.withPenalty(Map.of(StreetMode.CAR_TO_PARK, CAR_PENALTY))) + .withAccessEgress(it -> it.withPenalty(Map.of(StreetMode.CAR_TO_PARK, CAR_TO_PARK_PENALTY))) .withAccessEgress(it -> it.withMaxDuration(MAX_ACCESS_EGRESS, Map.of())) .withMaxDirectDuration(MAX_DIRECT, Map.of()) .withRoutingTimeout(ROUTING_TIMEOUT) @@ -56,7 +56,10 @@ void accessEgressPenalty() { TimeAndCostPenalty.ZERO, subject.accessEgress().penalty().valueOf(StreetMode.WALK) ); - assertEquals(CAR_PENALTY, subject.accessEgress().penalty().valueOf(StreetMode.CAR_TO_PARK)); + assertEquals( + CAR_TO_PARK_PENALTY, + subject.accessEgress().penalty().valueOf(StreetMode.CAR_TO_PARK) + ); } @Test @@ -112,7 +115,7 @@ void testToString() { "accessEgress: AccessEgressPreferences{penalty: TimeAndCostPenaltyForEnum{" + "CAR: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + "CAR_TO_PARK: " + - CAR_PENALTY + + CAR_TO_PARK_PENALTY + ", " + "CAR_PICKUP: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + "CAR_RENTAL: (timePenalty: 20m + 2.0 t, costFactor: 1.50), " + From d881c9d187eab594a49afab9d22e0ceacdd49f8a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 15 Dec 2024 12:51:41 +0000 Subject: [PATCH 81/98] fix(deps): update dependency graphql to v16.10.0 --- .../org/opentripplanner/apis/gtfs/generated/package.json | 2 +- .../org/opentripplanner/apis/gtfs/generated/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/package.json b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/package.json index cd5cbf005f0..e76f41b0cee 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/package.json +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/package.json @@ -14,6 +14,6 @@ "@graphql-codegen/cli": "5.0.3", "@graphql-codegen/java": "4.0.1", "@graphql-codegen/java-resolvers": "3.0.0", - "graphql": "16.9.0" + "graphql": "16.10.0" } } diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/yarn.lock b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/yarn.lock index 8ec320cb0e6..6b382a7babb 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/yarn.lock +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/yarn.lock @@ -2152,10 +2152,10 @@ graphql-ws@^5.14.0: resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.14.0.tgz#766f249f3974fc2c48fae0d1fb20c2c4c79cd591" integrity sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g== -graphql@16.9.0: - version "16.9.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" - integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== +graphql@16.10.0: + version "16.10.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c" + integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ== has-flag@^3.0.0: version "3.0.0" From 18215a995a15875e39a20ad29cbf6262bc6291a1 Mon Sep 17 00:00:00 2001 From: Ville Pihlava Date: Sun, 15 Dec 2024 18:03:46 +0200 Subject: [PATCH 82/98] Add comment. --- .../routing/algorithm/raptoradapter/transit/Transfer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java index 7e66498f349..2643067398e 100644 --- a/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java +++ b/application/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/Transfer.java @@ -75,6 +75,7 @@ public List getEdges() { return edges; } + /** Check if the given mode is a valid mode for the transfer. */ public boolean allowsMode(StreetMode mode) { return modes.contains(mode); } From 5a3ef6a739cfb46ba8e75c767fe4a74301e8a09d Mon Sep 17 00:00:00 2001 From: OTP Changelog Bot Date: Mon, 16 Dec 2024 10:05:47 +0000 Subject: [PATCH 83/98] Add changelog entry for #5393 [ci skip] --- doc/user/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/Changelog.md b/doc/user/Changelog.md index e652c7600d9..24418e1094d 100644 --- a/doc/user/Changelog.md +++ b/doc/user/Changelog.md @@ -63,6 +63,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Detect JSON array in addition to JSON objects when including a file in the config. [#6307](https://github.com/opentripplanner/OpenTripPlanner/pull/6307) - Use WCAG recommendation to fill in GTFS route text color if it is missing [#6308](https://github.com/opentripplanner/OpenTripPlanner/pull/6308) - Rename `otp-shaded-jar` artifact and fix deployment to Maven Central [#6331](https://github.com/opentripplanner/OpenTripPlanner/pull/6331) +- Add query for cancelled trips to GTFS GraphQL API [#5393](https://github.com/opentripplanner/OpenTripPlanner/pull/5393) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.6.0 (2024-09-18) From d305306ae606d8de72a581c1649fcd72f92564b3 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Mon, 16 Dec 2024 12:32:12 +0100 Subject: [PATCH 84/98] Show generalized cost in debug UI --- .../ItineraryList/ItineraryDetails.tsx | 4 ++++ .../ItineraryList/ItineraryLegDetails.tsx | 2 +- client/src/static/query/tripQuery.tsx | 2 ++ client/src/style.css | 6 ++++++ client/src/util/formatDuration.ts | 18 ++++++------------ 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/client/src/components/ItineraryList/ItineraryDetails.tsx b/client/src/components/ItineraryList/ItineraryDetails.tsx index 11fe14c73fb..58b705abf52 100644 --- a/client/src/components/ItineraryList/ItineraryDetails.tsx +++ b/client/src/components/ItineraryList/ItineraryDetails.tsx @@ -10,6 +10,10 @@ export function ItineraryDetails({ tripPattern }: { tripPattern: TripPattern }) {tripPattern.legs.map((leg, i) => ( ))} + +

+ Generalized cost: ${tripPattern.generalizedCost} +
); } diff --git a/client/src/components/ItineraryList/ItineraryLegDetails.tsx b/client/src/components/ItineraryList/ItineraryLegDetails.tsx index 65d790902a8..2239fd8d8bf 100644 --- a/client/src/components/ItineraryList/ItineraryLegDetails.tsx +++ b/client/src/components/ItineraryList/ItineraryLegDetails.tsx @@ -21,7 +21,7 @@ export function ItineraryLegDetails({ leg, isLast }: { leg: Leg; isLast: boolean return (
- {formatDistance(leg.distance)}, {formatDuration(leg.duration)} + {formatDistance(leg.distance)}, {formatDuration(leg.duration)}, ${leg.generalizedCost}
1) { - formatted = `${formatted}${hrs} hrs `; + if (hrs > 0) { + formatted = `${formatted}${hrs}h `; } - if (mins === 1) { - formatted = `${formatted}${mins} min `; - } else if (mins > 1) { - formatted = `${formatted}${mins} mins `; + if (mins > 0) { + formatted = `${formatted}${mins}min `; } - if (secs === 1) { - formatted = `${formatted}${secs} sec `; - } else if (secs > 1) { - formatted = `${formatted}${secs} secs `; + if (secs > 1) { + formatted = `${formatted}${secs}s`; } return formatted; From 8d321e7f1884f18e9214067dc3e4175d886e0c9c Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Mon, 16 Dec 2024 12:36:07 +0100 Subject: [PATCH 85/98] Add tooltip --- client/src/components/ItineraryList/ItineraryDetails.tsx | 4 +--- client/src/components/ItineraryList/ItineraryLegDetails.tsx | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/src/components/ItineraryList/ItineraryDetails.tsx b/client/src/components/ItineraryList/ItineraryDetails.tsx index 58b705abf52..ba2caf4d15d 100644 --- a/client/src/components/ItineraryList/ItineraryDetails.tsx +++ b/client/src/components/ItineraryList/ItineraryDetails.tsx @@ -11,9 +11,7 @@ export function ItineraryDetails({ tripPattern }: { tripPattern: TripPattern }) ))} -
- Generalized cost: ${tripPattern.generalizedCost} -
+
Generalized cost: ${tripPattern.generalizedCost}
); } diff --git a/client/src/components/ItineraryList/ItineraryLegDetails.tsx b/client/src/components/ItineraryList/ItineraryLegDetails.tsx index 2239fd8d8bf..86d2d4db7a4 100644 --- a/client/src/components/ItineraryList/ItineraryLegDetails.tsx +++ b/client/src/components/ItineraryList/ItineraryLegDetails.tsx @@ -21,7 +21,8 @@ export function ItineraryLegDetails({ leg, isLast }: { leg: Leg; isLast: boolean return (
- {formatDistance(leg.distance)}, {formatDuration(leg.duration)}, ${leg.generalizedCost} + {formatDistance(leg.distance)}, {formatDuration(leg.duration)},{' '} + ${leg.generalizedCost}
Date: Mon, 16 Dec 2024 11:50:08 +0000 Subject: [PATCH 86/98] Add changelog entry for #6293 [ci skip] --- doc/user/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/Changelog.md b/doc/user/Changelog.md index 24418e1094d..639ada44ac9 100644 --- a/doc/user/Changelog.md +++ b/doc/user/Changelog.md @@ -64,6 +64,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Use WCAG recommendation to fill in GTFS route text color if it is missing [#6308](https://github.com/opentripplanner/OpenTripPlanner/pull/6308) - Rename `otp-shaded-jar` artifact and fix deployment to Maven Central [#6331](https://github.com/opentripplanner/OpenTripPlanner/pull/6331) - Add query for cancelled trips to GTFS GraphQL API [#5393](https://github.com/opentripplanner/OpenTripPlanner/pull/5393) +- Enable mode-specific transfers by storing mode information in transfers [#6293](https://github.com/opentripplanner/OpenTripPlanner/pull/6293) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.6.0 (2024-09-18) From 74f2f220eb1a3b22fc42edb17a5c291e630ec5a2 Mon Sep 17 00:00:00 2001 From: OTP Serialization Version Bot Date: Mon, 16 Dec 2024 11:50:35 +0000 Subject: [PATCH 87/98] Bump serialization version id for #6293 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 735cecb3f94..1da8c407bc9 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ - 175 + 176 32.1 2.53 From 65e976af0e9c5e346612096349dfbcbee1b2b79a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 07:38:17 +0000 Subject: [PATCH 88/98] fix(deps): update test dependencies (#6338) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1da8c407bc9..27eada4007b 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ 2.53 2.18.2 3.1.9 - 5.11.3 + 5.11.4 1.14.1 5.6.0 1.5.12 @@ -196,7 +196,7 @@ me.fabriciorby maven-surefire-junit5-tree-reporter - 1.3.0 + 1.4.0 From e130997f19abee98ad0c70a31e9b2dd554106df0 Mon Sep 17 00:00:00 2001 From: OTP Changelog Bot Date: Tue, 17 Dec 2024 09:39:52 +0000 Subject: [PATCH 89/98] Add changelog entry for #6302 [ci skip] --- doc/user/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/Changelog.md b/doc/user/Changelog.md index 639ada44ac9..1ff69082268 100644 --- a/doc/user/Changelog.md +++ b/doc/user/Changelog.md @@ -65,6 +65,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Rename `otp-shaded-jar` artifact and fix deployment to Maven Central [#6331](https://github.com/opentripplanner/OpenTripPlanner/pull/6331) - Add query for cancelled trips to GTFS GraphQL API [#5393](https://github.com/opentripplanner/OpenTripPlanner/pull/5393) - Enable mode-specific transfers by storing mode information in transfers [#6293](https://github.com/opentripplanner/OpenTripPlanner/pull/6293) +- Add default penalty to all car API modes [#6302](https://github.com/opentripplanner/OpenTripPlanner/pull/6302) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.6.0 (2024-09-18) From edcba5a2aa1f9175780d6da3c606cc95cd5176fc Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 17 Dec 2024 10:45:41 +0100 Subject: [PATCH 90/98] Use cent sign for generalized cost --- client/src/components/ItineraryList/ItineraryDetails.tsx | 2 +- client/src/components/ItineraryList/ItineraryLegDetails.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/ItineraryList/ItineraryDetails.tsx b/client/src/components/ItineraryList/ItineraryDetails.tsx index ba2caf4d15d..23e67ce9a95 100644 --- a/client/src/components/ItineraryList/ItineraryDetails.tsx +++ b/client/src/components/ItineraryList/ItineraryDetails.tsx @@ -11,7 +11,7 @@ export function ItineraryDetails({ tripPattern }: { tripPattern: TripPattern }) ))} -
Generalized cost: ${tripPattern.generalizedCost}
+
Generalized cost: ¢{tripPattern.generalizedCost}
); } diff --git a/client/src/components/ItineraryList/ItineraryLegDetails.tsx b/client/src/components/ItineraryList/ItineraryLegDetails.tsx index 86d2d4db7a4..04ddc55c574 100644 --- a/client/src/components/ItineraryList/ItineraryLegDetails.tsx +++ b/client/src/components/ItineraryList/ItineraryLegDetails.tsx @@ -22,7 +22,7 @@ export function ItineraryLegDetails({ leg, isLast }: { leg: Leg; isLast: boolean
{formatDistance(leg.distance)}, {formatDuration(leg.duration)},{' '} - ${leg.generalizedCost} + ¢{leg.generalizedCost}
Date: Tue, 17 Dec 2024 11:51:27 +0000 Subject: [PATCH 91/98] Upgrade debug client to version 2024/12/2024-12-17T11:50 --- application/src/client/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/client/index.html b/application/src/client/index.html index 47c9ec2c7c9..f65d9a153ba 100644 --- a/application/src/client/index.html +++ b/application/src/client/index.html @@ -5,8 +5,8 @@ OTP Debug - - + +
From 313ac9ccb2c265193d12ff036cf41b9e3f705e30 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 18:33:29 +0000 Subject: [PATCH 92/98] fix(deps): update debug ui dependencies (non-major) --- client/package-lock.json | 74 ++++++++++++++++++++++++---------------- client/package.json | 12 +++---- 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 52d93d9d4cf..c9feb3450ea 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,11 +11,11 @@ "@googlemaps/polyline-codec": "1.0.28", "@js-temporal/polyfill": "0.4.4", "bootstrap": "5.3.3", - "graphql": "16.9.0", + "graphql": "16.10.0", "graphql-request": "7.1.2", "maplibre-gl": "4.7.1", "react": "19.0.0", - "react-bootstrap": "2.10.6", + "react-bootstrap": "2.10.7", "react-dom": "19.0.0", "react-map-gl": "7.1.7" }, @@ -26,7 +26,7 @@ "@parcel/watcher": "2.5.0", "@testing-library/react": "16.1.0", "@types/react": "19.0.1", - "@types/react-dom": "19.0.1", + "@types/react-dom": "19.0.2", "@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/parser": "7.18.0", "@vitejs/plugin-react": "4.3.4", @@ -36,12 +36,12 @@ "eslint-plugin-import": "2.31.0", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.2", - "eslint-plugin-react-hooks": "5.0.0", + "eslint-plugin-react-hooks": "5.1.0", "eslint-plugin-react-refresh": "0.4.16", "jsdom": "25.0.1", - "prettier": "3.4.1", + "prettier": "3.4.2", "typescript": "5.7.2", - "vite": "6.0.2", + "vite": "6.0.3", "vitest": "2.1.8" } }, @@ -3122,9 +3122,10 @@ } }, "node_modules/@restart/ui": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.1.tgz", - "integrity": "sha512-qghR21ynHiUrpcIkKCoKYB+3rJtezY5Y7ikrwradCL+7hZHdQ2Ozc5ffxtpmpahoAGgc31gyXaSx2sXXaThmqA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.2.tgz", + "integrity": "sha512-MWWqJqSyqUWWPBOOiRQrX57CBc/9CoYONg7sE+uag72GCAuYrHGU5c49vU5s4BUSBgiKNY6rL7TULqGDrouUaA==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", "@popperjs/core": "^2.11.8", @@ -3584,6 +3585,12 @@ "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz", "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.0.1", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.1.tgz", @@ -3593,12 +3600,13 @@ } }, "node_modules/@types/react-dom": { - "version": "19.0.1", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.1.tgz", - "integrity": "sha512-hljHij7MpWPKF6u5vojuyfV0YA4YURsQG7KT6SzV0Zs2BXAtgdTxG6A229Ub/xiWV4w/7JL8fi6aAyjshH4meA==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.2.tgz", + "integrity": "sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==", "dev": true, - "dependencies": { - "@types/react": "*" + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" } }, "node_modules/@types/react-transition-group": { @@ -5878,10 +5886,11 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", - "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", + "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6671,9 +6680,10 @@ "dev": true }, "node_modules/graphql": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", - "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "version": "16.10.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", + "integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -8912,10 +8922,11 @@ } }, "node_modules/prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", - "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -9043,13 +9054,15 @@ } }, "node_modules/react-bootstrap": { - "version": "2.10.6", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.6.tgz", - "integrity": "sha512-fNvKytSp0nHts1WRnRBJeBEt+I9/ZdrnhIjWOucEduRNvFRU1IXjZueDdWnBiqsTSJ7MckQJi9i/hxGolaRq+g==", + "version": "2.10.7", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.7.tgz", + "integrity": "sha512-w6mWb3uytB5A18S2oTZpYghcOUK30neMBBvZ/bEfA+WIF2dF4OGqjzoFVMpVXBjtyf92gkmRToHlddiMAVhQqQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.24.7", "@restart/hooks": "^0.4.9", - "@restart/ui": "^1.9.0", + "@restart/ui": "^1.9.2", + "@types/prop-types": "^15.7.12", "@types/react-transition-group": "^4.4.6", "classnames": "^2.3.2", "dom-helpers": "^5.2.1", @@ -10567,10 +10580,11 @@ } }, "node_modules/vite": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.2.tgz", - "integrity": "sha512-XdQ+VsY2tJpBsKGs0wf3U/+azx8BBpYRHFAyKm5VeEZNOJZRB63q7Sc8Iup3k0TrN3KO6QgyzFf+opSbfY1y0g==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.3.tgz", + "integrity": "sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.24.0", "postcss": "^8.4.49", diff --git a/client/package.json b/client/package.json index 92747c2fbb7..6cd715c8a58 100644 --- a/client/package.json +++ b/client/package.json @@ -20,11 +20,11 @@ "@googlemaps/polyline-codec": "1.0.28", "@js-temporal/polyfill": "0.4.4", "bootstrap": "5.3.3", - "graphql": "16.9.0", + "graphql": "16.10.0", "graphql-request": "7.1.2", "maplibre-gl": "4.7.1", "react": "19.0.0", - "react-bootstrap": "2.10.6", + "react-bootstrap": "2.10.7", "react-dom": "19.0.0", "react-map-gl": "7.1.7" }, @@ -35,7 +35,7 @@ "@parcel/watcher": "2.5.0", "@testing-library/react": "16.1.0", "@types/react": "19.0.1", - "@types/react-dom": "19.0.1", + "@types/react-dom": "19.0.2", "@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/parser": "7.18.0", "@vitejs/plugin-react": "4.3.4", @@ -45,12 +45,12 @@ "eslint-plugin-import": "2.31.0", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.2", - "eslint-plugin-react-hooks": "5.0.0", + "eslint-plugin-react-hooks": "5.1.0", "eslint-plugin-react-refresh": "0.4.16", "jsdom": "25.0.1", - "prettier": "3.4.1", + "prettier": "3.4.2", "typescript": "5.7.2", - "vite": "6.0.2", + "vite": "6.0.3", "vitest": "2.1.8" } } From e1e5fedd826a03f4083796ff98ed01fa71e0d05c Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 17 Dec 2024 23:04:43 +0100 Subject: [PATCH 93/98] Fix formatting --- .../src/components/ItineraryList/ItineraryLegDetails.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/client/src/components/ItineraryList/ItineraryLegDetails.tsx b/client/src/components/ItineraryList/ItineraryLegDetails.tsx index 04ddc55c574..67abb055665 100644 --- a/client/src/components/ItineraryList/ItineraryLegDetails.tsx +++ b/client/src/components/ItineraryList/ItineraryLegDetails.tsx @@ -25,11 +25,8 @@ export function ItineraryLegDetails({ leg, isLast }: { leg: Leg; isLast: boolean ¢{leg.generalizedCost}
- - + -{' '} +
{leg.mode}{' '} {leg.line && ( From 2d012a33c3726ab0d0e8d4ff4f85ab048466e587 Mon Sep 17 00:00:00 2001 From: OTP Bot Date: Wed, 18 Dec 2024 09:00:50 +0000 Subject: [PATCH 94/98] Upgrade debug client to version 2024/12/2024-12-18T09:00 --- application/src/client/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/client/index.html b/application/src/client/index.html index f65d9a153ba..7ebc0fee49a 100644 --- a/application/src/client/index.html +++ b/application/src/client/index.html @@ -5,8 +5,8 @@ OTP Debug - - + +
From 2eedb12cdbb3e48bb61f44ca1313a85add14aa88 Mon Sep 17 00:00:00 2001 From: Michael Tsang Date: Wed, 18 Dec 2024 10:53:22 +0000 Subject: [PATCH 95/98] fix test failure when building OTP in a path with special characters. https://stackoverflow.com/a/13470643 fixes #6337 --- .../org/opentripplanner/test/support/ResourceLoader.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java b/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java index 5670a49fab7..e22d47b7f94 100644 --- a/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java +++ b/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java @@ -8,6 +8,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.List; @@ -46,7 +47,12 @@ public static ResourceLoader of(Object object) { */ public File file(String path) { URL resource = url(path); - var file = new File(resource.getFile()); + File file; + try { + file = new File(new URI(resource.toString())); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } assertTrue( file.exists(), "File '%s' not found on file system.".formatted(file.getAbsolutePath()) From ed2d7f5f6e4866bfabad9b8789ba7ff094cbc36e Mon Sep 17 00:00:00 2001 From: OTP Changelog Bot Date: Thu, 19 Dec 2024 09:59:10 +0000 Subject: [PATCH 96/98] Add changelog entry for #6311 [ci skip] --- doc/user/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/Changelog.md b/doc/user/Changelog.md index 1ff69082268..a5eff7c9b2a 100644 --- a/doc/user/Changelog.md +++ b/doc/user/Changelog.md @@ -66,6 +66,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Add query for cancelled trips to GTFS GraphQL API [#5393](https://github.com/opentripplanner/OpenTripPlanner/pull/5393) - Enable mode-specific transfers by storing mode information in transfers [#6293](https://github.com/opentripplanner/OpenTripPlanner/pull/6293) - Add default penalty to all car API modes [#6302](https://github.com/opentripplanner/OpenTripPlanner/pull/6302) +- Make flex linking work together with boarding locations [#6311](https://github.com/opentripplanner/OpenTripPlanner/pull/6311) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.6.0 (2024-09-18) From b9f41354c42b0a5e32268f839bb964eb799a8077 Mon Sep 17 00:00:00 2001 From: Michael Tsang Date: Thu, 19 Dec 2024 10:14:01 +0000 Subject: [PATCH 97/98] remove unused import --- .../java/org/opentripplanner/test/support/ResourceLoader.java | 1 - 1 file changed, 1 deletion(-) diff --git a/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java b/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java index e22d47b7f94..523a613913d 100644 --- a/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java +++ b/application/src/test/java/org/opentripplanner/test/support/ResourceLoader.java @@ -8,7 +8,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.List; From 6e8ccffaac61bcbb19d52355bd9a6363b35e09d1 Mon Sep 17 00:00:00 2001 From: OTP Changelog Bot Date: Mon, 23 Dec 2024 14:16:44 +0000 Subject: [PATCH 98/98] Add changelog entry for #6303 [ci skip] --- doc/user/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/Changelog.md b/doc/user/Changelog.md index a5eff7c9b2a..a3d798051a7 100644 --- a/doc/user/Changelog.md +++ b/doc/user/Changelog.md @@ -67,6 +67,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Enable mode-specific transfers by storing mode information in transfers [#6293](https://github.com/opentripplanner/OpenTripPlanner/pull/6293) - Add default penalty to all car API modes [#6302](https://github.com/opentripplanner/OpenTripPlanner/pull/6302) - Make flex linking work together with boarding locations [#6311](https://github.com/opentripplanner/OpenTripPlanner/pull/6311) +- Add fallback name for corridors [#6303](https://github.com/opentripplanner/OpenTripPlanner/pull/6303) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.6.0 (2024-09-18)