merge master into nah.sh

This commit is contained in:
Jannis R 2018-03-17 17:21:18 +01:00
commit 0987383c72
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
11 changed files with 182 additions and 118 deletions

View file

@ -9,7 +9,6 @@ const getStations = require('vbb-stations')
const _createParseLine = require('../../parse/line')
const _parseLocation = require('../../parse/location')
const _createParseJourney = require('../../parse/journey')
const _createParseStopover = require('../../parse/stopover')
const _createParseDeparture = require('../../parse/departure')
const _formatStation = require('../../format/station')
const createParseBitmask = require('../../parse/products-bitmask')
@ -99,20 +98,6 @@ const createParseJourney = (profile, stations, lines, remarks) => {
return parseJourneyWithTickets
}
const createParseStopover = (profile, stations, lines, remarks, connection) => {
const parseStopover = _createParseStopover(profile, stations, lines, remarks, connection)
const parseStopoverWithShorten = (st) => {
const res = parseStopover(st)
if (res.station && res.station.name) {
res.station.name = shorten(res.station.name)
}
return res
}
return parseStopoverWithShorten
}
const createParseDeparture = (profile, stations, lines, remarks) => {
const parseDeparture = _createParseDeparture(profile, stations, lines, remarks)
@ -184,7 +169,6 @@ const vbbProfile = {
parseProducts: createParseBitmask(modes.allProducts, defaultProducts),
parseJourney: createParseJourney,
parseDeparture: createParseDeparture,
parseStopover: createParseStopover,
formatStation,
formatProducts,

View file

@ -1,7 +1,7 @@
{
"name": "hafas-client",
"description": "JavaScript client for HAFAS public transport APIs.",
"version": "2.4.0",
"version": "2.4.2",
"main": "index.js",
"files": [
"index.js",
@ -35,10 +35,10 @@
"capture-stack-trace": "^1.0.0",
"fetch-ponyfill": "^6.0.0",
"lodash": "^4.17.5",
"luxon": "^0.5.6",
"luxon": "^0.5.8",
"p-throttle": "^1.1.0",
"pinkie-promise": "^2.0.1",
"query-string": "^5.1.0",
"query-string": "^6.0.0",
"slugg": "^1.2.0",
"vbb-parse-line": "^0.3.1",
"vbb-parse-ticket": "^0.2.1",
@ -52,7 +52,7 @@
"is-roughly-equal": "^0.1.0",
"tap-spec": "^4.1.1",
"tape": "^4.8.0",
"tape-promise": "^2.0.1",
"tape-promise": "^3.0.0",
"validate-fptf": "^1.2.1",
"vbb-stations-autocomplete": "^3.1.0"
},

View file

@ -22,14 +22,14 @@ const createParseDeparture = (profile, stations, lines, remarks) => {
}
// todo: res.trip from rawLine.prodCtx.num?
// todo: DRY with parseStopover
// todo: DRY with parseJourneyLeg
if (d.stbStop.dTimeR && d.stbStop.dTimeS) {
const realtime = profile.parseDateTime(profile, d.date, d.stbStop.dTimeR)
const planned = profile.parseDateTime(profile, d.date, d.stbStop.dTimeS)
res.delay = Math.round((realtime - planned) / 1000)
} else res.delay = null
// todo: follow public-transport/friendly-public-transport-format#27 here
// see also derhuerst/vbb-rest#19
if (d.stbStop.aCncl || d.stbStop.dCncl) {
res.cancelled = true
Object.defineProperty(res, 'canceled', {value: true})

View file

@ -47,7 +47,7 @@ const createParseJourneyLeg = (profile, stations, lines, remarks) => {
if (pt.arr.aPlatfS) res.arrivalPlatform = pt.arr.aPlatfS
if (passed && pt.jny.stopL) {
const parse = profile.parseStopover(profile, stations, lines, remarks, j)
const parse = profile.parseStopover(profile, stations, lines, remarks, j.date)
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)
@ -71,22 +71,22 @@ const createParseJourneyLeg = (profile, stations, lines, remarks) => {
}
}
// todo: follow public-transport/friendly-public-transport-format#27 here
// see also derhuerst/vbb-rest#19
if (pt.arr.aCncl) {
// todo: DRY with parseDeparture
// todo: DRY with parseStopover
if (pt.arr.aCncl || pt.dep.dCncl) {
res.cancelled = true
Object.defineProperty(res, 'canceled', {value: true})
if (pt.arr.aCncl) {
res.arrival = res.arrivalPlatform = res.arrivalDelay = null
const arr = profile.parseDateTime(profile, j.date, pt.arr.aTimeS)
res.formerScheduledArrival = arr.toISO()
}
if (pt.dep.dCncl) {
res.cancelled = true
Object.defineProperty(res, 'canceled', {value: true})
res.departure = res.departurePlatform = res.departureDelay = null
const dep = profile.parseDateTime(profile, j.date, pt.dep.dTimeS)
res.formerScheduledDeparture = dep.toISO()
}
}
return res
}

View file

@ -19,7 +19,7 @@ const parseLocation = (profile, l, lines) => {
const station = {
type: 'station',
id: l.extId,
name: l.name,
name: profile.parseStationName(l.name),
location: 'number' === typeof res.latitude ? res : null
}

View file

@ -9,32 +9,7 @@ const createParseMovement = (profile, locations, lines, remarks) => {
// todo: what is m.ani.proc[n]? wut?
// todo: how does m.ani.poly work?
const parseMovement = (m) => {
const parseNextStop = (s) => {
const dep = s.dTimeR || s.dTimeS
? profile.parseDateTime(profile, m.date, s.dTimeR || s.dTimeS)
: null
const arr = s.aTimeR || s.aTimeS
? profile.parseDateTime(profile, m.date, s.aTimeR || s.aTimeS)
: null
const res = {
station: locations[s.locX],
departure: dep ? dep.toISO() : null,
arrival: arr ? arr.toISO() : null
}
if (m.dTimeR && m.dTimeS) {
const plannedDep = profile.parseDateTime(profile, m.date, s.dTimeS)
res.departureDelay = Math.round((dep - plannedDep) / 1000)
} else res.departureDelay = null
if (m.aTimeR && m.aTimeS) {
const plannedArr = profile.parseDateTime(profile, m.date, s.aTimeS)
res.arrivalDelay = Math.round((arr - plannedArr) / 1000)
} else res.arrivalDelay = null
return res
}
const pStopover = profile.parseStopover(profile, locations, lines, remarks, m.date)
const res = {
direction: profile.parseStationName(m.dirTxt),
@ -45,7 +20,7 @@ const createParseMovement = (profile, locations, lines, remarks) => {
latitude: m.pos.y / 1000000,
longitude: m.pos.x / 1000000
} : null,
nextStops: m.stopL.map(parseNextStop),
nextStops: m.stopL.map(pStopover),
frames: []
}

View file

@ -2,32 +2,38 @@
// todo: arrivalDelay, departureDelay or only delay ?
// todo: arrivalPlatform, departurePlatform
const createParseStopover = (profile, stations, lines, remarks, connection) => {
const createParseStopover = (profile, stations, lines, remarks, date) => {
const parseStopover = (st) => {
const res = {
station: stations[parseInt(st.locX)] || null
}
if (st.aTimeR || st.aTimeS) {
const arr = profile.parseDateTime(profile, connection.date, st.aTimeR || st.aTimeS)
const arr = profile.parseDateTime(profile, date, st.aTimeR || st.aTimeS)
res.arrival = arr.toISO()
}
if (st.dTimeR || st.dTimeS) {
const dep = profile.parseDateTime(profile, connection.date, st.dTimeR || st.dTimeS)
const dep = profile.parseDateTime(profile, date, st.dTimeR || st.dTimeS)
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) {
// todo: DRY with parseDeparture
// todo: DRY with parseJourneyLeg
if (st.aCncl || st.dCncl) {
res.cancelled = true
res.arrival = null
Object.defineProperty(res, 'canceled', {value: true})
if (st.aCncl) {
res.arrival = res.arrivalDelay = null
const arr = profile.parseDateTime(profile, d.date, st.aTimeS)
res.formerScheduledArrival = arr.toISO()
}
if (st.dCncl) {
res.cancelled = true
res.departure = null
res.departure = res.departureDelay = null
const arr = profile.parseDateTime(profile, d.date, st.dTimeS)
res.formerScheduledDeparture = arr.toISO()
}
}
return res

View file

@ -218,18 +218,44 @@ test('Berlin Jungfernheide to ATZE Musiktheater', co(function* (t) {
t.end()
}))
test('Berlin Hbf to München Hbf with stopover at Hannover Hbf', co(function* (t) {
const [journey] = yield client.journeys(berlinHbf, münchenHbf, {
via: hannoverHbf,
results: 1
test('journeys: via works with detour', co(function* (t) {
// Going from Westhafen to Wedding via Württembergalle without detour
// is currently impossible. We check if the routing engine computes a detour.
const westhafen = '008089116'
const wedding = '008089131'
const württembergallee = '731084'
const [journey] = yield client.journeys(westhafen, wedding, {
via: württembergallee,
results: 1,
when,
passedStations: true
})
const i = journey.legs.findIndex(leg => leg.destination.id === hannoverHbf)
t.ok(i >= 0, 'no leg with Hannover Hbf as destination')
t.ok(journey)
const nextLeg = journey.legs[i + 1]
t.ok(nextLeg)
t.equal(nextLeg.origin.id, hannoverHbf)
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === württembergallee))
t.ok(l, 'Württembergalle is not being passed')
t.end()
}))
test('journeys: via works without detour', co(function* (t) {
// When going from Ruhleben to Zoo via Kastanienallee, there is *no need*
// to change trains / no need for a "detour".
const ruhleben = '000731058'
const zoo = '008010406'
const kastanienallee = '730983'
const [journey] = yield client.journeys(ruhleben, zoo, {
via: kastanienallee,
results: 1,
when,
passedStations: true
})
t.ok(journey)
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === kastanienallee))
t.ok(l, 'Kastanienallee is not being passed')
t.end()
}))

View file

@ -189,22 +189,47 @@ test('Kloster Unser Lieben Frauen to Magdeburg Hbf', co(function*(t) {
t.end()
}))
test('Magdeburg-Buckau to Magdeburg-Neustadt with stopover at Magdeburg Hbf', co(function*(t) {
const magdeburgBuckau = '8013456'
const magdeburgNeustadt = '8010226'
const magdeburgHbf = '8010224'
const [journey] = yield client.journeys(magdeburgBuckau, magdeburgNeustadt, {
via: magdeburgHbf,
test('journeys: via works with detour', co(function* (t) {
// Going from Magdeburg, Hasselbachplatz (Sternstr.) (Tram/Bus) to Stendal via Dessau without detour
// is currently impossible. We check if the routing engine computes a detour.
const hasselbachplatzSternstrasse = '000006545'
const stendal = '008010334'
const dessau = '008010077'
const dessauPassed = '8010077'
const [journey] = yield client.journeys(hasselbachplatzSternstrasse, stendal, {
via: dessau,
results: 1,
when
when,
passedStations: true
})
const i1 = journey.legs.findIndex(leg => leg.destination.id === magdeburgHbf)
t.ok(i1 >= 0, 'no leg with Magdeburg Hbf as destination')
t.ok(journey)
const i2 = journey.legs.findIndex(leg => leg.origin.id === magdeburgHbf)
t.ok(i2 >= 0, 'no leg with Magdeburg Hbf as origin')
t.ok(i2 > i1, 'leg with Magdeburg Hbf as origin must be after leg to it')
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === dessauPassed))
t.ok(l, 'Dessau is not being passed')
t.end()
}))
test('journeys: via works without detour', co(function* (t) {
// When going from Magdeburg, Hasselbachplatz (Sternstr.) (Tram/Bus) to Magdeburg, Universität via Magdeburg, Breiter Weg, there is *no need*
// to change trains / no need for a "detour".
const hasselbachplatzSternstrasse = '000006545'
const universitaet = '000019686'
const breiterWeg = '000013519'
const breiterWegPassed = '13519'
const [journey] = yield client.journeys(hasselbachplatzSternstrasse, universitaet, {
via: breiterWeg,
results: 1,
when,
passedStations: true
})
t.ok(journey)
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === breiterWegPassed))
t.ok(l, 'Magdeburg, Breiter Weg is not being passed')
t.end()
}))

View file

@ -258,19 +258,47 @@ test('Albertina to Salzburg Hbf', co(function* (t) {
t.end()
}))
test('Wien to Klagenfurt Hbf with stopover at Salzburg Hbf', co(function* (t) {
const [journey] = yield client.journeys(wien, klagenfurtHbf, {
via: salzburgHbf,
test('journeys: via works with detour', co(function* (t) {
// Going from Stephansplatz to Schottenring via Donauinsel without detour
// is currently impossible. We check if the routing engine computes a detour.
const stephansplatz = '001390167'
const schottenring = '001390163'
const donauinsel = '001392277'
const donauinselPassed = '922001'
const [journey] = yield client.journeys(stephansplatz, schottenring, {
via: donauinsel,
results: 1,
when
when,
passedStations: true
})
const i1 = journey.legs.findIndex(leg => leg.destination.id === salzburgHbf)
t.ok(i1 >= 0, 'no leg with Salzburg Hbf as destination')
t.ok(journey)
const i2 = journey.legs.findIndex(leg => leg.origin.id === salzburgHbf)
t.ok(i2 >= 0, 'no leg with Salzburg Hbf as origin')
t.ok(i2 > i1, 'leg with Salzburg Hbf as origin must be after leg to it')
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === donauinselPassed))
t.ok(l, 'Donauinsel is not being passed')
t.end()
}))
test('journeys: via works without detour', co(function* (t) {
// When going from Karlsplatz to Praterstern via Museumsquartier, there is *no need*
// to change trains / no need for a "detour".
const karlsplatz = '001390461'
const praterstern = '001290201'
const museumsquartier = '001390171'
const museumsquartierPassed = '901014'
const [journey] = yield client.journeys(karlsplatz, praterstern, {
via: museumsquartier,
results: 1,
when,
passedStations: true
})
t.ok(journey)
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === museumsquartierPassed))
t.ok(l, 'Weihburggasse is not being passed')
t.end()
}))

View file

@ -300,27 +300,47 @@ test('journeys  station to POI', co(function* (t) {
t.end()
}))
test('journeys with stopover', co(function* (t) {
const halleschesTor = '900000012103'
const leopoldplatz = '900000009102'
const [journey] = yield client.journeys(spichernstr, halleschesTor, {
via: leopoldplatz,
results: 1
test('journeys: via works with detour', co(function* (t) {
// Going from Westhafen to Wedding via Württembergalle without detour
// is currently impossible. We check if the routing engine computes a detour.
const westhafen = '900000001201'
const wedding = '900000009104'
const württembergallee = '900000026153'
const [journey] = yield client.journeys(westhafen, wedding, {
via: württembergallee,
results: 1,
when,
passedStations: true
})
const i = journey.legs.findIndex(leg => leg.destination.id === leopoldplatz)
t.ok(i >= 0, 'no leg with Leopoldplatz as destination')
t.ok(journey)
const nextLeg = journey.legs[i + 1]
t.ok(nextLeg)
t.equal(nextLeg.origin.id, leopoldplatz)
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === württembergallee))
t.ok(l, 'Württembergalle is not being passed')
t.end()
}))
test('journeys: via works without detour', co(function* (t) {
// When going from Ruhleben to Zoo via Kastanienallee, there is *no need*
// to change trains / no need for a "detour".
const ruhleben = '900000025202'
const zoo = '900000023201'
const kastanienallee = '900000020152'
const [journey] = yield client.journeys(ruhleben, zoo, {
via: kastanienallee,
results: 1,
when,
passedStations: true
})
t.ok(journey)
const l = journey.legs.some(l => l.passed && l.passed.some(p => p.station.id === kastanienallee))
t.ok(l, 'Kastanienallee is not being passed')
t.end()
}))
test('departures', co(function* (t) {
const deps = yield client.departures(spichernstr, {duration: 5, when})