Skip to content

Commit f7aedcc

Browse files
committed
front: match PathStep and SuggestedOP with pathStepId
Matching via uic/trigram/ch/etc is unreliable because: - Two OPs can have the same trigram/ch. - The same OP could appear multiple times at different spots in a path. Moreover, we had multiple variants of the matching with slight differences. Some of the matching logic got adjusted to account for specific bugs, while others were left alone. Each path step can be identified with a unique ID stored in PathStep.id. Use that instead. Signed-off-by: Simon Ser <[email protected]>
1 parent cff7440 commit f7aedcc

File tree

7 files changed

+15
-73
lines changed

7 files changed

+15
-73
lines changed

front/src/applications/operationalStudies/hooks/useSetupItineraryForTrainUpdate.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
import buildOpSearchQuery from 'modules/operationalPoint/helpers/buildOpSearchQuery';
1616
import getPointOnPathCoordinates from 'modules/pathfinding/helpers/getPointOnPathCoordinates';
1717
import getTrackLengthCumulativeSums from 'modules/pathfinding/helpers/getTrackLengthCumulativeSums';
18-
import { formatSuggestedOperationalPoints, matchPathStepAndOp } from 'modules/pathfinding/utils';
18+
import { formatSuggestedOperationalPoints } from 'modules/pathfinding/utils';
1919
import { getSupportedElectrification, isThermal } from 'modules/rollingStock/helpers/electric';
2020
import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types';
2121
import computeBasePathStep from 'modules/trainschedule/helpers/computeBasePathStep';
@@ -42,8 +42,8 @@ export function updatePathStepsFromOperationalPoints(
4242
stepsCoordinates: Position[]
4343
) {
4444
const updatedPathSteps: PathStep[] = pathSteps.map((step, i) => {
45-
const correspondingOp = suggestedOperationalPoints.find((suggestedOp) =>
46-
matchPathStepAndOp(step, suggestedOp)
45+
const correspondingOp = suggestedOperationalPoints.find(
46+
(suggestedOp) => step.id === suggestedOp.pathStepId
4747
);
4848

4949
const { kp, name } = correspondingOp || step;

front/src/modules/pathfinding/components/Itinerary/ModalSuggestedVias.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { useSelector } from 'react-redux';
88
import ModalBodySNCF from 'common/BootstrapSNCF/ModalSNCF/ModalBodySNCF';
99
import ModalFooterSNCF from 'common/BootstrapSNCF/ModalSNCF/ModalFooterSNCF';
1010
import ModalHeaderSNCF from 'common/BootstrapSNCF/ModalSNCF/ModalHeaderSNCF';
11-
import { isVia, matchPathStepAndOp } from 'modules/pathfinding/utils';
1211
import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types';
1312
import { upsertViaFromSuggestedOP } from 'reducers/osrdconf/operationalStudiesConf';
1413
import {
@@ -39,12 +38,12 @@ const ModalSuggestedVias = ({ suggestedVias, launchPathfinding }: ModalSuggested
3938
);
4039

4140
const removeViaFromPath = (op: SuggestedOP) => {
42-
const newPathSteps = pathSteps.filter((step) => !matchPathStepAndOp(step!, op));
41+
const newPathSteps = pathSteps.filter((step) => step!.id !== op.pathStepId);
4342
launchPathfinding(newPathSteps);
4443
};
4544

4645
const formatOP = (op: SuggestedOP, idx: number, idxTrueVia: number) => {
47-
const isInVias = isVia(vias, op);
46+
const isInVias = vias.find((step) => step.id === op.pathStepId);
4847
return (
4948
<div
5049
key={`suggested-via-modal-${op.opId}-${idx}`}
@@ -107,7 +106,7 @@ const ModalSuggestedVias = ({ suggestedVias, launchPathfinding }: ModalSuggested
107106
{suggestedVias.map((via, idx) => {
108107
if (!isOriginOrDestination(via)) {
109108
// If name is undefined, we know the op/via has been added by clicking on map
110-
if (isVia(vias, via)) idxTrueVia += 1;
109+
if (vias.find((step) => step.id === via.pathStepId)) idxTrueVia += 1;
111110
return formatOP(via, idx, idxTrueVia);
112111
}
113112
return null;

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

+3-7
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ import type {
1313
PostInfraByInfraIdPathPropertiesApiArg,
1414
} from 'common/api/osrdEditoastApi';
1515
import { osrdEditoastApi } from 'common/api/osrdEditoastApi';
16-
import {
17-
formatSuggestedOperationalPoints,
18-
getPathfindingQuery,
19-
matchPathStepAndOp,
20-
} from 'modules/pathfinding/utils';
16+
import { formatSuggestedOperationalPoints, getPathfindingQuery } from 'modules/pathfinding/utils';
2117
import { useStoreDataForRollingStockSelector } from 'modules/rollingStock/components/RollingStockSelector/useStoreDataForRollingStockSelector';
2218
import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types';
2319
import { setFailure, setWarning } from 'reducers/main';
@@ -125,8 +121,8 @@ const usePathfinding = (
125121
// We update existing pathsteps with coordinates, positionOnPath and kp corresponding to the new pathfinding result
126122
const updatedPathSteps: (PathStep | null)[] = pathStepsInput.map((step, i) => {
127123
if (!step) return step;
128-
const correspondingOp = suggestedOperationalPoints.find((suggestedOp) =>
129-
matchPathStepAndOp(step, suggestedOp)
124+
const correspondingOp = suggestedOperationalPoints.find(
125+
(suggestedOp) => step.id === suggestedOp.pathStepId
130126
);
131127

132128
const theoreticalMargin = i === 0 ? step.theoreticalMargin || '0%' : step.theoreticalMargin;

front/src/modules/pathfinding/utils.ts

-34
Original file line numberDiff line numberDiff line change
@@ -154,40 +154,6 @@ export const upsertPathStepsInOPs = (ops: SuggestedOP[], pathSteps: PathStep[]):
154154
return updatedOPs;
155155
};
156156

157-
export const pathStepMatchesOp = (
158-
pathStep: PathStep,
159-
op: Pick<
160-
SuggestedOP,
161-
'pathStepId' | 'opId' | 'uic' | 'ch' | 'trigram' | 'track' | 'offsetOnTrack' | 'name' | 'kp'
162-
>,
163-
withKP = false
164-
) => {
165-
if (!matchPathStepAndOp(pathStep, op)) {
166-
return pathStep.id === op.pathStepId;
167-
}
168-
if ('uic' in pathStep) {
169-
return withKP ? pathStep.kp === op.kp : pathStep.name === op.name;
170-
}
171-
return true;
172-
};
173-
174-
/**
175-
* Check if a suggested operational point is a via.
176-
* Some OPs have same uic so we need to check also the ch (can be still not enough
177-
* probably because of imports problem).
178-
* If the vias has no uic, it has been added via map click and we know it has an id.
179-
* @param withKP - If true, we check the kp compatibility instead of the name.
180-
* It is used in the times and stops table to check if an operational point is a via.
181-
*/
182-
export const isVia = (
183-
vias: PathStep[],
184-
op: Pick<
185-
SuggestedOP,
186-
'pathStepId' | 'opId' | 'uic' | 'ch' | 'trigram' | 'track' | 'offsetOnTrack' | 'name' | 'kp'
187-
>,
188-
{ withKP = false } = {}
189-
) => vias.some((via) => pathStepMatchesOp(via, op, withKP));
190-
191157
export const isStation = (chCode: string): boolean =>
192158
chCode === 'BV' || chCode === '00' || chCode === '';
193159

front/src/modules/timesStops/TimesStopsInput.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import type { Operation } from 'react-datasheet-grid/dist/types';
77
import { useTranslation } from 'react-i18next';
88

99
import { useScenarioContext } from 'applications/operationalStudies/hooks/useScenarioContext';
10-
import { isVia, matchPathStepAndOp } from 'modules/pathfinding/utils';
1110
import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types';
1211
import {
1312
updatePathSteps,
@@ -48,7 +47,7 @@ const createClearViaButton = ({
4847
pathStepsAndSuggestedOPs &&
4948
rowIndex > 0 &&
5049
rowIndex < pathStepsAndSuggestedOPs.length - 1 &&
51-
isVia(pathSteps || [], rowData, { withKP: true }) &&
50+
pathSteps.find((step) => step.id === rowData.pathStepId) &&
5251
(!isNil(rowData.stopFor) ||
5352
rowData.theoreticalMargin !== undefined ||
5453
rowData.arrival !== undefined ||
@@ -81,9 +80,7 @@ const TimesStopsInput = ({
8180
const { getTrackSectionsByIds, trackSectionsLoading } = useScenarioContext();
8281

8382
const clearPathStep = (rowData: TimesStopsInputRow) => {
84-
const index = pathSteps.findIndex(
85-
(step) => matchPathStepAndOp(step, rowData) && step.positionOnPath === rowData.positionOnPath
86-
);
83+
const index = pathSteps.findIndex((step) => step.id === rowData.pathStepId);
8784

8885
const updatedPathSteps = pathSteps.map((step, i) => {
8986
if (i === index) {

front/src/modules/timesStops/helpers/utils.ts

+3-18
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { keyColumn, createTextColumn } from 'react-datasheet-grid';
66

77
import type { ReceptionSignal } from 'common/api/osrdEditoastApi';
88
import type { TimeString } from 'common/types';
9-
import { matchPathStepAndOp } from 'modules/pathfinding/utils';
109
import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types';
1110
import type { PathStep } from 'reducers/osrdconf/types';
1211
import { Duration } from 'utils/duration';
@@ -25,18 +24,6 @@ import {
2524
import { marginRegExValidation, MarginUnit } from '../consts';
2625
import { TableType, type TimeExtraDays, type TimesStopsInputRow } from '../types';
2726

28-
const matchPathStepAndOpWithKP = (step: PathStep, op: SuggestedOP) => {
29-
if (!matchPathStepAndOp(step, op)) {
30-
return step.id === op.pathStepId;
31-
}
32-
// We match the kp in case two OPs have the same uic+ch (can happen when the
33-
// infra is imported)
34-
if ('uic' in step || 'trigram' in step) {
35-
return step.kp === op.kp;
36-
}
37-
return true;
38-
};
39-
4027
export const formatSuggestedViasToRowVias = (
4128
operationalPoints: SuggestedOP[],
4229
pathSteps: PathStep[],
@@ -50,7 +37,7 @@ export const formatSuggestedViasToRowVias = (
5037
// to move it to the first position
5138
const origin = pathSteps[0];
5239
const originIndexInOps = origin
53-
? operationalPoints.findIndex((op) => matchPathStepAndOpWithKP(origin, op))
40+
? operationalPoints.findIndex((op) => origin.id === op.pathStepId)
5441
: -1;
5542
if (originIndexInOps !== -1) {
5643
[formattedOps[0], formattedOps[originIndexInOps]] = [
@@ -61,9 +48,7 @@ export const formatSuggestedViasToRowVias = (
6148

6249
// Ditto: destination should be last
6350
const dest = pathSteps[pathSteps.length - 1];
64-
const destIndexInOps = dest
65-
? operationalPoints.findIndex((op) => matchPathStepAndOpWithKP(dest, op))
66-
: -1;
51+
const destIndexInOps = dest ? operationalPoints.findIndex((op) => dest.id === op.pathStepId) : -1;
6752
if (destIndexInOps !== -1) {
6853
const lastOpIndex = formattedOps.length - 1;
6954
[formattedOps[lastOpIndex], formattedOps[destIndexInOps]] = [
@@ -73,7 +58,7 @@ export const formatSuggestedViasToRowVias = (
7358
}
7459

7560
return formattedOps.map((op, i) => {
76-
const pathStep = pathSteps.find((step) => matchPathStepAndOpWithKP(step, op));
61+
const pathStep = pathSteps.find((step) => step.id === op.pathStepId);
7762
const { name } = pathStep || op;
7863
const objectToUse = tableType === TableType.Input ? pathStep : op;
7964

front/src/reducers/osrdconf/helpers.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { v4 as uuidV4 } from 'uuid';
44

55
import { calculateDistanceAlongTrack } from 'applications/editor/tools/utils';
66
import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types';
7-
import { pathStepMatchesOp } from 'modules/pathfinding/utils';
87
import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types';
98
import { addElementAtIndex } from 'utils/array';
109

@@ -86,7 +85,7 @@ export function upsertPathStep(statePathSteps: (PathStep | null)[], op: Suggeste
8685
}),
8786
};
8887

89-
const stepIndex = cleanPathSteps.findIndex((step) => pathStepMatchesOp(step, op));
88+
const stepIndex = cleanPathSteps.findIndex((step) => step.id === op.pathStepId);
9089
if (stepIndex >= 0) {
9190
// Because of import issues, there can be multiple ops with same position on path
9291
// To avoid updating the wrong one, we need to find the one that matches the payload

0 commit comments

Comments
 (0)