2020import static org .opentripplanner .ext .carpooling .TestCarpoolTripBuilder .createTripWithStops ;
2121
2222import java .time .Duration ;
23+ import java .util .HashMap ;
2324import java .util .List ;
25+ import java .util .Map ;
2426import org .junit .jupiter .api .BeforeEach ;
2527import org .junit .jupiter .api .Test ;
2628import org .opentripplanner .astar .model .GraphPath ;
3133import org .opentripplanner .street .model .edge .Edge ;
3234import org .opentripplanner .street .model .vertex .Vertex ;
3335import org .opentripplanner .street .search .state .State ;
36+ import org .opentripplanner .utils .collection .Pair ;
3437
3538class InsertionEvaluatorTest {
3639
@@ -106,14 +109,14 @@ void findOptimalInsertion_routingFails_skipsPosition() {
106109 // 1. Baseline calculation (2 segments: OSLO_CENTER → OSLO_EAST → OSLO_NORTH) = mockPath x2
107110 // 2. First insertion attempt fails (null for first segment)
108111 // 3. Second insertion attempt succeeds (mockPath for all segments)
109- final int [] callCount = { 0 };
112+ @ SuppressWarnings ( "ConstantConditions" )
110113 RoutingFunction routingFunction = (from , to , linkingContext ) -> {
111- int call = callCount [ 0 ]++;
112- if ( call < 2 ) {
113- return mockPath ;
114- } else if ( call == 2 ) {
114+ if (
115+ new WgsCoordinate ( from . lat , from . lng ). equals ( OSLO_CENTER ) &&
116+ new WgsCoordinate ( to . lat , to . lng ). equals ( OSLO_MIDPOINT_NORTH )
117+ ) {
115118 return null ;
116- } else {
119+ }else {
117120 return mockPath ;
118121 }
119122 };
@@ -123,6 +126,11 @@ void findOptimalInsertion_routingFails_skipsPosition() {
123126
124127 // Should skip failed routing and find a valid one
125128 assertNotNull (result );
129+ /*
130+ Since segment between OSLO_CENTER and OSLO_MIDPOINT_NORTH is invalid,
131+ pickup position has to be after OSLO_EAST
132+ */
133+ assertEquals (2 , result .pickupPosition ());
126134 }
127135
128136 @ Test
@@ -173,42 +181,16 @@ void findOptimalInsertion_baselineDurationCalculationFails_returnsNull() {
173181 void findOptimalInsertion_selectsMinimumAdditionalDuration () {
174182 var trip = createTripWithDeviationBudget (Duration .ofMinutes (20 ), OSLO_CENTER , OSLO_NORTH );
175183
176- // Baseline: 1 segment (CENTER → NORTH) at 10 min
177- // The algorithm will try multiple pickup/dropoff positions
178- // We'll return different durations based on segment index
179- var mockPath10 = createGraphPath (Duration .ofMinutes (10 ));
180- var mockPath4 = createGraphPath (Duration .ofMinutes (4 ));
181- var mockPath6 = createGraphPath (Duration .ofMinutes (6 ));
182- var mockPath5 = createGraphPath (Duration .ofMinutes (5 ));
183- var mockPath7 = createGraphPath (Duration .ofMinutes (7 ));
184-
185- // Provide consistent route times
186- // Baseline
187- // First insertion (15 min total, 5 min additional)
188- // Second insertion (18 min total, 8 min additional)
189- @ SuppressWarnings ("unchecked" )
190- final GraphPath <State , Edge , Vertex >[] firstInsertionPaths = new GraphPath [] {
191- mockPath4 ,
192- mockPath5 ,
193- mockPath6 ,
194- };
195- @ SuppressWarnings ("unchecked" )
196- final GraphPath <State , Edge , Vertex >[] secondInsertionPaths = new GraphPath [] {
197- mockPath5 ,
198- mockPath6 ,
199- mockPath7 ,
200- };
201- final int [] callCount = { 0 };
202- RoutingFunction routingFunction = (from , to , linkingContext ) -> {
203- int call = callCount [0 ]++;
204- if (call == 0 ) {
205- return mockPath10 ;
206- } else if (call >= 1 && call <= 3 ) {
207- return firstInsertionPaths [call - 1 ];
208- } else {
209- return secondInsertionPaths [(call - 4 ) % 3 ];
210- }
211- };
184+ final Map <Pair <WgsCoordinate >, GraphPath <State , Edge , Vertex >> pathsMap = new HashMap <>(Map .of (
185+ new Pair <>(OSLO_CENTER , OSLO_NORTH ), createGraphPath (Duration .ofMinutes (10 )),
186+ new Pair <>(OSLO_CENTER , OSLO_EAST ), createGraphPath (Duration .ofMinutes (4 )),
187+ new Pair <>(OSLO_EAST , OSLO_WEST ), createGraphPath (Duration .ofMinutes (5 )),
188+ new Pair <>(OSLO_WEST , OSLO_NORTH ), createGraphPath (Duration .ofMinutes (6 ))
189+ ));
190+
191+ @ SuppressWarnings ("ConstantConditions" )
192+ RoutingFunction routingFunction = (from , to , linkingContext ) ->
193+ pathsMap .get (new Pair <>(new WgsCoordinate (from .lat , from .lng ), new WgsCoordinate (to .lat , to .lng )));
212194
213195 var result = findOptimalInsertion (trip , OSLO_EAST , OSLO_WEST , routingFunction );
214196
@@ -259,24 +241,18 @@ void findOptimalInsertion_insertBetweenTwoPoints_routesAllSegments() {
259241 // MIDPOINT_NORTH → NORTH
260242 var segmentDB = createGraphPath (Duration .ofMinutes (4 ));
261243
262- // Setup routing: return all segment mocks for any routing call
263- // The algorithm will evaluate multiple insertion positions
264- @ SuppressWarnings ("unchecked" )
265- final GraphPath <State , Edge , Vertex >[] paths = new GraphPath [] {
266- baselinePath ,
267- segmentAC ,
268- segmentCD ,
269- segmentDB ,
270- segmentAC ,
271- segmentCD ,
272- segmentDB ,
273- segmentAC ,
274- segmentCD ,
275- };
244+ final Map <Pair <WgsCoordinate >, GraphPath <State , Edge , Vertex >> pathsMap = new HashMap <>(Map .of (
245+ new Pair <>(OSLO_CENTER , OSLO_NORTH ), baselinePath ,
246+ new Pair <>(OSLO_CENTER , OSLO_EAST ), segmentAC ,
247+ new Pair <>(OSLO_EAST , OSLO_MIDPOINT_NORTH ), segmentCD ,
248+ new Pair <>(OSLO_MIDPOINT_NORTH , OSLO_NORTH ), segmentDB
249+ ));
250+
276251 final int [] callCount = { 0 };
252+ @ SuppressWarnings ("ConstantConditions" )
277253 RoutingFunction routingFunction = (from , to , linkingContext ) -> {
278- int call = callCount [0 ]++;
279- return call < paths . length ? paths [ call ] : segmentAC ;
254+ callCount [0 ]++;
255+ return pathsMap . get ( new Pair <>( new WgsCoordinate ( from . lat , from . lng ), new WgsCoordinate ( to . lat , to . lng ))) ;
280256 };
281257
282258 // Passenger pickup at OSLO_EAST, dropoff at OSLO_MIDPOINT_NORTH
0 commit comments