@@ -70,6 +70,34 @@ private InsertionCandidate findOptimalInsertion(
7070 return evaluator .findBestInsertion (trip , viablePositions , passengerPickup , passengerDropoff );
7171 }
7272
73+ private WgsCoordinate getCoordinateBetween (WgsCoordinate coordinate1 , WgsCoordinate coordinate2 ) {
74+ return new WgsCoordinate (
75+ (coordinate1 .latitude () + coordinate2 .latitude ()) / 2 ,
76+ (coordinate1 .longitude () + coordinate2 .longitude ()) / 2
77+ );
78+ }
79+
80+ @ Test
81+ void findOptimalInsertion_onDeviationBudgetExceeded_returnsNull () {
82+ var trip = createTripWithStops (
83+ OSLO_SOUTH ,
84+ List .of (createStopAt (0 , OSLO_CENTER ), createStopAt (0 , OSLO_NORTHEAST )),
85+ OSLO_NORTH
86+ );
87+
88+ var mockPath = createGraphPath (Duration .ofMinutes (4 ));
89+ RoutingFunction routingFunction = (from , to , linkingContext ) -> mockPath ;
90+
91+ var result = findOptimalInsertion (
92+ trip ,
93+ getCoordinateBetween (OSLO_SOUTH , OSLO_CENTER ),
94+ getCoordinateBetween (OSLO_NORTHEAST , OSLO_NORTH ),
95+ routingFunction
96+ );
97+
98+ assertNull (result );
99+ }
100+
73101 @ Test
74102 void findOptimalInsertion_noValidPositions_returnsNull () {
75103 var trip = createSimpleTrip (OSLO_CENTER , OSLO_NORTH );
@@ -103,20 +131,20 @@ void findOptimalInsertion_routingFails_skipsPosition() {
103131 var stop1 = createStopAt (0 , OSLO_EAST );
104132 var trip = createTripWithStops (OSLO_CENTER , List .of (stop1 ), OSLO_NORTH );
105133
106- var mockPath = createGraphPath (Duration .ofMinutes (5 ));
134+ var mockPath = createGraphPath (Duration .ofMinutes (3 ));
107135
108136 // Routing sequence:
109137 // 1. Baseline calculation (2 segments: OSLO_CENTER → OSLO_EAST → OSLO_NORTH) = mockPath x2
110138 // 2. First insertion attempt fails (null for first segment)
111139 // 3. Second insertion attempt succeeds (mockPath for all segments)
112140 @ SuppressWarnings ("ConstantConditions" )
113141 RoutingFunction routingFunction = (from , to , linkingContext ) -> {
114- if (
142+ if (
115143 new WgsCoordinate (from .lat , from .lng ).equals (OSLO_CENTER ) &&
116144 new WgsCoordinate (to .lat , to .lng ).equals (OSLO_MIDPOINT_NORTH )
117145 ) {
118146 return null ;
119- }else {
147+ } else {
120148 return mockPath ;
121149 }
122150 };
@@ -181,16 +209,24 @@ void findOptimalInsertion_baselineDurationCalculationFails_returnsNull() {
181209 void findOptimalInsertion_selectsMinimumAdditionalDuration () {
182210 var trip = createTripWithDeviationBudget (Duration .ofMinutes (20 ), OSLO_CENTER , OSLO_NORTH );
183211
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- ));
212+ final Map <Pair <WgsCoordinate >, GraphPath <State , Edge , Vertex >> pathsMap = new HashMap <>(
213+ Map .of (
214+ new Pair <>(OSLO_CENTER , OSLO_NORTH ),
215+ createGraphPath (Duration .ofMinutes (10 )),
216+ new Pair <>(OSLO_CENTER , OSLO_EAST ),
217+ createGraphPath (Duration .ofMinutes (4 )),
218+ new Pair <>(OSLO_EAST , OSLO_WEST ),
219+ createGraphPath (Duration .ofMinutes (5 )),
220+ new Pair <>(OSLO_WEST , OSLO_NORTH ),
221+ createGraphPath (Duration .ofMinutes (6 ))
222+ )
223+ );
190224
191225 @ SuppressWarnings ("ConstantConditions" )
192226 RoutingFunction routingFunction = (from , to , linkingContext ) ->
193- pathsMap .get (new Pair <>(new WgsCoordinate (from .lat , from .lng ), new WgsCoordinate (to .lat , to .lng )));
227+ pathsMap .get (
228+ new Pair <>(new WgsCoordinate (from .lat , from .lng ), new WgsCoordinate (to .lat , to .lng ))
229+ );
194230
195231 var result = findOptimalInsertion (trip , OSLO_EAST , OSLO_WEST , routingFunction );
196232
@@ -241,18 +277,26 @@ void findOptimalInsertion_insertBetweenTwoPoints_routesAllSegments() {
241277 // MIDPOINT_NORTH → NORTH
242278 var segmentDB = createGraphPath (Duration .ofMinutes (4 ));
243279
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- ));
280+ final Map <Pair <WgsCoordinate >, GraphPath <State , Edge , Vertex >> pathsMap = new HashMap <>(
281+ Map .of (
282+ new Pair <>(OSLO_CENTER , OSLO_NORTH ),
283+ baselinePath ,
284+ new Pair <>(OSLO_CENTER , OSLO_EAST ),
285+ segmentAC ,
286+ new Pair <>(OSLO_EAST , OSLO_MIDPOINT_NORTH ),
287+ segmentCD ,
288+ new Pair <>(OSLO_MIDPOINT_NORTH , OSLO_NORTH ),
289+ segmentDB
290+ )
291+ );
250292
251293 final int [] callCount = { 0 };
252294 @ SuppressWarnings ("ConstantConditions" )
253295 RoutingFunction routingFunction = (from , to , linkingContext ) -> {
254296 callCount [0 ]++;
255- return pathsMap .get (new Pair <>(new WgsCoordinate (from .lat , from .lng ), new WgsCoordinate (to .lat , to .lng )));
297+ return pathsMap .get (
298+ new Pair <>(new WgsCoordinate (from .lat , from .lng ), new WgsCoordinate (to .lat , to .lng ))
299+ );
256300 };
257301
258302 // Passenger pickup at OSLO_EAST, dropoff at OSLO_MIDPOINT_NORTH
@@ -268,8 +312,9 @@ void findOptimalInsertion_insertBetweenTwoPoints_routesAllSegments() {
268312 // (typically 1-2 seconds per edge due to millisecond rounding in StreetEdge.doTraverse())
269313 // The baseline should be approximately 10 minutes (within 10 seconds tolerance)
270314 assertTrue (
271- Math .abs (result .baselineDuration ().toSeconds () - 600 ) < 10 ,
272- "Baseline should be approximately 10 min (within 10s), got " + result .baselineDuration ()
315+ Math .abs (result .durationBetweenOriginAndDestination ().toSeconds () - 600 ) < 10 ,
316+ "Baseline should be approximately 10 min (within 10s), got " +
317+ result .durationBetweenOriginAndDestination ()
273318 );
274319
275320 // CRITICAL: Total duration should be sum of NEW segments, NOT baseline duration
@@ -302,7 +347,7 @@ void findOptimalInsertion_insertAtEnd_reusesMostSegments() {
302347 var trip = createTripWithStops (OSLO_CENTER , List .of (stop1 ), OSLO_NORTH );
303348
304349 // Baseline has 2 segments: CENTER→EAST, EAST→NORTH
305- var mockPath = createGraphPath (Duration .ofMinutes (5 ));
350+ var mockPath = createGraphPath (Duration .ofMinutes (3 ));
306351
307352 final int [] callCount = { 0 };
308353 RoutingFunction routingFunction = (from , to , linkingContext ) -> {
@@ -315,8 +360,12 @@ void findOptimalInsertion_insertAtEnd_reusesMostSegments() {
315360
316361 assertNotNull (result , "Should find valid insertion" );
317362
318- // Baseline should be calculated correctly
319- assertEquals (Duration .ofMinutes (10 ), result .baselineDuration ());
363+ // Duration between start and stop should be calculated correctly
364+ assertTrue (
365+ Duration .ofMinutes (3 ).minus (result .durationBetweenOriginAndDestination ()).toSeconds () < 10 ,
366+ "Baseline should be approximately 3 min (within 10s), got " +
367+ result .durationBetweenOriginAndDestination ()
368+ );
320369
321370 // The modified route should have more segments than baseline
322371 assertTrue (
@@ -342,7 +391,7 @@ void findOptimalInsertion_pickupAtExistingPoint_handlesCorrectly() {
342391 var stop1 = createStopAt (0 , OSLO_EAST );
343392 var trip = createTripWithStops (OSLO_CENTER , List .of (stop1 ), OSLO_NORTHEAST );
344393
345- var mockPath = createGraphPath (Duration .ofMinutes (5 ));
394+ var mockPath = createGraphPath (Duration .ofMinutes (3 ));
346395
347396 final int [] callCount = { 0 };
348397 RoutingFunction routingFunction = (from , to , linkingContext ) -> {
@@ -388,6 +437,6 @@ void findOptimalInsertion_singleSegmentTrip_routesAllNewSegments() {
388437
389438 // Total duration should be positive
390439 assertTrue (result .totalDuration ().compareTo (Duration .ZERO ) > 0 );
391- assertTrue (result .baselineDuration ().compareTo (Duration .ZERO ) > 0 );
440+ assertTrue (result .durationBetweenOriginAndDestination ().compareTo (Duration .ZERO ) > 0 );
392441 }
393442}
0 commit comments