Skip to content

Commit 6e5bd0a

Browse files
committed
front: add stops in stdcm simluation report sheet
1 parent a74c265 commit 6e5bd0a

File tree

5 files changed

+112
-54
lines changed

5 files changed

+112
-54
lines changed

front/src/applications/stdcm/components/SimulationReportSheet.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import iconAlert from 'assets/simulationReportSheet/icon_alert_fill.png';
88
import logoSNCF from 'assets/simulationReportSheet/logo_sncf_reseau.png';
99
import type { PostStdcmApiResponse, RollingStockWithLiveries } from 'common/api/osrdEditoastApi';
1010
import { formatDay } from 'utils/date';
11-
import { getStopDurationTime, getStopTime } from 'utils/timeManipulation';
11+
import { getStopTime } from 'utils/timeManipulation';
1212

1313
import styles from './SimulationReportStyleSheet';
14-
import { extractSpeedLimit, formatCreationDate } from '../utils';
14+
import { extractSpeedLimit, getStopDurationTime, formatCreationDate } from '../utils';
1515

1616
type SimulationReportSheetProps = {
1717
stdcmData: PostStdcmApiResponse;

front/src/applications/stdcm/components/SimulationReportSheetV2.tsx

+25-15
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { formatDateToString, formatDayV2 } from 'utils/date';
1010

1111
import styles from './SimulationReportStyleSheet';
1212
import type { SimulationReportSheetProps } from '../types';
13-
import { extractSpeedLimit, getOperationalPointsWithTimes } from '../utils';
13+
import { extractSpeedLimit, getStopDurationTime, getOperationalPointsWithTimes } from '../utils';
1414

1515
const SimulationReportSheetV2 = ({
1616
stdcmData,
@@ -158,7 +158,7 @@ const SimulationReportSheetV2 = ({
158158
{opList.map((step, index) => {
159159
const isFirstStep = index === 0;
160160
const isLastStep = index === opList.length - 1;
161-
const shouldRenderRow = isFirstStep || /* step.stop > '0' || */ isLastStep;
161+
const shouldRenderRow = isFirstStep || step.duration > 0 || isLastStep;
162162
if (shouldRenderRow) {
163163
renderedIndex += 1;
164164
return (
@@ -267,21 +267,24 @@ const SimulationReportSheetV2 = ({
267267
<TR
268268
key={index}
269269
style={
270-
/* step.stop !== '0' && !isLastStep
270+
step.duration !== 0 && !isLastStep
271271
? styles.simulation.blueRow
272-
: */ styles.simulation.tbody
272+
: styles.simulation.tbody
273273
}
274274
>
275275
<TD style={styles.simulation.indexColumn}>{index + 1}</TD>
276276
<View style={styles.simulation.opWidth}>
277277
<TD
278278
style={
279-
!isFirstStep && !isLastStep /* && step.stop !== '0' */
279+
!isFirstStep && !isLastStep && step.duration !== 0
280280
? styles.simulation.opStop
281281
: styles.simulation.td
282282
}
283283
>
284-
{!isFirstStep && !isLastStep && step.name === prevStep.name
284+
{!isFirstStep &&
285+
!isLastStep &&
286+
step.name === prevStep.name &&
287+
step.duration === 0
285288
? '='
286289
: step.name || 'Unknown'}
287290
</TD>
@@ -290,30 +293,37 @@ const SimulationReportSheetV2 = ({
290293
<TD style={styles.simulation.chColumn}>{step.ch}</TD>
291294
</View>
292295
<View style={styles.simulation.trackWidth}>
293-
{/* <TD style={styles.simulation.td}>{step.metadata?.trackName}</TD> */}
296+
<TD style={styles.simulation.td}>{step.trackName}</TD>
294297
</View>
295298
<View style={styles.simulation.endWidth}>
296299
<TD style={styles.simulation.stopColumn}>
297-
{isLastStep /* || step.stop !== '0' */ ? step.time : ''}
300+
{isLastStep || step.duration !== 0 ? step.time : ''}
298301
</TD>
299302
</View>
300303
<View style={styles.simulation.passageWidth}>
301-
<TD style={styles.simulation.stopColumn}>
304+
<TD
305+
style={{
306+
...(step.duration !== 0 && !isLastStep
307+
? {
308+
width: `${step.duration < 600 && step.duration >= 60 ? 60 : 70}px`,
309+
...styles.simulation.blueStop,
310+
}
311+
: styles.simulation.stopColumn),
312+
}}
313+
>
302314
{
303315
// eslint-disable-next-line no-nested-ternary
304316
!isFirstStep && !isLastStep
305-
? // ? step.stop !== '0'
306-
// ? /* getStopDurationTime(step.stop) */ 'test'
307-
step.time
317+
? step.duration !== 0
318+
? getStopDurationTime(step.duration)
319+
: step.time
308320
: ''
309321
}
310322
</TD>
311323
</View>
312324
<View style={styles.simulation.startWidth}>
313325
<TD style={styles.simulation.stopColumn}>
314-
{isFirstStep /* || step.stop !== '0' */
315-
? step.departureTime /* + step.stop */
316-
: ''}
326+
{isFirstStep || step.duration !== 0 ? step.stopEndTime : ''}
317327
</TD>
318328
</View>
319329
<View style={styles.simulation.weightWidth}>

front/src/applications/stdcm/components/SimulationReportStyleSheet.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -496,16 +496,15 @@ const styles = {
496496
marginLeft: '14',
497497
},
498498
blueStop: {
499-
height: '20',
499+
height: '24',
500500
fontSize: '16',
501-
fontWeight: 'medium',
501+
fontWeight: 'semibold',
502502
backgroundColor: '#216482',
503503
color: '#FFFFFF',
504504
borderRadius: '12',
505505
padding: '0 8',
506506
marginLeft: '8',
507-
marginTop: '1',
508-
marginBottom: '1',
507+
marginVertical: '1',
509508
},
510509
td: {
511510
fontSize: '14',

front/src/applications/stdcm/utils.ts

+82-23
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,92 @@ export function formatCreationDate(date: string) {
3737
};
3838
}
3939

40+
export function getStopDurationTime(sec: number) {
41+
const timeInMilliseconds = sec * 1000;
42+
const time = new Date(timeInMilliseconds);
43+
44+
if (timeInMilliseconds < 60000) {
45+
return `${time.getUTCSeconds()} sec`;
46+
}
47+
return `${time.getUTCMinutes()} min`;
48+
}
49+
4050
export function extractSpeedLimit(speedLimitByTag: string): string {
4151
const parts = speedLimitByTag.split(' - ');
4252
return parts[parts.length - 1];
4353
}
4454

55+
function secondsToTimeString(duration: number): string {
56+
const minutes = Math.floor(duration / 60);
57+
const seconds = duration % 60;
58+
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
59+
}
60+
61+
function timeStringToSeconds(time: string): number {
62+
const [minutes, seconds] = time.split(':').map(Number);
63+
return minutes * 60 + seconds;
64+
}
65+
66+
/**
67+
* Based on a stop arrival time and a stop duration, calculate the departure time on this stop
68+
*/
69+
function computeStopDepartureTime(hhmm: string, mmss: string): string {
70+
const [hh, mm] = hhmm.split(':').map(Number);
71+
const totalSeconds1 = hh * 3600 + mm * 60;
72+
const totalSeconds2 = timeStringToSeconds(mmss);
73+
74+
const totalSeconds = totalSeconds1 + totalSeconds2;
75+
const hours = Math.floor(totalSeconds / 3600);
76+
const minutes = Math.floor((totalSeconds % 3600) / 60);
77+
78+
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
79+
}
80+
81+
// Function to add minutes to the departure time
82+
const addMinutesToTime = (baseHour: number, baseMinute: number, minutesToAdd: number): string => {
83+
const totalMinutes = baseHour * 60 + baseMinute + minutesToAdd;
84+
const finalHour = Math.floor(totalMinutes / 60) % 24;
85+
const finalMinutes = totalMinutes % 60;
86+
return `${String(finalHour).padStart(2, '0')}:${String(finalMinutes).padStart(2, '0')}`;
87+
};
88+
89+
const getTimeAtPosition = (
90+
trainPosition: number,
91+
trainPositions: number[],
92+
trainTimes: number[],
93+
trainDepartureHour: number,
94+
trainDepartureMinute: number
95+
): string => {
96+
const index = trainPositions.findIndex((pos) => pos >= trainPosition);
97+
const timeInMillis = trainTimes[index];
98+
const timeInMinutes = Math.floor(timeInMillis / 60000);
99+
return addMinutesToTime(trainDepartureHour, trainDepartureMinute, timeInMinutes);
100+
};
101+
102+
const getStopDurationBetweenToPositions = (
103+
position: number,
104+
trainPositions: number[],
105+
trainTimes: number[]
106+
): number | null => {
107+
const firstIndex = trainPositions.indexOf(position);
108+
const lastIndex = trainPositions.lastIndexOf(position);
109+
if (firstIndex !== -1 && lastIndex !== -1 && firstIndex !== lastIndex) {
110+
return trainTimes[lastIndex] - trainTimes[firstIndex];
111+
}
112+
return null;
113+
};
114+
45115
export function getOperationalPointsWithTimes(simulationReport: SimulationReportSheetProps): {
46116
opId: string;
47117
positionOnPath: number;
48118
time: string | null;
49119
name: string | undefined;
50120
ch: string | undefined;
51121
stop: string | null | undefined;
122+
duration: number;
52123
departureTime: string;
124+
stopEndTime: string;
125+
trackName: string | undefined;
53126
}[] {
54127
const operationalPoints = simulationReport.pathProperties?.suggestedOperationalPoints || [];
55128
const { simulation } = simulationReport.stdcmData;
@@ -66,29 +139,7 @@ export function getOperationalPointsWithTimes(simulationReport: SimulationReport
66139
// Parse departure time into hours and minutes
67140
const [departureHour, departureMinute] = departureTime.split(':').map(Number);
68141

69-
// Function to add minutes to the departure time
70-
const addMinutesToTime = (baseHour: number, baseMinute: number, minutesToAdd: number): string => {
71-
const totalMinutes = baseHour * 60 + baseMinute + minutesToAdd;
72-
const finalHour = Math.floor(totalMinutes / 60) % 24;
73-
const finalMinutes = totalMinutes % 60;
74-
return `${String(finalHour).padStart(2, '0')}:${String(finalMinutes).padStart(2, '0')}`;
75-
};
76-
77-
const getTimeAtPosition = (
78-
trainPosition: number,
79-
trainPositions: number[],
80-
trainTimes: number[],
81-
trainDepartureHour: number,
82-
trainDepartureMinute: number
83-
): string | null => {
84-
const index = trainPositions.findIndex((pos) => pos >= trainPosition);
85-
if (index === -1) return null;
86-
const timeInMillis = trainTimes[index];
87-
const timeInMinutes = Math.floor(timeInMillis / 60000);
88-
return addMinutesToTime(trainDepartureHour, trainDepartureMinute, timeInMinutes);
89-
};
90-
91-
// Map operational points with their positions and times
142+
// Map operational points with their positions, times, and stop durations
92143
const opResults = operationalPoints.map((op) => {
93144
const formattedTime = getTimeAtPosition(
94145
op.positionOnPath,
@@ -98,14 +149,22 @@ export function getOperationalPointsWithTimes(simulationReport: SimulationReport
98149
departureMinute
99150
);
100151

152+
const duration = getStopDurationBetweenToPositions(op.positionOnPath, positions, times);
153+
const durationInSeconds = duration !== null ? duration / 1000 : 0;
154+
const durationToString = secondsToTimeString(durationInSeconds);
155+
const stopEndTime = computeStopDepartureTime(formattedTime, durationToString);
156+
101157
return {
102158
opId: op.opId,
103159
positionOnPath: op.positionOnPath,
104160
time: formattedTime,
105161
name: op.name,
106162
ch: op.ch,
107163
stop: op.stopFor,
164+
duration: durationInSeconds,
108165
departureTime,
166+
stopEndTime,
167+
trackName: op.metadata?.trackName,
109168
};
110169
});
111170

front/src/utils/timeManipulation.ts

-10
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,3 @@ export function ISO8601Duration2sec(duration: string) {
9292
export function getStopTime(sec: number) {
9393
return new Date(sec * 1000).toISOString().substr(11, 5);
9494
}
95-
96-
export function getStopDurationTime(sec: number) {
97-
const timeInMilliseconds = sec * 1000;
98-
const time = new Date(timeInMilliseconds);
99-
100-
if (timeInMilliseconds < 60000) {
101-
return `${time.getUTCSeconds()} sec`;
102-
}
103-
return `${time.getUTCMinutes()} min`;
104-
}

0 commit comments

Comments
 (0)