import * as _ from 'underscore' ; import { LatLng , LegMode , ProfileOption , StreetEdgeInfo , TransitEdgeInfo , TransitModes , ZonedDateTime , } from '../../common/r5-types' ; import { Route , Step , SummaryStep } from '../route' ; import { Feature } from '../../../utils' ; export const SECONDS_PER_HOUR = 3600 ; export const SECONDS_PER_MINUTE = 60 ; /** High-level summary of the route, e.g. Walk -> Bus -> Walk */ interface SummarizedRoute { features : Feature [ ] ; steps : Step [ ] ; summary : SummaryStep [ ] ; } export function dateTimeToSeconds ( dateTime ) { return dateTime . hour * SECONDS_PER_HOUR + dateTime . minute * SECONDS_PER_MINUTE + dateTime . second ; } export function profileOptionToRoute ( origin , destination , option ) { const { features , steps , summary } = summarizeOption ( option ) ; const itinerary = _ . min ( option . itinerary , it => it . duration ) ; const departureSecs = dateTimeToSeconds ( itinerary . startTime ) ; const arriveTimeSecs = dateTimeToSeconds ( itinerary . endTime ) ; const travelTimeSecs = itinerary . duration ; const distanceKm = ( itinerary . distance + itinerary . transitDistance ) / 1000 / 1000 ; return { origin : { id : 'origin' , latitude : origin . lat , longitude : origin . lng , } , destination : { id : 'destination' , latitude : destination . lat , longitude : destination . lng , } , departureSecs , arriveTimeSecs , travelTimeSecs , distanceKm , steps , summary , geojson : { type : 'FeatureCollection' , features , } , } ; } function summarizeOption ( option ) { const makeLegSummary = ( leg ) => _ . pick ( leg , 'mode' , 'distance' , 'duration' ) ; const fastestAccess = _ . min ( option . access , acc => acc . duration ) ; const { streetEdges } = fastestAccess ; const features = streetEdges . map ( featureFromStreetEdgeInfo ) ; const steps = streetEdges . map ( stepFromStreetEdgeInfo ) ; const summary = [ ] ; summary . push ( makeLegSummary ( fastestAccess ) ) ; if ( option . transit ) { for ( const s of option . transit ) { const startTimeSecs = dateTimeToSeconds ( s . transitEdges [ 0 ] . fromDepartureTime [ 0 ] ) ; for ( const e of s . transitEdges ) { features . push ( featureFromTransitEdgeInfo ( e , s . mode ) ) ; steps . push ( stepFromTransitEdgeInfo ( e , s . mode ) ) ; } const { shortName , longName , agencyName } = s . routes [ 0 ] ; summary . push ( { mode : s . mode , shortName , longName , agencyName , startTimeSecs } ) ; const { middle } = s ; if ( middle ) { summary . push ( makeLegSummary ( middle ) ) ; for ( const m of s . middle . streetEdges ) { features . push ( featureFromStreetEdgeInfo ( m ) ) ; steps . push ( stepFromStreetEdgeInfo ( m ) ) ; } } } const fastestEgress = _ . min ( option . egress , eg => eg . duration ) ; for ( const e of fastestEgress . streetEdges ) { features . push ( featureFromStreetEdgeInfo ( e ) ) ; steps . push ( stepFromStreetEdgeInfo ( e ) ) ; } summary . push ( makeLegSummary ( fastestEgress ) ) ; } return { features , steps , summary } ; } function featureFromStreetEdgeInfo ( e ) { return { geometry : e . geometry , type : 'Feature' , properties : { mode : e . mode , streetName : e . streetName , distanceKm : e . distanceMm / 1000 / 1000 , edgeId : e . edgeId , stroke : modeToLineStyle ( e . mode ) , } , } ; } function featureFromTransitEdgeInfo ( e , mode ) { return { geometry : e . geometry , type : 'Feature' , properties : { mode , fromStopID : e . fromStopID , toStopID : e . toStopID , edgeId : e . id , routeId : e . routeID , stroke : e . routeColor && e . routeColor . match ( /^[a-f0-9]{6}/i ) ? '#' + e . routeColor : '#000077' , tripId : e . routeID , } , } ; } function stepFromStreetEdgeInfo ( e ) { const startPoint = e . geometry . coordinates [ 0 ] ; const endPoint = e . geometry . coordinates [ 1 ] ; return { from : { id : 'origin' , latitude : startPoint [ 1 ] , longitude : startPoint [ 0 ] , } , to : { id : 'destination' , latitude : endPoint [ 1 ] , longitude : endPoint [ 0 ] , } , mode : e . mode , departTimeSecs : 0 , arriveTimeSecs : 0 , travelTimeSecs : 0 , description : e . absoluteDirection + ' on ' + e . streetName , distanceKm : e . distanceMm / 1000 / 1000 , } ; } function stepFromTransitEdgeInfo ( e , mode ) { const startPoint = e . geometry . coordinates [ 0 ] ; const endPoint = e . geometry . coordinates [ 1 ] ; return { from : { id : 'origin' , latitude : startPoint [ 1 ] , longitude : startPoint [ 0 ] , } , to : { id : 'destination' , latitude : endPoint [ 1 ] , longitude : endPoint [ 0 ] , } , mode , departTimeSecs : 0 , arriveTimeSecs : 0 , travelTimeSecs : 0 , description : '' , routeId : e . routeID , } ; } function modeToLineStyle ( mode ) { switch ( mode ) { case LegMode . BICYCLE : return '#0000ff' ; case LegMode . BICYCLE_RENT : return '#800080' ; case LegMode . CAR : return '#ff0000' ; case LegMode . WALK : default : return '#00ff00' ; } }