Skip to content

Commit

Permalink
feat(NormalizeStopTimesModal): add stop time normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
philip-cline committed Nov 5, 2023
1 parent 1295be7 commit f044955
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
12 changes: 6 additions & 6 deletions lib/editor/actions/tripPattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ import {createAction, type ActionType} from 'redux-actions'
import {ActionCreators} from 'redux-undo'
import {toast} from 'react-toastify'

import {resetActiveGtfsEntity, savedGtfsEntity, updateActiveGtfsEntity, updateEditSetting} from './active'
import {createVoidPayloadAction, fetchGraphQL, secureFetch} from '../../common/actions'
import {snakeCaseKeys} from '../../common/util/map-keys'
import {generateUID} from '../../common/util/util'
import {showEditorModal} from './editor'
import {shapes} from '../../gtfs/util/graphql'
import {fetchGTFSEntities, receiveGTFSEntities} from '../../manager/actions/versions'
import {fetchTripCounts} from './trip'
import {getEditorNamespace} from '../util/gtfs'
import {resequenceStops, resequenceShapePoints} from '../util/map'
import {entityIsNew} from '../util/objects'

import type {ControlPoint, Pattern, PatternStop} from '../../types'
import type {dispatchFn, getStateFn} from '../../types/reducers'

import {fetchTripCounts} from './trip'
import {showEditorModal} from './editor'
import {resetActiveGtfsEntity, savedGtfsEntity, updateActiveGtfsEntity, updateEditSetting} from './active'

const fetchingTripPatterns = createVoidPayloadAction('FETCHING_TRIP_PATTERNS')
const savedTripPattern = createVoidPayloadAction('SAVED_TRIP_PATTERN')
export const setActivePatternSegment = createAction(
Expand Down Expand Up @@ -51,12 +51,12 @@ export type EditorTripPatternActions = ActionType<typeof normalizeStopTimes> |
* provides a way to bulk update existing trips when pattern stops are modified
* (e.g., a pattern stop is inserted, removed, or its travel times modified).
*/
export function normalizeStopTimes (patternId: number, beginStopSequence: number) {
export function normalizeStopTimes (patternId: number, beginStopSequence: number, interpolateStopTimes: boolean) {
return function (dispatch: dispatchFn, getState: getStateFn) {
const {data} = getState().editor
const {feedSourceId} = data.active
const sessionId = data.lock.sessionId || ''
const url = `/api/editor/secure/pattern/${patternId}/stop_times?feedId=${feedSourceId || ''}&sessionId=${sessionId}&stopSequence=${beginStopSequence}`
const url = `/api/editor/secure/pattern/${patternId}/stop_times?feedId=${feedSourceId || ''}&sessionId=${sessionId}&stopSequence=${beginStopSequence}&interpolateStopTimes=${interpolateStopTimes.toString()}`
return dispatch(secureFetch(url, 'put'))
.then(res => res.json())
.then(json => toast.info(`ⓘ ${json.updateResult}`, {
Expand Down
23 changes: 20 additions & 3 deletions lib/editor/components/pattern/NormalizeStopTimesModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Icon from '@conveyal/woonerf/components/icon'
import React, { Component } from 'react'
import { Alert, Button, ControlLabel, FormControl, Modal } from 'react-bootstrap'
import { Alert, Button, Checkbox, ControlLabel, FormControl, Modal } from 'react-bootstrap'

import * as tripPatternActions from '../../actions/tripPattern'
import type { GtfsStop, Pattern } from '../../../types'
Expand All @@ -15,17 +15,18 @@ type Props = {
stops: Array<GtfsStop>
}

type State = { patternStopIndex: number, show: boolean }
type State = { interpolateStopTimes: boolean, patternStopIndex: number, show: boolean }

export default class NormalizeStopTimesModal extends Component<Props, State> {
state = {
interpolateStopTimes: false,
patternStopIndex: 0, // default to zeroth pattern stop
show: false
}

_onClickNormalize = () => {
const { activePattern, normalizeStopTimes } = this.props
normalizeStopTimes(activePattern.id, this.state.patternStopIndex)
normalizeStopTimes(activePattern.id, this.state.patternStopIndex, this.state.interpolateStopTimes)
}

_onChangeStop = (evt: SyntheticInputEvent<HTMLInputElement>) => {
Expand All @@ -37,6 +38,10 @@ export default class NormalizeStopTimesModal extends Component<Props, State> {
this.props.onClose()
}

_onChangeInterpolation = () => {
this.setState({interpolateStopTimes: !this.state.interpolateStopTimes})
}

render () {
const { Body, Footer, Header, Title } = Modal
const { activePattern, stops } = this.props
Expand Down Expand Up @@ -69,6 +74,12 @@ export default class NormalizeStopTimesModal extends Component<Props, State> {
}
)}
</FormControl>
<Checkbox
onChange={this._onChangeInterpolation}
value={this.state.interpolateStopTimes}
>
Interpolate stop times between timepoints?
</Checkbox>
<br />
<Alert bsStyle='warning'>
{this.state.patternStopIndex === 0
Expand Down Expand Up @@ -96,6 +107,12 @@ export default class NormalizeStopTimesModal extends Component<Props, State> {
you can normalize the stop times to bring them into alignment with the
updated travel times reflected in the pattern stops.
<hr />
Interpolating stop times calculates the implicit speed between timepoints
based on the shape distance and the default travel times. This speed is
then applied to the shape distance traveled for each intermediate non-timepoint
stop to provide interpolated travel times. The default travel time for non-timepoint
stops will not be modified.
<hr />
<strong>Note:</strong> this does not account for any variation
in travel time between stops for trips throughout the day (e.g.,
due to slower travel speeds during the AM peak). It overwrites ALL
Expand Down

0 comments on commit f044955

Please sign in to comment.