Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

front: introduce Duration type #9934

Merged
merged 4 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions front/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, it, expect } from 'vitest';

import type { PathfindingResult } from 'common/api/osrdEditoastApi';
import { Duration } from 'utils/duration';

import { updatePathStepsFromOperationalPoints } from '../useSetupItineraryForTrainUpdate';

Expand Down Expand Up @@ -154,7 +155,7 @@ describe('updatePathStepsFrom', () => {
uic: 87747006,
secondary_code: 'P2',
name: '87747006',
arrival: '15:00:00',
arrival: Duration.parse('PT60S'),
stopFor: null,
},
{
Expand Down Expand Up @@ -198,7 +199,7 @@ describe('updatePathStepsFrom', () => {
uic: 87747006,
secondary_code: 'P2', // should not be BV here, it has the same uic but not the same ch
name: 'Grenadille',
arrival: '15:00:00',
arrival: Duration.parse('PT60S'),
stopFor: null,
kp: '129+952',
positionOnPath: 586000,
Expand Down Expand Up @@ -234,7 +235,7 @@ describe('updatePathStepsFrom', () => {
trigram: 'GE',
secondary_code: 'P2',
name: '87747006',
arrival: '15:00:00',
arrival: Duration.parse('PT60S'),
},
{
id: 'who-0',
Expand Down Expand Up @@ -272,7 +273,7 @@ describe('updatePathStepsFrom', () => {
trigram: 'GE',
secondary_code: 'P2',
name: 'Grenadille',
arrival: '15:00:00',
arrival: Duration.parse('PT60S'),
kp: '129+952',
positionOnPath: 586000,
coordinates: [5.711846462951984, 45.19643525506182],
Expand Down Expand Up @@ -303,7 +304,7 @@ describe('updatePathStepsFrom', () => {
trigram: 'GE',
secondary_code: 'P2',
name: '87747006',
arrival: '15:00:00',
arrival: Duration.parse('PT60S'),
},
{
id: 'who-0',
Expand Down Expand Up @@ -341,7 +342,7 @@ describe('updatePathStepsFrom', () => {
secondary_code: 'P2',
trigram: 'GE',
name: '87747006',
arrival: '15:00:00',
arrival: Duration.parse('PT60S'),
kp: undefined,
positionOnPath: 586000,
coordinates: [5.711846462951984, 45.19643525506182],
Expand Down
6 changes: 0 additions & 6 deletions front/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ export const DATA_TYPES = {
*/
export type TimeString = string;

/**
* A ISO 8601 duration string
* @example "PT3600S"
*/
export type IsoDurationString = string;

export type RangedValue = {
begin: number;
end: number;
Expand Down
2 changes: 1 addition & 1 deletion front/src/modules/pathfinding/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const getPathfindingQuery = ({
export const upsertPathStepsInOPs = (ops: SuggestedOP[], pathSteps: PathStep[]): SuggestedOP[] => {
let updatedOPs = [...ops];
pathSteps.forEach((step) => {
const { stopFor, arrival, receptionSignal, theoreticalMargin } = step;
const { arrival, stopFor, receptionSignal, theoreticalMargin } = step;
// We check only for pathSteps added by map click
if ('track' in step) {
const formattedStep: SuggestedOP = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, it, expect } from 'vitest';

import { type TimesStopsInputRow } from 'modules/timesStops/types';
import { Duration } from 'utils/duration';

import {
updateRowTimesAndMargin,
Expand Down Expand Up @@ -820,7 +821,7 @@ describe('durationSinceStartTime', () => {

const result = durationSinceStartTime(startTime, stepTimeDays);

expect(result).toBe('PT36000S');
expect(result).toEqual(Duration.parse('PT36000S'));
});

it('should return the correct duration. daySinceDeparture 1', () => {
Expand All @@ -832,14 +833,14 @@ describe('durationSinceStartTime', () => {

const result = durationSinceStartTime(startTime, stepTimeDays);

expect(result).toBe('PT90000S');
expect(result).toEqual(Duration.parse('PT90000S'));
});
});

describe('calculateStepTimeDays', () => {
it('should return correct time and daySinceDeparture', () => {
const startTime = new Date('2023-09-01T10:00:00Z');
const isoDuration = 'PT36000S'; // 10 hours
const isoDuration = Duration.parse('PT36000S'); // 10 hours

const result = calculateStepTimeAndDays(startTime, isoDuration);

Expand All @@ -851,7 +852,7 @@ describe('calculateStepTimeDays', () => {

it('should return correct time and daySinceDeparture, daySinceDeparture 1', () => {
const startTime = new Date('2023-09-01T10:00:00Z');
const isoDuration = 'PT122400S'; // 1 day 10 hours
const isoDuration = Duration.parse('PT122400S'); // 1 day 10 hours

const result = calculateStepTimeAndDays(startTime, isoDuration);

Expand Down
26 changes: 12 additions & 14 deletions front/src/modules/timesStops/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { round, isEqual, isNil } from 'lodash';
import { keyColumn, createTextColumn } from 'react-datasheet-grid';

import type { ReceptionSignal } from 'common/api/osrdEditoastApi';
import type { IsoDurationString, TimeString } from 'common/types';
import type { TimeString } from 'common/types';
import { matchPathStepAndOp } from 'modules/pathfinding/utils';
import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types';
import type { PathStep } from 'reducers/osrdconf/types';
import { Duration } from 'utils/duration';
import { msToS } from 'utils/physics';
import { NO_BREAK_SPACE } from 'utils/strings';
import {
calculateTimeDifferenceInSeconds,
datetime2sec,
durationInSeconds,
formatDurationAsISO8601,
sec2time,
SECONDS_IN_A_DAY,
secToHoursString,
Expand Down Expand Up @@ -79,10 +79,10 @@ export const formatSuggestedViasToRowVias = (
const { arrival, receptionSignal, stopFor, theoreticalMargin } = objectToUse || {};

const isMarginValid = theoreticalMargin ? marginRegExValidation.test(theoreticalMargin) : true;
const durationArrivalTime = i === 0 ? 'PT0S' : arrival;
const arrivalInSeconds = durationArrivalTime ? time2sec(durationArrivalTime) : null;
const arrivalDuration = i === 0 ? Duration.zero : arrival;
const arrivalInSeconds = arrivalDuration ? msToS(arrivalDuration.ms) : null;

const formattedArrival = calculateStepTimeAndDays(startTime, durationArrivalTime);
const formattedArrival = calculateStepTimeAndDays(startTime, arrivalDuration);

const departureTime =
stopFor && arrivalInSeconds
Expand Down Expand Up @@ -281,7 +281,7 @@ export function updateDaySinceDeparture(
export function durationSinceStartTime(
startTime?: Date,
stepTimeDays?: TimeExtraDays
): IsoDurationString | null {
): Duration | null {
if (!startTime || !stepTimeDays?.time || stepTimeDays?.daySinceDeparture === undefined) {
return null;
}
Expand All @@ -290,23 +290,21 @@ export function durationSinceStartTime(
stepTimeDays.daySinceDeparture,
'day'
);
return formatDurationAsISO8601(
calculateTimeDifferenceInSeconds(start.toISOString(), step.toISOString())
);
return Duration.subtractDate(step.toDate(), startTime);
}

export function calculateStepTimeAndDays(
startTime?: Date | null,
isoDuration?: IsoDurationString | null
duration?: Duration | null
): TimeExtraDays | undefined {
if (!startTime || !isoDuration) {
if (!startTime || !duration) {
return undefined;
}

const start = dayjs(startTime);
const duration = dayjs.duration(isoDuration);
const dur = dayjs.duration(duration.ms);

const waypointArrivalTime = start.add(duration);
const waypointArrivalTime = start.add(dur);
const daySinceDeparture = waypointArrivalTime.diff(start, 'day');
const time: TimeString = waypointArrivalTime.format('HH:mm:ss');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, expect, it } from 'vitest';

import type { PathStep } from 'reducers/osrdconf/types';
import { Duration } from 'utils/duration';

import formatSchedule from '../formatSchedule';

Expand Down Expand Up @@ -31,7 +32,7 @@ describe('formatSchedule', () => {
kp: '117+422',
name: 'V',
positionOnPath: 13116000,
arrival: 'PT60S',
arrival: Duration.parse('PT60S'),
stopFor: '0',
locked: false,
receptionSignal: 'OPEN',
Expand All @@ -40,7 +41,7 @@ describe('formatSchedule', () => {
const result = formatSchedule(pathSteps);
expect(result).toEqual([
{
arrival: 'PT60S',
arrival: 'PT1M',
at: 'id332',
locked: false,
reception_signal: 'OPEN',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const formatSchedule = (pathSteps: PathStep[]): TrainScheduleBase['schedule'] =>
if (step?.arrival || step.stopFor) {
return {
at: step.id,
arrival: step.arrival ?? undefined,
arrival: step.arrival?.toISOString() ?? undefined,
locked: step.locked,
reception_signal: step.receptionSignal,
stop_for:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Feature, Position } from 'geojson';

import type { ReceptionSignal, TrainScheduleBase } from 'common/api/osrdEditoastApi';
import type { IsoDurationString } from 'common/types';
import type { Duration } from 'utils/duration';

export type SuggestedOP = {
pathStepId?: string;
Expand All @@ -21,7 +21,7 @@ export type SuggestedOP = {
It's useful for soft deleting the point (waiting to fix / remove all references)
If true, the train schedule is consider as invalid and must be edited */
deleted?: boolean;
arrival?: IsoDurationString | null; // value asked by user, number of seconds since departure
arrival?: Duration | null; // value asked by user, number of seconds since departure
locked?: boolean;
stopFor?: string | null; // value asked by user
theoreticalMargin?: string; // value asked by user
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { TrainScheduleResult } from 'common/api/osrdEditoastApi';
import type { PathStep } from 'reducers/osrdconf/types';
import { Duration } from 'utils/duration';
import { mmToM } from 'utils/physics';
import { ISO8601Duration2sec } from 'utils/timeManipulation';

Expand Down Expand Up @@ -51,7 +52,7 @@ const computeBasePathStep = (
...step,
...('track' in step ? { offset: mmToM(step.offset) } : null),
name,
arrival, // ISODurationString
arrival: arrival ? Duration.parse(arrival) : null,
stopFor: stopFor ? ISO8601Duration2sec(stopFor).toString() : stopFor,
locked,
receptionSignal,
Expand Down
12 changes: 11 additions & 1 deletion front/src/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import simulationReducer, {
import type { SimulationResultsState } from 'reducers/simulationResults/types';
import userReducer, { userInitialState, userSlice } from 'reducers/user';
import type { UserState } from 'reducers/user';
import { Duration } from 'utils/duration';

import type { ConfSlice } from './osrdconf/osrdConfCommon';

Expand Down Expand Up @@ -79,14 +80,23 @@ const operationalStudiesDateTransform = createTransform(
}),
{ whitelist: ['operationalStudiesConf'] }
);
const pathStepsTransform = createTransform(
null,
(pathSteps: ({ arrival: string } | null)[]) =>
pathSteps.map((pathStep) => {
if (!pathStep) return null;
return { ...pathStep, arrival: pathStep.arrival ? Duration.parse(pathStep.arrival) : null };
}),
{ whitelist: ['pathSteps'] }
);

// Useful to only blacklist a sub-propertie of osrdconf
const buildOsrdConfPersistConfig = <T extends OperationalStudiesConfState | OsrdStdcmConfState>(
slice: ConfSlice
): PersistConfig<T> => ({
key: slice.name,
storage,
transforms: [stdcmPathStepsDateTransform, operationalStudiesDateTransform],
transforms: [stdcmPathStepsDateTransform, operationalStudiesDateTransform, pathStepsTransform],
});

export const persistConfig = {
Expand Down
Loading
Loading