add profile and tests for oebb

This commit is contained in:
Julius Tens 2017-12-29 10:01:02 +01:00
parent ac56493768
commit 809c6ac616
4 changed files with 467 additions and 6 deletions

View file

@ -5,18 +5,92 @@
const createParseBitmask = require('../../parse/products-bitmask') const createParseBitmask = require('../../parse/products-bitmask')
const createFormatBitmask = require('../../format/products-bitmask') const createFormatBitmask = require('../../format/products-bitmask')
const _parseLine = require('../../parse/line')
const _parseLocation = require('../../parse/location')
const _createParseMovement = require('../../parse/movement')
const products = require('./products') const products = require('./products')
const transformReqBody = (body) => { const transformReqBody = (body) => {
body.client = {type: 'IPA', id: 'OEBB'} // todo: necessary headers?
body.client = {
type: 'IPA',
id: 'OEBB',
v: '6000500',
name: 'oebbIPAD_ADHOC',
os: 'iOS 10.3.3'
}
// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L33 shows 1.16 // todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L33 shows 1.16
body.ver = '1.15' body.ver = '1.16'
body.auth = {type: 'AID', aid: 'OWDL4fE4ixNiPBBm'} body.auth = {aid: 'OWDL4fE4ixNiPBBm'}
body.lang = 'de'
return body return body
} }
const parseLine = (profile, l) => {
const res = _parseLine(profile, l)
res.mode = res.product = null
if ('class' in res) {
const data = products.bitmasks[parseInt(res.class)]
if (data) {
res.mode = data.mode
res.product = data.product
}
}
return res
}
const parseLocation = (profile, l) => {
// ÖBB has some 'stations' **in austria** with no departures/products, like station entrances, that are actually POI
const res = _parseLocation(profile, l)
if(res.type === 'station' && !res.products && res.name && res.id && res.id.length !== 7){
const newRes = {
type: 'location',
id: res.id,
name: res.name
}
return Object.assign({}, newRes, res.location)
}
return res
}
const createParseMovement = (profile, locations, lines, remarks) => {
const _parseMovement = _createParseMovement(profile, locations, lines, remarks)
const parseMovement = (m) => {
const res = _parseMovement(m)
// filter POI
res.nextStops = res.nextStops.filter(s => s.type === 'station')
res.frames = res.frames.filter(f => !(f.origin.type === 'location' && f.destination.type === 'location'))
return res
}
return parseMovement
}
const defaultProducts = {
nationalExp: true,
national: true,
interregional: true,
regional: true,
suburban: true,
bus: true,
ferry: true,
subway: true,
tram: true,
onCall: true
}
const formatBitmask = createFormatBitmask(products)
const formatProducts = (products) => {
products = Object.assign(Object.create(null), defaultProducts, products)
return {
type: 'PROD',
mode: 'INC',
value: formatBitmask(products) + ''
}
}
const oebbProfile = { const oebbProfile = {
locale: 'de-AT', locale: 'de-AT',
timezone: 'Europe/Vienna', timezone: 'Europe/Vienna',
@ -27,8 +101,14 @@ const oebbProfile = {
products: products.allProducts, products: products.allProducts,
parseProducts: createParseBitmask(products.bitmasks), parseProducts: createParseBitmask(products.bitmasks),
parseLine,
parseLocation,
parseMovement: createParseMovement,
formatProducts: createFormatBitmask(products) formatProducts,
journeyLeg: true,
radar: true
} }
module.exports = oebbProfile module.exports = oebbProfile

View file

@ -20,7 +20,7 @@ const p = {
name: 'Durchgangszug & EuroNight', name: 'Durchgangszug & EuroNight',
short: 'D/EN', short: 'D/EN',
mode: 'train', mode: 'train',
product: 'regional' product: 'interregional'
}, },
regional: { regional: {
bitmask: 16, bitmask: 16,
@ -61,7 +61,7 @@ const p = {
bitmask: 512, bitmask: 512,
name: 'Tram', name: 'Tram',
short: 'T', short: 'T',
mode: 'tram', mode: 'train',
product: 'tram' product: 'tram'
}, },
onCall: { onCall: {
@ -83,6 +83,7 @@ p.bitmasks = []
p.bitmasks[1] = p.nationalExp p.bitmasks[1] = p.nationalExp
p.bitmasks[2] = p.national p.bitmasks[2] = p.national
p.bitmasks[4] = p.national p.bitmasks[4] = p.national
p.bitmasks[2+4] = p.national
p.bitmasks[8] = p.interregional p.bitmasks[8] = p.interregional
p.bitmasks[16] = p.regional p.bitmasks[16] = p.regional
p.bitmasks[32] = p.suburban p.bitmasks[32] = p.suburban
@ -90,8 +91,10 @@ p.bitmasks[64] = p.bus
p.bitmasks[128] = p.ferry p.bitmasks[128] = p.ferry
p.bitmasks[256] = p.subway p.bitmasks[256] = p.subway
p.bitmasks[512] = p.tram p.bitmasks[512] = p.tram
p.bitmasks[1024] = p.unknown
p.bitmasks[2048] = p.onCall p.bitmasks[2048] = p.onCall
p.bitmasks[4096] = p.interregional p.bitmasks[4096] = p.interregional
p.bitmasks[8+4096] = p.interregional
p.allProducts = [ p.allProducts = [
p.nationalExp, p.nationalExp,

View file

@ -2,3 +2,4 @@
require('./db') require('./db')
require('./vbb') require('./vbb')
require('./oebb')

377
test/oebb.js Normal file
View file

@ -0,0 +1,377 @@
'use strict'
// todo
// const getStations = require('db-stations').full
const tapePromise = require('tape-promise').default
const tape = require('tape')
const co = require('co')
const isRoughlyEqual = require('is-roughly-equal')
const createClient = require('..')
const oebbProfile = require('../p/oebb')
const products = require('../p/oebb/products')
const {
assertValidStation,
assertValidPoi,
assertValidAddress,
assertValidLocation,
assertValidLine,
assertValidStopover,
hour, createWhen, assertValidWhen
} = require('./util.js')
const when = createWhen('Europe/Vienna', 'de-AT')
const assertValidStationProducts = (t, p) => {
t.ok(p)
t.equal(typeof p.nationalExp, 'boolean')
t.equal(typeof p.national, 'boolean')
t.equal(typeof p.interregional, 'boolean')
t.equal(typeof p.regional, 'boolean')
t.equal(typeof p.suburban, 'boolean')
t.equal(typeof p.bus, 'boolean')
t.equal(typeof p.ferry, 'boolean')
t.equal(typeof p.subway, 'boolean')
t.equal(typeof p.tram, 'boolean')
t.equal(typeof p.onCall, 'boolean')
}
// todo
// const findStation = (id) => new Promise((yay, nay) => {
// const stations = getStations()
// stations
// .once('error', nay)
// .on('data', (s) => {
// if (
// s.id === id ||
// (s.additionalIds && s.additionalIds.includes(id))
// ) {
// yay(s)
// stations.destroy()
// }
// })
// .once('end', yay)
// })
const isSalzburgHbf = (s) => {
return s.type === 'station' &&
(s.id === '008100002' || s.id === '8100002') &&
s.name === 'Salzburg Hbf' &&
s.location &&
isRoughlyEqual(s.location.latitude, 47.812851, .0005) &&
isRoughlyEqual(s.location.longitude, 13.045604, .0005)
}
const assertIsSalzburgHbf = (t, s) => {
t.equal(s.type, 'station')
t.ok(s.id === '008100002' || s.id === '8100002', 'id should be 8100002')
t.equal(s.name, 'Salzburg Hbf')
t.ok(s.location)
t.ok(isRoughlyEqual(s.location.latitude, 47.812851, .0005))
t.ok(isRoughlyEqual(s.location.longitude, 13.045604, .0005))
}
// todo: this doesnt seem to work
// todo: DRY with assertValidStationProducts
const assertValidProducts = (t, p) => {
for (let k of Object.keys(products)) {
t.ok('boolean', typeof products[k], 'mode ' + k + ' must be a boolean')
}
}
const assertValidPrice = (t, p) => {
t.ok(p)
if (p.amount !== null) {
t.equal(typeof p.amount, 'number')
t.ok(p.amount > 0)
}
if (p.hint !== null) {
t.equal(typeof p.hint, 'string')
t.ok(p.hint)
}
}
const test = tapePromise(tape)
const client = createClient(oebbProfile)
test('Salzburg Hbf to Wien Westbahnhof', co.wrap(function* (t) {
const salzburgHbf = '8100002'
const wienWestbahnhof = '1291501'
const journeys = yield client.journeys(salzburgHbf, wienWestbahnhof, {
when, passedStations: true
})
t.ok(Array.isArray(journeys))
t.ok(journeys.length > 0, 'no journeys')
for (let journey of journeys) {
assertValidStation(t, journey.origin)
assertValidStationProducts(t, journey.origin.products)
// todo
// if (!(yield findStation(journey.origin.id))) {
// console.error('unknown station', journey.origin.id, journey.origin.name)
// }
if (journey.origin.products) {
assertValidProducts(t, journey.origin.products)
}
assertValidWhen(t, journey.departure, when)
assertValidStation(t, journey.destination)
assertValidStationProducts(t, journey.origin.products)
// todo
// if (!(yield findStation(journey.origin.id))) {
// console.error('unknown station', journey.destination.id, journey.destination.name)
// }
if (journey.destination.products) {
assertValidProducts(t, journey.destination.products)
}
assertValidWhen(t, journey.arrival, when)
t.ok(Array.isArray(journey.legs))
t.ok(journey.legs.length > 0, 'no legs')
const leg = journey.legs[0]
assertValidStation(t, leg.origin)
assertValidStationProducts(t, leg.origin.products)
// todo
// if (!(yield findStation(leg.origin.id))) {
// console.error('unknown station', leg.origin.id, leg.origin.name)
// }
assertValidWhen(t, leg.departure, when)
t.equal(typeof leg.departurePlatform, 'string')
assertValidStation(t, leg.destination)
assertValidStationProducts(t, leg.origin.products)
// todo
// if (!(yield findStation(leg.destination.id))) {
// console.error('unknown station', leg.destination.id, leg.destination.name)
// }
assertValidWhen(t, leg.arrival, when)
t.equal(typeof leg.arrivalPlatform, 'string')
assertValidLine(t, leg.line)
t.ok(Array.isArray(leg.passed))
for (let stopover of leg.passed) assertValidStopover(t, stopover)
if (journey.price) assertValidPrice(t, journey.price)
}
t.end()
}))
test('Salzburg Hbf to 1220 Wien, Wagramer Straße 5', co.wrap(function* (t) {
const salzburgHbf = '8100002'
const wagramerStr = {
type: 'location',
latitude: 48.236216,
longitude: 16.425863,
address: '1220 Wien, Wagramer Straße 5'
}
const journeys = yield client.journeys(salzburgHbf, wagramerStr, {when})
t.ok(Array.isArray(journeys))
t.ok(journeys.length >= 1, 'no journeys')
const journey = journeys[0]
const firstLeg = journey.legs[0]
const lastLeg = journey.legs[journey.legs.length - 1]
assertValidStation(t, firstLeg.origin)
assertValidStationProducts(t, firstLeg.origin.products)
// todo
// if (!(yield findStation(leg.origin.id))) {
// console.error('unknown station', leg.origin.id, leg.origin.name)
// }
if (firstLeg.origin.products) assertValidProducts(t, firstLeg.origin.products)
assertValidWhen(t, firstLeg.departure, when)
assertValidWhen(t, firstLeg.arrival, when)
assertValidWhen(t, lastLeg.departure, when)
assertValidWhen(t, lastLeg.arrival, when)
const d = lastLeg.destination
assertValidAddress(t, d)
t.equal(d.address, '1220 Wien, Wagramer Straße 5')
t.ok(isRoughlyEqual(.0001, d.latitude, 48.236216))
t.ok(isRoughlyEqual(.0001, d.longitude, 16.425863))
t.end()
}))
test('Albertina to Salzburg Hbf', co.wrap(function* (t) {
const albertina = {
type: 'location',
latitude: 48.204699,
longitude: 16.368404,
name: 'Albertina',
id: '975900003'
}
const salzburgHbf = '8100002'
const journeys = yield client.journeys(albertina, salzburgHbf, {when})
t.ok(Array.isArray(journeys))
t.ok(journeys.length >= 1, 'no journeys')
const journey = journeys[0]
const firstLeg = journey.legs[0]
const lastLeg = journey.legs[journey.legs.length - 1]
const o = firstLeg.origin
assertValidPoi(t, o)
t.equal(o.name, 'Albertina')
t.ok(isRoughlyEqual(.0001, o.latitude, 48.204699))
t.ok(isRoughlyEqual(.0001, o.longitude, 16.368404))
assertValidWhen(t, firstLeg.departure, when)
assertValidWhen(t, firstLeg.arrival, when)
assertValidWhen(t, lastLeg.departure, when)
assertValidWhen(t, lastLeg.arrival, when)
assertValidStation(t, lastLeg.destination)
assertValidStationProducts(t, lastLeg.destination.products)
if (lastLeg.destination.products) assertValidProducts(t, lastLeg.destination.products)
// todo
// if (!(yield findStation(leg.destination.id))) {
// console.error('unknown station', leg.destination.id, leg.destination.name)
// }
t.end()
}))
test('leg details for Wien Westbahnhof to München Hbf', co.wrap(function* (t) {
const wienWestbahnhof = '1291501'
const muenchenHbf = '8000261'
const journeys = yield client.journeys(wienWestbahnhof, muenchenHbf, {
results: 1, when
})
const p = journeys[0].legs[0]
t.ok(p.id, 'precondition failed')
t.ok(p.line.name, 'precondition failed')
const leg = yield client.journeyLeg(p.id, p.line.name, {when})
t.equal(typeof leg.id, 'string')
t.ok(leg.id)
assertValidLine(t, leg.line)
t.equal(typeof leg.direction, 'string')
t.ok(leg.direction)
t.ok(Array.isArray(leg.passed))
for (let passed of leg.passed) assertValidStopover(t, passed)
t.end()
}))
test('departures at Salzburg Hbf', co.wrap(function* (t) {
const salzburgHbf = '8100002'
const deps = yield client.departures(salzburgHbf, {
duration: 5, when
})
t.ok(Array.isArray(deps))
for (let dep of deps) {
assertValidStation(t, dep.station)
assertValidStationProducts(t, dep.station.products)
// todo
// if (!(yield findStation(dep.station.id))) {
// console.error('unknown station', dep.station.id, dep.station.name)
// }
if (dep.station.products) assertValidProducts(t, dep.station.products)
assertValidWhen(t, dep.when, when)
}
t.end()
}))
test('nearby Salzburg Hbf', co.wrap(function* (t) {
const salzburgHbfPosition = {
longitude: 13.045604,
latitude: 47.812851
}
const nearby = yield client.nearby(salzburgHbfPosition.latitude, salzburgHbfPosition.longitude, {
results: 2, distance: 400
})
t.ok(Array.isArray(nearby))
t.equal(nearby.length, 2)
assertIsSalzburgHbf(t, nearby[0])
t.ok(nearby[0].distance >= 0)
t.ok(nearby[0].distance <= 100)
for (let n of nearby) {
if (n.type === 'station') assertValidStation(t, n)
else assertValidLocation(t, n)
}
t.end()
}))
test('locations named Salzburg', co.wrap(function* (t) {
const locations = yield client.locations('Salzburg', {
results: 10
})
t.ok(Array.isArray(locations))
t.ok(locations.length > 0)
t.ok(locations.length <= 10)
for (let l of locations) {
if (l.type === 'station') assertValidStation(t, l)
else assertValidLocation(t, l)
}
t.ok(locations.some(isSalzburgHbf))
t.end()
}))
test('radar Salzburg', co.wrap(function* (t) {
const vehicles = yield client.radar(47.827203, 13.001261, 47.773278, 13.07562, {
duration: 5 * 60, when
})
t.ok(Array.isArray(vehicles))
t.ok(vehicles.length > 0)
for (let v of vehicles) {
// todo
// t.ok(findStation(v.direction))
assertValidLine(t, v.line)
t.equal(typeof v.location.latitude, 'number')
t.ok(v.location.latitude <= 52, 'vehicle is too far away')
t.ok(v.location.latitude >= 42, 'vehicle is too far away')
t.equal(typeof v.location.longitude, 'number')
t.ok(v.location.longitude >= 10, 'vehicle is too far away')
t.ok(v.location.longitude <= 16, 'vehicle is too far away')
t.ok(Array.isArray(v.nextStops))
for (let st of v.nextStops) {
assertValidStopover(t, st, true)
if (st.arrival) {
t.equal(typeof st.arrival, 'string')
const arr = +new Date(st.arrival)
// note that this can be an ICE train
t.ok(isRoughlyEqual(14 * hour, +when, arr))
}
if (st.departure) {
t.equal(typeof st.departure, 'string')
const dep = +new Date(st.departure)
t.ok(isRoughlyEqual(14 * hour, +when, dep))
}
}
t.ok(Array.isArray(v.frames))
for (let f of v.frames) {
assertValidStation(t, f.origin, true)
// can contain stations in germany which don't have a products property, would break
// assertValidStationProducts(t, f.origin.products)
assertValidStation(t, f.destination, true)
// can contain stations in germany which don't have a products property, would break
// assertValidStationProducts(t, f.destination.products)
t.equal(typeof f.t, 'number')
}
}
t.end()
}))