adapt profiles to ctx-based parse fns

This commit is contained in:
Jannis R 2019-10-20 00:19:52 +02:00
parent 7b7293efea
commit 9fc6664302
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
13 changed files with 303 additions and 363 deletions

25
lib/profile-hooks.js Normal file
View file

@ -0,0 +1,25 @@
'use strict'
// For any type of "thing to parse", there's >=1 parse functions.
// By composing custom parse function(s) with the default ones, one
// can customize the behaviour of hafas-client. Profiles extensively
// use this mechanism.
// Each parse function has the following signature:
// ({opt, profile, common, res}, ...raw) => newParsed
// Compose a new/custom parse function with the old/existing parse
// function, so that the new fn will be called with the output of the
// old fn.
const parseHook = (oldParse, newParse) => {
return (ctx, ...args) => {
return newParse({
...ctx,
parsed: oldParse({...ctx, parsed: {}}, ...args)
}, ...args)
}
}
module.exports = {
parseHook
}

View file

@ -4,16 +4,17 @@ const shorten = require('vbb-short-station-name')
const {to12Digit, to9Digit} = require('vbb-translate-ids')
const parseLineName = require('vbb-parse-line')
const getStations = require('vbb-stations')
const {parseHook} = require('../../lib/profile-hooks')
const _createParseLine = require('../../parse/line')
const _parseLine = require('../../parse/line')
const _parseLocation = require('../../parse/location')
const _createParseDeparture = require('../../parse/departure')
const _createParseJourneyLeg = require('../../parse/journey-leg')
const _parseDeparture = require('../../parse/departure')
const _parseJourneyLeg = require('../../parse/journey-leg')
const _formatStation = require('../../format/station')
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {type: 'IPA', id: 'BVG', name: 'FahrInfo', v: '6020000'}
body.ext = 'BVG.1'
body.ver = '1.21'
@ -22,66 +23,51 @@ const transformReqBody = (body) => {
return body
}
const createParseLine = (profile, opt, data) => {
const parseLine = _createParseLine(profile, opt, data)
const parseLineWithMoreDetails = ({parsed}, p) => {
parsed.name = p.name.replace(/^(bus|tram)\s+/i, '')
const details = parseLineName(parsed.name)
parsed.symbol = details.symbol
parsed.nr = details.nr
parsed.metro = details.metro
parsed.express = details.express
parsed.night = details.night
const parseLineWithMoreDetails = (l) => {
const res = parseLine(l)
res.name = l.name.replace(/^(bus|tram)\s+/i, '')
const details = parseLineName(res.name)
res.symbol = details.symbol
res.nr = details.nr
res.metro = details.metro
res.express = details.express
res.night = details.night
return res
}
return parseLineWithMoreDetails
return parsed
}
const parseLocation = (profile, opt, data, l) => {
const res = _parseLocation(profile, opt, data, l)
if (res.type === 'stop' || res.type === 'station') {
res.name = shorten(res.name)
res.id = to12Digit(res.id)
if (!res.location.latitude || !res.location.longitude) {
const [s] = getStations(res.id)
if (s) Object.assign(res.location, s.location)
const parseLocation = ({parsed}, l) => {
if (parsed.type === 'stop' || parsed.type === 'station') {
parsed.name = shorten(parsed.name)
parsed.id = to12Digit(parsed.id)
if (!parsed.location.latitude || !parsed.location.longitude) {
const [s] = getStations(parsed.id)
if (s) Object.assign(parsed.location, s.location)
}
}
return res
return parsed
}
const createParseDeparture = (profile, opt, data) => {
const parseDeparture = _createParseDeparture(profile, opt, data)
const ringbahnClockwise = /^ringbahn s\s?41$/i
const ringbahnAnticlockwise = /^ringbahn s\s?42$/i
const parseDepartureRenameRingbahn = (j) => {
const res = parseDeparture(j)
if (res.line && res.line.product === 'suburban') {
const d = res.direction && res.direction.trim()
if (ringbahnClockwise.test(d)) res.direction = 'Ringbahn S41 ⟳'
else if (ringbahnAnticlockwise.test(d)) res.direction = 'Ringbahn S42 ⟲'
const ringbahnClockwise = /^ringbahn s\s?41$/i
const ringbahnAnticlockwise = /^ringbahn s\s?42$/i
const parseDepartureRenameRingbahn = ({parsed}) => {
if (parsed.line && parsed.line.product === 'suburban') {
const d = parsed.direction && parsed.direction.trim()
if (ringbahnClockwise.test(d)) {
parsed.direction = 'Ringbahn S41 ⟳'
} else if (ringbahnAnticlockwise.test(d)) {
parsed.direction = 'Ringbahn S42 ⟲'
}
return res
}
return parseDepartureRenameRingbahn
return parsed
}
const createParseJourneyLeg = (profile, opt, data) => {
const _parseJourneyLeg = _createParseJourneyLeg(profile, opt, data)
const parseJourneyLeg = (journey, leg, parseStopovers = true) => {
const parseJourneyLegWithBerlkönig = (ctx, leg, date) => {
if (leg.type === 'KISS') {
const icon = data.icons[leg.icoX]
const icon = ctx.common.icons[leg.icoX]
if (icon && icon.type === 'prod_berl') {
const res = _parseJourneyLeg(journey, {...leg, type: 'WALK'}, parseStopovers)
const res = _parseJourneyLeg(ctx, {
...leg, type: 'WALK'
}, date)
delete res.walking
const mcp = leg.dep.mcp || {}
@ -102,9 +88,7 @@ const createParseJourneyLeg = (profile, opt, data) => {
return res
}
}
return _parseJourneyLeg(journey, leg, parseStopovers)
}
return parseJourneyLeg
return _parseJourneyLeg(ctx, leg, date)
}
const validIBNR = /^\d+$/
@ -121,7 +105,7 @@ const formatStation = (id) => {
}
// use the Berlkönig ride sharing service?
const requestJourneysWithBerlkoenig = (query, opt) => {
const requestJourneysWithBerlkoenig = ({opt}, query) => {
if (('numF' in query) && opt.berlkoenig) {
// todo: check if this is still true
throw new Error('The `berlkoenig` and `results` options are mutually exclusive.')
@ -144,11 +128,11 @@ const bvgProfile = {
products,
parseStationName: shorten,
parseLocation,
parseLine: createParseLine,
parseDeparture: createParseDeparture,
parseJourneyLeg: createParseJourneyLeg,
parseLine: parseHook(_parseLine, parseLineWithMoreDetails),
parseLocation: parseHook(_parseLocation, parseLocation),
parseStationName: (ctx, name) => shorten(name),
parseDeparture: parseHook(_parseDeparture, parseDepartureRenameRingbahn),
parseJourneyLeg: parseJourneyLegWithBerlkönig,
formatStation,

View file

@ -2,7 +2,7 @@
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {
type: 'IPH',
id: 'HAFAS',

View file

@ -2,7 +2,7 @@
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {
type: 'IPH',
id: 'CMTA',

View file

@ -1,12 +1,13 @@
'use strict'
const trim = require('lodash/trim')
const {parseHook} = require('../../lib/profile-hooks')
const _createParseArrival = require('../../parse/arrival')
const _createParseDeparture = require('../../parse/departure')
const _createParseJourney = require('../../parse/journey')
const _createParseJourneyLeg = require('../../parse/journey-leg')
const _createParseLine = require('../../parse/line')
const _parseJourney = require('../../parse/journey')
const _parseJourneyLeg = require('../../parse/journey-leg')
const _parseLine = require('../../parse/line')
const _parseArrival = require('../../parse/arrival')
const _parseDeparture = require('../../parse/departure')
const _parseHint = require('../../parse/hint')
const _formatStation = require('../../format/station')
const {bike} = require('../../format/filters')
@ -14,7 +15,7 @@ const {bike} = require('../../format/filters')
const products = require('./products')
const formatLoyaltyCard = require('./loyalty-cards').format
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
const req = body.svcReqL[0] || {}
// see https://pastebin.com/qZ9WS3Cx
@ -41,24 +42,15 @@ const parseLoadFactor = (opt, tcocL, tcocX) => {
return load && loadFactors[load.r] || null
}
const createParseArrOrDep = (createParse) => (profile, opt, data) => {
const parse = createParse(profile, opt, data)
const parseWithLoadFactor = (d) => {
const result = parse(d)
const parseArrOrDepWithLoadFactor = ({parsed, res, opt}, d) => {
if (d.stbStop.dTrnCmpSX && Array.isArray(d.stbStop.dTrnCmpSX.tcocX)) {
const {tcocL} = data.common
const load = parseLoadFactor(opt, tcocL, d.stbStop.dTrnCmpSX.tcocX)
if (load) result.loadFactor = load
const load = parseLoadFactor(opt, res.common.tcocL || [], d.stbStop.dTrnCmpSX.tcocX)
if (load) parsed.loadFactor = load
}
return result
}
return parseWithLoadFactor
return parsed
}
const createParseArrival = createParseArrOrDep(_createParseArrival)
const createParseDeparture = createParseArrOrDep(_createParseDeparture)
const transformJourneysQuery = (query, opt) => {
const transformJourneysQuery = ({opt}, query) => {
const filters = query.jnyFltrL
if (opt.bike) filters.push(bike)
@ -76,31 +68,21 @@ const transformJourneysQuery = (query, opt) => {
return query
}
const createParseLine = (profile, opt, data) => {
const parseLine = _createParseLine(profile, opt, data)
const parseLineWithAdditionalName = (l) => {
const res = parseLine(l)
if (l.nameS && ['bus', 'tram', 'ferry'].includes(res.product)) {
res.name = l.nameS
const parseLineWithAdditionalName = ({parsed}, l) => {
if (l.nameS && ['bus', 'tram', 'ferry'].includes(l.product)) {
parsed.name = l.nameS
}
if (l.addName) {
res.additionalName = res.name
res.name = l.addName
parsed.additionalName = parsed.name
parsed.name = l.addName
}
return res
}
return parseLineWithAdditionalName
return parsed
}
const createParseJourney = (profile, opt, data) => {
const parseJourney = _createParseJourney(profile, opt, data)
// todo: j.sotRating, j.conSubscr, j.isSotCon, j.showARSLink, k.sotCtxt
// todo: j.conSubscr, j.showARSLink, j.useableTime
const parseJourneyWithPrice = (j) => {
const res = parseJourney(j)
res.price = null
// todo: sotRating, conSubscr, isSotCon, showARSLink, sotCtxt
// todo: conSubscr, showARSLink, useableTime
const parseJourneyWithPrice = ({parsed}, raw) => {
parsed.price = null
// todo: find cheapest, find discounts
// todo: write a parser like vbb-parse-ticket
// [ {
@ -112,15 +94,15 @@ const createParseJourney = (profile, opt, data) => {
// buttonText: 'To offer selection'
// } ]
if (
j.trfRes &&
Array.isArray(j.trfRes.fareSetL) &&
j.trfRes.fareSetL[0] &&
Array.isArray(j.trfRes.fareSetL[0].fareL) &&
j.trfRes.fareSetL[0].fareL[0]
raw.trfRes &&
Array.isArray(raw.trfRes.fareSetL) &&
raw.trfRes.fareSetL[0] &&
Array.isArray(raw.trfRes.fareSetL[0].fareL) &&
raw.trfRes.fareSetL[0].fareL[0]
) {
const tariff = j.trfRes.fareSetL[0].fareL[0]
const tariff = raw.trfRes.fareSetL[0].fareL[0]
if (tariff.prc >= 0) { // wat
res.price = {
parsed.price = {
amount: tariff.prc / 100,
currency: 'EUR',
hint: null
@ -128,24 +110,16 @@ const createParseJourney = (profile, opt, data) => {
}
}
return res
}
return parseJourneyWithPrice
return parsed
}
const createParseJourneyLeg = (profile, opt, data) => {
const parseJourneyLeg = _createParseJourneyLeg(profile, opt, data)
const parseJourneyLegWithLoadFactor = (j, pt, parseStopovers) => {
const result = parseJourneyLeg(j, pt, parseStopovers)
if (pt.jny && pt.jny.dTrnCmpSX && Array.isArray(pt.jny.dTrnCmpSX.tcocX)) {
const {tcocL} = data.common
const load = parseLoadFactor(opt, tcocL, pt.jny.dTrnCmpSX.tcocX)
if (load) result.loadFactor = load
const parseJourneyLegWithLoadFactor = ({parsed, res, opt}, raw) => {
const tcocX = raw.jny && raw.jny.dTrnCmpSX && raw.jny.dTrnCmpSX.tcocX
if (Array.isArray(tcocX) && Array.isArray(res.tcocL)) {
const load = parseLoadFactor(opt, res.tcocL, tcocX)
if (load) parsed.loadFactor = load
}
return result
}
return parseJourneyLegWithLoadFactor
return parsed
}
// todo:
@ -349,20 +323,20 @@ const codesByText = Object.assign(Object.create(null), {
'platform change': 'changed platform', // todo: use dash, German variant
})
const parseHint = (profile, h, icons) => {
if (h.type === 'A') {
const hint = hintsByCode[h.code && h.code.trim().toLowerCase()]
const parseHintByCode = ({parsed}, raw) => {
if (raw.type === 'A') {
const hint = hintsByCode[raw.code && raw.code.trim().toLowerCase()]
if (hint) {
return Object.assign({text: h.txtN}, hint)
return Object.assign({text: raw.txtN}, hint)
}
}
const res = _parseHint(profile, h, icons)
if (res && h.txtN) {
const text = trim(h.txtN.toLowerCase(), ' ()')
if (codesByText[text]) res.code = codesByText[text]
if (parsed && raw.txtN) {
const text = trim(raw.txtN.toLowerCase(), ' ()')
if (codesByText[text]) parsed.code = codesByText[text]
}
return res
return parsed
}
const isIBNR = /^\d{6,}$/
@ -387,12 +361,12 @@ const dbProfile = {
products: products,
// todo: parseLocation
parseJourney: createParseJourney,
parseJourneyLeg: createParseJourneyLeg,
parseLine: createParseLine,
parseArrival: createParseArrival,
parseDeparture: createParseDeparture,
parseHint,
parseJourney: parseHook(_parseJourney, parseJourneyWithPrice),
parseJourneyLeg: parseHook(_parseJourneyLeg, parseJourneyLegWithLoadFactor),
parseLine: parseHook(_parseLine, parseLineWithAdditionalName),
parseArrival: parseHook(_parseArrival, parseArrOrDepWithLoadFactor),
parseDeparture: parseHook(_parseDeparture, parseArrOrDepWithLoadFactor),
parseHint: parseHook(_parseHint, parseHintByCode),
formatStation,

View file

@ -2,7 +2,7 @@
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {type: 'AND', id: 'HVV', name: 'HVVPROD_ADHOC', v: '4020100'}
body.ext = 'HVV.1'
body.ver = '1.16'

View file

@ -2,7 +2,7 @@
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {
type: 'IPH',
id: 'NASA',

View file

@ -1,14 +1,15 @@
'use strict'
const _parseLocation = require('../../parse/location')
const _createParseJourney = require('../../parse/journey')
const _createParseMovement = require('../../parse/movement')
const {parseHook} = require('../../lib/profile-hooks')
const _parseLocation = require('../../parse/location')
const _parseJourney = require('../../parse/journey')
const _parseMovement = require('../../parse/movement')
const products = require('./products')
// todo: journey prices
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {
id: 'NAHSH',
name: 'NAHSHPROD',
@ -21,33 +22,27 @@ const transformReqBody = (body) => {
return body
}
const parseLocation = (profile, opt, data, l) => {
const res = _parseLocation(profile, opt, data, l)
const fixLocation = ({parsed}, l) => {
// weird fix for empty lines, e.g. IC/EC at Flensburg Hbf
if (res.lines) {
res.lines = res.lines.filter(x => x.id && x.name)
if (parsed.lines) {
parsed.lines = parsed.lines.filter(x => x.id && x.name)
}
// remove leading zeroes, todo
if (res.id && res.id.length > 0) {
res.id = res.id.replace(/^0+/, '')
if (parsed.id && parsed.id.length > 0) {
parsed.id = parsed.id.replace(/^0+/, '')
}
return res
return parsed
}
const createParseJourney = (profile, opt, data) => {
const parseJourney = _createParseJourney(profile, opt, data)
const parseJourneyWithTickets = (j) => {
const res = parseJourney(j)
const parseJourneyWithTickets = ({parsed}, j) => {
if (
j.trfRes &&
Array.isArray(j.trfRes.fareSetL) &&
j.trfRes.fareSetL.length > 0
) {
res.tickets = []
parsed.tickets = []
for (let t of j.trfRes.fareSetL) {
const tariff = t.desc
@ -67,28 +62,20 @@ const createParseJourney = (profile, opt, data) => {
ticket.amount = null
ticket.hint = 'No pricing information available.'
}
res.tickets.push(ticket)
parsed.tickets.push(ticket)
}
}
}
return res
}
return parseJourneyWithTickets
return parsed
}
const createParseMovement = (profile, opt, data) => {
const _parseMovement = _createParseMovement(profile, opt, data)
const parseMovement = (m) => {
const res = _parseMovement(m)
const fixMovement = ({parsed}, m) => {
// filter out empty nextStopovers entries
res.nextStopovers = res.nextStopovers.filter((f) => {
parsed.nextStopovers = parsed.nextStopovers.filter((f) => {
return f.stop !== null || f.arrival !== null || f.departure !== null
})
return res
}
return parseMovement
return parsed
}
const nahshProfile = {
@ -99,9 +86,9 @@ const nahshProfile = {
products,
parseLocation,
parseJourney: createParseJourney,
parseMovement: createParseMovement,
parseLocation: parseHook(_parseLocation, fixLocation),
parseJourney: parseHook(_parseJourney, parseJourneyWithTickets),
parseMovement: parseHook(_parseMovement, fixMovement),
trip: true,
radar: true, // todo: see #34

View file

@ -2,7 +2,7 @@
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {
type: 'IPH',
id: 'NVV',

View file

@ -3,12 +3,13 @@
// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L5
// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L47-L234
const _parseLocation = require('../../parse/location')
const _createParseMovement = require('../../parse/movement')
const {parseHook} = require('../../lib/profile-hooks')
const _parseLocation = require('../../parse/location')
const _parseMovement = require('../../parse/movement')
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
// todo: necessary headers?
body.client = {
type: 'IPA',
@ -25,33 +26,29 @@ const transformReqBody = (body) => {
return body
}
const parseLocation = (profile, opt, data, l) => {
// ÖBB has some 'stations' **in austria** with no departures/products,
// like station entrances, that are actually POIs.
const res = _parseLocation(profile, opt, data, l)
// ÖBB has some 'stations' **in austria** with no departures/products,
// like station entrances, that are actually POIs.
const fixWeirdPOIs = ({parsed}) => {
if (
(res.type === 'station' || res.type === 'stop') &&
!res.products &&
res.name &&
res.id && res.id.length !== 7
(parsed.type === 'station' || parsed.type === 'stop') &&
!parsed.products &&
parsed.name &&
parsed.id && parsed.id.length !== 7
) {
return Object.assign({
type: 'location',
id: res.id,
id: parsed.id,
poi: true,
name: res.name
}, res.location)
name: parsed.name
}, parsed.location)
}
return res
return parsed
}
const createParseMovement = (profile, opt, data) => {
const _parseMovement = _createParseMovement(profile, opt, data)
const parseMovement = (m) => {
const res = _parseMovement(m)
const fixMovement = ({parsed}, m) => {
// filter out POIs
// todo: make use of them, as some of them specify fare zones
res.nextStopovers = res.nextStopovers.filter(st => {
parsed.nextStopovers = parsed.nextStopovers.filter(st => {
const s = st.stop || {}
if (s.station) {
s = s.station
@ -59,12 +56,10 @@ const createParseMovement = (profile, opt, data) => {
}
return s.type === 'stop' || s.type === 'station'
})
res.frames = res.frames.filter((f) => {
parsed.frames = parsed.frames.filter((f) => {
return f.origin.type !== 'location' && f.destination.type !== 'location'
})
return res
}
return parseMovement
return parsed
}
const oebbProfile = {
@ -76,8 +71,8 @@ const oebbProfile = {
products: products,
parseLocation,
parseMovement: createParseMovement,
parseLocation: parseHook(_parseLocation, fixWeirdPOIs),
parseMovement: parseHook(_parseMovement, fixMovement),
journeysNumF: false,
trip: true,

View file

@ -1,9 +1,11 @@
'use strict'
const _createParseMovement = require('../../parse/movement')
const {parseHook} = require('../../lib/profile-hooks')
const _parseMovement = require('../../parse/movement')
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {
type: 'AND',
id: 'ZPS-SAAR',
@ -18,15 +20,10 @@ const transformReqBody = (body) => {
return body
}
const createParseMovement = (profile, opt, data) => {
const _parseMovement = _createParseMovement(profile, opt, data)
const parseMovement = (m) => {
const res = _parseMovement(m)
const fixMovement = ({parsed}, m) => {
// filter out empty stopovers
res.nextStopovers = res.nextStopovers.filter(st => !!st.stop)
return res
}
return parseMovement
parsed.nextStopovers = parsed.nextStopovers.filter(st => !!st.stop)
return parsed
}
const saarfahrplanProfile = {
@ -41,7 +38,7 @@ const saarfahrplanProfile = {
products: products,
parseMovement: createParseMovement,
parseMovement: parseHook(_parseMovement, fixMovement),
departuresGetPasslist: false,
departuresStbFltrEquiv: false,

View file

@ -2,7 +2,7 @@
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {type: 'IPH', id: 'DB-REGIO-MVV', name: 'MuenchenNavigator', v: '5010100'}
body.ext = 'DB.R15.12.a'
body.ver = '1.18'

View file

@ -5,16 +5,17 @@ const {to12Digit, to9Digit} = require('vbb-translate-ids')
const parseLineName = require('vbb-parse-line')
const parseTicket = require('vbb-parse-ticket')
const getStations = require('vbb-stations')
const {parseHook} = require('../../lib/profile-hooks')
const _createParseLine = require('../../parse/line')
const _parseLine = require('../../parse/line')
const _parseLocation = require('../../parse/location')
const _createParseJourney = require('../../parse/journey')
const _createParseDeparture = require('../../parse/departure')
const _parseJourney = require('../../parse/journey')
const _parseDeparture = require('../../parse/departure')
const _formatStation = require('../../format/station')
const products = require('./products')
const transformReqBody = (body) => {
const transformReqBody = (ctx, body) => {
body.client = {type: 'IPA', id: 'VBB', name: 'vbbPROD', v: '4010300'}
body.ext = 'VBB.1'
body.ver = '1.16'
@ -23,87 +24,64 @@ const transformReqBody = (body) => {
return body
}
const createParseLine = (profile, opt, data) => {
const parseLine = _createParseLine(profile, opt, data)
const parseLineWithMoreDetails = ({parsed}, p) => {
parsed.name = p.name.replace(/^(bus|tram)\s+/i, '')
const details = parseLineName(parsed.name)
parsed.symbol = details.symbol
parsed.nr = details.nr
parsed.metro = details.metro
parsed.express = details.express
parsed.night = details.night
const parseLineWithMoreDetails = (l) => {
const res = parseLine(l)
res.name = l.name.replace(/^(bus|tram)\s+/i, '')
const details = parseLineName(res.name)
res.symbol = details.symbol
res.nr = details.nr
res.metro = details.metro
res.express = details.express
res.night = details.night
return res
}
return parseLineWithMoreDetails
return parsed
}
const parseLocation = (profile, opt, data, l) => {
const res = _parseLocation(profile, opt, data, l)
if (res.type === 'stop' || res.type === 'station') {
res.name = shorten(res.name)
res.id = to12Digit(res.id)
if (!res.location.latitude || !res.location.longitude) {
const [s] = getStations(res.id)
if (s) Object.assign(res.location, s.location)
const parseLocation = ({parsed}, l) => {
if (parsed.type === 'stop' || parsed.type === 'station') {
parsed.name = shorten(parsed.name)
parsed.id = to12Digit(parsed.id)
if (!parsed.location.latitude || !parsed.location.longitude) {
const [s] = getStations(parsed.id)
if (s) Object.assign(parsed.location, s.location)
}
}
return res
return parsed
}
const createParseJourney = (profile, opt, data) => {
const parseJourney = _createParseJourney(profile, opt, data)
const parseJourneyWithTickets = (j) => {
const res = parseJourney(j)
const parseJourneyWithTickets = ({parsed}, j) => {
if (
j.trfRes &&
Array.isArray(j.trfRes.fareSetL) &&
j.trfRes.fareSetL[0] &&
Array.isArray(j.trfRes.fareSetL[0].fareL)
) {
res.tickets = []
parsed.tickets = []
const sets = j.trfRes.fareSetL[0].fareL
for (let s of sets) {
if (!Array.isArray(s.ticketL) || s.ticketL.length === 0) continue
for (let t of s.ticketL) {
const ticket = parseTicket(t)
ticket.name = s.name + ' ' + ticket.name
res.tickets.push(ticket)
parsed.tickets.push(ticket)
}
}
}
return res
}
return parseJourneyWithTickets
return parsed
}
const createParseDeparture = (profile, opt, data) => {
const parseDeparture = _createParseDeparture(profile, opt, data)
const ringbahnClockwise = /^ringbahn s\s?41$/i
const ringbahnAnticlockwise = /^ringbahn s\s?42$/i
const parseDepartureRenameRingbahn = (j) => {
const res = parseDeparture(j)
if (res.line && res.line.product === 'suburban') {
const d = res.direction && res.direction.trim()
if (ringbahnClockwise.test(d)) res.direction = 'Ringbahn S41 ⟳'
else if (ringbahnAnticlockwise.test(d)) res.direction = 'Ringbahn S42 ⟲'
const ringbahnClockwise = /^ringbahn s\s?41$/i
const ringbahnAnticlockwise = /^ringbahn s\s?42$/i
const parseDepartureRenameRingbahn = ({parsed}) => {
if (parsed.line && parsed.line.product === 'suburban') {
const d = parsed.direction && parsed.direction.trim()
if (ringbahnClockwise.test(d)) {
parsed.direction = 'Ringbahn S41 ⟳'
} else if (ringbahnAnticlockwise.test(d)) {
parsed.direction = 'Ringbahn S42 ⟲'
}
return res
}
return parseDepartureRenameRingbahn
return parsed
}
const validIBNR = /^\d+$/
@ -133,11 +111,11 @@ const vbbProfile = {
products: products,
parseStationName: shorten,
parseLocation,
parseLine: createParseLine,
parseJourney: createParseJourney,
parseDeparture: createParseDeparture,
parseLine: parseHook(_parseLine, parseLineWithMoreDetails),
parseLocation: parseHook(_parseLocation, parseLocation),
parseStationName: (ctx, name) => shorten(name),
parseJourney: parseHook(_parseJourney, parseJourneyWithTickets),
parseDeparture: parseHook(_parseDeparture, parseDepartureRenameRingbahn),
formatStation,