earlierThan/laterThan options (cherry-picked from next-journeys-by-ref)

This commit is contained in:
Jannis R 2018-03-04 19:53:53 +01:00
parent 07389ef418
commit 869c9a8e98
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
5 changed files with 341 additions and 130 deletions

View file

@ -41,6 +41,8 @@ With `opt`, you can override the default options, which look like this:
```js
{
when: new Date(),
earlierThan: null, // ref to get journeys earlier than the last query
laterThan: null, // ref to get journeys later than the last query
results: 5, // how many journeys?
via: null, // let journeys pass this station
passedStations: false, // return stations on the way?
@ -85,7 +87,8 @@ client.journeys('900000003201', '900000100008', {
The response may look like this:
```js
[ {
[
{
legs: [ {
id: '1|31041|35|86|17122017',
origin: {
@ -201,7 +204,10 @@ The response may look like this:
},
arrival: '2017-12-17T19:47:00.000+01:00',
arrivalDelay: 30
} ]
},
earlierRef: '…', // use with the `earlierThan` option
laterRef: '…' // use with the `laterThan` option
]
```
Some [profiles](../p) are able to parse the ticket information, if returned by the API. For example, if you pass `tickets: true` with the [VBB profile](../p/vbb), each `journey` will have a tickets array that looks like this:
@ -242,3 +248,31 @@ Some [profiles](../p) are able to parse the ticket information, if returned by t
```
If a journey leg has been cancelled, a `cancelled: true` will be added. Also, `departure`/`departureDelay`/`departurePlatform` and `arrival`/`arrivalDelay`/`arrivalPlatform` will be `null`.
To get more journeys earlier/later than the current set of results, use `journey.earlierRef`/`journey.laterRef` as follows:
```js
const hbf = '900000003201'
const heinrichHeineStr = '900000100008'
client.journeys(hbf, heinrichHeineStr)
.then((journeys) => {
const lastJourney = journeys[journeys.length - 1]
console.log('departure of last journey', lastJourney.departure)
// get later journeys
return client.journeys(hbf, heinrichHeineStr, {
laterThan: journeys.laterRef
})
})
.then((laterourneys) => {
const firstJourney = laterourneys[laterourneys.length - 1]
console.log('departure of first (later) journey', firstJourney.departure)
})
.catch(console.error)
```
```
departure of last journey 2017-12-17T19:07:00.000+01:00
departure of first (later) journey 2017-12-17T19:19:00.000+01:00
```

View file

@ -8,6 +8,7 @@ const defaultProfile = require('./lib/default-profile')
const _request = require('./lib/request')
const isObj = o => o !== null && 'object' === typeof o && !Array.isArray(o)
const isNonEmptyString = str => 'string' === typeof str && str.length > 0
const createClient = (profile, request = _request) => {
profile = Object.assign({}, defaultProfile, profile)
@ -51,6 +52,29 @@ const createClient = (profile, request = _request) => {
from = profile.formatLocation(profile, from)
to = profile.formatLocation(profile, to)
if (('earlierThan' in opt) && ('laterThan' in opt)) {
throw new Error('opt.laterThan and opt.laterThan are mutually exclusive.')
}
let journeysRef = null
if ('earlierThan' in opt) {
if (!isNonEmptyString(opt.earlierThan)) {
throw new Error('opt.earlierThan must be a non-empty string.')
}
if ('when' in opt) {
throw new Error('opt.earlierThan and opt.when are mutually exclusive.')
}
journeysRef = opt.earlierThan
}
if ('laterThan' in opt) {
if (!isNonEmptyString(opt.laterThan)) {
throw new Error('opt.laterThan must be a non-empty string.')
}
if ('when' in opt) {
throw new Error('opt.laterThan and opt.when are mutually exclusive.')
}
journeysRef = opt.laterThan
}
opt = Object.assign({
results: 5, // how many journeys?
via: null, // let journeys pass this station?
@ -80,6 +104,7 @@ const createClient = (profile, request = _request) => {
const query = profile.transformJourneysQuery({
outDate: profile.formatDate(profile, opt.when),
outTime: profile.formatTime(profile, opt.when),
ctxScr: journeysRef,
numF: opt.results,
getPasslist: !!opt.passedStations,
maxChg: opt.transfers,
@ -105,12 +130,16 @@ const createClient = (profile, request = _request) => {
.then((d) => {
if (!Array.isArray(d.outConL)) return []
const parse = profile.parseJourney(profile, d.locations, d.lines, d.remarks)
return d.outConL.map(parse)
const res = d.outConL.map(parse)
if (d.outCtxScrB) res.earlierRef = d.outCtxScrB
if (d.outCtxScrF) res.laterRef = d.outCtxScrF
return res
})
}
const locations = (query, opt = {}) => {
if ('string' !== typeof query || !query) {
if (!isNonEmptyString(query)) {
throw new Error('query must be a non-empty string.')
}
opt = Object.assign({
@ -204,10 +233,10 @@ const createClient = (profile, request = _request) => {
}
const journeyLeg = (ref, lineName, opt = {}) => {
if ('string' !== typeof ref || !ref) {
if (!isNonEmptyString(ref)) {
throw new Error('ref must be a non-empty string.')
}
if ('string' !== typeof lineName || !lineName) {
if (!isNonEmptyString(lineName)) {
throw new Error('lineName must be a non-empty string.')
}
opt = Object.assign({

View file

@ -53,7 +53,7 @@ const findStation = (id) => new Promise((yay, nay) => {
const isJungfernheide = (s) => {
return s.type === 'station' &&
(s.id === '008011167' || s.id === '8011167') &&
(s.id === '008011167' || s.id === jungfernh) &&
s.name === 'Berlin Jungfernheide' &&
s.location &&
isRoughlyEqual(s.location.latitude, 52.530408, .0005) &&
@ -62,7 +62,7 @@ const isJungfernheide = (s) => {
const assertIsJungfernheide = (t, s) => {
t.equal(s.type, 'station')
t.ok(s.id === '008011167' || s.id === '8011167', 'id should be 8011167')
t.ok(s.id === '008011167' || s.id === jungfernh, 'id should be 8011167')
t.equal(s.name, 'Berlin Jungfernheide')
t.ok(s.location)
t.ok(isRoughlyEqual(s.location.latitude, 52.530408, .0005))
@ -92,8 +92,14 @@ const assertValidPrice = (t, p) => {
const test = tapePromise(tape)
const client = createClient(dbProfile)
const jungfernh = '8011167'
const berlinHbf = '8011160'
const münchenHbf = '8000261'
const hannoverHbf = '8000152'
const regensburgHbf = '8000309'
test('Berlin Jungfernheide to München Hbf', co(function* (t) {
const journeys = yield client.journeys('8011167', '8000261', {
const journeys = yield client.journeys(jungfernh, münchenHbf, {
when, passedStations: true
})
@ -154,7 +160,7 @@ test('Berlin Jungfernheide to München Hbf', co(function* (t) {
}))
test('Berlin Jungfernheide to Torfstraße 17', co(function* (t) {
const journeys = yield client.journeys('8011167', {
const journeys = yield client.journeys(jungfernh, {
type: 'location', address: 'Torfstraße 17',
latitude: 52.5416823, longitude: 13.3491223
}, {when})
@ -183,7 +189,7 @@ test('Berlin Jungfernheide to Torfstraße 17', co(function* (t) {
}))
test('Berlin Jungfernheide to ATZE Musiktheater', co(function* (t) {
const journeys = yield client.journeys('8011167', {
const journeys = yield client.journeys(jungfernh, {
type: 'location', id: '991598902', name: 'ATZE Musiktheater',
latitude: 52.542417, longitude: 13.350437
}, {when})
@ -212,9 +218,6 @@ test('Berlin Jungfernheide to ATZE Musiktheater', co(function* (t) {
}))
test('Berlin Hbf to München Hbf with stopover at Hannover Hbf', co(function* (t) {
const berlinHbf = '8011160'
const münchenHbf = '8000261'
const hannoverHbf = '8000152'
const [journey] = yield client.journeys(berlinHbf, münchenHbf, {
via: hannoverHbf,
results: 1
@ -230,8 +233,58 @@ test('Berlin Hbf to München Hbf with stopover at Hannover Hbf', co(function* (t
t.end()
}))
test('earlier/later journeys, Jungfernheide -> München Hbf', co(function* (t) {
const model = yield client.journeys(jungfernh, münchenHbf, {
results: 3, when
})
t.equal(typeof model.earlierRef, 'string')
t.ok(model.earlierRef)
t.equal(typeof model.laterRef, 'string')
t.ok(model.laterRef)
// when and earlierThan/laterThan should be mutually exclusive
t.throws(() => {
client.journeys(jungfernh, münchenHbf, {
when, earlierThan: model.earlierRef
})
})
t.throws(() => {
client.journeys(jungfernh, münchenHbf, {
when, laterThan: model.laterRef
})
})
let earliestDep = Infinity, latestDep = -Infinity
for (let j of model) {
const dep = +new Date(j.departure)
if (dep < earliestDep) earliestDep = dep
else if (dep > latestDep) latestDep = dep
}
const earlier = yield client.journeys(jungfernh, münchenHbf, {
results: 3,
// todo: single journey ref?
earlierThan: model.earlierRef
})
for (let j of earlier) {
t.ok(new Date(j.departure) < earliestDep)
}
const later = yield client.journeys(jungfernh, münchenHbf, {
results: 3,
// todo: single journey ref?
laterThan: model.laterRef
})
for (let j of later) {
t.ok(new Date(j.departure) > latestDep)
}
t.end()
}))
test('departures at Berlin Jungfernheide', co(function* (t) {
const deps = yield client.departures('8011167', {
const deps = yield client.departures(jungfernh, {
duration: 5, when
})
@ -252,7 +305,7 @@ test('departures at Berlin Jungfernheide', co(function* (t) {
test('departures with station object', co(function* (t) {
yield client.departures({
type: 'station',
id: '8011167',
id: jungfernh,
name: 'Berlin Jungfernheide',
location: {
type: 'location',
@ -308,7 +361,6 @@ test('locations named Jungfernheide', co(function* (t) {
}))
test('location', co(function* (t) {
const regensburgHbf = '8000309'
const loc = yield client.location(regensburgHbf)
assertValidStation(t, loc)

View file

@ -110,9 +110,14 @@ const assertValidLine = (t, l) => { // with optional mode
const test = tapePromise(tape)
const client = createClient(oebbProfile)
test('Salzburg Hbf to Wien Westbahnhof', co(function* (t) {
const salzburgHbf = '8100002'
const wienWestbahnhof = '1291501'
const wien = '1190100'
const klagenfurtHbf = '8100085'
const muenchenHbf = '8000261'
const grazHbf = '8100173'
test('Salzburg Hbf to Wien Westbahnhof', co(function* (t) {
const journeys = yield client.journeys(salzburgHbf, wienWestbahnhof, {
when, passedStations: true
})
@ -178,7 +183,6 @@ test('Salzburg Hbf to Wien Westbahnhof', co(function* (t) {
}))
test('Salzburg Hbf to 1220 Wien, Wagramer Straße 5', co(function* (t) {
const salzburgHbf = '8100002'
const wagramerStr = {
type: 'location',
latitude: 48.236216,
@ -223,7 +227,6 @@ test('Albertina to Salzburg Hbf', co(function* (t) {
name: 'Albertina',
id: '975900003'
}
const salzburgHbf = '8100002'
const journeys = yield client.journeys(albertina, salzburgHbf, {when})
t.ok(Array.isArray(journeys))
@ -255,9 +258,6 @@ test('Albertina to Salzburg Hbf', co(function* (t) {
}))
test('Wien to Klagenfurt Hbf with stopover at Salzburg Hbf', co(function* (t) {
const wien = '1190100'
const klagenfurtHbf = '8100085'
const salzburgHbf = '8100002'
const [journey] = yield client.journeys(wien, klagenfurtHbf, {
via: salzburgHbf,
results: 1,
@ -274,9 +274,57 @@ test('Wien to Klagenfurt Hbf with stopover at Salzburg Hbf', co(function* (t) {
t.end()
}))
test('earlier/later journeys, Salzburg Hbf -> Wien Westbahnhof', co(function* (t) {
const model = yield client.journeys(salzburgHbf, wienWestbahnhof, {
results: 3, when
})
t.equal(typeof model.earlierRef, 'string')
t.ok(model.earlierRef)
t.equal(typeof model.laterRef, 'string')
t.ok(model.laterRef)
// when and earlierThan/laterThan should be mutually exclusive
t.throws(() => {
client.journeys(salzburgHbf, wienWestbahnhof, {
when, earlierThan: model.earlierRef
})
})
t.throws(() => {
client.journeys(salzburgHbf, wienWestbahnhof, {
when, laterThan: model.laterRef
})
})
let earliestDep = Infinity, latestDep = -Infinity
for (let j of model) {
const dep = +new Date(j.departure)
if (dep < earliestDep) earliestDep = dep
else if (dep > latestDep) latestDep = dep
}
const earlier = yield client.journeys(salzburgHbf, wienWestbahnhof, {
results: 3,
// todo: single journey ref?
earlierThan: model.earlierRef
})
for (let j of earlier) {
t.ok(new Date(j.departure) < earliestDep)
}
const later = yield client.journeys(salzburgHbf, wienWestbahnhof, {
results: 3,
// todo: single journey ref?
laterThan: model.laterRef
})
for (let j of later) {
t.ok(new Date(j.departure) > latestDep)
}
t.end()
}))
test('leg details for Wien Westbahnhof to München Hbf', co(function* (t) {
const wienWestbahnhof = '1291501'
const muenchenHbf = '8000261'
const journeys = yield client.journeys(wienWestbahnhof, muenchenHbf, {
results: 1, when
})
@ -301,7 +349,6 @@ test('leg details for Wien Westbahnhof to München Hbf', co(function* (t) {
}))
test('departures at Salzburg Hbf', co(function* (t) {
const salzburgHbf = '8100002'
const deps = yield client.departures(salzburgHbf, {
duration: 5, when
})
@ -365,7 +412,6 @@ test('locations named Salzburg', co(function* (t) {
}))
test('location', co(function* (t) {
const grazHbf = '8100173'
const loc = yield client.location(grazHbf)
assertValidStation(t, loc)

View file

@ -166,6 +166,56 @@ test('journeys  fails with no product', co(function* (t) {
}
}))
test('earlier/later journeys', co(function* (t) {
const model = yield client.journeys(spichernstr, bismarckstr, {
results: 3, when
})
t.equal(typeof model.earlierRef, 'string')
t.ok(model.earlierRef)
t.equal(typeof model.laterRef, 'string')
t.ok(model.laterRef)
// when and earlierThan/laterThan should be mutually exclusive
t.throws(() => {
client.journeys(spichernstr, bismarckstr, {
when, earlierThan: model.earlierRef
})
})
t.throws(() => {
client.journeys(spichernstr, bismarckstr, {
when, laterThan: model.laterRef
})
})
let earliestDep = Infinity, latestDep = -Infinity
for (let j of model) {
const dep = +new Date(j.departure)
if (dep < earliestDep) earliestDep = dep
else if (dep > latestDep) latestDep = dep
}
const earlier = yield client.journeys(spichernstr, bismarckstr, {
results: 3,
// todo: single journey ref?
earlierThan: model.earlierRef
})
for (let j of earlier) {
t.ok(new Date(j.departure) < earliestDep)
}
const later = yield client.journeys(spichernstr, bismarckstr, {
results: 3,
// todo: single journey ref?
laterThan: model.laterRef
})
for (let j of later) {
t.ok(new Date(j.departure) > latestDep)
}
t.end()
}))
test('journey leg details', co(function* (t) {
const journeys = yield client.journeys(spichernstr, amrumerStr, {
results: 1, when