22
33import React , { Component } from 'react'
44import moment from 'moment'
5- import intersection from 'lodash/intersection'
65
76import Loading from '../../../common/components/Loading'
87import toSentenceCase from '../../../common/util/to-sentence-case'
@@ -15,46 +14,47 @@ type Props = {
1514}
1615
1716const maxDaysToShow = 500
17+ const orderedPossibleModes = [ 'other' , 'metro' , 'rail' , 'tram' , 'bus' ]
1818
1919export default class ServicePerModeChart extends Component < Props > {
20- _getData = ( validationResult : ValidationResult ) => {
20+ _getData = ( validationResult : ValidationResult ) : {
21+ data : Array < {
22+ bus : number ,
23+ date : moment ,
24+ metro : number ,
25+ other : number ,
26+ rail : number ,
27+ total : number ,
28+ tram : number
29+ } > ,
30+ modes : Array < string >
31+ } => {
2132 const { dailyBusSeconds, dailyTramSeconds, dailyMetroSeconds, dailyRailSeconds, dailyTotalSeconds, firstCalendarDate} = validationResult
2233 const firstDate = moment ( firstCalendarDate )
23- const hasBus = dailyBusSeconds . filter ( s => s > 0 ) . length > 0
24- const hasTram = dailyTramSeconds . filter ( s => s > 0 ) . length > 0
25- const hasMetro = dailyMetroSeconds . filter ( s => s > 0 ) . length > 0
26- const hasRail = dailyRailSeconds . filter ( s => s > 0 ) . length > 0
27- let hasOther = false
2834 const data = [ ]
35+ const modes = { }
2936 const limit = Math . min ( dailyTotalSeconds . length , maxDaysToShow )
3037 for ( let i = 0 ; i < limit ; i ++ ) {
3138 const column = { }
3239 column . date = firstDate . clone ( ) . add ( i , 'days' )
33- let other = dailyTotalSeconds [ i ]
3440 column . total = this . _secondsToHours ( dailyTotalSeconds [ i ] ) // total
35- if ( hasBus ) {
36- column . bus = this . _secondsToHours ( dailyBusSeconds [ i ] ) // bus
37- other -= dailyBusSeconds [ i ]
38- }
39- if ( hasMetro ) {
40- column . metro = this . _secondsToHours ( dailyMetroSeconds [ i ] ) // metro
41- other -= dailyMetroSeconds [ i ]
42- }
43- if ( hasRail ) {
44- column . rail = this . _secondsToHours ( dailyRailSeconds [ i ] ) // rail
45- other -= dailyRailSeconds [ i ]
46- }
47- if ( hasTram ) {
48- column . tram = this . _secondsToHours ( dailyTramSeconds [ i ] ) // tram
49- other -= dailyTramSeconds [ i ]
50- }
51- if ( other || hasOther ) {
52- column . other = this . _secondsToHours ( other )
53- hasOther = true
54- }
41+ column . bus = this . _secondsToHours ( dailyBusSeconds [ i ] ) // bus
42+ column . metro = this . _secondsToHours ( dailyMetroSeconds [ i ] ) // metro
43+ column . rail = this . _secondsToHours ( dailyRailSeconds [ i ] ) // rail
44+ column . tram = this . _secondsToHours ( dailyTramSeconds [ i ] ) // tram
45+ column . other = column . total -
46+ column . bus -
47+ column . metro -
48+ column . rail -
49+ column . tram
50+ orderedPossibleModes . forEach ( mode => {
51+ if ( column [ mode ] > 0 ) {
52+ modes [ mode ] = true
53+ }
54+ } )
5555 data . push ( column )
5656 }
57- return data
57+ return { data, modes : Object . keys ( modes ) }
5858 }
5959
6060 _secondsToHours = ( seconds : number ) => Math . floor ( seconds / 60 / 60 * 100 ) / 100
@@ -64,13 +64,10 @@ export default class ServicePerModeChart extends Component<Props> {
6464 if ( ! validationResult || ! validationResult . dailyTripCounts ) {
6565 return < Loading />
6666 }
67- const data = this . _getData ( validationResult )
67+ const { data, modes } = this . _getData ( validationResult )
68+ const orderedModes = orderedPossibleModes
69+ . filter ( mode => modes . indexOf ( mode ) > - 1 )
6870 if ( data . length === 0 ) return < p > No service found < / p >
69- // Get list of modes found in GTFS
70- const modes = intersection (
71- [ 'other' , 'metro' , 'rail' , 'tram' , 'bus' ] ,
72- Object . keys ( data [ 0 ] )
73- )
7471 const graphHeight = 300
7572 const spacing = 8
7673 const leftMargin = 50
@@ -126,7 +123,7 @@ export default class ServicePerModeChart extends Component<Props> {
126123 // generate the stacked bar for this date
127124 return (
128125 < g key = { index } >
129- { modes . map ( ( k , i ) => {
126+ { orderedModes . map ( ( k , i ) => {
130127 const top = previousY
131128 const bottom = previousY + d [ k ] * yScaleFactor
132129 const g = d [ k ]
@@ -165,21 +162,21 @@ export default class ServicePerModeChart extends Component<Props> {
165162 stroke = 'black'
166163 strokeWidth = { 2 } />
167164 { /* Add legend for bar colors */ }
168- { modes . reverse ( ) . map ( ( mode , i ) => (
165+ { orderedModes . reverse ( ) . map ( ( mode , i ) => (
169166 < g key = { mode } >
170167 < rect
171168 x = { 100 * i - 5 }
172169 y = { graphHeight + 30 }
173170 width = '80'
174171 height = '18'
175- fill = { colors [ modes . length - i - 1 ] } />
172+ fill = { colors [ orderedModes . length - i - 1 ] } />
176173 < text x = { 100 * i } y = { graphHeight + 43 } fill = 'black' >
177174 { toSentenceCase ( mode ) }
178175 </ text >
179176 </ g >
180177 ) ) }
181178 { curtailed &&
182- < text x = { 100 * modes . length } y = { graphHeight + 43 } >
179+ < text x = { 100 * orderedModes . length } y = { graphHeight + 43 } >
183180 * only first 500 days of service shown
184181 </ text >
185182 }
0 commit comments