Skip to content

Commit

Permalink
front: add logic to handle non-feasibility in stdcm simulations
Browse files Browse the repository at this point in the history
Signed-off-by: Achraf Mohyeddine <[email protected]>
  • Loading branch information
achrafmohye authored and SharglutDev committed Oct 31, 2024
1 parent aaae986 commit c3d0409
Show file tree
Hide file tree
Showing 17 changed files with 502 additions and 105 deletions.
12 changes: 11 additions & 1 deletion front/public/locales/en/stdcm.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,17 @@
"downloadSimulationSheet": "Download simulation report sheet",
"formatCreationDate": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}",
"gesicoRequest": "and attach this document to your GESICO DSDM request.",
"notFound": "No solution has been found for this configuration.",
"notFound": "No solution was found for this configuration",
"conflictsTitle": "Here are the problems encountered when calculating the shortest path:",
"trackConflict": "conflict with a train path between <strong>{{waypointBefore}}</strong> and <strong>{{waypointAfter}}</strong> from {{startDate}} at {{startTime}} to {{endDate}} at {{endTime}}",
"trackConflictSameDay": "conflict with a train path between <strong>{{waypointBefore}}</strong> and <strong>{{waypointAfter}}</strong> on {{startDate}} between {{startTime}} and {{endTime}}",
"remainingTrackConflicts": "{{count}} other conflicts with other train paths",
"remainingTrackConflicts_one": "one other conflict with another train path",
"remainingWorkConflicts": "{{count}} other works in conflict",
"remainingWorkConflicts_one": "one other work in conflict",
"workConflictSameDay": "scheduled work from <strong>{{waypointBefore}}</strong> to <strong>{{waypointAfter}}</strong> on {{startDate}} between {{startTime}} and {{endTime}}",
"workConflict": "scheduled work from <strong>{{waypointBefore}}</strong> to <strong>{{waypointAfter}}</strong> from {{startDate}} at {{startTime}} to {{endDate}} at {{endTime}}",
"changeSearchCriteria": "You can modify your search criteria to find a solution",
"retainThisSimulation": "Retain this simulation",
"simulationName": {
"withOutputs": "Simulation n°{{id}}",
Expand Down
12 changes: 11 additions & 1 deletion front/public/locales/fr/stdcm.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,17 @@
"downloadSimulationSheet": "Télécharger la fiche de simulation",
"formatCreationDate": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}",
"gesicoRequest": "et joignez ce document à votre demande GESICO DSDM",
"notFound": "Aucune solution n’a été trouvée pour cette configuration",
"notFound": "Aucune solution n'a été trouvée pour cette configuration",
"conflictsTitle": "Voici les problèmes rencontrés au moment du calcul sur le chemin le plus court :",
"trackConflict": "conflit avec un autre sillon entre <strong>{{waypointBefore}}</strong> et <strong>{{waypointAfter}}</strong> du {{startDate}} à {{startTime}} au {{endDate}} à {{endTime}}",
"trackConflictSameDay": "conflit avec un sillon entre <strong>{{waypointBefore}}</strong> et <strong>{{waypointAfter}}</strong> le {{startDate}} entre {{startTime}} et {{endTime}}",
"remainingTrackConflicts": "{{count}} autres conflits avec d'autres sillons",
"remainingTrackConflicts_one": "un autre conflit avec un autre sillon",
"remainingWorkConflicts": "{{count}} autres travaux en conflit",
"remainingWorkConflicts_one": "un autre conflit avec des travaux",
"workConflictSameDay": "travaux de <strong>{{waypointBefore}}</strong> à <strong>{{waypointAfter}}</strong> le {{startDate}} entre {{startTime}} et {{endTime}}",
"workConflict": "travaux de <strong>{{waypointBefore}}</strong> à <strong>{{waypointAfter}}</strong> du {{startDate}} à {{startTime}} au {{endDate}} à {{endTime}}",
"changeSearchCriteria": "Vous pouvez modifier vos critères de recherche pour trouver une solution",
"retainThisSimulation": "Retenir cette simulation",
"simulationName": {
"withOutputs": "Simulation n°{{id}}",
Expand Down
7 changes: 7 additions & 0 deletions front/scripts/i18n-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ const IGNORE_MISSING: RegExp[] = [
/translation:departureTime/,
/translation:destinationTime/,
/translation:leaveAt/,
/stdcm:simulation.results/,
/translation:remainingTrackConflicts/,
/translation:remainingWorkConflicts/,
/translation:trackConflict/,
/translation:trackConflictSameDay/,
/translation:workConflict/,
/translation:workConflictSameDay/,
];
const IGNORE_UNUSED: RegExp[] = [
/.*-generated$/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useSelector } from 'react-redux';

import { STDCM_TRAIN_ID } from 'applications/stdcm/consts';
import useProjectedTrainsForStdcm from 'applications/stdcm/hooks/useProjectedTrainsForStdcm';
import type { StdcmSimulationOutputs } from 'applications/stdcm/types';
import type { StdcmResultsOutput } from 'applications/stdcm/types';
import { osrdEditoastApi, type TrackRange } from 'common/api/osrdEditoastApi';
import { useOsrdConfSelectors } from 'common/osrdContext';
import i18n from 'i18n';
Expand All @@ -17,7 +17,7 @@ const HANDLE_TAB_RESIZE_HEIGHT = 20;

type StdcmDebugResultsProps = {
pathTrackRanges: TrackRange[];
simulationOutputs: StdcmSimulationOutputs;
simulationOutputs: StdcmResultsOutput;
};

const StdcmDebugResults = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { useMemo, useState } from 'react';

import { Button } from '@osrd-project/ui-core';
import { PDFDownloadLink } from '@react-pdf/renderer';
import { useTranslation } from 'react-i18next';
import { useTranslation, Trans } from 'react-i18next';

import useConflictsMessages from 'applications/stdcm/hooks/useConflictsMessages';
import type { StdcmSimulation } from 'applications/stdcm/types';
import {
generateCodeNumber,
getOperationalPointsWithTimes,
} from 'applications/stdcm/utils/formatSimulationReportSheet';
import { hasConflicts, hasResults } from 'applications/stdcm/utils/simulationOutputUtils';
import { type TrackRange } from 'common/api/osrdEditoastApi';
import { Map } from 'modules/trainschedule/components/ManageTrainSchedule';

Expand Down Expand Up @@ -43,25 +45,31 @@ const StcdmResults = ({
pathTrackRanges,
}: StcdmResultsProps) => {
const { t } = useTranslation('stdcm', { keyPrefix: 'simulation.results' });

const [mapCanvas, setMapCanvas] = useState<string>();

const selectedSimulation = simulationsList[selectedSimulationIndex];
const simulationReportSheetNumber = generateCodeNumber();
const { outputs } = selectedSimulation || {};

const hasConflictResults = hasConflicts(outputs);
const hasSimulationResults = hasResults(outputs);

const { trackConflicts, workConflicts } = useConflictsMessages(t, outputs);

const simulationReportSheetNumber = generateCodeNumber();
const isSelectedSimulationRetained = selectedSimulationIndex === retainedSimulationIndex;

const operationalPointsList = useMemo(() => {
if (!selectedSimulation || !selectedSimulation.outputs) {
return [];
}

if (!hasSimulationResults) return [];
return getOperationalPointsWithTimes(
selectedSimulation.outputs.pathProperties?.suggestedOperationalPoints || [],
selectedSimulation.outputs.results.simulation,
selectedSimulation.outputs.results.departure_time
outputs.pathProperties?.suggestedOperationalPoints || [],
outputs.results.simulation,
outputs.results.departure_time
);
}, [selectedSimulation]);
}, [outputs]);

