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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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