mirror of
https://github.com/public-transport/db-vendo-client.git
synced 2025-02-23 15:19:35 +02:00
adapt profiles to ctx-based parse fns
This commit is contained in:
parent
7b7293efea
commit
9fc6664302
13 changed files with 303 additions and 363 deletions
25
lib/profile-hooks.js
Normal file
25
lib/profile-hooks.js
Normal 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
|
||||||
|
}
|
104
p/bvg/index.js
104
p/bvg/index.js
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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',
|
||||||
|
|
128
p/db/index.js
128
p/db/index.js
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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'
|
||||||
|
|
100
p/vbb/index.js
100
p/vbb/index.js
|
@ -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,
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue