pass in parsers

This commit is contained in:
Jannis R 2017-11-12 01:23:34 +01:00
parent 5b96c89b5b
commit 3c9f3393ba
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
12 changed files with 105 additions and 82 deletions

View file

@ -1,41 +1,59 @@
'use strict' 'use strict'
const parseLocation = require('./parse/location') const parseDateTime = require('./parse/date-time')
const parseDeparture = require('./parse/departure')
const parseJourney = require('./parse/journey')
const parseLine = require('./parse/line') const parseLine = require('./parse/line')
const parseRemark = require('./parse/remark') const parseLocation = require('./parse/location')
const parseMovement = require('./parse/movement')
const parseNearby = require('./parse/nearby')
const parseOperator = require('./parse/operator') const parseOperator = require('./parse/operator')
const parseRemark = require('./parse/remark')
const parseStopover = require('./parse/stopover')
const formatAddress = require('./format/address')
const formatCoord = require('./format/coord')
const formatDate = require('./format/date')
const filters = require('./format/filters')
const formatLocationFilter = require('./format/location-filter')
const formatPoi = require('./format/poi')
const formatStation = require('./format/station')
const formatTime = require('./format/time')
const request = require('./lib/request') const request = require('./lib/request')
const id = x => x const id = x => x
// todo: find out which are actually necessary
const defaultProfile = { const defaultProfile = {
transformReqBody: id, transformReqBody: id,
transformReq: id, transformReq: id,
parseLocation: parseLocation,
parseLine: parseLine, parseDateTime,
parseRemark: parseRemark, parseDeparture,
parseOperator: parseOperator parseJourney,
parseLine,
parseLocation,
parseMovement,
parseNearby,
parseOperator,
parseRemark,
parseStopover,
formatAddress,
formatCoord,
formatDate,
filters,
formatLocationFilter,
formatPoi,
formatStation,
formatTime
} }
const createClient = (profile) => { const createClient = (profile) => {
profile = Object.assign({}, defaultProfile, profile) profile = Object.assign({}, defaultProfile, profile)
if ('function' !== profile.transformReqBody) { if ('string' !== typeof profile.timezone) {
throw new Error('profile.transformReqBody must be a function.') throw new Error('profile.timezone must be a string.')
}
if ('function' !== profile.transformReq) {
throw new Error('profile.transformReq must be a function.')
}
if ('function' !== profile.parseLocation) {
throw new Error('profile.parseLocation must be a function.')
}
if ('function' !== profile.parseLine) {
throw new Error('profile.parseLine must be a function.')
}
if ('function' !== profile.parseRemark) {
throw new Error('profile.parseRemark must be a function.')
}
if ('function' !== profile.parseOperator) {
throw new Error('profile.parseOperator must be a function.')
} }
const client = data => request(profile, data) const client = data => request(profile, data)

View file

@ -42,10 +42,18 @@ const request = (profile, data) => {
const d = b.svcResL[0].res const d = b.svcResL[0].res
const c = d.common || {} const c = d.common || {}
if (Array.isArray(c.locL)) d.locations = c.locL.map(profile.parseLocation) if (Array.isArray(c.locL)) {
if (Array.isArray(c.prodL)) d.lines = c.prodL.map(profile.parseLine) d.locations = c.locL.map(loc => profile.parseLocation(profile, loc))
if (Array.isArray(c.remL)) d.remarks = c.remL.map(profile.parseRemark) }
if (Array.isArray(c.opL)) d.operators = c.opL.map(profile.parseOperator) if (Array.isArray(c.prodL)) {
d.lines = c.prodL.map(line => profile.parseLine(profile, line))
}
if (Array.isArray(c.remL)) {
d.remarks = c.remL.map(rem => profile.parseRemark(profile, rem))
}
if (Array.isArray(c.opL)) {
d.operators = c.opL.map(op => profile.parseOperator(profile, op))
}
return d return d
}) })
} }

View file

@ -2,14 +2,14 @@
const moment = require('moment-timezone') const moment = require('moment-timezone')
const parseDateTime = (timezone, date, time) => { const parseDateTime = (profile, date, time) => {
let offset = 0 // in days let offset = 0 // in days
if (time.length > 6) { if (time.length > 6) {
offset = +time.slice(0, -6) offset = +time.slice(0, -6)
time = time.slice(-6) time = time.slice(-6)
} }
return moment.tz(date + 'T' + time, timezone) return moment.tz(date + 'T' + time, profile.timezone)
.add(offset, 'days') .add(offset, 'days')
} }

