Skip to content

Commit

Permalink
Merge pull request #5606 from entur/booking_time
Browse files Browse the repository at this point in the history
Add support for query parameter to enforce booking time in trip search for flexible services
  • Loading branch information
t2gran authored Jun 6, 2024
2 parents 519a1c2 + e7b622d commit e210605
Show file tree
Hide file tree
Showing 128 changed files with 2,934 additions and 1,411 deletions.
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.

51 changes: 3 additions & 48 deletions src/ext-test/java/org/opentripplanner/ext/flex/GtfsFlexTest.java
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

0 comments on commit e210605

Please sign in to comment.