2016-06-22 01:39:04 +02:00
|
|
|
'use strict'
|
|
|
|
|
2017-11-12 14:52:04 +01:00
|
|
|
const defaultProfile = require('./lib/default-profile')
|
2017-11-11 22:49:04 +01:00
|
|
|
const request = require('./lib/request')
|
2016-06-22 02:09:02 +02:00
|
|
|
|
2017-11-11 22:49:04 +01:00
|
|
|
const createClient = (profile) => {
|
|
|
|
profile = Object.assign({}, defaultProfile, profile)
|
2017-11-12 01:23:34 +01:00
|
|
|
if ('string' !== typeof profile.timezone) {
|
|
|
|
throw new Error('profile.timezone must be a string.')
|
2016-06-22 01:39:59 +02:00
|
|
|
}
|
2017-10-03 17:36:42 +02:00
|
|
|
|
2017-11-12 18:06:16 +01:00
|
|
|
const departures = (station, opt = {}) => {
|
|
|
|
if ('string' !== typeof station) throw new Error('station must be a string.')
|
|
|
|
|
|
|
|
opt = Object.assign({
|
|
|
|
direction: null, // only show departures heading to this station
|
|
|
|
duration: 10 // show departures for the next n minutes
|
|
|
|
}, opt)
|
|
|
|
opt.when = opt.when || new Date()
|
|
|
|
const products = profile.formatProducts(opt.products || {})
|
|
|
|
|
|
|
|
const dir = opt.direction ? profile.formatStation(opt.direction) : null
|
|
|
|
return request(profile, {
|
|
|
|
meth: 'StationBoard',
|
|
|
|
req: {
|
|
|
|
type: 'DEP',
|
|
|
|
date: profile.formatDate(profile, opt.when),
|
|
|
|
time: profile.formatTime(profile, opt.when),
|
|
|
|
stbLoc: profile.formatStation(station),
|
|
|
|
dirLoc: dir,
|
2017-11-12 20:02:32 +01:00
|
|
|
jnyFltrL: [products],
|
2017-11-12 18:06:16 +01:00
|
|
|
dur: opt.duration,
|
|
|
|
getPasslist: false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then((d) => {
|
|
|
|
if (!Array.isArray(d.jnyL)) return [] // todo: throw err?
|
|
|
|
const parse = profile.parseDeparture(profile, d.locations, d.lines, d.remarks)
|
|
|
|
return d.jnyL.map(parse)
|
2017-11-18 10:14:17 +01:00
|
|
|
.sort((a, b) => new Date(a.when) - new Date(b.when))
|
2017-11-12 18:06:16 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-12 20:02:32 +01:00
|
|
|
const journeys = (from, to, opt = {}) => {
|
|
|
|
from = profile.formatLocation(profile, from)
|
|
|
|
to = profile.formatLocation(profile, to)
|
|
|
|
|
|
|
|
opt = Object.assign({
|
|
|
|
results: 5, // how many journeys?
|
|
|
|
via: null, // let journeys pass this station?
|
|
|
|
passedStations: false, // return stations on the way?
|
|
|
|
transfers: 5, // maximum of 5 transfers
|
|
|
|
transferTime: 0, // minimum time for a single transfer in minutes
|
|
|
|
// todo: does this work with every endpoint?
|
|
|
|
accessibility: 'none', // 'none', 'partial' or 'complete'
|
|
|
|
bike: false, // only bike-friendly journeys
|
|
|
|
}, opt)
|
|
|
|
if (opt.via) opt.via = profile.formatLocation(profile, opt.via)
|
|
|
|
opt.when = opt.when || new Date()
|
|
|
|
const products = profile.formatProducts(opt.products || {})
|
|
|
|
|
|
|
|
const query = profile.transformJourneysQuery({
|
|
|
|
outDate: profile.formatDate(profile, opt.when),
|
|
|
|
outTime: profile.formatTime(profile, opt.when),
|
|
|
|
numF: opt.results,
|
|
|
|
getPasslist: !!opt.passedStations,
|
|
|
|
maxChg: opt.transfers,
|
|
|
|
minChgTime: opt.transferTime,
|
|
|
|
depLocL: [from],
|
|
|
|
viaLocL: opt.via ? [opt.via] : null,
|
|
|
|
arrLocL: [to],
|
|
|
|
jnyFltrL: [products],
|
|
|
|
|
|
|
|
// todo: what is req.gisFltrL?
|
|
|
|
// todo: what are all these for?
|
|
|
|
getPT: true,
|
|
|
|
outFrwd: true,
|
|
|
|
getTariff: false,
|
|
|
|
getIV: false, // walk & bike as alternatives?
|
|
|
|
getPolyline: false // shape for displaying on a map?
|
|
|
|
}, opt)
|
|
|
|
|
|
|
|
return request(profile, {
|
|
|
|
cfg: {polyEnc: 'GPA'},
|
|
|
|
meth: 'TripSearch',
|
|
|
|
req: query
|
|
|
|
})
|
|
|
|
.then((d) => {
|
|
|
|
if (!Array.isArray(d.outConL)) return []
|
|
|
|
const parse = profile.parseJourney(profile, d.locations, d.lines, d.remarks)
|
|
|
|
return d.outConL.map(parse)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-12 20:19:33 +01:00
|
|
|
const locations = (query, opt = {}) => {
|
|
|
|
if ('string' !== typeof query) throw new Error('query must be a string.')
|
|
|
|
opt = Object.assign({
|
|
|
|
fuzzy: true, // find only exact matches?
|
|
|
|
results: 10, // how many search results?
|
|
|
|
stations: true,
|
|
|
|
addresses: true,
|
|
|
|
poi: true // points of interest
|
|
|
|
}, opt)
|
|
|
|
|
|
|
|
const f = profile.formatLocationFilter(opt.stations, opt.addresses, opt.poi)
|
|
|
|
return request(profile, {
|
|
|
|
cfg: {polyEnc: 'GPA'},
|
|
|
|
meth: 'LocMatch',
|
|
|
|
req: {input: {
|
|
|
|
loc: {
|
|
|
|
type: f,
|
|
|
|
name: opt.fuzzy ? query + '?' : query
|
|
|
|
},
|
|
|
|
maxLoc: opt.results,
|
|
|
|
field: 'S' // todo: what is this?
|
|
|
|
}}
|
|
|
|
})
|
|
|
|
.then((d) => {
|
|
|
|
if (!d.match || !Array.isArray(d.match.locL)) return []
|
|
|
|
const parse = profile.parseLocation
|
|
|
|
return d.match.locL.map(loc => parse(profile, loc))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-12 20:29:57 +01:00
|
|
|
const nearby = (latitude, longitude, opt = {}) => {
|
|
|
|
if ('number' !== typeof latitude) throw new Error('latitude must be a number.')
|
|
|
|
if ('number' !== typeof longitude) throw new Error('longitude must be a number.')
|
|
|
|
opt = Object.assign({
|
|
|
|
results: 8, // maximum number of results
|
|
|
|
distance: null, // maximum walking distance in meters
|
|
|
|
poi: false, // return points of interest?
|
|
|
|
stations: true, // return stations?
|
|
|
|
}, opt)
|
|
|
|
|
|
|
|
return request(profile, {
|
|
|
|
cfg: {polyEnc: 'GPA'},
|
|
|
|
meth: 'LocGeoPos',
|
|
|
|
req: {
|
|
|
|
ring: {
|
|
|
|
cCrd: {
|
|
|
|
x: profile.formatCoord(longitude),
|
|
|
|
y: profile.formatCoord(latitude)
|
|
|
|
},
|
|
|
|
maxDist: opt.distance || -1,
|
|
|
|
minDist: 0
|
|
|
|
},
|
|
|
|
getPOIs: !!opt.poi,
|
|
|
|
getStops: !!opt.stations,
|
|
|
|
maxLoc: opt.results
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then((d) => {
|
|
|
|
if (!Array.isArray(d.locL)) return []
|
|
|
|
const parse = profile.parseNearby
|
|
|
|
return d.locL.map(loc => parse(profile, loc))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return {departures, journeys, locations, nearby}
|
2016-06-22 01:39:59 +02:00
|
|
|
}
|
|
|
|
|
2017-11-12 14:52:04 +01:00
|
|
|
module.exports = createClient
|