Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add previousLegs into GTFS GraphQL API #6142

Merged
merged 12 commits into from
Nov 14, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.opentripplanner.routing.alertpatch.TransitAlert;
import org.opentripplanner.routing.alternativelegs.AlternativeLegs;
import org.opentripplanner.routing.alternativelegs.AlternativeLegsFilter;
import org.opentripplanner.routing.alternativelegs.NavigationDirection;
import org.opentripplanner.transit.model.network.Route;
import org.opentripplanner.transit.model.organization.Agency;
import org.opentripplanner.transit.model.timetable.Trip;
Expand Down Expand Up @@ -275,8 +276,17 @@ private Leg getSource(DataFetchingEnvironment environment) {
return environment.getSource();
}

@Override
public DataFetcher<Iterable<Leg>> previousLegs() {
return alternativeLegs(NavigationDirection.PREVIOUS);
}

@Override
public DataFetcher<Iterable<Leg>> nextLegs() {
return alternativeLegs(NavigationDirection.NEXT);
}

private DataFetcher<Iterable<Leg>> alternativeLegs(NavigationDirection direction) {
return environment -> {
if (environment.getSource() instanceof ScheduledTransitLeg originalLeg) {
var args = new GraphQLTypes.GraphQLLegNextLegsArgs(environment.getArguments());
Expand Down Expand Up @@ -311,7 +321,7 @@ public DataFetcher<Iterable<Leg>> nextLegs() {
environment.getSource(),
numberOfLegs,
environment.<GraphQLRequestContext>getContext().transitService(),
false,
direction,
AlternativeLegsFilter.NO_FILTER,
limitToExactOriginStop,
limitToExactDestinationStop
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ public interface GraphQLLeg {

public DataFetcher<String> pickupType();

public DataFetcher<Iterable<Leg>> previousLegs();

public DataFetcher<Boolean> realTime();

public DataFetcher<GraphQLRealtimeState> realtimeState();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,69 @@ public void setGraphQLOriginModesWithParentStation(
}
}

public static class GraphQLLegPreviousLegsArgs {

private List<GraphQLTransitMode> destinationModesWithParentStation;
private Integer numberOfLegs;
private List<GraphQLTransitMode> originModesWithParentStation;

public GraphQLLegPreviousLegsArgs(Map<String, Object> args) {
if (args != null) {
if (args.get("destinationModesWithParentStation") != null) {
this.destinationModesWithParentStation =
((List<Object>) args.get("destinationModesWithParentStation")).stream()
.map(item ->
item instanceof GraphQLTransitMode
? item
: GraphQLTransitMode.valueOf((String) item)
)
.map(GraphQLTransitMode.class::cast)
.collect(Collectors.toList());
}
this.numberOfLegs = (Integer) args.get("numberOfLegs");
if (args.get("originModesWithParentStation") != null) {
this.originModesWithParentStation =
((List<Object>) args.get("originModesWithParentStation")).stream()
.map(item ->
item instanceof GraphQLTransitMode
? item
: GraphQLTransitMode.valueOf((String) item)
)
.map(GraphQLTransitMode.class::cast)
.collect(Collectors.toList());
}
}
}

public List<GraphQLTransitMode> getGraphQLDestinationModesWithParentStation() {
return this.destinationModesWithParentStation;
}

public Integer getGraphQLNumberOfLegs() {
return this.numberOfLegs;
}

public List<GraphQLTransitMode> getGraphQLOriginModesWithParentStation() {
return this.originModesWithParentStation;
}

public void setGraphQLDestinationModesWithParentStation(
List<GraphQLTransitMode> destinationModesWithParentStation
) {
this.destinationModesWithParentStation = destinationModesWithParentStation;
}

public void setGraphQLNumberOfLegs(Integer numberOfLegs) {
this.numberOfLegs = numberOfLegs;
}

public void setGraphQLOriginModesWithParentStation(
List<GraphQLTransitMode> originModesWithParentStation
) {
this.originModesWithParentStation = originModesWithParentStation;
}
}

public static class GraphQLLocalDateRangeInput {

private java.time.LocalDate end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.opentripplanner.model.plan.TransitLeg;
import org.opentripplanner.model.plan.legreference.LegReferenceSerializer;
import org.opentripplanner.routing.alternativelegs.AlternativeLegs;
import org.opentripplanner.routing.alternativelegs.NavigationDirection;

public class LegType {

Expand Down Expand Up @@ -485,7 +486,7 @@ public static GraphQLObjectType create(
leg,
env.getArgument("previous"),
GqlUtil.getTransitService(env),
true,
NavigationDirection.PREVIOUS,
env.getArgument("filter")
);
})
Expand Down Expand Up @@ -525,7 +526,7 @@ public static GraphQLObjectType create(
leg,
env.getArgument("next"),
GqlUtil.getTransitService(env),
false,
NavigationDirection.NEXT,
env.getArgument("filter")
);
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,10 @@ public static List<ScheduledTransitLeg> getAlternativeLegs(
Leg leg,
Integer numberLegs,
TransitService transitService,
boolean searchBackward,
NavigationDirection direction,
AlternativeLegsFilter filter
) {
return getAlternativeLegs(
leg,
numberLegs,
transitService,
searchBackward,
filter,
false,
false
);
return getAlternativeLegs(leg, numberLegs, transitService, direction, filter, false, false);
}

/**
Expand All @@ -66,9 +58,8 @@ public static List<ScheduledTransitLeg> getAlternativeLegs(
* @param numberLegs The number of alternative legs requested. If fewer legs are found,
* only the found legs are returned.
* @param transitService The transit service used for the search
* @param includeDepartBefore Boolean indicating whether the alternative legs should depart
* earlier or later than the original leg True if earlier, false if
* later.
* @param direction Indicating whether the alternative legs should depart before or
* after than the original.
* @param filter AlternativeLegsFilter indicating which properties of the original
* leg should not change in the alternative legs
* @param exactOriginStop Boolean indicating whether the exact departure stop of the original
Expand All @@ -82,7 +73,7 @@ public static List<ScheduledTransitLeg> getAlternativeLegs(
Leg leg,
Integer numberLegs,
TransitService transitService,
boolean includeDepartBefore,
NavigationDirection direction,
AlternativeLegsFilter filter,
boolean exactOriginStop,
boolean exactDestinationStop
Expand All @@ -105,7 +96,7 @@ public static List<ScheduledTransitLeg> getAlternativeLegs(
ScheduledTransitLeg::getStartTime
);

if (includeDepartBefore) {
if (direction == NavigationDirection.PREVIOUS) {
legComparator = legComparator.reversed();
}

Expand All @@ -119,13 +110,7 @@ public static List<ScheduledTransitLeg> getAlternativeLegs(
.distinct()
.flatMap(tripPattern -> withBoardingAlightingPositions(origins, destinations, tripPattern))
.flatMap(t ->
generateLegs(
transitService,
t,
leg.getStartTime(),
leg.getServiceDate(),
includeDepartBefore
)
generateLegs(transitService, t, leg.getStartTime(), leg.getServiceDate(), direction)
)
.filter(Predicate.not(leg::isPartiallySameTransitLeg))
.sorted(legComparator)
Expand All @@ -142,7 +127,7 @@ private static Stream<ScheduledTransitLeg> generateLegs(
TripPatternBetweenStops tripPatternBetweenStops,
ZonedDateTime departureTime,
LocalDate originalDate,
boolean includeDepartBefore
NavigationDirection direction
) {
TripPattern pattern = tripPatternBetweenStops.tripPattern;
int boardingPosition = tripPatternBetweenStops.positions.boardingPosition;
Expand All @@ -155,7 +140,7 @@ private static Stream<ScheduledTransitLeg> generateLegs(
tts.getServiceDayMidnight() + tts.getRealtimeDeparture()
);

if (includeDepartBefore) {
if (direction == NavigationDirection.PREVIOUS) {
comparator = comparator.reversed();
}

Expand Down Expand Up @@ -185,7 +170,7 @@ private static Stream<ScheduledTransitLeg> generateLegs(
continue;
}

boolean departureTimeInRange = includeDepartBefore
boolean departureTimeInRange = direction == NavigationDirection.PREVIOUS
? tripTimes.getDepartureTime(boardingPosition) <= secondsSinceMidnight
: tripTimes.getDepartureTime(boardingPosition) >= secondsSinceMidnight;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.opentripplanner.routing.alternativelegs;

/**
* This enum describes how the user navigates on a list of items.
*/
public enum NavigationDirection {
miklcct marked this conversation as resolved.
Show resolved Hide resolved
/**
* Get the next set of items.
*/
NEXT,

/**
* Get the previous set of items.
*/
PREVIOUS,
}
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,24 @@ type Leg {
pickupBookingInfo: BookingInfo
"This is used to indicate if boarding this leg is possible only with special arrangements."
pickupType: PickupDropoffType
"Previous legs with same origin and destination stops or stations"
previousLegs(
"""
Transportation modes for which all stops in the parent station are used as possible destination stops
for the previous legs. For modes not listed, only the exact destination stop of the leg is considered.
"""
destinationModesWithParentStation: [TransitMode!],
"""
The number of alternative legs searched. If fewer than the requested number are found,
then only the found legs are returned.
"""
numberOfLegs: Int!,
"""
Transportation modes for which all stops in the parent station are used as possible origin stops
for the previous legs. For modes not listed, only the exact origin stop of the leg is considered.
"""
originModesWithParentStation: [TransitMode!]
): [Leg!]
"Whether there is real-time data about this Leg"
realTime: Boolean
"State of real-time data"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.opentripplanner.model.plan.legreference.ScheduledTransitLegReference;
import org.opentripplanner.routing.alternativelegs.AlternativeLegs;
import org.opentripplanner.routing.alternativelegs.AlternativeLegsFilter;
import org.opentripplanner.routing.alternativelegs.NavigationDirection;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.service.DefaultTransitService;

Expand Down Expand Up @@ -51,7 +52,7 @@ void testPreviousLegs() {
originalLeg,
3,
transitService,
true,
NavigationDirection.PREVIOUS,
AlternativeLegsFilter.NO_FILTER
);

Expand Down Expand Up @@ -85,7 +86,7 @@ void testNextLegs() {
originalLeg,
3,
transitService,
false,
NavigationDirection.NEXT,
AlternativeLegsFilter.NO_FILTER
);

Expand Down Expand Up @@ -119,7 +120,7 @@ void testCircularRoutes() {
originalLeg,
2,
transitService,
false,
NavigationDirection.NEXT,
AlternativeLegsFilter.NO_FILTER
);

Expand Down Expand Up @@ -147,7 +148,7 @@ void testComplexCircularRoutes() {
originalLeg,
2,
transitService,
false,
NavigationDirection.NEXT,
AlternativeLegsFilter.NO_FILTER
);
var legs = toString(alternativeLegs);
Expand Down
Loading