diff --git a/lib/journeys.js b/lib/journeys.js index b5b18e9..f5abac6 100644 --- a/lib/journeys.js +++ b/lib/journeys.js @@ -15,17 +15,10 @@ const { parseDateTime: formatOutputDate, normalizeEmpty: m, parseSparseStation: createStation, + parseOperator: createOperator, } = require('./util') const fetch = require('./fetch') -const createOperator = (o) => ({ - type: 'operator', - id: o.key, - name: o.label, - url: o.url, - address: o.address -}) - const extractLegs = (rawOrigin, rawDestination, rawJourney) => { let { departure, diff --git a/lib/regions.js b/lib/regions.js index e75198e..5dba850 100644 --- a/lib/regions.js +++ b/lib/regions.js @@ -5,13 +5,12 @@ const merge = require('lodash/merge') const intoStream = require('into-stream').object const { normalizeEmpty: m, + parseCountry: formatCountry, } = require('./util') const defaults = { } -const formatCountry = (country) => (country ? { name: m(country.name), code: m(country.alpha2_code) } : null) - const createRegion = (city) => ({ type: 'region', id: city.id + '', diff --git a/lib/stations.js b/lib/stations.js index a44c619..aa189cf 100644 --- a/lib/stations.js +++ b/lib/stations.js @@ -7,22 +7,16 @@ const intoStream = require('into-stream').object const { normalizeEmpty: m, parseStation, + parseCountry: formatCountry, } = require('./util') const defaults = { } -const formatCountry = (country) => (country ? { name: m(country.name), code: m(country.alpha2_code) } : null) - const createStation = (station) => { const res = parseStation(station) return { - ...res, - location: { - ...res.location, - country: formatCountry(station.country), - zip: station.zip, - }, + ...parseStation(station), slug: m(station.slugs), aliases: (station.aliases ? csv(station.aliases) : null), regions: [m(station.city_id + '')].filter((x) => !!x), diff --git a/lib/timetable.js b/lib/timetable.js index eb4579e..3b86c26 100644 --- a/lib/timetable.js +++ b/lib/timetable.js @@ -1,17 +1,28 @@ 'use strict' const { - parseDateTime, + parseWhen, parseStation, normalizeEmpty, } = require('./util') const fetch = require('./fetch') const parseArrivalDeparture = (dep, station) => { + const cancelled = dep.is_cancelled === true + const { + when, + plannedWhen, + prognosedWhen, + delay, + } = parseWhen({ + planned: 'datetime', + // @todo does this route provide realtime data? + }, dep, cancelled) + return { tripId: dep.trip_uid, // @todo: `dep.ride_id`? - when: parseDateTime(dep.datetime), - cancelled: dep.is_cancelled === true, + when, plannedWhen, prognosedWhen, delay, + cancelled, direction: dep.direction, lineName: dep.line_code, stop: station, diff --git a/lib/util.js b/lib/util.js index 5df79c7..dc3990d 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,6 +1,7 @@ 'use strict' const moment = require('moment-timezone') +const slug = require('slugg') const formatDateTime = (date) => { return moment(date).tz('Europe/Berlin').format('DD.MM.YYYY') @@ -20,6 +21,14 @@ const parseSparseStation = (s) => ({ name: normalizeEmpty(s.name), }) +const parseCountry = (country) => { + if (!country) return null + return { + name: normalizeEmpty(country.name), + code: normalizeEmpty(country.alpha2_code), + } +} + const parseStation = (s) => ({ ...parseSparseStation(s), location: { @@ -28,14 +37,55 @@ const parseStation = (s) => ({ latitude: normalizeEmpty(s.coordinates.latitude), address: normalizeEmpty(s.full_address), street: normalizeEmpty(s.address), + zip: normalizeEmpty(s.zip), + country: parseCountry(s.country), + notes: normalizeEmpty(s.warnings), }, importance: Number.isInteger(s.importance_order) ? normalizeEmpty(+s.importance_order) : null, }) +const parseOperator = (o) => ({ + type: 'operator', + id: o.key ? o.key : (o.label ? slug(o.label) : null), + name: o.label, + url: normalizeEmpty(o.url), + address: normalizeEmpty(o.address), +}) + +const parseWhen = (keys, data, cancelled = false) => { + let plannedWhen = keys.planned && data[keys.planned] || null + if (plannedWhen) { + plannedWhen = parseDateTime(plannedWhen) + } + let prognosedWhen = keys.prognosed && data[keys.prognosed] || null + if (prognosedWhen && prognosedWhen.eta) { + prognosedWhen = parseDateTime(prognosedWhen.eta) + } + const delay = plannedWhen && prognosedWhen + ? Math.round((new Date(prognosedWhen) - new Date(plannedWhen)) / 1000) + : null + + if (cancelled) { + return { + when: null, + plannedWhen, + prognosedWhen, + delay, + } + } + return { + when: prognosedWhen || plannedWhen, + plannedWhen, + delay, + } +} + module.exports = { formatDateTime, parseDateTime, normalizeEmpty, parseSparseStation, parseStation, + parseOperator, + parseWhen, }