1
- /* eslint-disable no-restricted-syntax */
2
- import React , { useState , useEffect } from 'react' ;
1
+ import React , { useEffect , useMemo } from 'react' ;
3
2
import { useDispatch , useSelector } from 'react-redux' ;
4
3
import { useTranslation } from 'react-i18next' ;
5
4
import { updatePowerRestriction } from 'reducers/osrdconf' ;
@@ -10,67 +9,125 @@ import {
10
9
getPowerRestriction ,
11
10
getPathfindingID ,
12
11
} from 'reducers/osrdconf/selectors' ;
13
- import { osrdEditoastApi , LightRollingStock } from 'common/api/osrdEditoastApi' ;
12
+ import { osrdEditoastApi , RollingStock } from 'common/api/osrdEditoastApi' ;
14
13
import { osrdMiddlewareApi , PowerRestrictionRange } from 'common/api/osrdMiddlewareApi' ;
15
14
import { lengthFromLineCoordinates } from 'utils/geometry' ;
15
+ import { setFailure } from 'reducers/main' ;
16
+ import { compact , reduce , uniq } from 'lodash' ;
16
17
17
18
type selectorOption = { key : string | undefined ; value : string | undefined } ;
18
19
20
+ type ElectrificationPR = {
21
+ [ key : string ] : string [ ] | string [ ] ;
22
+ } ;
23
+
19
24
export default function PowerRestrictionSelector ( ) {
20
25
const { t } = useTranslation ( [ 'operationalStudies/manageTrainSchedule' ] ) ;
21
26
const dispatch = useDispatch ( ) ;
22
27
const rollingStockID : number | undefined = useSelector ( getRollingStockID ) ;
23
28
const pathFindingID = useSelector ( getPathfindingID ) ;
24
29
const powerRestriction = useSelector ( getPowerRestriction ) ;
25
- const [ powerRestrictions , setPowerRestrictions ] = useState < selectorOption [ ] | undefined > ( ) ;
26
- const [ getRollingStockById ] = osrdEditoastApi . endpoints . getLightRollingStockById . useLazyQuery ( { } ) ;
27
- const [ getPathFindingById ] = osrdMiddlewareApi . endpoints . getPathfindingById . useLazyQuery ( { } ) ;
28
30
29
- const getPowerRestrictionsList = async ( rollingStockInfo : LightRollingStock ) => {
30
- if ( rollingStockInfo . power_restrictions ) {
31
- const powerRestrictionsList = Object . entries ( rollingStockInfo . power_restrictions ) . map (
31
+ const { data : pathFinding } = osrdMiddlewareApi . useGetPathfindingByIdQuery (
32
+ { id : pathFindingID as number } ,
33
+ { skip : ! pathFindingID }
34
+ ) ;
35
+
36
+ const { data : pathWithCatenaries } = osrdEditoastApi . useGetPathfindingByPathIdCatenariesQuery (
37
+ { pathId : pathFindingID as number } ,
38
+ { skip : ! pathFindingID }
39
+ ) ;
40
+
41
+ const { data : rollingStock } = osrdEditoastApi . useGetRollingStockByIdQuery (
42
+ { id : rollingStockID as number } ,
43
+ { skip : ! rollingStockID }
44
+ ) ;
45
+
46
+ const powerRestrictions = useMemo ( ( ) => {
47
+ let powerRestrictionsList : selectorOption [ ] = [ ] ;
48
+ if ( rollingStock ) {
49
+ powerRestrictionsList = Object . entries ( rollingStock . power_restrictions ) . map (
32
50
( [ key , _ ] : [ string | undefined , string ] ) => ( { key, value : key } )
33
51
) ;
34
- if ( powerRestrictionsList . length > 0 ) {
35
- powerRestrictionsList . unshift ( { key : undefined , value : t ( 'noPowerRestriction' ) } ) ;
36
- }
37
- setPowerRestrictions ( powerRestrictionsList ) ;
52
+ powerRestrictionsList . unshift ( { key : undefined , value : t ( 'noPowerRestriction' ) } ) ;
38
53
}
54
+ return powerRestrictionsList ;
55
+ } , [ rollingStock ] ) ;
56
+
57
+ // Extract unique rollingstock's power restriction codes allowed by each electrification mode
58
+ const cleanConditionalEffortCurves = ( rollingStockToClean : RollingStock ) => {
59
+ const curvesMode = rollingStockToClean . effort_curves . modes ;
60
+ const curvesModesKey = Object . keys ( curvesMode ) ;
61
+
62
+ const parsedElectrification : ElectrificationPR = reduce (
63
+ curvesModesKey ,
64
+ ( result , mode ) => {
65
+ const powerCodes = curvesMode [ mode ] . curves . map (
66
+ ( curve ) => curve . cond ?. power_restriction_code
67
+ ) ;
68
+ compact ( uniq ( powerCodes ) ) ;
69
+ return {
70
+ ...result ,
71
+ [ mode ] : powerCodes ,
72
+ } ;
73
+ } ,
74
+ { }
75
+ ) ;
76
+
77
+ return parsedElectrification ;
39
78
} ;
40
79
41
- const definePowerRestrictionRange = ( powerRestrictionCode ?: string ) => {
42
- if ( powerRestrictionCode && pathFindingID ) {
43
- getPathFindingById ( { id : pathFindingID } )
44
- . unwrap ( )
45
- . then ( ( pathFinding ) => {
46
- const pathLength = Math . round (
47
- lengthFromLineCoordinates ( pathFinding ?. geographic ?. coordinates ) * 1000
48
- ) ;
49
- const powerRestrictionRange : PowerRestrictionRange [ ] = [
50
- {
51
- begin_position : 0 ,
52
- end_position : pathLength ,
53
- power_restriction_code : powerRestrictionCode ,
54
- } ,
55
- ] ;
56
- dispatch ( updatePowerRestriction ( powerRestrictionRange ) ) ;
57
- } ) ;
80
+ const definePowerRestrictionRange = async ( powerRestrictionCode ?: string ) => {
81
+ if ( powerRestrictionCode && pathFinding ) {
82
+ const pathLength = Math . round (
83
+ lengthFromLineCoordinates ( pathFinding . geographic ?. coordinates ) * 1000
84
+ ) ;
85
+ const powerRestrictionRange : PowerRestrictionRange = {
86
+ begin_position : 0 ,
87
+ end_position : pathLength ,
88
+ power_restriction_code : powerRestrictionCode ,
89
+ } ;
90
+
91
+ dispatch ( updatePowerRestriction ( powerRestrictionRange ) ) ;
58
92
} else dispatch ( updatePowerRestriction ( undefined ) ) ;
59
93
} ;
60
94
61
95
useEffect ( ( ) => {
62
- if ( rollingStockID ) {
63
- dispatch ( updatePowerRestriction ( undefined ) ) ;
64
- setPowerRestrictions ( undefined ) ;
65
- getRollingStockById ( { id : rollingStockID } )
66
- . unwrap ( )
67
- . then ( ( rollingStockInfo ) => {
68
- getPowerRestrictionsList ( rollingStockInfo ) ;
96
+ if ( powerRestriction && rollingStock && pathWithCatenaries ) {
97
+ const parsedElectrification = cleanConditionalEffortCurves ( rollingStock ) ;
98
+
99
+ const powerRestrictionCode = powerRestriction . power_restriction_code ;
100
+ const pathCatenaryRanges = pathWithCatenaries . catenary_ranges ;
101
+
102
+ if ( pathCatenaryRanges && powerRestrictionCode ) {
103
+ // Extract path electrification mode and check compatibility
104
+ const pathElectrification = compact ( pathCatenaryRanges . map ( ( range ) => range . mode ) ) ;
105
+
106
+ // Display an error when the first incompatibility is encountered
107
+ pathElectrification . some ( ( electrification ) => {
108
+ const isInvalid =
109
+ ! parsedElectrification [ electrification as keyof ElectrificationPR ] . includes (
110
+ powerRestrictionCode
111
+ ) ;
112
+ if ( isInvalid ) {
113
+ dispatch (
114
+ setFailure ( {
115
+ name : t ( 'errorMessages.error' ) ,
116
+ message : t ( 'errorMessages.powerRestrictionInvalidCombination' , {
117
+ powerRestrictionCode,
118
+ electrification,
119
+ } ) ,
120
+ } )
121
+ ) ;
122
+ }
123
+
124
+ return isInvalid ;
69
125
} ) ;
126
+ }
70
127
}
71
- } , [ rollingStockID ] ) ;
128
+ } , [ powerRestriction ] ) ;
72
129
73
- return powerRestrictions && powerRestrictions . length > 0 && pathFindingID ? (
130
+ return powerRestrictions . length > 1 && pathFindingID ? (
74
131
< div className = "osrd-config-item mb-2" >
75
132
< div className = "osrd-config-item-container" >
76
133
< img width = "32px" className = "mr-2" src = { icon } alt = "PowerRestrictionIcon" />
0 commit comments