const simulationPathSteps = hasSimulationResults
? outputs.results.simulationPathSteps
: undefined;

return (
<>
Expand All @@ -74,10 +82,10 @@ const StcdmResults = ({
retainedSimulationIndex={retainedSimulationIndex}
/>
<div className="simulation-results">
{selectedSimulation.outputs ? (
{hasSimulationResults && !hasConflictResults ? (
<div className="results-and-sheet">
<StcdmResultsTable
stdcmData={selectedSimulation.outputs.results}
stdcmData={outputs.results}
consist={selectedSimulation.inputs.consist}
isSimulationRetained={isSelectedSimulationRetained}
operationalPointsList={operationalPointsList}
Expand All @@ -90,7 +98,7 @@ const StcdmResults = ({
document={
<SimulationReportSheet
stdcmLinkedPaths={selectedSimulation.inputs.linkedPaths}
stdcmData={selectedSimulation.outputs.results}
stdcmData={outputs.results}
consist={selectedSimulation.inputs.consist}
simulationReportSheetNumber={simulationReportSheetNumber}
mapCanvas={mapCanvas}
Expand All @@ -114,7 +122,34 @@ const StcdmResults = ({
) : (
<div className="simulation-failure">
<span className="title">{t('notFound')}</span>
<span className="change-criteria">{t('changeCriteria')}</span>
<span className="change-criteria">{t('conflictsTitle')}</span>

{trackConflicts.length > 0 && (
<ul>
{trackConflicts.map((message, index) => (
<li key={index}>
<span>
<Trans>&bull; {message}</Trans>
</span>
</li>
))}
</ul>
)}

{trackConflicts.length > 0 && workConflicts.length > 0 && <br />}

{workConflicts.length > 0 && (
<ul>
{workConflicts.map((message, index) => (
<li key={index}>
<span>
<Trans>&bull; {message}</Trans>
</span>
</li>
))}
</ul>
)}
<span>{t('changeSearchCriteria')}</span>
</div>
)}
<div className="osrd-config-item-container osrd-config-item-container-map map-results no-pointer-events">
Expand All @@ -123,17 +158,15 @@ const StcdmResults = ({
isReadOnly
hideAttribution
showStdcmAssets
isFeasible={!hasConflictResults}
setMapCanvas={setMapCanvas}
pathGeometry={selectedSimulation.outputs?.pathProperties.geometry}
simulationPathSteps={selectedSimulation.outputs?.results.simulationPathSteps}
pathGeometry={outputs?.pathProperties?.geometry}
simulationPathSteps={simulationPathSteps}
/>
</div>
</div>
{isDebugMode && pathTrackRanges && selectedSimulation.outputs && (
<StdcmDebugResults
pathTrackRanges={pathTrackRanges}
simulationOutputs={selectedSimulation.outputs}
/>
{isDebugMode && pathTrackRanges && hasSimulationResults && (
<StdcmDebugResults pathTrackRanges={pathTrackRanges} simulationOutputs={outputs} />
)}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';

import useHorizontalScroll from 'applications/stdcm/hooks/useHorizontalScroll';
import type { StdcmSimulation } from 'applications/stdcm/types';
import { hasConflicts } from 'applications/stdcm/utils/simulationOutputUtils';
import { formatDateToString } from 'utils/date';

export const SIMULATION_ITEM_CLASSNAME = 'simulation-item';
Expand Down Expand Up @@ -66,7 +67,7 @@ const StdcmSimulationNavigator = ({
>
<div className="simulation-name">
<div>
{outputs
{outputs && !hasConflicts(outputs)
? t('simulationName.withOutputs', { id })
: t('simulationName.withoutOutputs')}
</div>
Expand Down
101 changes: 101 additions & 0 deletions front/src/applications/stdcm/hooks/useConflictsMessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { useEffect, useState } from 'react';

import type { TFunction } from 'i18next';

import { formatConflicts } from 'applications/stdcm/utils/formatConflicts';
import { hasConflicts } from 'applications/stdcm/utils/simulationOutputUtils';

import type { StdcmSimulationOutputs } from '../types';

const useConflictsMessages = (t: TFunction, selectedSimulationOutput?: StdcmSimulationOutputs) => {
const [trackConflicts, setTrackConflicts] = useState<string[]>([]);
const [workConflicts, setWorkConflicts] = useState<string[]>([]);

useEffect(() => {
if (!hasConflicts(selectedSimulationOutput)) return;

const generateConflictMessages = () => {
const { pathProperties } = selectedSimulationOutput;
const { trackConflictsData, workConflictsData } = formatConflicts(
selectedSimulationOutput?.conflicts,
pathProperties
);

const trackMessages: string[] = [];
trackConflictsData.slice(0, 2).forEach((conflict) => {
const { waypointBefore, waypointAfter, startDate, endDate, startTime, endTime } = conflict;

if (startDate === endDate) {
trackMessages.push(
t('trackConflictSameDay', {
waypointBefore,
waypointAfter,
startTime,
endTime,
startDate,
})
);
} else {
trackMessages.push(
t('trackConflict', {
waypointBefore,
waypointAfter,
startDate,
endDate,
startTime,
endTime,
})
);
}
});

const remainingTrackConflicts = trackConflictsData.length - 2;
if (remainingTrackConflicts > 0) {
trackMessages.push(t('remainingTrackConflicts', { count: remainingTrackConflicts }));
}

const workMessages: string[] = [];
workConflictsData.slice(0, 2).forEach((conflict) => {
const { waypointBefore, waypointAfter, startDate, endDate, startTime, endTime } = conflict;

if (startDate === endDate) {
workMessages.push(
t('workConflictSameDay', {
waypointBefore,
waypointAfter,
startDate,
startTime,
endTime,
})
);
} else {
workMessages.push(
t('workConflict', {
waypointBefore,
waypointAfter,
startDate,
startTime,
endDate,
endTime,
})
);
}
});

const remainingWorkConflicts = workConflictsData.length - 2;
if (remainingWorkConflicts > 0) {
workMessages.push(t('remainingWorkConflicts', { count: remainingWorkConflicts }));
}

// Update the state with generated messages
setTrackConflicts(trackMessages);
setWorkConflicts(workMessages);
};

generateConflictMessages();
}, [t, selectedSimulationOutput]);

return { trackConflicts, workConflicts };
};

export default useConflictsMessages;
Loading

0 comments on commit c3d0409

Please sign in to comment.