Skip to content

Commit e57c515

Browse files
committed
front: simplify usePathfinding
Split startPathFinding into 2 functions and reorganize the code. No functional change. Signed-off-by: Clara Ni <clara.ni@outlook.fr>
1 parent 6c88432 commit e57c515

File tree

1 file changed

+152
-140
lines changed

1 file changed

+152
-140
lines changed

front/src/modules/pathfinding/hooks/usePathfinding.ts

+152-140
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import { useSelector } from 'react-redux';
77
import { useScenarioContext } from 'applications/operationalStudies/hooks/useScenarioContext';
88
import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types';
99
import type {
10+
IncompatibleConstraints,
1011
PathfindingInputError,
12+
PathfindingResultSuccess,
1113
PostInfraByInfraIdPathPropertiesApiArg,
1214
PostInfraByInfraIdPathfindingBlocksApiArg,
1315
RollingStockWithLiveries,
@@ -250,152 +252,163 @@ export const usePathfinding = (
250252
};
251253

252254
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+
253333
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
263367
);
368+
pathfindingDispatch({
369+
type: 'PATHFINDING_INCOMPATIBLE_CONSTRAINTS',
370+
message: t(`pathfindingErrors.${pathfindingResult.error_type}`),
371+
});
264372
return;
265373
}
266374

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);
397409
}
398410
}
411+
pathfindingDispatch({ type: 'PATHFINDING_ERROR', message: error });
399412
}
400413
}
401414
};
@@ -410,7 +423,6 @@ export const usePathfinding = (
410423
return {
411424
isPathfindingInitialized,
412425
pathfindingState,
413-
pathfindingDispatch,
414426
infraInfos: {
415427
infra,
416428
reloadCount,

0 commit comments

Comments
 (0)