@@ -7,7 +7,9 @@ import { useSelector } from 'react-redux';
7
7
import { useScenarioContext } from 'applications/operationalStudies/hooks/useScenarioContext' ;
8
8
import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types' ;
9
9
import type {
10
+ IncompatibleConstraints ,
10
11
PathfindingInputError ,
12
+ PathfindingResultSuccess ,
11
13
PostInfraByInfraIdPathPropertiesApiArg ,
12
14
PostInfraByInfraIdPathfindingBlocksApiArg ,
13
15
RollingStockWithLiveries ,
@@ -250,152 +252,163 @@ export const usePathfinding = (
250
252
} ;
251
253
252
254
useEffect ( ( ) => {
255
+ const populateStoreWithSuccessfulPathfinding = async (
256
+ pathResult : PathfindingResultSuccess ,
257
+ incompatibleConstraints ?: IncompatibleConstraints
258
+ ) => {
259
+ const pathPropertiesParams : PostInfraByInfraIdPathPropertiesApiArg = {
260
+ infraId,
261
+ props : [ 'electrifications' , 'geometry' , 'operational_points' ] ,
262
+ pathPropertiesInput : {
263
+ track_section_ranges : pathResult . track_section_ranges ,
264
+ } ,
265
+ } ;
266
+ const { electrifications, geometry, operational_points } =
267
+ await postPathProperties ( pathPropertiesParams ) . unwrap ( ) ;
268
+
269
+ if ( ! electrifications || ! geometry || ! operational_points ) {
270
+ return ;
271
+ }
272
+
273
+ const suggestedOperationalPoints : SuggestedOP [ ] = formatSuggestedOperationalPoints (
274
+ operational_points ,
275
+ geometry ,
276
+ pathResult . length
277
+ ) ;
278
+
279
+ // We update existing pathsteps with coordinates, positionOnPath and kp corresponding to the new pathfinding result
280
+ const updatedPathSteps : ( PathStep | null ) [ ] = pathSteps . map ( ( step , i ) => {
281
+ if ( ! step ) return step ;
282
+ const correspondingOp = suggestedOperationalPoints . find ( ( suggestedOp ) =>
283
+ matchPathStepAndOp ( step , suggestedOp )
284
+ ) ;
285
+
286
+ const theoreticalMargin = i === 0 ? step . theoreticalMargin || '0%' : step . theoreticalMargin ;
287
+
288
+ const stopFor = i === pathSteps . length - 1 && ! step . stopFor ? '0' : step . stopFor ;
289
+ const stopType = i === pathSteps . length - 1 && ! step . stopFor ? undefined : step . stopType ;
290
+
291
+ return {
292
+ ...step ,
293
+ positionOnPath : pathResult . path_item_positions [ i ] ,
294
+ stopFor,
295
+ stopType,
296
+ theoreticalMargin,
297
+ ...( correspondingOp && {
298
+ name : correspondingOp . name ,
299
+ uic : correspondingOp . uic ,
300
+ ch : correspondingOp . ch ,
301
+ kp : correspondingOp . kp ,
302
+ coordinates : correspondingOp . coordinates ,
303
+ } ) ,
304
+ } ;
305
+ } ) ;
306
+
307
+ if ( ! isEmptyArray ( powerRestrictions ) ) {
308
+ dispatch (
309
+ setWarning ( {
310
+ title : t ( 'warningMessages.pathfindingChange' ) ,
311
+ text : t ( 'warningMessages.powerRestrictionsReset' ) ,
312
+ } )
313
+ ) ;
314
+ }
315
+ dispatch ( updatePathSteps ( updatedPathSteps ) ) ;
316
+
317
+ const allWaypoints = upsertPathStepsInOPs (
318
+ suggestedOperationalPoints ,
319
+ compact ( updatedPathSteps )
320
+ ) ;
321
+
322
+ setPathProperties ?.( {
323
+ electrifications,
324
+ geometry,
325
+ suggestedOperationalPoints,
326
+ allWaypoints,
327
+ length : pathResult . length ,
328
+ trackSectionRanges : pathResult . track_section_ranges ,
329
+ incompatibleConstraints,
330
+ } ) ;
331
+ } ;
332
+
253
333
const startPathFinding = async ( ) => {
254
- if ( ! pathfindingState . running ) {
255
- pathfindingDispatch ( { type : 'PATHFINDING_STARTED' } ) ;
256
- const pathfindingInput = generatePathfindingParams ( ) ;
257
- if ( ! pathfindingInput || ! infraId ) {
258
- dispatch (
259
- setFailure ( {
260
- name : t ( 'pathfinding' ) ,
261
- message : t ( 'pathfindingMissingParamsSimple' ) ,
262
- } )
334
+ if ( pathfindingState . running ) {
335
+ return ;
336
+ }
337
+
338
+ pathfindingDispatch ( { type : 'PATHFINDING_STARTED' } ) ;
339
+ const pathfindingInput = generatePathfindingParams ( ) ;
340
+ if ( ! pathfindingInput ) {
341
+ dispatch (
342
+ setFailure ( {
343
+ name : t ( 'pathfinding' ) ,
344
+ message : t ( 'pathfindingMissingParamsSimple' ) ,
345
+ } )
346
+ ) ;
347
+ return ;
348
+ }
349
+
350
+ try {
351
+ const pathfindingResult = await postPathfindingBlocks ( pathfindingInput ) . unwrap ( ) ;
352
+
353
+ if ( pathfindingResult . status === 'success' ) {
354
+ await populateStoreWithSuccessfulPathfinding ( pathfindingResult ) ;
355
+ pathfindingDispatch ( { type : 'PATHFINDING_FINISHED' } ) ;
356
+ return ;
357
+ }
358
+
359
+ const incompatibleConstraintsCheck =
360
+ pathfindingResult . failed_status === 'pathfinding_not_found' &&
361
+ pathfindingResult . error_type === 'incompatible_constraints' ;
362
+
363
+ if ( incompatibleConstraintsCheck ) {
364
+ await populateStoreWithSuccessfulPathfinding (
365
+ pathfindingResult . relaxed_constraints_path ,
366
+ pathfindingResult . incompatible_constraints
263
367
) ;
368
+ pathfindingDispatch ( {
369
+ type : 'PATHFINDING_INCOMPATIBLE_CONSTRAINTS' ,
370
+ message : t ( `pathfindingErrors.${ pathfindingResult . error_type } ` ) ,
371
+ } ) ;
264
372
return ;
265
373
}
266
374
267
- try {
268
- const pathfindingResult = await postPathfindingBlocks ( pathfindingInput ) . unwrap ( ) ;
269
- const incompatibleConstraintsCheck =
270
- pathfindingResult . status === 'failure' &&
271
- pathfindingResult . failed_status === 'pathfinding_not_found' &&
272
- pathfindingResult . error_type === 'incompatible_constraints' ;
273
- if (
274
- pathfindingResult . status === 'failure' &&
275
- pathfindingResult . failed_status === 'pathfinding_input_error' &&
276
- pathfindingResult . error_type === 'invalid_path_items'
277
- ) {
278
- handleInvalidPathItems ( pathSteps , pathfindingResult . items ) ;
279
- } else if ( pathfindingResult . status === 'success' || incompatibleConstraintsCheck ) {
280
- const pathResult =
281
- pathfindingResult . status === 'success'
282
- ? pathfindingResult
283
- : pathfindingResult . relaxed_constraints_path ;
284
-
285
- const pathPropertiesParams : PostInfraByInfraIdPathPropertiesApiArg = {
286
- infraId,
287
- props : [ 'electrifications' , 'geometry' , 'operational_points' ] ,
288
- pathPropertiesInput : {
289
- track_section_ranges : pathResult . track_section_ranges ,
290
- } ,
291
- } ;
292
- const { electrifications, geometry, operational_points } =
293
- await postPathProperties ( pathPropertiesParams ) . unwrap ( ) ;
294
-
295
- if ( electrifications && geometry && operational_points ) {
296
- const suggestedOperationalPoints : SuggestedOP [ ] = formatSuggestedOperationalPoints (
297
- operational_points ,
298
- geometry ,
299
- pathResult . length
300
- ) ;
301
-
302
- // We update existing pathsteps with coordinates, positionOnPath and kp corresponding to the new pathfinding result
303
- const updatedPathSteps : ( PathStep | null ) [ ] = pathSteps . map ( ( step , i ) => {
304
- if ( ! step ) return step ;
305
- const correspondingOp = suggestedOperationalPoints . find ( ( suggestedOp ) =>
306
- matchPathStepAndOp ( step , suggestedOp )
307
- ) ;
308
-
309
- const theoreticalMargin =
310
- i === 0 ? step . theoreticalMargin || '0%' : step . theoreticalMargin ;
311
-
312
- const stopFor = i === pathSteps . length - 1 && ! step . stopFor ? '0' : step . stopFor ;
313
- const stopType =
314
- i === pathSteps . length - 1 && ! step . stopFor ? undefined : step . stopType ;
315
-
316
- return {
317
- ...step ,
318
- positionOnPath : pathResult . path_item_positions [ i ] ,
319
- stopFor,
320
- stopType,
321
- theoreticalMargin,
322
- ...( correspondingOp && {
323
- name : correspondingOp . name ,
324
- uic : correspondingOp . uic ,
325
- ch : correspondingOp . ch ,
326
- kp : correspondingOp . kp ,
327
- coordinates : correspondingOp . coordinates ,
328
- } ) ,
329
- } ;
330
- } ) ;
331
-
332
- if ( ! isEmptyArray ( powerRestrictions ) ) {
333
- dispatch (
334
- setWarning ( {
335
- title : t ( 'warningMessages.pathfindingChange' ) ,
336
- text : t ( 'warningMessages.powerRestrictionsReset' ) ,
337
- } )
338
- ) ;
339
- }
340
- dispatch (
341
- updatePathSteps ( updatedPathSteps )
342
- ) ;
343
-
344
- const allWaypoints = upsertPathStepsInOPs (
345
- suggestedOperationalPoints ,
346
- compact ( updatedPathSteps )
347
- ) ;
348
-
349
- if ( setPathProperties )
350
- setPathProperties ( {
351
- electrifications,
352
- geometry,
353
- suggestedOperationalPoints,
354
- allWaypoints,
355
- length : pathResult . length ,
356
- trackSectionRanges : pathResult . track_section_ranges ,
357
- incompatibleConstraints : incompatibleConstraintsCheck
358
- ? pathfindingResult . incompatible_constraints
359
- : undefined ,
360
- } ) ;
361
-
362
- if ( pathfindingResult . status === 'success' ) {
363
- pathfindingDispatch ( { type : 'PATHFINDING_FINISHED' } ) ;
364
- } else {
365
- pathfindingDispatch ( {
366
- type : 'PATHFINDING_INCOMPATIBLE_CONSTRAINTS' ,
367
- message : t ( `pathfindingErrors.${ pathfindingResult . error_type } ` ) ,
368
- } ) ;
369
- }
370
- }
371
- } else if ( pathfindingResult . failed_status === 'internal_error' ) {
372
- const translationKey = pathfindingResult . core_error . type . startsWith ( 'core:' )
373
- ? pathfindingResult . core_error . type . replace ( 'core:' , '' )
374
- : pathfindingResult . core_error . type ;
375
- pathfindingDispatch ( {
376
- type : 'PATHFINDING_ERROR' ,
377
- message : t ( `coreErrors.${ translationKey } ` , {
378
- defaultValue : pathfindingResult . core_error . message ,
379
- } ) ,
380
- } ) ;
381
- } else {
382
- pathfindingDispatch ( {
383
- type : 'PATHFINDING_ERROR' ,
384
- message : t ( `pathfindingErrors.${ pathfindingResult . error_type } ` ) ,
385
- } ) ;
386
- }
387
- } catch ( e ) {
388
- if ( isObject ( e ) ) {
389
- if ( 'error' in e ) {
390
- dispatch ( setFailure ( castErrorToFailure ( e , { name : t ( 'pathfinding' ) } ) ) ) ;
391
- pathfindingDispatch ( { type : 'PATHFINDING_ERROR' , message : 'failedRequest' } ) ;
392
- } else if ( 'data' in e && isObject ( e . data ) && 'message' in e . data ) {
393
- pathfindingDispatch ( { type : 'PATHFINDING_ERROR' , message : e . data . message as string } ) ;
394
- if ( e . data . message === 'Infra not loaded' || e . data . message === 'Invalid version' ) {
395
- setIsInfraError ( true ) ;
396
- }
375
+ const hasInvalidPathItems =
376
+ pathfindingResult . failed_status === 'pathfinding_input_error' &&
377
+ pathfindingResult . error_type === 'invalid_path_items' ;
378
+
379
+ if ( hasInvalidPathItems ) {
380
+ handleInvalidPathItems ( pathSteps , pathfindingResult . items ) ;
381
+ return ;
382
+ }
383
+
384
+ let error : string ;
385
+ if ( pathfindingResult . failed_status === 'internal_error' ) {
386
+ const translationKey = pathfindingResult . core_error . type . startsWith ( 'core:' )
387
+ ? pathfindingResult . core_error . type . replace ( 'core:' , '' )
388
+ : pathfindingResult . core_error . type ;
389
+ error = t ( `coreErrors.${ translationKey } ` , {
390
+ defaultValue : pathfindingResult . core_error . message ,
391
+ } ) ;
392
+ } else {
393
+ error = t ( `pathfindingErrors.${ pathfindingResult . error_type } ` ) ;
394
+ }
395
+ pathfindingDispatch ( {
396
+ type : 'PATHFINDING_ERROR' ,
397
+ message : error ,
398
+ } ) ;
399
+ } catch ( e ) {
400
+ if ( isObject ( e ) ) {
401
+ let error ;
402
+ if ( 'error' in e ) {
403
+ dispatch ( setFailure ( castErrorToFailure ( e , { name : t ( 'pathfinding' ) } ) ) ) ;
404
+ error = 'failedRequest' ;
405
+ } else if ( 'data' in e && isObject ( e . data ) && 'message' in e . data ) {
406
+ error = e . data . message as string ;
407
+ if ( e . data . message === 'Infra not loaded' || e . data . message === 'Invalid version' ) {
408
+ setIsInfraError ( true ) ;
397
409
}
398
410
}
411
+ pathfindingDispatch ( { type : 'PATHFINDING_ERROR' , message : error } ) ;
399
412
}
400
413
}
401
414
} ;
@@ -410,7 +423,6 @@ export const usePathfinding = (
410
423
return {
411
424
isPathfindingInitialized,
412
425
pathfindingState,
413
- pathfindingDispatch,
414
426
infraInfos : {
415
427
infra,
416
428
reloadCount,
0 commit comments