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 support for query parameter to enforce booking time in trip search for flexible services #5606

Merged
merged 75 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
2d53250
Add RoutingAccessEgress
vpaturet Dec 20, 2023
e2483f4
Add request parameter earliestBookingTime
vpaturet Dec 20, 2023
f9073e1
Adjust earliest departure time with booking time
vpaturet Dec 20, 2023
7a95f28
Adjust minimum booking period time with booking time
vpaturet Jan 5, 2024
f6e05bb
Move time adjustement logic to a dedicated class
vpaturet Jan 8, 2024
c3f3f7b
Code cleanup
vpaturet Jan 10, 2024
dfe4fa8
Add unit tests
vpaturet Jan 11, 2024
5c78c9b
Fix earliest booking time converstion to OTP time
vpaturet Jan 16, 2024
61ad5b5
doc: Remove old todo - this PR fixes the issue
t2gran Jan 18, 2024
a02eebc
refactor: Move method withPenalty down together with accessor
t2gran Jan 19, 2024
fae8998
refactor: Get rid of instanceOf and add a contract for booking info i…
t2gran Jan 19, 2024
c140fab
feature: Add method in TimeUtils for converting a java.time.Instant t…
t2gran Apr 25, 2024
06bc5c4
refactor: Add message to OtpHttpClientException
t2gran Apr 28, 2024
2923646
refactor: Rename to `bookingTime` from `earliestBookingTime`
t2gran Apr 29, 2024
6253cf5
fature: Add bookingTime parameter to REST API
t2gran Apr 29, 2024
eac9b9f
refactor: cleanup code
t2gran Apr 29, 2024
93782ab
Use the DefaultAccessEgress base class in the main internal model, no…
t2gran Apr 29, 2024
760cfb2
refactor and fix latestArrivalTime, tmePenalty and cleanup
t2gran Apr 29, 2024
d49f821
refactor: move booking classes to booking package
t2gran Apr 29, 2024
c69494a
test: Add unit test to booking package
t2gran Apr 29, 2024
5c94c24
refactor: move booking classes into transit.model.timetable.booking
t2gran Apr 29, 2024
74b0be7
fix: potential NPE
t2gran Apr 30, 2024
3e1594c
refactor: Integrate duration and offset into RoutingBookingInfo
t2gran Apr 30, 2024
77265d2
refactor: Interface RoutingAccessEgress is preferred in declarations
t2gran Apr 30, 2024
9000243
refactor: Rename to AbstractFlexTemplate from FlexAccessEgressTemplate
t2gran May 8, 2024
b5082a0
refactor: Reduce coupling in FlexTrip
t2gran May 8, 2024
cc4385d
fix: Fix dropOff and pickup booking info
t2gran May 8, 2024
19ac4d8
refactor: Remove input flag to cause method branching
t2gran May 8, 2024
750d802
refactor: Rename 'findBoard-/Alight-Index' methods in FlexTrip
t2gran May 8, 2024
61d60fe
refactor: Remove dependency on NearbyStop and the templates in FlexTrip
t2gran May 8, 2024
2a273ee
fix: Flex trips are not allowed to board and alight at the same stop.…
t2gran May 10, 2024
b818a82
refactor: Remove forbidden dependency from flex domain to OTP configu…
t2gran May 10, 2024
0ab020b
refactor: Cleanup TEST_MODEL.areaStop
t2gran May 10, 2024
8e3ddcc
refactor: Rename groupStop from (groupStopForTest) - repeating context
t2gran May 10, 2024
5dfcc62
refactor: Simplify and encapsulate id for TransitModelForTest#unsched…
t2gran May 10, 2024
c5865b8
refactor: Rename FlexTest to FlexIntegrationTestData
t2gran May 13, 2024
119fea0
refactor: Fix constant naming in FlexIntegrationTestData
t2gran May 13, 2024
0675eb4
refactor: Remove inheritance on FlexIntegrationTestData
t2gran May 13, 2024
103c7d8
refactor: Encapsulate fields in FlexIntegrationTestData
t2gran May 13, 2024
e69999e
test: Add unit-test on FlexTemplateFactory
t2gran May 13, 2024
f7466f0
refactor: Move FlexServiceDate into template package
t2gran May 24, 2024
6fdc37d
refactor: Introduce an interface to hide dependencies to the graph an…
t2gran May 24, 2024
8ea57a3
refactor: Declare generic types for FlexTrip
t2gran May 24, 2024
46ad6d6
refactor: Inline state in FlexRouter
t2gran May 24, 2024
387f698
refactor: Cleanup flex-service-dates creation
t2gran May 24, 2024
78b180d
refactor: remove itinerary mapping from flex direct search
t2gran May 24, 2024
a94def8
refactor: Pass arguments to create access/egress methods, without set…
t2gran May 24, 2024
77f336b
refactor: Separate integration and business logic in FlexRouter
t2gran May 25, 2024
c94b013
refactor: Move ClosestTrip logic out of FlexRouter
t2gran May 26, 2024
00a7b40
fix: Add NearbyStop#isBetter and use in FlexRouting - this uses cost/…
t2gran May 25, 2024
c1597c1
refactor: Move domain logic from FlexRouter into domain classes
t2gran May 26, 2024
93d759f
refactor: Encapsulate fields in FlexTripEdge and remove dependency on…
t2gran May 26, 2024
7de5fa8
refactor: Rename and doc on FlexAccessEgressCallbackAdapter
t2gran May 26, 2024
1651f85
doc: Add JavaDoc on DirectFlexPath
t2gran May 26, 2024
84657a0
refactor: Restrict access to template package
t2gran May 26, 2024
dc00a9b
refactor: Remove redundant code from FlexTemplateFactory
t2gran May 26, 2024
b583746
refactor: Make FlexTemplateFactory a member of Access/Egress factories
t2gran May 26, 2024
9b1e9af
refactor: Replace constructor with factory method for TransitStopVertex
t2gran May 26, 2024
339a382
refactor: Replace constructor with factory method for TransitStopVertex
t2gran May 26, 2024
ec0640b
refactor: Cleanup ClosestTrip
t2gran May 26, 2024
a7cb04f
refactor: Remove duplicate logic from FlexTemplateFactory
t2gran May 26, 2024
3363d8e
refactor: Cleanup naming stopIndex -> stopPosition
t2gran May 26, 2024
ab83cdf
Merge remote-tracking branch 'otp/dev-2.x' into otp2_entur_develop
t2gran May 28, 2024
c5d8c47
refactor: Small cleanups
t2gran May 28, 2024
6688514
refactor: Remove booking info restrictions on access/egress.
t2gran May 28, 2024
d970098
refactor: rename from-/to-StopIndex to board-/alight-StopPosition
t2gran May 28, 2024
26e9446
refactor: Copy direct logic from FlexAccessTemplate to FlexDirectPath…
t2gran May 28, 2024
ae7a20e
feature: Support for min-booking-notice and latest-booking-time
t2gran May 28, 2024
cd53540
doc: Update bookingTime doc.
t2gran May 29, 2024
4865cdc
Apply suggestions from code review
t2gran May 29, 2024
3bbdd65
refactor: Rename test
t2gran May 30, 2024
d7be638
Apply suggestions from code review
t2gran May 30, 2024
626c6ab
refactor: Fix doc generation failure
t2gran May 31, 2024
a4124b4
Merge remote-tracking branch 'otp/dev-2.x' into booking_time
t2gran Jun 3, 2024
e7b622d
Apply suggestions from code review
t2gran Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class AreaStopsToVerticesMapperTest {

private static final TransitModelForTest TEST_MODEL = TransitModelForTest.of();

private static final AreaStop BERLIN_AREA_STOP = TEST_MODEL.areaStopForTest(
"berlin",
Polygons.BERLIN
);
private static final AreaStop BERLIN_AREA_STOP = TEST_MODEL
.areaStop("berlin")
.withGeometry(Polygons.BERLIN)
.build();
public static final StopModel STOP_MODEL = TEST_MODEL
.stopModelBuilder()
.withAreaStop(AreaStopsToVerticesMapperTest.BERLIN_AREA_STOP)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.opentripplanner.ConstantsForTests;
import org.opentripplanner.TestOtpModel;
import org.opentripplanner.TestServerContext;
import org.opentripplanner.framework.application.OTPFeature;
Expand Down Expand Up @@ -57,14 +56,18 @@ public class FlexIntegrationTest {
@BeforeAll
static void setup() {
OTPFeature.enableFeatures(Map.of(OTPFeature.FlexRouting, true));
TestOtpModel model = ConstantsForTests.buildOsmGraph(FlexTest.COBB_OSM);
TestOtpModel model = FlexIntegrationTestData.cobbOsm();
graph = model.graph();
transitModel = model.transitModel();

addGtfsToGraph(
graph,
transitModel,
List.of(FlexTest.COBB_BUS_30_GTFS, FlexTest.MARTA_BUS_856_GTFS, FlexTest.COBB_FLEX_GTFS)
List.of(
FlexIntegrationTestData.COBB_BUS_30_GTFS,
FlexIntegrationTestData.MARTA_BUS_856_GTFS,
FlexIntegrationTestData.COBB_FLEX_GTFS
)
);
service = TestServerContext.createServerContext(graph, transitModel).routingService();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.opentripplanner.ext.flex;

import static graphql.Assert.assertTrue;

import gnu.trove.set.hash.TIntHashSet;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import org.opentripplanner.ConstantsForTests;
import org.opentripplanner.TestOtpModel;
import org.opentripplanner.ext.flex.flexpathcalculator.DirectFlexPathCalculator;
import org.opentripplanner.ext.flex.template.FlexServiceDate;
import org.opentripplanner.framework.application.OTPFeature;
import org.opentripplanner.gtfs.graphbuilder.GtfsBundle;
import org.opentripplanner.gtfs.graphbuilder.GtfsModule;
import org.opentripplanner.model.calendar.ServiceDateInterval;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.test.support.ResourceLoader;
import org.opentripplanner.transit.model.framework.Deduplicator;
import org.opentripplanner.transit.model.timetable.booking.RoutingBookingInfo;
import org.opentripplanner.transit.service.StopModel;
import org.opentripplanner.transit.service.TransitModel;

public final class FlexIntegrationTestData {

private static final ResourceLoader RES = ResourceLoader.of(FlexIntegrationTestData.class);

private static final File ASPEN_GTFS = RES.file("aspen-flex-on-demand.gtfs");
static final File COBB_BUS_30_GTFS = RES.file("cobblinc-bus-30-only.gtfs.zip");
static final File COBB_FLEX_GTFS = RES.file("cobblinc-scheduled-deviated-flex.gtfs");
private static final File COBB_OSM = RES.file("cobb-county.filtered.osm.pbf");
private static final File LINCOLN_COUNTY_GTFS = RES.file("lincoln-county-flex.gtfs");
static final File MARTA_BUS_856_GTFS = RES.file("marta-bus-856-only.gtfs.zip");

public static final DirectFlexPathCalculator CALCULATOR = new DirectFlexPathCalculator();
private static final LocalDate SERVICE_DATE = LocalDate.of(2021, 4, 11);
private static final int SECONDS_SINCE_MIDNIGHT = LocalTime.of(10, 0).toSecondOfDay();
public static final FlexServiceDate FLEX_DATE = new FlexServiceDate(
SERVICE_DATE,
SECONDS_SINCE_MIDNIGHT,
RoutingBookingInfo.NOT_SET,
new TIntHashSet()
);

public static TestOtpModel aspenGtfs() {
return buildFlexGraph(ASPEN_GTFS);
}

public static TestOtpModel cobbFlexGtfs() {
return buildFlexGraph(COBB_FLEX_GTFS);
}

public static TestOtpModel cobbBus30Gtfs() {
return buildFlexGraph(COBB_BUS_30_GTFS);
}

public static TestOtpModel martaBus856Gtfs() {
return buildFlexGraph(MARTA_BUS_856_GTFS);
}

public static TestOtpModel lincolnCountyGtfs() {
return buildFlexGraph(LINCOLN_COUNTY_GTFS);
}

public static TestOtpModel cobbOsm() {
return ConstantsForTests.buildOsmGraph(COBB_OSM);
}

private static TestOtpModel buildFlexGraph(File file) {
var deduplicator = new Deduplicator();
var graph = new Graph(deduplicator);
var transitModel = new TransitModel(new StopModel(), deduplicator);
GtfsBundle gtfsBundle = new GtfsBundle(file);
GtfsModule module = new GtfsModule(
List.of(gtfsBundle),
transitModel,
graph,
new ServiceDateInterval(LocalDate.of(2021, 1, 1), LocalDate.of(2022, 1, 1))
);
OTPFeature.enableFeatures(Map.of(OTPFeature.FlexRouting, true));
module.buildGraph();
transitModel.index();
graph.index(transitModel.getStopModel());
OTPFeature.enableFeatures(Map.of(OTPFeature.FlexRouting, false));
assertTrue(transitModel.hasFlexTrips());
return new TestOtpModel(graph, transitModel);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
public class FlexStopTimesForTest {

private static final TransitModelForTest TEST_MODEL = TransitModelForTest.of();
private static final StopLocation AREA_STOP = TEST_MODEL.areaStopForTest("area", Polygons.BERLIN);
private static final StopLocation AREA_STOP = TEST_MODEL
.areaStop("area")
.withGeometry(Polygons.BERLIN)
.build();
private static final RegularStop REGULAR_STOP = TEST_MODEL.stop("stop").build();

public static StopTime area(String startTime, String endTime) {
Expand Down
62 changes: 0 additions & 62 deletions src/ext-test/java/org/opentripplanner/ext/flex/FlexTest.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,31 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.opentripplanner.TestOtpModel;
import org.opentripplanner.ext.flex.trip.FlexTrip;
import org.opentripplanner.ext.flex.trip.UnscheduledTrip;
import org.opentripplanner.routing.graphfinder.NearbyStop;
import org.opentripplanner.standalone.config.sandbox.FlexConfig;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.service.TransitModel;

/**
* This test makes sure that one of the example feeds in the GTFS-Flex repo works. It's the City of
* Aspen Downtown taxi service which is a completely unscheduled trip that takes you door-to-door in
* Aspen Downtown taxi service, which is a completely unscheduled trip that takes you door-to-door in
* the city.
* <p>
* It only contains a single stop time which in GTFS static would not work but is valid in GTFS
* Flex.
*/
public class GtfsFlexTest extends FlexTest {
class GtfsFlexTest {

private static TransitModel transitModel;

@BeforeAll
static void setup() {
TestOtpModel model = FlexTest.buildFlexGraph(ASPEN_GTFS);
TestOtpModel model = FlexIntegrationTestData.aspenGtfs();
transitModel = model.transitModel();
}

Expand All @@ -49,50 +46,8 @@ void parseAspenTaxiAsUnscheduledTrip() {
);
}

@Test
void calculateAccessTemplate() {
var trip = getFlexTrip();
var nearbyStop = getNearbyStop(trip);

var accesses = trip
.getFlexAccessTemplates(nearbyStop, flexDate, calculator, FlexConfig.DEFAULT)
.toList();

assertEquals(1, accesses.size());

var access = accesses.get(0);
assertEquals(0, access.fromStopIndex);
assertEquals(0, access.toStopIndex);
}

@Test
void calculateEgressTemplate() {
var trip = getFlexTrip();
var nearbyStop = getNearbyStop(trip);
var egresses = trip
.getFlexEgressTemplates(nearbyStop, flexDate, calculator, FlexConfig.DEFAULT)
.toList();

assertEquals(1, egresses.size());

var egress = egresses.get(0);
assertEquals(0, egress.fromStopIndex);
assertEquals(0, egress.toStopIndex);
}

@Test
void shouldGeneratePatternForFlexTripWithSingleStop() {
assertFalse(transitModel.getAllTripPatterns().isEmpty());
}

private static NearbyStop getNearbyStop(FlexTrip<?, ?> trip) {
assertEquals(1, trip.getStops().size());
var stopLocation = trip.getStops().iterator().next();
return new NearbyStop(stopLocation, 0, List.of(), null);
}

private static FlexTrip<?, ?> getFlexTrip() {
var flexTrips = transitModel.getAllFlexTrips();
return flexTrips.iterator().next();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ScheduledFlexPathCalculatorTest {

@Test
void calculateTime() {
var c = (FlexPathCalculator) (fromv, tov, fromStopIndex, toStopIndex) ->
var c = (FlexPathCalculator) (fromv, tov, boardStopPosition, alightStopPosition) ->
new FlexPath(10_000, (int) Duration.ofMinutes(10).toSeconds(), () -> LineStrings.SIMPLE);
var calc = new ScheduledFlexPathCalculator(c, TRIP);
var path = calc.calculateFlexPath(V1, V2, 0, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TimePenaltyCalculatorTest {

@Test
void calculate() {
FlexPathCalculator delegate = (fromv, tov, fromStopIndex, toStopIndex) ->
FlexPathCalculator delegate = (fromv, tov, boardStopPosition, alightStopPosition) ->
new FlexPath(10_000, THIRTY_MINS_IN_SECONDS, () -> LineStrings.SIMPLE);

var mod = TimePenalty.of(Duration.ofMinutes(10), 1.5f);
Expand All @@ -26,7 +26,7 @@ void calculate() {

@Test
void nullValue() {
FlexPathCalculator delegate = (fromv, tov, fromStopIndex, toStopIndex) -> null;
FlexPathCalculator delegate = (fromv, tov, boardStopPosition, alightStopPosition) -> null;
var mod = TimePenalty.of(Duration.ofMinutes(10), 1.5f);
var calc = new TimePenaltyCalculator(delegate, mod);
var path = calc.calculateFlexPath(StreetModelForTest.V1, StreetModelForTest.V2, 0, 5);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.opentripplanner.ext.flex.template;

enum BoardAlight {
BOARD_ONLY,
ALIGHT_ONLY,
BOARD_AND_ALIGHT,
}
Loading
Loading