View file

@ -1,18 +1,17 @@
'use strict' 'use strict'
const parseDateTime = require('./date-time')
// todos from derhuerst/hafas-client#2 // todos from derhuerst/hafas-client#2
// - stdStop.dCncl // - stdStop.dCncl
// - stdStop.dPlatfS, stdStop.dPlatfR // - stdStop.dPlatfS, stdStop.dPlatfR
// todo: what is d.jny.dirFlg? // todo: what is d.jny.dirFlg?
// todo: d.stbStop.dProgType // todo: d.stbStop.dProgType
const createParseDeparture = (timezone, stations, lines, remarks) => { const createParseDeparture = (profile, stations, lines, remarks) => {
const tz = profile.timezone
const findRemark = rm => remarks[parseInt(rm.remX)] || null const findRemark = rm => remarks[parseInt(rm.remX)] || null
const parseDeparture = (d) => { const parseDeparture = (d) => {
const when = parseDateTime(timezone, d.date, d.stbStop.dTimeR || d.stbStop.dTimeS) const when = profile.parseDateTime(tz, d.date, d.stbStop.dTimeR || d.stbStop.dTimeS)
const res = { const res = {
ref: d.jid, ref: d.jid,
station: stations[parseInt(d.stbStop.locX)] || null, station: stations[parseInt(d.stbStop.locX)] || null,
@ -24,8 +23,8 @@ const createParseDeparture = (timezone, stations, lines, remarks) => {
} }
if (d.stbStop.dTimeR && d.stbStop.dTimeS) { if (d.stbStop.dTimeR && d.stbStop.dTimeS) {
const realtime = parseDateTime(timezone, d.date, d.stbStop.dTimeR) const realtime = profile.parseDateTime(tz, d.date, d.stbStop.dTimeR)
const planned = parseDateTime(timezone, d.date, d.stbStop.dTimeS) const planned = profile.parseDateTime(tz, d.date, d.stbStop.dTimeS)
res.delay = Math.round((realtime - planned) / 1000) res.delay = Math.round((realtime - planned) / 1000)
} else res.delay = null } else res.delay = null

View file

@ -4,8 +4,10 @@ const parseDateTime = require('./date-time')
const clone = obj => Object.assign({}, obj) const clone = obj => Object.assign({}, obj)
const createParseStopover = (tz, stations, lines, remarks, j) => { // j = journey const createParseJourney = (profile, stations, lines, remarks) => {
const parseStopover = (st) => { const tz = profile.timezone
const parseStopover = (j, st) => {
const res = { const res = {
station: stations[parseInt(st.locX)] station: stations[parseInt(st.locX)]
} }
@ -17,26 +19,20 @@ const createParseStopover = (tz, stations, lines, remarks, j) => { // j = journe
const dep = parseDateTime(tz, j.date, st.dTimeR || st.dTimeS) const dep = parseDateTime(tz, j.date, st.dTimeR || st.dTimeS)
res.departure = dep.format() res.departure = dep.format()
} }
return res return res
} }
return parseStopover
}
const createApplyRemark = (stations, lines, remarks, j) => { // j = journey
// todo: finish parse/remark.js first // todo: finish parse/remark.js first
const applyRemark = (rm) => {} const applyRemark = (j, rm) => {}
return applyRemark
}
const createParsePart = (tz, stations, lines, remarks, j) => { // j = journey
// todo: pt.sDays // todo: pt.sDays
// todo: pt.dep.dProgType, pt.arr.dProgType // todo: pt.dep.dProgType, pt.arr.dProgType
// todo: what is pt.jny.dirFlg? // todo: what is pt.jny.dirFlg?
// todo: how does pt.freq work? // todo: how does pt.freq work?
const parsePart = (pt) => { const parsePart = (j, pt) => { // j = journey, pt = part
const dep = parseDateTime(tz, j.date, pt.dep.dTimeR || pt.dep.dTimeS) const dep = profile.parseDateTime(tz, j.date, pt.dep.dTimeR || pt.dep.dTimeS)
const arr = parseDateTime(tz, j.date, pt.arr.aTimeR || pt.arr.aTimeS) const arr = profile.parseDateTime(tz, j.date, pt.arr.aTimeR || pt.arr.aTimeS)
const res = { const res = {
origin: clone(stations[parseInt(pt.dep.locX)]) || null, origin: clone(stations[parseInt(pt.dep.locX)]) || null,
destination: clone(stations[parseInt(pt.arr.locX)]), destination: clone(stations[parseInt(pt.arr.locX)]),
@ -45,8 +41,8 @@ const createParsePart = (tz, stations, lines, remarks, j) => { // j = journey
} }
if (pt.dep.dTimeR && pt.dep.dTimeS) { if (pt.dep.dTimeR && pt.dep.dTimeS) {
const realtime = parseDateTime(tz, j.date, pt.dep.dTimeR) const realtime = profile.parseDateTime(tz, j.date, pt.dep.dTimeR)
const planned = parseDateTime(tz, j.date, pt.dep.dTimeS) const planned = profile.parseDateTime(tz, j.date, pt.dep.dTimeS)
res.delay = Math.round((realtime - planned) / 1000) res.delay = Math.round((realtime - planned) / 1000)
} }
@ -61,18 +57,21 @@ const createParsePart = (tz, stations, lines, remarks, j) => { // j = journey
if (pt.arr.aPlatfS) res.arrivalPlatform = pt.arr.aPlatfS if (pt.arr.aPlatfS) res.arrivalPlatform = pt.arr.aPlatfS
if (pt.jny.stopL) { if (pt.jny.stopL) {
const parseStopover = createParseStopover(tz, stations, lines, remarks, j) res.passed = pt.jny.stopL.map(stopover => parseStopover(j, stopover))
res.passed = pt.jny.stopL.map(parseStopover)
} }
if (Array.isArray(pt.jny.remL)) { if (Array.isArray(pt.jny.remL)) {
pt.jny.remL.forEach(createApplyRemark(stations, lines, remarks, j)) for (let remark of pt.jny.remL) applyRemark(j, remark)
} }
if (pt.jny.freq && pt.jny.freq.jnyL) { if (pt.jny.freq && pt.jny.freq.jnyL) {
const parseAlternative = (a) => ({ const parseAlternative = (a) => {
// todo: realtime
const when = profile.parseDateTime(tz, j.date, a.stopL[0].dTimeS)
return {
line: lines[parseInt(a.prodX)] || null, line: lines[parseInt(a.prodX)] || null,
when: parseDateTime(tz, j.date, a.stopL[0].dTimeS).format() // todo: realtime when: when.format()
}) }
}
res.alternatives = pt.jny.freq.jnyL res.alternatives = pt.jny.freq.jnyL
.filter(a => a.stopL[0].locX === pt.dep.locX) .filter(a => a.stopL[0].locX === pt.dep.locX)
.map(parseAlternative) .map(parseAlternative)
@ -81,17 +80,14 @@ const createParsePart = (tz, stations, lines, remarks, j) => { // j = journey
return res return res
} }
return parsePart
}
const createParseJourney = (tz, stations, lines, remarks, p = createParsePart) => {
// todo: c.sDays // todo: c.sDays
// todo: c.dep.dProgType, c.arr.dProgType // todo: c.dep.dProgType, c.arr.dProgType
// todo: c.conSubscr // todo: c.conSubscr
// todo: c.trfRes x vbb-parse-ticket // todo: c.trfRes x vbb-parse-ticket
// todo: use computed information from part // todo: use computed information from part
const parseJourney = (journey) => { const parseJourney = (j) => {
const parts = journey.secL.map(p(tz, stations, lines, remarks, journey)) const parts = j.secL.map(part => parsePart(j, part))
return { return {
parts, parts,
origin: parts[0].origin, origin: parts[0].origin,

View file

@ -3,7 +3,8 @@
// todo: what is p.number vs p.line? // todo: what is p.number vs p.line?
// todo: what is p.icoX? // todo: what is p.icoX?
// todo: what is p.oprX? // todo: what is p.oprX?
const parseLine = (p) => { // todo: is passing in profile necessary?
const parseLine = (profile, p) => {
if (!p) return null // todo: handle this upstream if (!p) return null // todo: handle this upstream
const res = {type: 'line', name: p.line || p.name} const res = {type: 'line', name: p.line || p.name}

View file

@ -6,9 +6,10 @@ types.S = 'station'
types.A = 'address' types.A = 'address'
// todo: what is s.rRefL? // todo: what is s.rRefL?
const parseLocation = (l) => { // todo: is passing in profile necessary?
const parseLocation = (profile, l) => {
const type = types[l.type] || 'unknown' const type = types[l.type] || 'unknown'
const result = { const res = {
type, type,
name: l.name, name: l.name,
coordinates: l.crd ? { coordinates: l.crd ? {
@ -17,10 +18,10 @@ const parseLocation = (l) => {
} : null } : null
} }
if (type === 'poi' || type === 'station') result.id = l.extId if (type === 'poi' || type === 'station') res.id = l.extId
if ('pCls' in l) result.products = l.pCls if ('pCls' in l) res.products = l.pCls
return result return res
} }
module.exports = parseLocation module.exports = parseLocation

View file

@ -1,8 +1,8 @@
'use strict' 'use strict'
const parseDateTime = require('./date-time') const createParseMovement = (profile, locations, lines, remarks) => {
const tz = profile.timezone
const createParseMovement = (tz, locations, lines, remarks) => {
// todo: what is m.dirGeo? maybe the speed? // todo: what is m.dirGeo? maybe the speed?
// todo: what is m.stopL? // todo: what is m.stopL?
// todo: what is m.proc? wut? // todo: what is m.proc? wut?
@ -13,10 +13,10 @@ const createParseMovement = (tz, locations, lines, remarks) => {
const parseMovement = (m) => { const parseMovement = (m) => {
const parseNextStop = (s) => { const parseNextStop = (s) => {
const dep = s.dTimeR || s.dTimeS const dep = s.dTimeR || s.dTimeS
? parseDateTime(tz, m.date, s.dTimeR || s.dTimeS) ? profile.parseDateTime(tz, m.date, s.dTimeR || s.dTimeS)
: null : null
const arr = s.aTimeR || s.aTimeS const arr = s.aTimeR || s.aTimeS
? parseDateTime(tz, m.date, s.aTimeR || s.aTimeS) ? profile.parseDateTime(tz, m.date, s.aTimeR || s.aTimeS)
: null : null
return { return {

View file

@ -1,14 +1,12 @@
'use strict' 'use strict'
const parseLocation = require('./location')
// todo: remarks // todo: remarks
// todo: lines // todo: lines
// todo: what is s.pCls? // todo: what is s.pCls?
// todo: what is s.wt? // todo: what is s.wt?
// todo: what is s.dur? // todo: what is s.dur?
const parseNearby = (n) => { const parseNearby = (profile, n) => {
const res = parseLocation(n) const res = profile.parseLocation(profile, n)
res.distance = n.dist res.distance = n.dist
return res return res
} }

View file

@ -2,7 +2,8 @@
const slugg = require('slugg') const slugg = require('slugg')
const parseOperator = (a) => { // todo: is passing in profile necessary?
const parseOperator = (profile, a) => {
return { return {
type: 'operator', type: 'operator',
id: slugg(a.name), // todo: find a more reliable way id: slugg(a.name), // todo: find a more reliable way

View file

@ -1,6 +1,7 @@
'use strict' 'use strict'
const parseRemark = (r) => { // todo: is passing in profile necessary?
const parseRemark = (profile, r) => {
return null // todo return null // todo
} }

View file

@ -1,18 +1,18 @@
'use strict' 'use strict'
const parseDateTime = require('./date-time') const createParseStopover = (profile, stations, lines, remarks, connection) => {
const tz = profile.timezone
const createParseStopover = (tz, stations, lines, remarks, connection) => {
const parseStopover = (st) => { const parseStopover = (st) => {
const res = { const res = {
station: stations[parseInt(st.locX)] || null station: stations[parseInt(st.locX)] || null
} }
if (st.aTimeR || st.aTimeS) { if (st.aTimeR || st.aTimeS) {
const arr = parseDateTime(tz, connection.date, st.aTimeR || st.aTimeS) const arr = profile.parseDateTime(tz, connection.date, st.aTimeR || st.aTimeS)
res.arrival = arr.format() res.arrival = arr.format()
} }
if (st.dTimeR || st.dTimeS) { if (st.dTimeR || st.dTimeS) {
const dep = parseDateTime(tz, connection.date, st.dTimeR || st.dTimeS) const dep = profile.parseDateTime(tz, connection.date, st.dTimeR || st.dTimeS)
res.departure = dep.format() res.departure = dep.format()
} }
return res return res