From 477124a7691b5716a7cdfb1716e10d424fcf15db Mon Sep 17 00:00:00 2001 From: Jannis R Date: Mon, 18 Dec 2017 23:24:11 +0100 Subject: [PATCH 01/16] =?UTF-8?q?WIP=20=C3=96BB=20profile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- p/oebb/index.js | 23 ++++++++++ p/oebb/modes.js | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 p/oebb/index.js create mode 100644 p/oebb/modes.js diff --git a/p/oebb/index.js b/p/oebb/index.js new file mode 100644 index 00000000..3420d452 --- /dev/null +++ b/p/oebb/index.js @@ -0,0 +1,23 @@ +'use strict' + +// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L5 +// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L47-L234 + +const transformReqBody = (body) => { + body.client = {type: 'IPA', id: 'OEBB'} + // todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L33 shows 1.16 + body.ver = '1.15' + body.auth = {type: 'AID', aid: 'OWDL4fE4ixNiPBBm'} + + return body +} + +const oebbProfile = { + locale: 'de-AT', + timezone: 'Europe/Vienna', + // todo: there is also https://beta.verkehrsauskunft.at/bin/mgate.exe + endpoint: 'http://fahrplan.oebb.at/bin/mgate.exe', + transformReqBody +} + +module.exports = oebbProfile diff --git a/p/oebb/modes.js b/p/oebb/modes.js new file mode 100644 index 00000000..7025ded2 --- /dev/null +++ b/p/oebb/modes.js @@ -0,0 +1,110 @@ +'use strict' + +// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_products-properties-L32-L144 +// - walking +// - bicycle +// - car +// - taxi_t +// - ic_bus, bus_t +// - pr +// - comm, comm_t +// - sub_t +// - tram_t +// - wchair +// - ic +// - reg +// - gen +// - ship +// - plane +// - transf +// etc. + +const m = [ + { + category: 1, + bitmask: null, // todo + name: 'walking', + shortName: 'walking', + mode: 'walking', + product: 'walking' + }, { + category: 2, + bitmask: null, // todo + name: 'bicycle', + shortName: 'bicycle', + mode: 'bicycle', + product: 'bicycle' + }, { + category: 3, + bitmask: null, // todo + name: 'car', + shortName: 'car', + mode: 'car', + product: 'car' + }, { + category: 4, + bitmask: null, // todo + name: 'Taxi', + shortName: 'Taxi', + mode: 'taxi', + product: 'taxi' + }, { + category: 6, + bitmask: null, // todo + name: 'Bus', + shortName: 'Bus', + mode: 'bus', + product: 'bus' + }, { + category: 12, + bitmask: null, // todo + name: 'Subway', + shortName: 'Subway', + mode: 'train', + product: 'subway' + }, { + category: 14, + bitmask: null, // todo + name: 'Tram', + shortName: 'Tram', + mode: 'train', + product: 'tram' + }, { + category: 17, + bitmask: 1, + name: 'RailJet/InterCityExpress/TGV highspeed train', + shortName: 'RJ/ICE/TGV', // todo: is there a way to tell which? + mode: 'train', + product: 'nationalExpress' + }, { + category: 18, + bitmask: 2, + name: 'EuroCity/InterCity train', + shortName: 'EC/IC', + mode: 'train', + product: 'national' + }, { + category: 24, + bitmask: 3, + name: 'NightJet/EuroNight/D train', + shortName: 'EN/D', + mode: 'train', + product: 'sleeper' + }, { + category: 22, + bitmask: null, // todo + name: 'Airplane', + shortName: 'Plane', + mode: 'aircraft', + product: 'airplane' + }, { + category: 0, + bitmask: null, + name: 'unknown', + shortName: '?', + mode: null, + product: null + } +} + +module.exports = m From 4d4412d63f53ddbb41deb26b78b0db2ec26c5ecc Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Tue, 26 Dec 2017 00:58:12 +0100 Subject: [PATCH 02/16] add products/modes for oebb --- p/oebb/index.js | 13 +++- p/oebb/modes.js | 195 ++++++++++++++++++++++++------------------------ 2 files changed, 109 insertions(+), 99 deletions(-) diff --git a/p/oebb/index.js b/p/oebb/index.js index 3420d452..3a0780dc 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -3,6 +3,11 @@ // todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L5 // todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L47-L234 +const createParseBitmask = require('../../parse/products-bitmask') +const createFormatBitmask = require('../../format/products-bitmask') + +const modes = require('./modes') + const transformReqBody = (body) => { body.client = {type: 'IPA', id: 'OEBB'} // todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L33 shows 1.16 @@ -17,7 +22,13 @@ const oebbProfile = { timezone: 'Europe/Vienna', // todo: there is also https://beta.verkehrsauskunft.at/bin/mgate.exe endpoint: 'http://fahrplan.oebb.at/bin/mgate.exe', - transformReqBody + transformReqBody, + + products: modes.allProducts, + + parseProducts: createParseBitmask(modes.bitmasks), + + formatProducts: createFormatBitmask(modes) } module.exports = oebbProfile diff --git a/p/oebb/modes.js b/p/oebb/modes.js index 7025ded2..2b582094 100644 --- a/p/oebb/modes.js +++ b/p/oebb/modes.js @@ -1,110 +1,109 @@ 'use strict' -// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_products-properties-L32-L144 -// - walking -// - bicycle -// - car -// - taxi_t -// - ic_bus, bus_t -// - pr -// - comm, comm_t -// - sub_t -// - tram_t -// - wchair -// - ic -// - reg -// - gen -// - ship -// - plane -// - transf -// etc. - -const m = [ - { - category: 1, - bitmask: null, // todo - name: 'walking', - shortName: 'walking', - mode: 'walking', - product: 'walking' - }, { - category: 2, - bitmask: null, // todo - name: 'bicycle', - shortName: 'bicycle', - mode: 'bicycle', - product: 'bicycle' - }, { - category: 3, - bitmask: null, // todo - name: 'car', - shortName: 'car', - mode: 'car', - product: 'car' - }, { - category: 4, - bitmask: null, // todo - name: 'Taxi', - shortName: 'Taxi', - mode: 'taxi', - product: 'taxi' - }, { - category: 6, - bitmask: null, // todo - name: 'Bus', - shortName: 'Bus', - mode: 'bus', - product: 'bus' - }, { - category: 12, - bitmask: null, // todo - name: 'Subway', - shortName: 'Subway', - mode: 'train', - product: 'subway' - }, { - category: 14, - bitmask: null, // todo - name: 'Tram', - shortName: 'Tram', - mode: 'train', - product: 'tram' - }, { - category: 17, +const m = { + nationalExp: { bitmask: 1, - name: 'RailJet/InterCityExpress/TGV highspeed train', - shortName: 'RJ/ICE/TGV', // todo: is there a way to tell which? + name: 'InterCityExpress & RailJet', + short: 'ICE/RJ', mode: 'train', - product: 'nationalExpress' - }, { - category: 18, - bitmask: 2, - name: 'EuroCity/InterCity train', - shortName: 'EC/IC', + product: 'nationalExp' + }, + national: { + bitmask: 2 + 4, + name: 'InterCity & EuroCity', + short: 'IC/EC', mode: 'train', product: 'national' - }, { - category: 24, - bitmask: 3, - name: 'NightJet/EuroNight/D train', - shortName: 'EN/D', + }, + interregional: { + bitmask: 8 + 4096, + name: 'Durchgangszug & EuroNight', + short: 'D/EN', mode: 'train', - product: 'sleeper' - }, { - category: 22, - bitmask: null, // todo - name: 'Airplane', - shortName: 'Plane', - mode: 'aircraft', - product: 'airplane' - }, { - category: 0, - bitmask: null, + product: 'regional' + }, + regional: { + bitmask: 16, + name: 'Regional & RegionalExpress', + short: 'R/REX', + mode: 'train', + product: 'regional' + }, + suburban: { + bitmask: 32, + name: 'S-Bahn', + short: 'S', + mode: 'train', + product: 'suburban' + }, + bus: { + bitmask: 64, + name: 'Bus', + short: 'B', + mode: 'bus', + product: 'bus' + }, + ferry: { + bitmask: 128, + name: 'Ferry', + short: 'F', + mode: 'watercraft', + product: 'ferry' + }, + subway: { + bitmask: 256, + name: 'U-Bahn', + short: 'U', + mode: 'train', + product: 'subway' + }, + tram: { + bitmask: 512, + name: 'Tram', + short: 'T', + mode: 'tram', + product: 'tram' + }, + onCall: { + bitmask: 2048, + name: 'On-call transit', + short: 'on-call', + mode: null, // todo + product: 'onCall' + }, + unknown: { + bitmask: 0, name: 'unknown', - shortName: '?', - mode: null, - product: null + short: '?', + product: 'unknown' } } +m.bitmasks = [] +m.bitmasks[1] = m.nationalExp +m.bitmasks[2] = m.national +m.bitmasks[4] = m.national +m.bitmasks[8] = m.interregional +m.bitmasks[16] = m.regional +m.bitmasks[32] = m.suburban +m.bitmasks[64] = m.bus +m.bitmasks[128] = m.ferry +m.bitmasks[256] = m.subway +m.bitmasks[512] = m.tram +m.bitmasks[2048] = m.onCall +m.bitmasks[4096] = m.interregional + +m.allProducts = [ + m.nationalExp, + m.national, + m.interregional, + m.regional, + m.suburban, + m.bus, + m.ferry, + m.subway, + m.tram, + m.onCall +] + module.exports = m From de4399fd43614eaec53c51d217c4235138e65e26 Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Thu, 28 Dec 2017 15:29:24 +0100 Subject: [PATCH 03/16] correction: rename 'modes' to 'products' --- p/oebb/index.js | 8 ++--- p/oebb/{modes.js => products.js} | 52 ++++++++++++++++---------------- 2 files changed, 30 insertions(+), 30 deletions(-) rename p/oebb/{modes.js => products.js} (70%) diff --git a/p/oebb/index.js b/p/oebb/index.js index 3a0780dc..e309bc91 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -6,7 +6,7 @@ const createParseBitmask = require('../../parse/products-bitmask') const createFormatBitmask = require('../../format/products-bitmask') -const modes = require('./modes') +const products = require('./products') const transformReqBody = (body) => { body.client = {type: 'IPA', id: 'OEBB'} @@ -24,11 +24,11 @@ const oebbProfile = { endpoint: 'http://fahrplan.oebb.at/bin/mgate.exe', transformReqBody, - products: modes.allProducts, + products: products.allProducts, - parseProducts: createParseBitmask(modes.bitmasks), + parseProducts: createParseBitmask(products.bitmasks), - formatProducts: createFormatBitmask(modes) + formatProducts: createFormatBitmask(products) } module.exports = oebbProfile diff --git a/p/oebb/modes.js b/p/oebb/products.js similarity index 70% rename from p/oebb/modes.js rename to p/oebb/products.js index 2b582094..13c2b125 100644 --- a/p/oebb/modes.js +++ b/p/oebb/products.js @@ -1,6 +1,6 @@ 'use strict' -const m = { +const p = { nationalExp: { bitmask: 1, name: 'InterCityExpress & RailJet', @@ -79,31 +79,31 @@ const m = { } } -m.bitmasks = [] -m.bitmasks[1] = m.nationalExp -m.bitmasks[2] = m.national -m.bitmasks[4] = m.national -m.bitmasks[8] = m.interregional -m.bitmasks[16] = m.regional -m.bitmasks[32] = m.suburban -m.bitmasks[64] = m.bus -m.bitmasks[128] = m.ferry -m.bitmasks[256] = m.subway -m.bitmasks[512] = m.tram -m.bitmasks[2048] = m.onCall -m.bitmasks[4096] = m.interregional +p.bitmasks = [] +p.bitmasks[1] = p.nationalExp +p.bitmasks[2] = p.national +p.bitmasks[4] = p.national +p.bitmasks[8] = p.interregional +p.bitmasks[16] = p.regional +p.bitmasks[32] = p.suburban +p.bitmasks[64] = p.bus +p.bitmasks[128] = p.ferry +p.bitmasks[256] = p.subway +p.bitmasks[512] = p.tram +p.bitmasks[2048] = p.onCall +p.bitmasks[4096] = p.interregional -m.allProducts = [ - m.nationalExp, - m.national, - m.interregional, - m.regional, - m.suburban, - m.bus, - m.ferry, - m.subway, - m.tram, - m.onCall +p.allProducts = [ + p.nationalExp, + p.national, + p.interregional, + p.regional, + p.suburban, + p.bus, + p.ferry, + p.subway, + p.tram, + p.onCall ] -module.exports = m +module.exports = p From 5814a69dd51db7c5949796bc153f8d0130e4eb6b Mon Sep 17 00:00:00 2001 From: Jannis R Date: Mon, 18 Dec 2017 23:33:29 +0100 Subject: [PATCH 04/16] =?UTF-8?q?bugfixes=20=F0=9F=90=9B=F0=9F=92=9A,=20up?= =?UTF-8?q?date=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- p/db/modes.js | 1 + package.json | 4 ++-- parse/departure.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/p/db/modes.js b/p/db/modes.js index be2252c3..0718f79d 100644 --- a/p/db/modes.js +++ b/p/db/modes.js @@ -1,5 +1,6 @@ 'use strict' +// todo: https://gist.github.com/anonymous/d3323a5d2d6e159ed42b12afd0380434#file-haf_products-properties-L1-L95 const m = { nationalExp: { bitmask: 1, diff --git a/package.json b/package.json index 3437284b..83856381 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "vbb-parse-line": "^0.2.5", "vbb-parse-ticket": "^0.2.1", "vbb-short-station-name": "^0.4.0", - "vbb-stations": "^5.8.0", + "vbb-stations": "^5.9.0", "vbb-translate-ids": "^3.1.0" }, "devDependencies": { @@ -49,7 +49,7 @@ "tape": "^4.8.0", "tape-promise": "^2.0.1", "validate-fptf": "^1.0.2", - "vbb-stations-autocomplete": "^2.9.0" + "vbb-stations-autocomplete": "^2.11.0" }, "scripts": { "test": "node test/index.js", diff --git a/parse/departure.js b/parse/departure.js index 1db0f914..a4fce0dd 100644 --- a/parse/departure.js +++ b/parse/departure.js @@ -30,7 +30,7 @@ const createParseDeparture = (profile, stations, lines, remarks) => { // todo: follow public-transport/friendly-public-transport-format#27 here // see also derhuerst/vbb-rest#19 - if (pt.arr.aCncl || pt.dep.dCncl) { + if (d.stbStop.aCncl || d.stbStop.dCncl) { res.cancelled = true res.when = res.delay = null } From b0eb6d6474fab589007fbe05793913eecc408750 Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Thu, 28 Dec 2017 16:50:30 +0100 Subject: [PATCH 05/16] fix requests with no filters --- format/products-bitmask.js | 1 + index.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/format/products-bitmask.js b/format/products-bitmask.js index 9ec158e0..af2a6361 100644 --- a/format/products-bitmask.js +++ b/format/products-bitmask.js @@ -2,6 +2,7 @@ const createFormatBitmask = (modes) => { const formatBitmask = (products) => { + if(Object.keys(products).length === 0) return null let bitmask = 0 for (let product in products) { if (products[product] === true) bitmask += modes[product].bitmask diff --git a/index.js b/index.js index 93409c1c..b4c14de7 100644 --- a/index.js +++ b/index.js @@ -30,7 +30,7 @@ const createClient = (profile) => { time: profile.formatTime(profile, opt.when), stbLoc: profile.formatStation(station), dirLoc: dir, - jnyFltrL: [products], + jnyFltrL: [products].filter(x => x !== null), dur: opt.duration, getPasslist: false } @@ -63,7 +63,7 @@ const createClient = (profile) => { const filters = [ profile.formatProducts(opt.products || {}) - ] + ].filter(x => x !== null) if ( opt.accessibility && profile.filters && @@ -226,7 +226,7 @@ const createClient = (profile) => { ageOfReport: true, // todo: what is this? jnyFltrL: [ profile.formatProducts(opt.products || {}) - ], + ].filter(x => x !== null), trainPosMode: 'CALC' // todo: what is this? what about realtime? } }) From 851e68d3c422fb3794112e3627a6eda6cd15380b Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Thu, 28 Dec 2017 17:12:46 +0100 Subject: [PATCH 06/16] throw error if products filter is empty --- format/products-bitmask.js | 2 +- index.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/format/products-bitmask.js b/format/products-bitmask.js index af2a6361..f28e5a9a 100644 --- a/format/products-bitmask.js +++ b/format/products-bitmask.js @@ -2,7 +2,7 @@ const createFormatBitmask = (modes) => { const formatBitmask = (products) => { - if(Object.keys(products).length === 0) return null + if(Object.keys(products).length === 0) throw new Error('products filter must not be empty') let bitmask = 0 for (let product in products) { if (products[product] === true) bitmask += modes[product].bitmask diff --git a/index.js b/index.js index b4c14de7..93409c1c 100644 --- a/index.js +++ b/index.js @@ -30,7 +30,7 @@ const createClient = (profile) => { time: profile.formatTime(profile, opt.when), stbLoc: profile.formatStation(station), dirLoc: dir, - jnyFltrL: [products].filter(x => x !== null), + jnyFltrL: [products], dur: opt.duration, getPasslist: false } @@ -63,7 +63,7 @@ const createClient = (profile) => { const filters = [ profile.formatProducts(opt.products || {}) - ].filter(x => x !== null) + ] if ( opt.accessibility && profile.filters && @@ -226,7 +226,7 @@ const createClient = (profile) => { ageOfReport: true, // todo: what is this? jnyFltrL: [ profile.formatProducts(opt.products || {}) - ].filter(x => x !== null), + ], trainPosMode: 'CALC' // todo: what is this? what about realtime? } }) From 66d869a3eba3d3fd303e66f808a5246f19ec7dd6 Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Thu, 28 Dec 2017 22:57:22 +0100 Subject: [PATCH 07/16] make when timezone- and local-independent --- test/db.js | 22 ++++++++++++---------- test/util.js | 22 ++++++++++++---------- test/vbb.js | 22 ++++++++++++---------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/test/db.js b/test/db.js index 317b3c65..36a0620b 100644 --- a/test/db.js +++ b/test/db.js @@ -16,9 +16,11 @@ const { assertValidLocation, assertValidLine, assertValidStopover, - when, isValidWhen + createWhen, assertValidWhen } = require('./util.js') +const when = createWhen('Europe/Berlin', 'de-DE') + const assertValidStationProducts = (t, p) => { t.ok(p) t.equal(typeof p.nationalExp, 'boolean') @@ -106,7 +108,7 @@ test('Berlin Jungfernheide to München Hbf', co.wrap(function* (t) { if (journey.origin.products) { assertValidProducts(t, journey.origin.products) } - t.ok(isValidWhen(journey.departure)) + assertValidWhen(t, journey.departure, when) assertValidStation(t, journey.destination) assertValidStationProducts(t, journey.origin.products) @@ -116,7 +118,7 @@ test('Berlin Jungfernheide to München Hbf', co.wrap(function* (t) { if (journey.destination.products) { assertValidProducts(t, journey.destination.products) } - t.ok(isValidWhen(journey.arrival)) + assertValidWhen(t, journey.arrival, when) t.ok(Array.isArray(journey.legs)) t.ok(journey.legs.length > 0, 'no legs') @@ -127,7 +129,7 @@ test('Berlin Jungfernheide to München Hbf', co.wrap(function* (t) { if (!(yield findStation(leg.origin.id))) { console.error('unknown station', leg.origin.id, leg.origin.name) } - t.ok(isValidWhen(leg.departure)) + assertValidWhen(t, leg.departure, when) t.equal(typeof leg.departurePlatform, 'string') assertValidStation(t, leg.destination) @@ -135,7 +137,7 @@ test('Berlin Jungfernheide to München Hbf', co.wrap(function* (t) { if (!(yield findStation(leg.destination.id))) { console.error('unknown station', leg.destination.id, leg.destination.name) } - t.ok(isValidWhen(leg.arrival)) + assertValidWhen(t, leg.arrival, when) t.equal(typeof leg.arrivalPlatform, 'string') assertValidLine(t, leg.line) @@ -166,8 +168,8 @@ test('Berlin Jungfernheide to Torfstraße 17', co.wrap(function* (t) { console.error('unknown station', leg.origin.id, leg.origin.name) } if (leg.origin.products) assertValidProducts(t, leg.origin.products) - t.ok(isValidWhen(leg.departure)) - t.ok(isValidWhen(leg.arrival)) + assertValidWhen(t, leg.departure, when) + assertValidWhen(t, leg.arrival, when) const d = leg.destination assertValidAddress(t, d) @@ -195,8 +197,8 @@ test('Berlin Jungfernheide to ATZE Musiktheater', co.wrap(function* (t) { console.error('unknown station', leg.origin.id, leg.origin.name) } if (leg.origin.products) assertValidProducts(t, leg.origin.products) - t.ok(isValidWhen(leg.departure)) - t.ok(isValidWhen(leg.arrival)) + assertValidWhen(t, leg.departure, when) + assertValidWhen(t, leg.arrival, when) const d = leg.destination assertValidPoi(t, d) @@ -220,7 +222,7 @@ test('departures at Berlin Jungfernheide', co.wrap(function* (t) { console.error('unknown station', dep.station.id, dep.station.name) } if (dep.station.products) assertValidProducts(t, dep.station.products) - t.ok(isValidWhen(dep.when)) + assertValidWhen(t, dep.when, when) } t.end() diff --git a/test/util.js b/test/util.js index 6a374bac..fbd0d8c5 100644 --- a/test/util.js +++ b/test/util.js @@ -98,18 +98,20 @@ const hour = 60 * 60 * 1000 const week = 7 * 24 * hour // next Monday 10 am -const when = DateTime.fromMillis(Date.now(), { - zone: 'Europe/Berlin', - locale: 'de-DE' -}).startOf('week').plus({weeks: 1, hours: 10}).toJSDate() -const isValidWhen = (w) => { - const ts = +new Date(w) +const createWhen = (timezone, locale) => { + return DateTime.fromMillis(Date.now(), { + zone: timezone, + locale, + }).startOf('week').plus({weeks: 1, hours: 10}).toJSDate() +} +const isValidWhen = (actual, expected) => { + const ts = +new Date(actual) if (Number.isNaN(ts)) return false - return isRoughlyEqual(12 * hour, +when, ts) + return isRoughlyEqual(12 * hour, +expected, ts) } -const assertValidWhen = (t, w) => { - t.ok(isValidWhen(w), 'invalid when') +const assertValidWhen = (t, actual, expected) => { + t.ok(isValidWhen(actual, expected), 'invalid when') } const assertValidTicket = (t, ti) => { @@ -151,6 +153,6 @@ module.exports = { assertValidLine, isValidDateTime, assertValidStopover, - hour, when, isValidWhen, assertValidWhen, + hour, createWhen, isValidWhen, assertValidWhen, assertValidTicket } diff --git a/test/vbb.js b/test/vbb.js index cc9eec9d..733792ee 100644 --- a/test/vbb.js +++ b/test/vbb.js @@ -17,11 +17,13 @@ const { assertValidLocation, assertValidLine: _assertValidLine, assertValidStopover, - hour, when, + hour, createWhen, assertValidWhen, assertValidTicket } = require('./util') +const when = createWhen('Europe/Berlin', 'de-DE') + const assertValidStation = (t, s, coordsOptional = false) => { _assertValidStation(t, s, coordsOptional) t.equal(s.name, shorten(s.name)) @@ -70,12 +72,12 @@ test('journeys – station to station', co.wrap(function* (t) { assertValidStationProducts(t, journey.origin.products) t.ok(journey.origin.name.indexOf('(Berlin)') === -1) t.strictEqual(journey.origin.id, spichernstr) - assertValidWhen(t, journey.departure) + assertValidWhen(t, journey.departure, when) assertValidStation(t, journey.destination) assertValidStationProducts(t, journey.destination.products) t.strictEqual(journey.destination.id, amrumerStr) - assertValidWhen(t, journey.arrival) + assertValidWhen(t, journey.arrival, when) t.ok(Array.isArray(journey.legs)) t.strictEqual(journey.legs.length, 1) @@ -87,12 +89,12 @@ test('journeys – station to station', co.wrap(function* (t) { assertValidStationProducts(t, leg.origin.products) t.ok(leg.origin.name.indexOf('(Berlin)') === -1) t.strictEqual(leg.origin.id, spichernstr) - assertValidWhen(t, leg.departure) + assertValidWhen(t, leg.departure, when) assertValidStation(t, leg.destination) assertValidStationProducts(t, leg.destination.products) t.strictEqual(leg.destination.id, amrumerStr) - assertValidWhen(t, leg.arrival) + assertValidWhen(t, leg.arrival, when) assertValidLine(t, leg.line) t.ok(findStation(leg.direction)) @@ -198,14 +200,14 @@ test('journeys – station to address', co.wrap(function* (t) { assertValidStation(t, leg.origin) assertValidStationProducts(t, leg.origin.products) - assertValidWhen(t, leg.departure) + assertValidWhen(t, leg.departure, when) const dest = leg.destination assertValidAddress(t, dest) t.strictEqual(dest.address, 'Torfstraße 17') t.ok(isRoughlyEqual(.0001, dest.latitude, 52.5416823)) t.ok(isRoughlyEqual(.0001, dest.longitude, 13.3491223)) - assertValidWhen(t, leg.arrival) + assertValidWhen(t, leg.arrival, when) t.end() })) @@ -225,14 +227,14 @@ test('journeys – station to POI', co.wrap(function* (t) { assertValidStation(t, leg.origin) assertValidStationProducts(t, leg.origin.products) - assertValidWhen(t, leg.departure) + assertValidWhen(t, leg.departure, when) const dest = leg.destination assertValidPoi(t, dest) t.strictEqual(dest.name, 'ATZE Musiktheater') t.ok(isRoughlyEqual(.0001, dest.latitude, 52.543333)) t.ok(isRoughlyEqual(.0001, dest.longitude, 13.351686)) - assertValidWhen(t, leg.arrival) + assertValidWhen(t, leg.arrival, when) t.end() })) @@ -253,7 +255,7 @@ test('departures', co.wrap(function* (t) { assertValidStationProducts(t, dep.station.products) t.strictEqual(dep.station.id, spichernstr) - assertValidWhen(t, dep.when) + assertValidWhen(t, dep.when, when) t.ok(findStation(dep.direction)) assertValidLine(t, dep.line) } From 54865e67e6a47ab9f3dbf61b1c40a18c6fb15854 Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 07:49:47 +0100 Subject: [PATCH 08/16] allow multiple bitmask positions for one product --- parse/products-bitmask.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse/products-bitmask.js b/parse/products-bitmask.js index 4880da7d..04f9b89a 100644 --- a/parse/products-bitmask.js +++ b/parse/products-bitmask.js @@ -5,7 +5,7 @@ const createParseBitmask = (bitmasks) => { const products = {} let i = 1 do { - products[bitmasks[i].product] = !!(bitmask & i) + products[bitmasks[i].product] = products[bitmasks[i].product] || !!(bitmask & i) i *= 2 } while (bitmasks[i] && bitmasks[i].product) return products From ac56493768ce8de4ae0b689ab89a7c8dbc7cbaca Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 09:00:18 +0100 Subject: [PATCH 09/16] mark & filter stations that are passed without stopping, as they contain no arrival/departure time information which would violate the fptf spec --- parse/journey-leg.js | 4 +++- parse/stopover.js | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/parse/journey-leg.js b/parse/journey-leg.js index cf8a4f7a..56630d15 100644 --- a/parse/journey-leg.js +++ b/parse/journey-leg.js @@ -43,7 +43,9 @@ const createParseJourneyLeg = (profile, stations, lines, remarks) => { if (passed && pt.jny.stopL) { const parse = profile.parseStopover(profile, stations, lines, remarks, j) - res.passed = pt.jny.stopL.map(parse) + const passedStations = pt.jny.stopL.map(parse) + // filter stations the train passes without stopping, as this doesn't comply with fptf (yet) + res.passed = passedStations.filter((x) => !x.passBy) } if (Array.isArray(pt.jny.remL)) { for (let remark of pt.jny.remL) applyRemark(j, remark) diff --git a/parse/stopover.js b/parse/stopover.js index 216d9c1b..e17e1be3 100644 --- a/parse/stopover.js +++ b/parse/stopover.js @@ -16,6 +16,9 @@ const createParseStopover = (profile, stations, lines, remarks, connection) => { res.departure = dep.toISO() } + // mark stations the train passes without stopping + if(st.dInS === false && st.aOutS === false) res.passBy = true + // todo: follow public-transport/friendly-public-transport-format#27 here // see also derhuerst/vbb-rest#19 if (st.aCncl) { From 809c6ac61673c7ac85fde6c691d79dc287ac37cd Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 10:01:02 +0100 Subject: [PATCH 10/16] add profile and tests for oebb --- p/oebb/index.js | 88 ++++++++++- p/oebb/products.js | 7 +- test/index.js | 1 + test/oebb.js | 377 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 467 insertions(+), 6 deletions(-) create mode 100644 test/oebb.js diff --git a/p/oebb/index.js b/p/oebb/index.js index e309bc91..32d4849e 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -5,18 +5,92 @@ const createParseBitmask = require('../../parse/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 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 - body.ver = '1.15' - body.auth = {type: 'AID', aid: 'OWDL4fE4ixNiPBBm'} + body.ver = '1.16' + body.auth = {aid: 'OWDL4fE4ixNiPBBm'} + body.lang = 'de' 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 = { locale: 'de-AT', timezone: 'Europe/Vienna', @@ -27,8 +101,14 @@ const oebbProfile = { products: products.allProducts, parseProducts: createParseBitmask(products.bitmasks), + parseLine, + parseLocation, + parseMovement: createParseMovement, - formatProducts: createFormatBitmask(products) + formatProducts, + + journeyLeg: true, + radar: true } module.exports = oebbProfile diff --git a/p/oebb/products.js b/p/oebb/products.js index 13c2b125..646d4588 100644 --- a/p/oebb/products.js +++ b/p/oebb/products.js @@ -20,7 +20,7 @@ const p = { name: 'Durchgangszug & EuroNight', short: 'D/EN', mode: 'train', - product: 'regional' + product: 'interregional' }, regional: { bitmask: 16, @@ -61,7 +61,7 @@ const p = { bitmask: 512, name: 'Tram', short: 'T', - mode: 'tram', + mode: 'train', product: 'tram' }, onCall: { @@ -83,6 +83,7 @@ p.bitmasks = [] p.bitmasks[1] = p.nationalExp p.bitmasks[2] = p.national p.bitmasks[4] = p.national +p.bitmasks[2+4] = p.national p.bitmasks[8] = p.interregional p.bitmasks[16] = p.regional p.bitmasks[32] = p.suburban @@ -90,8 +91,10 @@ p.bitmasks[64] = p.bus p.bitmasks[128] = p.ferry p.bitmasks[256] = p.subway p.bitmasks[512] = p.tram +p.bitmasks[1024] = p.unknown p.bitmasks[2048] = p.onCall p.bitmasks[4096] = p.interregional +p.bitmasks[8+4096] = p.interregional p.allProducts = [ p.nationalExp, diff --git a/test/index.js b/test/index.js index 85c39e86..5675edb4 100644 --- a/test/index.js +++ b/test/index.js @@ -2,3 +2,4 @@ require('./db') require('./vbb') +require('./oebb') diff --git a/test/oebb.js b/test/oebb.js new file mode 100644 index 00000000..a9630c53 --- /dev/null +++ b/test/oebb.js @@ -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() +})) From 6af49f58ca5506b1c223385a72fa606d1db74cfe Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 10:04:24 +0100 Subject: [PATCH 11/16] add juliuste to contributors --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 83856381..244157c0 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "docs" ], "author": "Jannis R ", + "contributors": ["Julius Tens "], "homepage": "https://github.com/derhuerst/hafas-client", "repository": "derhuerst/hafas-client", "bugs": "https://github.com/derhuerst/hafas-client/issues", From 03b3d2c1c8234a40ef32864cc0b44cb004802930 Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 10:05:54 +0100 Subject: [PATCH 12/16] add abbreviations for db and vbb --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 23840a56..bc7e64a1 100644 --- a/readme.md +++ b/readme.md @@ -2,8 +2,8 @@ **A client for HAFAS public transport APIs**. Sort of like [public-transport-enabler](https://github.com/schildbach/public-transport-enabler), but with a smaller scope. It also [contains customisations](p) for the following transport networks: -- [Deutsche Bahn](https://en.wikipedia.org/wiki/Deutsche_Bahn) - [docs](p/db/readme.md) – [usage example](p/db/example.js) – [src](p/db/index.js) -- [Berlin public transport](https://en.wikipedia.org/wiki/Verkehrsverbund_Berlin-Brandenburg) - [docs](p/vbb/readme.md) – [usage example](p/vbb/example.js) – [src](p/vbb/index.js) +- [Deutsche Bahn (DB)](https://en.wikipedia.org/wiki/Deutsche_Bahn) - [docs](p/db/readme.md) – [usage example](p/db/example.js) – [src](p/db/index.js) +- [Berlin public transport (VBB)](https://en.wikipedia.org/wiki/Verkehrsverbund_Berlin-Brandenburg) - [docs](p/vbb/readme.md) – [usage example](p/vbb/example.js) – [src](p/vbb/index.js) [![npm version](https://img.shields.io/npm/v/hafas-client.svg)](https://www.npmjs.com/package/hafas-client) [![build status](https://img.shields.io/travis/derhuerst/hafas-client.svg)](https://travis-ci.org/derhuerst/hafas-client) From 4bbb3c67247eae2b414bd7b161802128830973b2 Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 10:15:32 +0100 Subject: [PATCH 13/16] add docs for oebb --- p/oebb/example.js | 18 ++++++++++++++++++ p/oebb/readme.md | 18 ++++++++++++++++++ readme.md | 1 + 3 files changed, 37 insertions(+) create mode 100644 p/oebb/example.js create mode 100644 p/oebb/readme.md diff --git a/p/oebb/example.js b/p/oebb/example.js new file mode 100644 index 00000000..9c656063 --- /dev/null +++ b/p/oebb/example.js @@ -0,0 +1,18 @@ +'use strict' + +const createClient = require('../..') +const oebbProfile = require('.') + +const client = createClient(oebbProfile) + +// Wien Westbahnhof to Salzburg Hbf +client.journeys('1291501', '8100002', {results: 1}) +// client.departures('8100002', {duration: 1}) +// client.locations('Salzburg', {results: 2}) +// client.nearby(47.812851, 13.045604, {distance: 60}) +// client.radar(47.827203, 13.001261, 47.773278, 13.07562, {results: 10}) + +.then((data) => { + console.log(require('util').inspect(data, {depth: null})) +}) +.catch(console.error) diff --git a/p/oebb/readme.md b/p/oebb/readme.md new file mode 100644 index 00000000..d57dcd08 --- /dev/null +++ b/p/oebb/readme.md @@ -0,0 +1,18 @@ +# ÖBB profile for `hafas-client` + +[*Österreichische Bundesbahnen (ÖBB)*](https://en.wikipedia.org/wiki/Austrian_Federal_Railways) is the largest Austrian long-distance public transport company. This profile adds *ÖBB*-specific customizations to `hafas-client`. Consider using [`oebb-hafas`](https://github.com/juliuste/oebb-hafas#oebb-hafas), to always get the customized client right away. + +## Usage + +```js +const createClient = require('hafas-client') +const oebbProfile = require('hafas-client/p/oebb') + +// create a client with DB profile +const client = createClient(oebbProfile) +``` + + +## Customisations + +- parses *ÖBB*-specific products (such as *RailJet*) diff --git a/readme.md b/readme.md index bc7e64a1..79d4ac59 100644 --- a/readme.md +++ b/readme.md @@ -4,6 +4,7 @@ - [Deutsche Bahn (DB)](https://en.wikipedia.org/wiki/Deutsche_Bahn) - [docs](p/db/readme.md) – [usage example](p/db/example.js) – [src](p/db/index.js) - [Berlin public transport (VBB)](https://en.wikipedia.org/wiki/Verkehrsverbund_Berlin-Brandenburg) - [docs](p/vbb/readme.md) – [usage example](p/vbb/example.js) – [src](p/vbb/index.js) +- [Österreichische Bundesbahnen (ÖBB)](https://en.wikipedia.org/wiki/Austrian_Federal_Railways) - [docs](p/oebb/readme.md) – [usage example](p/oebb/example.js) – [src](p/oebb/index.js) [![npm version](https://img.shields.io/npm/v/hafas-client.svg)](https://www.npmjs.com/package/hafas-client) [![build status](https://img.shields.io/travis/derhuerst/hafas-client.svg)](https://travis-ci.org/derhuerst/hafas-client) From 46a84c3cfc3d121a35f9defa9721d9f66f8a8dc8 Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 10:16:41 +0100 Subject: [PATCH 14/16] fix typo --- p/oebb/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p/oebb/readme.md b/p/oebb/readme.md index d57dcd08..feeaeaa0 100644 --- a/p/oebb/readme.md +++ b/p/oebb/readme.md @@ -8,7 +8,7 @@ const createClient = require('hafas-client') const oebbProfile = require('hafas-client/p/oebb') -// create a client with DB profile +// create a client with ÖBB profile const client = createClient(oebbProfile) ``` From 2a67733edffb199c5fefc1488119d5a53e111b5b Mon Sep 17 00:00:00 2001 From: Julius Tens Date: Fri, 29 Dec 2017 10:20:22 +0100 Subject: [PATCH 15/16] clarify journeyLeg api --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 79d4ac59..a9c015f3 100644 --- a/readme.md +++ b/readme.md @@ -29,7 +29,7 @@ npm install hafas-client ## API - [`journeys(from, to, [opt])`](docs/journeys.md) – get journeys between locations -- [`journeyLeg(ref, name, [opt])`](docs/journey-leg.md) – get details for a leg of a journey +- [`journeyLeg(ref, lineName, [opt])`](docs/journey-leg.md) – get details for a leg of a journey - [`departures(station, [opt])`](docs/departures.md) – query the next departures at a station - [`locations(query, [opt])`](docs/locations.md) – find stations, POIs and addresses - [`nearby(latitude, longitude, [opt])`](docs/nearby.md) – show stations & POIs around From 4ec458bf6a8d9dd1525a5e0ad19245a1cc27c01c Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 29 Dec 2017 23:46:07 +0100 Subject: [PATCH 16/16] =?UTF-8?q?=C3=96BB:=20code=20style=20:shirt:,=20add?= =?UTF-8?q?=20TODOs,=20improve=20docs=20:memo:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- p/oebb/index.js | 22 +++++++++++++++------- p/oebb/readme.md | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/p/oebb/index.js b/p/oebb/index.js index 32d4849e..9fc74fe3 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -44,15 +44,20 @@ const parseLine = (profile, l) => { } const parseLocation = (profile, l) => { - // ÖBB has some 'stations' **in austria** with no departures/products, like station entrances, that are actually POI + // ÖBB has some 'stations' **in austria** with no departures/products, + // like station entrances, that are actually POIs. const res = _parseLocation(profile, l) - if(res.type === 'station' && !res.products && res.name && res.id && res.id.length !== 7){ - const newRes = { + if ( + res.type === 'station' && + !res.products && + res.name && + res.id && res.id.length !== 7 + ) { + return Object.assign({ type: 'location', id: res.id, name: res.name - } - return Object.assign({}, newRes, res.location) + }, res.location) } return res } @@ -61,9 +66,12 @@ const createParseMovement = (profile, locations, lines, remarks) => { const _parseMovement = _createParseMovement(profile, locations, lines, remarks) const parseMovement = (m) => { const res = _parseMovement(m) - // filter POI + // filter out POIs + // todo: make use of them, as some of them specify fare zones res.nextStops = res.nextStops.filter(s => s.type === 'station') - res.frames = res.frames.filter(f => !(f.origin.type === 'location' && f.destination.type === 'location')) + res.frames = res.frames.filter((f) => { + return f.origin.type !== 'location' && f.destination.type !== 'location' + }) return res } return parseMovement diff --git a/p/oebb/readme.md b/p/oebb/readme.md index feeaeaa0..f45b9c28 100644 --- a/p/oebb/readme.md +++ b/p/oebb/readme.md @@ -16,3 +16,4 @@ const client = createClient(oebbProfile) ## Customisations - parses *ÖBB*-specific products (such as *RailJet*) +- parses invalid empty stations from the API as [`location`](https://github.com/public-transport/friendly-public-transport-format/blob/1.0.1/spec/readme.md#location-objects)s