Skip to content

Commit

Permalink
front: stdcm consist form validation
Browse files Browse the repository at this point in the history
Signed-off-by: Egor Berezovskiy <[email protected]>
  • Loading branch information
Wadjetz committed Jan 7, 2025
1 parent cae4d30 commit 858b862
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 21 deletions.
16 changes: 15 additions & 1 deletion front/public/locales/en/stdcm.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,21 @@
"tonnage": "Tonnage",
"maxSpeed": "Max speed",
"tractionEngine": "Traction engine",
"towedRollingStock": "Towed rolling stock"
"towedRollingStock": "Towed rolling stock",
"errors": {
"totalMass": {
"negative": "Must be positive.",
"range": "The total weight must be between {{low}} and {{high}}t"
},
"totalLength": {
"negative": "Must be positive.",
"range": "The total length must be between {{low}} and {{high}}m"
},
"maxSpeed": {
"negative": "Must be positive.",
"range": "The max speed must be between {{low}} and {{high}}km/h"
}
}
},
"datetimeOutsideWindow": "Date must be between {{low}} and {{high}}",
"debug": {
Expand Down
16 changes: 15 additions & 1 deletion front/public/locales/fr/stdcm.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,21 @@
"tonnage": "Tonnage",
"maxSpeed": "Vitesse max.",
"tractionEngine": "Engin de traction",
"towedRollingStock": "Matériel remorqué"
"towedRollingStock": "Matériel remorqué",
"errors": {
"totalMass": {
"negative": "Doit être positif.",
"range": "Le tonnage total doit être compris entre {{low}} et {{high}}t"
},
"totalLength": {
"negative": "Doit être positif.",
"range": "La longueur totale doit être comprise entre {{low}} et {{high}}m"
},
"maxSpeed": {
"negative": "Doit être positif.",
"range": "La vitesse max. doit être comprise entre {{low}} et {{high}}km/h"
}
}
},
"datetimeOutsideWindow": "La date et l'heure doivent être comprises entre le {{low}} et le {{high}}",
"debug": {
Expand Down
44 changes: 42 additions & 2 deletions front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ import cx from 'classnames';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';

import useStdcmTowedRollingStock from 'applications/stdcm/hooks/useStdcmTowedRollingStock';
import { extractMarkersInfo } from 'applications/stdcm/utils';
import {
validateMaxSpeed,
validateTotalLength,
validateTotalMass,
} from 'applications/stdcm/utils/consistValidation';
import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext';
import useInfraStatus from 'modules/pathfinding/hooks/useInfraStatus';
import { useStoreDataForRollingStockSelector } from 'modules/rollingStock/components/RollingStockSelector/useStoreDataForRollingStockSelector';
import { Map } from 'modules/trainschedule/components/ManageTrainSchedule';
import { type StdcmConfSliceActions, resetMargins } from 'reducers/osrdconf/stdcmConf';
import type { StdcmConfSelectors } from 'reducers/osrdconf/stdcmConf/selectors';
Expand Down Expand Up @@ -61,6 +68,9 @@ const StdcmConfig = ({
getProjectID,
getScenarioID,
getStudyID,
getTotalMass,
getTotalLength,
getMaxSpeed,
} = useOsrdConfSelectors() as StdcmConfSelectors;
const origin = useSelector(getStdcmOrigin);
const pathSteps = useSelector(getStdcmPathSteps);
Expand All @@ -69,11 +79,38 @@ const StdcmConfig = ({
const studyID = useSelector(getStudyID);
const scenarioID = useSelector(getScenarioID);

const totalMass = useSelector(getTotalMass);
const totalLength = useSelector(getTotalLength);
const maxSpeed = useSelector(getMaxSpeed);

const pathfinding = useStaticPathfinding(infra);
const formRef = useRef<HTMLDivElement>(null);

const [formErrors, setFormErrors] = useState<StdcmConfigErrors>();

const { rollingStock } = useStoreDataForRollingStockSelector();
const towedRollingStock = useStdcmTowedRollingStock();

const consistErrors = useMemo(() => {
const totalMassError = validateTotalMass({
tractionEngineMass: rollingStock?.mass,
towedMass: towedRollingStock?.mass,
totalMass,
});

const totalLengthError = validateTotalLength({
tractionEngineLength: rollingStock?.length,
towedLength: towedRollingStock?.length,
totalLength,
});

return {
totalMass: totalMassError,
totalLength: totalLengthError,
maxSpeed: validateMaxSpeed(maxSpeed, rollingStock?.max_speed),
};
}, [rollingStock, towedRollingStock, totalMass, totalLength, maxSpeed]);

const disabled = isPending || retainedSimulationIndex > -1;

const markersInfo = useMemo(() => extractMarkersInfo(pathSteps), [pathSteps]);
Expand Down Expand Up @@ -146,7 +183,7 @@ const StdcmConfig = ({
/>
<div className="stdcm-simulation-inputs">
<div className="stdcm-consist-container">
<StdcmConsist disabled={disabled} />
<StdcmConsist consistErrors={consistErrors} disabled={disabled} />
</div>
<div className="stdcm__separator" />
<div ref={formRef} className="stdcm-simulation-itinerary">
Expand Down Expand Up @@ -175,7 +212,10 @@ const StdcmConfig = ({
isDisabled={
disabled ||
!showBtnToLaunchSimulation ||
formErrors?.errorType === StdcmConfigErrorTypes.INFRA_NOT_LOADED
formErrors?.errorType === StdcmConfigErrorTypes.INFRA_NOT_LOADED ||
!!consistErrors.totalMass ||
!!consistErrors.totalLength ||
!!consistErrors.maxSpeed
}
/>
{formErrors && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { Input, ComboBox } from '@osrd-project/ui-core';
import { useTranslation } from 'react-i18next';

import useStdcmTowedRollingStock from 'applications/stdcm/hooks/useStdcmTowedRollingStock';
import {
CONSIST_MAX_SPEED_MIN,
CONSIST_TOTAL_LENGTH_MAX,
CONSIST_TOTAL_MASS_MAX,
} from 'applications/stdcm/utils/consistValidation';
import type { LightRollingStockWithLiveries, TowedRollingStock } from 'common/api/osrdEditoastApi';
import { useOsrdConfActions } from 'common/osrdContext';
import SpeedLimitByTagSelector from 'common/SpeedLimitByTagSelector/SpeedLimitByTagSelector';
Expand All @@ -14,6 +19,7 @@ import useFilterRollingStock from 'modules/rollingStock/hooks/useFilterRollingSt
import useFilterTowedRollingStock from 'modules/towedRollingStock/hooks/useFilterTowedRollingStock';
import { type StdcmConfSliceActions } from 'reducers/osrdconf/stdcmConf';
import { useAppDispatch } from 'store';
import { kgToT, kmhToMs, msToKmh } from 'utils/physics';

import StdcmCard from './StdcmCard';
import useStdcmConsist from '../../hooks/useStdcmConsist';
Expand All @@ -33,7 +39,7 @@ const ConsistCardTitle = ({
);
};

const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => {
const StdcmConsist = ({ consistErrors = {}, disabled = false }: StdcmConfigCardProps) => {
const { t } = useTranslation('stdcm');
const { speedLimitByTag, speedLimitsByTags, dispatchUpdateSpeedLimitByTag } =
useStoreDataForSpeedLimitByTagSelector({ isStdcm: true });
Expand Down Expand Up @@ -166,6 +172,20 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => {
value={totalMass ?? ''}
onChange={onTotalMassChange}
disabled={disabled}
statusWithMessage={
consistErrors?.totalMass
? {
status: 'error',
tooltip: 'left',
message: t(consistErrors.totalMass, {
low: Math.floor(
kgToT((rollingStock?.mass ?? 0) + (towedRollingStock?.mass ?? 0))
),
high: CONSIST_TOTAL_MASS_MAX,
}),
}
: undefined
}
/>
<Input
id="length"
Expand All @@ -176,6 +196,18 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => {
value={totalLength ?? ''}
onChange={onTotalLengthChange}
disabled={disabled}
statusWithMessage={
consistErrors?.totalLength
? {
status: 'error',
tooltip: 'right',
message: t(consistErrors.totalLength, {
low: Math.floor((rollingStock?.length ?? 0) + (towedRollingStock?.length ?? 0)),
high: CONSIST_TOTAL_LENGTH_MAX,
}),
}
: undefined
}
/>
</div>
<div className="stdcm-consist__properties">
Expand All @@ -194,6 +226,20 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => {
value={maxSpeed ?? ''}
onChange={onMaxSpeedChange}
disabled={disabled}
statusWithMessage={
consistErrors?.maxSpeed
? {
status: 'error',
tooltip: 'right',
message: t(consistErrors.maxSpeed, {
low: CONSIST_MAX_SPEED_MIN,
high: Math.floor(
msToKmh(Math.min(rollingStock?.max_speed ?? kmhToMs(CONSIST_MAX_SPEED_MIN)))
),
}),
}
: undefined
}
/>
</div>
</StdcmCard>
Expand Down
14 changes: 2 additions & 12 deletions front/src/applications/stdcm/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,6 @@ export const STDCM_REQUEST_STATUS = Object.freeze({

export const STDCM_TRAIN_ID = -10;

export const COMPOSITION_CODES = [
'HLP',
'MA100',
'MA80',
'MA90',
'ME100',
'ME120',
'ME140',
'MV160',
'MVGV',
];

export const COMPOSITION_CODES_MAX_SPEEDS: Record<string, number | undefined> = {
MA80: 80,
MA90: 90,
Expand All @@ -32,3 +20,5 @@ export const COMPOSITION_CODES_MAX_SPEEDS: Record<string, number | undefined> =
HLP: 100,
MVGV: 200,
};

export const COMPOSITION_CODES = Object.keys(COMPOSITION_CODES_MAX_SPEEDS);
7 changes: 7 additions & 0 deletions front/src/applications/stdcm/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ export type StdcmResultsOperationalPoint = {
trackName?: string;
};

export type ConsistErrors = {
totalMass?: string;
totalLength?: string;
maxSpeed?: string;
};

export type StdcmResults = {
stdcmResponse: StdcmSuccessResponse;
speedSpaceChartData: SpeedSpaceChartData | null;
Expand Down Expand Up @@ -145,6 +151,7 @@ export type StdcmSimulation = {
/** This type is used for StdcmConsist, StdcmOrigin, StdcmDestination and StdcmVias components */
export type StdcmConfigCardProps = {
disabled?: boolean;
consistErrors?: ConsistErrors;
};

export enum ArrivalTimeTypes {
Expand Down
78 changes: 78 additions & 0 deletions front/src/applications/stdcm/utils/consistValidation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { kgToT, msToKmh } from 'utils/physics';

export const CONSIST_TOTAL_MASS_MAX = 10000; // ton
export const CONSIST_TOTAL_LENGTH_MAX = 750; // m
export const CONSIST_MAX_SPEED_MIN = 30; // km/h

export const validateTotalMass = ({
tractionEngineMass = 0,
towedMass = 0,
totalMass,
}: {
tractionEngineMass?: number;
towedMass?: number;
totalMass?: number;
}) => {
if (!totalMass) {
return undefined;
}

if (totalMass <= 0) {
return 'consist.errors.totalMass.negative';
}

const tractionMassInTons = kgToT(tractionEngineMass);
const consistMassInTons = kgToT(tractionEngineMass + towedMass);
const massLimit = towedMass ? consistMassInTons : tractionMassInTons;

if (totalMass < massLimit || totalMass >= CONSIST_TOTAL_MASS_MAX) {
return 'consist.errors.totalMass.range';
}

return undefined;
};

export const validateTotalLength = ({
tractionEngineLength = 0,
towedLength = 0,
totalLength,
}: {
tractionEngineLength?: number;
towedLength?: number;
totalLength?: number;
}) => {
if (!totalLength) {
return undefined;
}

if (totalLength <= 0) {
return 'consist.errors.totalLength.negative';
}

const consistLength = Math.floor(tractionEngineLength + towedLength);

if (totalLength < consistLength || totalLength >= CONSIST_TOTAL_LENGTH_MAX) {
return 'consist.errors.totalLength.range';
}

return undefined;
};

export const validateMaxSpeed = (maxSpeed?: number, tractionEngineMaxSpeed?: number) => {
if (!maxSpeed) {
return undefined;
}

if (maxSpeed <= 0) {
return 'consist.errors.maxSpeed.negative';
}

if (
maxSpeed < CONSIST_MAX_SPEED_MIN ||
(tractionEngineMaxSpeed && maxSpeed > Math.floor(msToKmh(tractionEngineMaxSpeed)))
) {
return 'consist.errors.maxSpeed.range';
}

return undefined;
};
13 changes: 9 additions & 4 deletions front/src/styles/scss/applications/stdcm/_card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
background-color: rgba(255, 255, 255, 1);
height: fit-content;
position: relative;
display: flex;
flex-direction: column;
gap: 5px;

.stdcm-default-card-icon {
color: #1844ef;
Expand Down Expand Up @@ -89,7 +92,9 @@
}

.feed-back {
padding: 0;
--field-wrapper-padding-bottom: 9px;
padding-top: 3px;
padding-bottom: 3px;
}

.date-picker {
Expand Down Expand Up @@ -121,7 +126,8 @@

// cards styles
&.consist {
padding-left: 24px;
padding-left: 11px;
padding-right: 11px;
padding-bottom: 15px;

.towed-rolling-stock {
Expand All @@ -130,9 +136,8 @@

.stdcm-consist__properties {
display: grid;
grid-template-columns: 119px 127px;
grid-template-columns: 139px 147px;
justify-content: space-between;
padding-block: 8px;

.osrd-config-item {
padding-right: 3px;
Expand Down

0 comments on commit 858b862

Please sign in to comment.