mirror of
https://github.com/public-transport/db-vendo-client.git
synced 2025-02-23 15:19:35 +02:00
commit
7aba19f137
19 changed files with 343 additions and 591 deletions
|
@ -1,16 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const createFormatBitmask = (allProducts) => {
|
|
||||||
const formatBitmask = (products) => {
|
|
||||||
if(Object.keys(products).length === 0) throw new Error('products filter must not be empty')
|
|
||||||
let bitmask = 0
|
|
||||||
for (let product in products) {
|
|
||||||
if (!allProducts[product]) throw new Error('unknown product ' + product)
|
|
||||||
if (products[product] === true) bitmask += allProducts[product].bitmask
|
|
||||||
}
|
|
||||||
return bitmask
|
|
||||||
}
|
|
||||||
return formatBitmask
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = createFormatBitmask
|
|
35
format/products-filter.js
Normal file
35
format/products-filter.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const isObj = require('lodash/isObject')
|
||||||
|
|
||||||
|
const hasProp = (o, k) => Object.prototype.hasOwnProperty.call(o, k)
|
||||||
|
|
||||||
|
const createFormatProductsFilter = (profile) => {
|
||||||
|
const byProduct = {}
|
||||||
|
const defaultProducts = {}
|
||||||
|
for (let product of profile.products) {
|
||||||
|
byProduct[product.id] = product
|
||||||
|
defaultProducts[product.id] = product.default
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatProductsFilter = (filter) => {
|
||||||
|
if (!isObj(filter)) throw new Error('products filter must be an object')
|
||||||
|
filter = Object.assign({}, defaultProducts, filter)
|
||||||
|
|
||||||
|
let res = 0
|
||||||
|
for (let product in filter) {
|
||||||
|
if (!hasProp(filter, product) || filter[product] !== true) continue
|
||||||
|
if (!byProduct[product]) throw new Error('unknown product ' + product)
|
||||||
|
for (let bitmask of byProduct[product].bitmasks) res += bitmask
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'PROD',
|
||||||
|
mode: 'INC',
|
||||||
|
value: res + ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formatProductsFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = createFormatProductsFilter
|
18
index.js
18
index.js
|
@ -2,16 +2,24 @@
|
||||||
|
|
||||||
const minBy = require('lodash/minBy')
|
const minBy = require('lodash/minBy')
|
||||||
const maxBy = require('lodash/maxBy')
|
const maxBy = require('lodash/maxBy')
|
||||||
|
const isObj = require('lodash/isObject')
|
||||||
|
|
||||||
const validateProfile = require('./lib/validate-profile')
|
|
||||||
const defaultProfile = require('./lib/default-profile')
|
const defaultProfile = require('./lib/default-profile')
|
||||||
|
const createParseBitmask = require('./parse/products-bitmask')
|
||||||
|
const createFormatProductsFilter = require('./format/products-filter')
|
||||||
|
const validateProfile = require('./lib/validate-profile')
|
||||||
const _request = require('./lib/request')
|
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 isNonEmptyString = str => 'string' === typeof str && str.length > 0
|
||||||
|
|
||||||
const createClient = (profile, request = _request) => {
|
const createClient = (profile, request = _request) => {
|
||||||
profile = Object.assign({}, defaultProfile, profile)
|
profile = Object.assign({}, defaultProfile, profile)
|
||||||
|
if (!profile.parseProducts) {
|
||||||
|
profile.parseProducts = createParseBitmask(profile)
|
||||||
|
}
|
||||||
|
if (!profile.formatProductsFilter) {
|
||||||
|
profile.formatProductsFilter = createFormatProductsFilter(profile)
|
||||||
|
}
|
||||||
validateProfile(profile)
|
validateProfile(profile)
|
||||||
|
|
||||||
const departures = (station, opt = {}) => {
|
const departures = (station, opt = {}) => {
|
||||||
|
@ -24,7 +32,7 @@ const createClient = (profile, request = _request) => {
|
||||||
duration: 10 // show departures for the next n minutes
|
duration: 10 // show departures for the next n minutes
|
||||||
}, opt)
|
}, opt)
|
||||||
opt.when = opt.when || new Date()
|
opt.when = opt.when || new Date()
|
||||||
const products = profile.formatProducts(opt.products || {})
|
const products = profile.formatProductsFilter(opt.products || {})
|
||||||
|
|
||||||
const dir = opt.direction ? profile.formatStation(opt.direction) : null
|
const dir = opt.direction ? profile.formatStation(opt.direction) : null
|
||||||
return request(profile, {
|
return request(profile, {
|
||||||
|
@ -90,7 +98,7 @@ const createClient = (profile, request = _request) => {
|
||||||
opt.when = opt.when || new Date()
|
opt.when = opt.when || new Date()
|
||||||
|
|
||||||
const filters = [
|
const filters = [
|
||||||
profile.formatProducts(opt.products || {})
|
profile.formatProductsFilter(opt.products || {})
|
||||||
]
|
]
|
||||||
if (
|
if (
|
||||||
opt.accessibility &&
|
opt.accessibility &&
|
||||||
|
@ -317,7 +325,7 @@ const createClient = (profile, request = _request) => {
|
||||||
perStep: Math.round(durationPerStep),
|
perStep: Math.round(durationPerStep),
|
||||||
ageOfReport: true, // todo: what is this?
|
ageOfReport: true, // todo: what is this?
|
||||||
jnyFltrL: [
|
jnyFltrL: [
|
||||||
profile.formatProducts(opt.products || {})
|
profile.formatProductsFilter(opt.products || {})
|
||||||
],
|
],
|
||||||
trainPosMode: 'CALC' // todo: what is this? what about realtime?
|
trainPosMode: 'CALC' // todo: what is this? what about realtime?
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,27 @@ const validateProfile = (profile) => {
|
||||||
throw new Error(`profile.${key} must not be null.`)
|
throw new Error(`profile.${key} must not be null.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(profile.products)) {
|
||||||
|
throw new Error('profile.products must be an array.')
|
||||||
|
}
|
||||||
|
if (profile.products.length === 0) throw new Error('profile.products is empty.')
|
||||||
|
for (let product of profile.products) {
|
||||||
|
if ('string' !== typeof product.id) {
|
||||||
|
throw new Error('profile.products[].id must be a string.')
|
||||||
|
}
|
||||||
|
if ('boolean' !== typeof product.default) {
|
||||||
|
throw new Error('profile.products[].default must be a boolean.')
|
||||||
|
}
|
||||||
|
if (!Array.isArray(product.bitmasks)) {
|
||||||
|
throw new Error(product.id + '.bitmasks must be an array.')
|
||||||
|
}
|
||||||
|
for (let bitmask of product.bitmasks) {
|
||||||
|
if ('number' !== typeof bitmask) {
|
||||||
|
throw new Error(product.id + '.bitmasks[] must be a number.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = validateProfile
|
module.exports = validateProfile
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const _createParseLine = require('../../parse/line')
|
|
||||||
const _createParseJourney = require('../../parse/journey')
|
const _createParseJourney = require('../../parse/journey')
|
||||||
const _formatStation = require('../../format/station')
|
const _formatStation = require('../../format/station')
|
||||||
const createParseBitmask = require('../../parse/products-bitmask')
|
|
||||||
const createFormatBitmask = require('../../format/products-bitmask')
|
|
||||||
const {bike} = require('../../format/filters')
|
const {bike} = require('../../format/filters')
|
||||||
|
|
||||||
const modes = require('./modes')
|
const products = require('./products')
|
||||||
const formatLoyaltyCard = require('./loyalty-cards').format
|
const formatLoyaltyCard = require('./loyalty-cards').format
|
||||||
|
|
||||||
const formatBitmask = createFormatBitmask(modes)
|
|
||||||
|
|
||||||
const transformReqBody = (body) => {
|
const transformReqBody = (body) => {
|
||||||
body.client = {id: 'DB', v: '16040000', type: 'IPH', name: 'DB Navigator'}
|
body.client = {id: 'DB', v: '16040000', type: 'IPH', name: 'DB Navigator'}
|
||||||
body.ext = 'DB.R15.12.a'
|
body.ext = 'DB.R15.12.a'
|
||||||
|
@ -39,26 +34,6 @@ const transformJourneysQuery = (query, opt) => {
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
const createParseLine = (profile, operators) => {
|
|
||||||
const parseLine = _createParseLine(profile, operators)
|
|
||||||
|
|
||||||
const parseLineWithMode = (l) => {
|
|
||||||
const res = parseLine(l)
|
|
||||||
|
|
||||||
res.mode = res.product = null
|
|
||||||
if ('class' in res) {
|
|
||||||
const data = modes.bitmasks[parseInt(res.class)]
|
|
||||||
if (data) {
|
|
||||||
res.mode = data.mode
|
|
||||||
res.product = data.product
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
return parseLineWithMode
|
|
||||||
}
|
|
||||||
|
|
||||||
const createParseJourney = (profile, stations, lines, remarks) => {
|
const createParseJourney = (profile, stations, lines, remarks) => {
|
||||||
const parseJourney = _createParseJourney(profile, stations, lines, remarks)
|
const parseJourney = _createParseJourney(profile, stations, lines, remarks)
|
||||||
|
|
||||||
|
@ -103,27 +78,6 @@ const formatStation = (id) => {
|
||||||
return _formatStation(id)
|
return _formatStation(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultProducts = {
|
|
||||||
suburban: true,
|
|
||||||
subway: true,
|
|
||||||
tram: true,
|
|
||||||
bus: true,
|
|
||||||
ferry: true,
|
|
||||||
national: true,
|
|
||||||
nationalExp: true,
|
|
||||||
regional: true,
|
|
||||||
regionalExp: true,
|
|
||||||
taxi: false
|
|
||||||
}
|
|
||||||
const formatProducts = (products) => {
|
|
||||||
products = Object.assign(Object.create(null), defaultProducts, products)
|
|
||||||
return {
|
|
||||||
type: 'PROD',
|
|
||||||
mode: 'INC',
|
|
||||||
value: formatBitmask(products) + ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: find option for absolute number of results
|
// todo: find option for absolute number of results
|
||||||
|
|
||||||
const dbProfile = {
|
const dbProfile = {
|
||||||
|
@ -137,15 +91,12 @@ const dbProfile = {
|
||||||
transformReqBody,
|
transformReqBody,
|
||||||
transformJourneysQuery,
|
transformJourneysQuery,
|
||||||
|
|
||||||
products: modes.allProducts,
|
products: products,
|
||||||
|
|
||||||
// todo: parseLocation
|
// todo: parseLocation
|
||||||
parseLine: createParseLine,
|
|
||||||
parseProducts: createParseBitmask(modes.allProducts, defaultProducts),
|
|
||||||
parseJourney: createParseJourney,
|
parseJourney: createParseJourney,
|
||||||
|
|
||||||
formatStation,
|
formatStation
|
||||||
formatProducts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = dbProfile
|
module.exports = dbProfile
|
||||||
|
|
108
p/db/modes.js
108
p/db/modes.js
|
@ -1,108 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
// todo: https://gist.github.com/anonymous/d3323a5d2d6e159ed42b12afd0380434#file-haf_products-properties-L1-L95
|
|
||||||
const m = {
|
|
||||||
nationalExp: {
|
|
||||||
bitmask: 1,
|
|
||||||
name: 'InterCityExpress',
|
|
||||||
short: 'ICE',
|
|
||||||
mode: 'train',
|
|
||||||
product: 'nationalExp'
|
|
||||||
},
|
|
||||||
national: {
|
|
||||||
bitmask: 2,
|
|
||||||
name: 'InterCity & EuroCity',
|
|
||||||
short: 'IC/EC',
|
|
||||||
mode: 'train',
|
|
||||||
product: 'national'
|
|
||||||
},
|
|
||||||
regionalExp: {
|
|
||||||
bitmask: 4,
|
|
||||||
name: 'RegionalExpress & InterRegio',
|
|
||||||
short: 'RE/IR',
|
|
||||||
mode: 'train',
|
|
||||||
product: 'regionalExp'
|
|
||||||
},
|
|
||||||
regional: {
|
|
||||||
bitmask: 8,
|
|
||||||
name: 'Regio',
|
|
||||||
short: 'RB',
|
|
||||||
mode: 'train',
|
|
||||||
product: 'regional'
|
|
||||||
},
|
|
||||||
suburban: {
|
|
||||||
bitmask: 16,
|
|
||||||
name: 'S-Bahn',
|
|
||||||
short: 'S',
|
|
||||||
mode: 'train',
|
|
||||||
product: 'suburban'
|
|
||||||
},
|
|
||||||
bus: {
|
|
||||||
bitmask: 32,
|
|
||||||
name: 'Bus',
|
|
||||||
short: 'B',
|
|
||||||
mode: 'bus',
|
|
||||||
product: 'bus'
|
|
||||||
},
|
|
||||||
ferry: {
|
|
||||||
bitmask: 64,
|
|
||||||
name: 'Ferry',
|
|
||||||
short: 'F',
|
|
||||||
mode: 'watercraft',
|
|
||||||
product: 'ferry'
|
|
||||||
},
|
|
||||||
subway: {
|
|
||||||
bitmask: 128,
|
|
||||||
name: 'U-Bahn',
|
|
||||||
short: 'U',
|
|
||||||
mode: 'train',
|
|
||||||
product: 'subway'
|
|
||||||
},
|
|
||||||
tram: {
|
|
||||||
bitmask: 256,
|
|
||||||
name: 'Tram',
|
|
||||||
short: 'T',
|
|
||||||
mode: 'tram',
|
|
||||||
product: 'tram'
|
|
||||||
},
|
|
||||||
taxi: {
|
|
||||||
bitmask: 512,
|
|
||||||
name: 'Group Taxi',
|
|
||||||
short: 'Taxi',
|
|
||||||
mode: 'taxi',
|
|
||||||
product: 'taxi'
|
|
||||||
},
|
|
||||||
unknown: {
|
|
||||||
bitmask: 0,
|
|
||||||
name: 'unknown',
|
|
||||||
short: '?',
|
|
||||||
product: 'unknown'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.bitmasks = []
|
|
||||||
m.bitmasks[1] = m.nationalExp
|
|
||||||
m.bitmasks[2] = m.national
|
|
||||||
m.bitmasks[4] = m.regionalExp
|
|
||||||
m.bitmasks[8] = m.regional
|
|
||||||
m.bitmasks[16] = m.suburban
|
|
||||||
m.bitmasks[32] = m.bus
|
|
||||||
m.bitmasks[64] = m.ferry
|
|
||||||
m.bitmasks[128] = m.subway
|
|
||||||
m.bitmasks[256] = m.tram
|
|
||||||
m.bitmasks[512] = m.taxi
|
|
||||||
|
|
||||||
m.allProducts = [
|
|
||||||
m.nationalExp,
|
|
||||||
m.national,
|
|
||||||
m.regionalExp,
|
|
||||||
m.regional,
|
|
||||||
m.suburban,
|
|
||||||
m.bus,
|
|
||||||
m.ferry,
|
|
||||||
m.subway,
|
|
||||||
m.tram,
|
|
||||||
m.taxi
|
|
||||||
]
|
|
||||||
|
|
||||||
module.exports = m
|
|
85
p/db/products.js
Normal file
85
p/db/products.js
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
// todo: https://gist.github.com/anonymous/d3323a5d2d6e159ed42b12afd0380434#file-haf_products-properties-L1-L95
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
id: 'nationalExp',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [1],
|
||||||
|
name: 'InterCityExpress',
|
||||||
|
short: 'ICE',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'national',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [2],
|
||||||
|
name: 'InterCity & EuroCity',
|
||||||
|
short: 'IC/EC',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'regionalExp',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [4],
|
||||||
|
name: 'RegionalExpress & InterRegio',
|
||||||
|
short: 'RE/IR',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'regional',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [8],
|
||||||
|
name: 'Regio',
|
||||||
|
short: 'RB',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'suburban',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [16],
|
||||||
|
name: 'S-Bahn',
|
||||||
|
short: 'S',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'bus',
|
||||||
|
mode: 'bus',
|
||||||
|
bitmasks: [32],
|
||||||
|
name: 'Bus',
|
||||||
|
short: 'B',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ferry',
|
||||||
|
mode: 'watercraft',
|
||||||
|
bitmasks: [64],
|
||||||
|
name: 'Ferry',
|
||||||
|
short: 'F',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'subway',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [128],
|
||||||
|
name: 'U-Bahn',
|
||||||
|
short: 'U',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'tram',
|
||||||
|
mode: 'tram',
|
||||||
|
bitmasks: [256],
|
||||||
|
name: 'Tram',
|
||||||
|
short: 'T',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'taxi',
|
||||||
|
mode: 'taxi',
|
||||||
|
bitmasks: [512],
|
||||||
|
name: 'Group Taxi',
|
||||||
|
short: 'Taxi',
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
]
|
|
@ -1,20 +1,6 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const _createParseLine = require('../../parse/line')
|
|
||||||
const products = require('./products')
|
const products = require('./products')
|
||||||
const createParseBitmask = require('../../parse/products-bitmask')
|
|
||||||
const createFormatBitmask = require('../../format/products-bitmask')
|
|
||||||
|
|
||||||
const defaultProducts = {
|
|
||||||
nationalExp: true,
|
|
||||||
national: true,
|
|
||||||
regional: true,
|
|
||||||
suburban: true,
|
|
||||||
bus: true,
|
|
||||||
tram: true,
|
|
||||||
tourismTrain: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const transformReqBody = (body) => {
|
const transformReqBody = (body) => {
|
||||||
body.client = {
|
body.client = {
|
||||||
|
@ -31,49 +17,13 @@ const transformReqBody = (body) => {
|
||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
|
|
||||||
const createParseLine = (profile, operators) => {
|
|
||||||
const parseLine = _createParseLine(profile, operators)
|
|
||||||
|
|
||||||
const parseLineWithMode = (l) => {
|
|
||||||
const res = parseLine(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
|
|
||||||
}
|
|
||||||
return parseLineWithMode
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatProducts = (products) => {
|
|
||||||
products = Object.assign(Object.create(null), defaultProducts, products)
|
|
||||||
return {
|
|
||||||
type: 'PROD',
|
|
||||||
mode: 'INC',
|
|
||||||
value: formatBitmask(products) + ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatBitmask = createFormatBitmask(products)
|
|
||||||
|
|
||||||
|
|
||||||
const insaProfile = {
|
const insaProfile = {
|
||||||
locale: 'de-DE',
|
locale: 'de-DE',
|
||||||
timezone: 'Europe/Berlin',
|
timezone: 'Europe/Berlin',
|
||||||
endpoint: 'http://reiseauskunft.insa.de/bin/mgate.exe',
|
endpoint: 'http://reiseauskunft.insa.de/bin/mgate.exe',
|
||||||
transformReqBody,
|
transformReqBody,
|
||||||
|
|
||||||
products: products.allProducts,
|
products: products,
|
||||||
parseProducts: createParseBitmask(products.allProducts, defaultProducts),
|
|
||||||
formatProducts,
|
|
||||||
|
|
||||||
parseLine: createParseLine,
|
|
||||||
|
|
||||||
journeyLeg: true,
|
journeyLeg: true,
|
||||||
radar: true
|
radar: true
|
||||||
|
|
|
@ -1,82 +1,60 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
// TODO Jannis R.: DRY
|
module.exports = [
|
||||||
const p = {
|
{
|
||||||
nationalExp: {
|
id: 'nationalExp',
|
||||||
bitmask: 1,
|
mode: 'train',
|
||||||
|
bitmasks: [1],
|
||||||
name: 'InterCityExpress',
|
name: 'InterCityExpress',
|
||||||
short: 'ICE',
|
short: 'ICE',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'nationalExp'
|
|
||||||
},
|
},
|
||||||
national: {
|
{
|
||||||
bitmask: 2,
|
id: 'national',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [2],
|
||||||
name: 'InterCity & EuroCity',
|
name: 'InterCity & EuroCity',
|
||||||
short: 'IC/EC',
|
short: 'IC/EC',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'national'
|
|
||||||
},
|
},
|
||||||
regional: {
|
{
|
||||||
bitmask: 8,
|
id: 'regional',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [8],
|
||||||
name: 'RegionalExpress & RegionalBahn',
|
name: 'RegionalExpress & RegionalBahn',
|
||||||
short: 'RE/RB',
|
short: 'RE/RB',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'regional'
|
|
||||||
},
|
},
|
||||||
suburban: {
|
{
|
||||||
bitmask: 16,
|
id: 'suburban',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [16],
|
||||||
name: 'S-Bahn',
|
name: 'S-Bahn',
|
||||||
short: 'S',
|
short: 'S',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'suburban'
|
|
||||||
},
|
},
|
||||||
tram: {
|
{
|
||||||
bitmask: 32,
|
id: 'tram',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [32],
|
||||||
name: 'Tram',
|
name: 'Tram',
|
||||||
short: 'T',
|
short: 'T',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'tram'
|
|
||||||
},
|
},
|
||||||
bus: {
|
{
|
||||||
bitmask: 64+128,
|
id: 'bus',
|
||||||
|
mode: 'bus',
|
||||||
|
bitmasks: [64, 128],
|
||||||
name: 'Bus',
|
name: 'Bus',
|
||||||
short: 'B',
|
short: 'B',
|
||||||
mode: 'bus',
|
default: true
|
||||||
product: 'bus'
|
|
||||||
},
|
},
|
||||||
tourismTrain: {
|
{
|
||||||
bitmask: 256,
|
id: 'tourismTrain',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [256],
|
||||||
name: 'Tourism Train',
|
name: 'Tourism Train',
|
||||||
short: 'TT',
|
short: 'TT',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'tourismTrain'
|
|
||||||
},
|
|
||||||
unknown: {
|
|
||||||
bitmask: 0,
|
|
||||||
name: 'unknown',
|
|
||||||
short: '?',
|
|
||||||
product: 'unknown'
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
p.bitmasks = []
|
|
||||||
p.bitmasks[1] = p.nationalExp
|
|
||||||
p.bitmasks[2] = p.national
|
|
||||||
p.bitmasks[8] = p.regional
|
|
||||||
p.bitmasks[16] = p.suburban
|
|
||||||
p.bitmasks[32] = p.tram
|
|
||||||
p.bitmasks[64] = p.bus
|
|
||||||
p.bitmasks[128] = p.bus
|
|
||||||
p.bitmasks[256] = p.tourismTrain
|
|
||||||
|
|
||||||
p.allProducts = [
|
|
||||||
p.nationalExp,
|
|
||||||
p.national,
|
|
||||||
p.regional,
|
|
||||||
p.suburban,
|
|
||||||
p.tram,
|
|
||||||
p.bus,
|
|
||||||
p.tourismTrain
|
|
||||||
]
|
]
|
||||||
|
|
||||||
module.exports = p
|
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
// 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-L5
|
||||||
// todo: https://gist.github.com/anonymous/a5fc856bc80ae7364721943243f934f4#file-haf_config_base-properties-L47-L234
|
// 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 _createParseLine = require('../../parse/line')
|
|
||||||
const _parseLocation = require('../../parse/location')
|
const _parseLocation = require('../../parse/location')
|
||||||
const _createParseMovement = require('../../parse/movement')
|
const _createParseMovement = require('../../parse/movement')
|
||||||
|
|
||||||
|
@ -28,26 +25,6 @@ const transformReqBody = (body) => {
|
||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
|
|
||||||
const createParseLine = (profile, operators) => {
|
|
||||||
const parseLine = _createParseLine(profile, operators)
|
|
||||||
|
|
||||||
const parseLineWithMode = (l) => {
|
|
||||||
const res = parseLine(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
|
|
||||||
}
|
|
||||||
return parseLineWithMode
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseLocation = (profile, l, lines) => {
|
const parseLocation = (profile, l, lines) => {
|
||||||
// ÖBB has some 'stations' **in austria** with no departures/products,
|
// ÖBB has some 'stations' **in austria** with no departures/products,
|
||||||
// like station entrances, that are actually POIs.
|
// like station entrances, that are actually POIs.
|
||||||
|
@ -82,28 +59,6 @@ const createParseMovement = (profile, locations, lines, remarks) => {
|
||||||
return parseMovement
|
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',
|
||||||
|
@ -111,15 +66,11 @@ const oebbProfile = {
|
||||||
endpoint: 'http://fahrplan.oebb.at/bin/mgate.exe',
|
endpoint: 'http://fahrplan.oebb.at/bin/mgate.exe',
|
||||||
transformReqBody,
|
transformReqBody,
|
||||||
|
|
||||||
products: products.allProducts,
|
products: products,
|
||||||
|
|
||||||
parseProducts: createParseBitmask(products.allProducts, defaultProducts),
|
|
||||||
parseLine: createParseLine,
|
|
||||||
parseLocation,
|
parseLocation,
|
||||||
parseMovement: createParseMovement,
|
parseMovement: createParseMovement,
|
||||||
|
|
||||||
formatProducts,
|
|
||||||
|
|
||||||
journeyLeg: true,
|
journeyLeg: true,
|
||||||
radar: true
|
radar: true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,112 +1,84 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const p = {
|
module.exports = [
|
||||||
nationalExp: {
|
{
|
||||||
bitmask: 1,
|
id: 'nationalExp',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [1],
|
||||||
name: 'InterCityExpress & RailJet',
|
name: 'InterCityExpress & RailJet',
|
||||||
short: 'ICE/RJ',
|
short: 'ICE/RJ',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'nationalExp'
|
|
||||||
},
|
},
|
||||||
national: {
|
{
|
||||||
bitmask: 2 + 4,
|
id: 'national',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [2, 4],
|
||||||
name: 'InterCity & EuroCity',
|
name: 'InterCity & EuroCity',
|
||||||
short: 'IC/EC',
|
short: 'IC/EC',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'national'
|
|
||||||
},
|
},
|
||||||
interregional: {
|
{
|
||||||
bitmask: 8 + 4096,
|
id: 'interregional',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [8, 4096],
|
||||||
name: 'Durchgangszug & EuroNight',
|
name: 'Durchgangszug & EuroNight',
|
||||||
short: 'D/EN',
|
short: 'D/EN',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'interregional'
|
|
||||||
},
|
},
|
||||||
regional: {
|
{
|
||||||
bitmask: 16,
|
id: 'regional',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [16],
|
||||||
name: 'Regional & RegionalExpress',
|
name: 'Regional & RegionalExpress',
|
||||||
short: 'R/REX',
|
short: 'R/REX',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'regional'
|
|
||||||
},
|
},
|
||||||
suburban: {
|
{
|
||||||
bitmask: 32,
|
id: 'suburban',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [32],
|
||||||
name: 'S-Bahn',
|
name: 'S-Bahn',
|
||||||
short: 'S',
|
short: 'S',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'suburban'
|
|
||||||
},
|
},
|
||||||
bus: {
|
{
|
||||||
bitmask: 64,
|
id: 'bus',
|
||||||
|
mode: 'bus',
|
||||||
|
bitmasks: [64],
|
||||||
name: 'Bus',
|
name: 'Bus',
|
||||||
short: 'B',
|
short: 'B',
|
||||||
mode: 'bus',
|
default: true
|
||||||
product: 'bus'
|
|
||||||
},
|
},
|
||||||
ferry: {
|
{
|
||||||
bitmask: 128,
|
id: 'ferry',
|
||||||
|
mode: 'watercraft',
|
||||||
|
bitmasks: [128],
|
||||||
name: 'Ferry',
|
name: 'Ferry',
|
||||||
short: 'F',
|
short: 'F',
|
||||||
mode: 'watercraft',
|
default: true
|
||||||
product: 'ferry'
|
|
||||||
},
|
},
|
||||||
subway: {
|
{
|
||||||
bitmask: 256,
|
id: 'subway',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [256],
|
||||||
name: 'U-Bahn',
|
name: 'U-Bahn',
|
||||||
short: 'U',
|
short: 'U',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'subway'
|
|
||||||
},
|
},
|
||||||
tram: {
|
{
|
||||||
bitmask: 512,
|
id: 'tram',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [512],
|
||||||
name: 'Tram',
|
name: 'Tram',
|
||||||
short: 'T',
|
short: 'T',
|
||||||
mode: 'train',
|
default: true
|
||||||
product: 'tram'
|
|
||||||
},
|
},
|
||||||
onCall: {
|
{
|
||||||
bitmask: 2048,
|
id: 'onCall',
|
||||||
|
mode: null, // todo
|
||||||
|
bitmasks: [2048],
|
||||||
name: 'On-call transit',
|
name: 'On-call transit',
|
||||||
short: 'on-call',
|
short: 'on-call',
|
||||||
mode: null, // todo
|
default: true
|
||||||
product: 'onCall'
|
|
||||||
},
|
|
||||||
unknown: {
|
|
||||||
bitmask: 0,
|
|
||||||
name: 'unknown',
|
|
||||||
short: '?',
|
|
||||||
product: 'unknown'
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
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,
|
|
||||||
p.national,
|
|
||||||
p.interregional,
|
|
||||||
p.regional,
|
|
||||||
p.suburban,
|
|
||||||
p.bus,
|
|
||||||
p.ferry,
|
|
||||||
p.subway,
|
|
||||||
p.tram,
|
|
||||||
p.onCall
|
|
||||||
]
|
]
|
||||||
|
|
||||||
module.exports = p
|
|
||||||
|
|
|
@ -12,12 +12,8 @@ const _createParseJourney = require('../../parse/journey')
|
||||||
const _createParseStopover = require('../../parse/stopover')
|
const _createParseStopover = require('../../parse/stopover')
|
||||||
const _createParseDeparture = require('../../parse/departure')
|
const _createParseDeparture = require('../../parse/departure')
|
||||||
const _formatStation = require('../../format/station')
|
const _formatStation = require('../../format/station')
|
||||||
const createParseBitmask = require('../../parse/products-bitmask')
|
|
||||||
const createFormatBitmask = require('../../format/products-bitmask')
|
|
||||||
|
|
||||||
const modes = require('./modes')
|
const products = require('./products')
|
||||||
|
|
||||||
const formatBitmask = createFormatBitmask(modes)
|
|
||||||
|
|
||||||
const transformReqBody = (body) => {
|
const transformReqBody = (body) => {
|
||||||
body.client = {type: 'IPA', id: 'VBB', name: 'vbbPROD', v: '4010300'}
|
body.client = {type: 'IPA', id: 'VBB', name: 'vbbPROD', v: '4010300'}
|
||||||
|
@ -31,18 +27,9 @@ const transformReqBody = (body) => {
|
||||||
const createParseLine = (profile, operators) => {
|
const createParseLine = (profile, operators) => {
|
||||||
const parseLine = _createParseLine(profile, operators)
|
const parseLine = _createParseLine(profile, operators)
|
||||||
|
|
||||||
const parseLineWithMode = (l) => {
|
const parseLineWithMoreDetails = (l) => {
|
||||||
const res = parseLine(l)
|
const res = parseLine(l)
|
||||||
|
|
||||||
res.mode = res.product = null
|
|
||||||
if ('class' in res) {
|
|
||||||
const data = modes.bitmasks[parseInt(res.class)]
|
|
||||||
if (data) {
|
|
||||||
res.mode = data.mode
|
|
||||||
res.product = data.product
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const details = parseLineName(l.name)
|
const details = parseLineName(l.name)
|
||||||
res.symbol = details.symbol
|
res.symbol = details.symbol
|
||||||
res.nr = details.nr
|
res.nr = details.nr
|
||||||
|
@ -52,7 +39,7 @@ const createParseLine = (profile, operators) => {
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
return parseLineWithMode
|
return parseLineWithMoreDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseLocation = (profile, l, lines) => {
|
const parseLocation = (profile, l, lines) => {
|
||||||
|
@ -146,24 +133,6 @@ const formatStation = (id) => {
|
||||||
return _formatStation(id)
|
return _formatStation(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultProducts = {
|
|
||||||
suburban: true,
|
|
||||||
subway: true,
|
|
||||||
tram: true,
|
|
||||||
bus: true,
|
|
||||||
ferry: true,
|
|
||||||
express: true,
|
|
||||||
regional: true
|
|
||||||
}
|
|
||||||
const formatProducts = (products) => {
|
|
||||||
products = Object.assign(Object.create(null), defaultProducts, products)
|
|
||||||
return {
|
|
||||||
type: 'PROD',
|
|
||||||
mode: 'INC',
|
|
||||||
value: formatBitmask(products) + ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const vbbProfile = {
|
const vbbProfile = {
|
||||||
locale: 'de-DE',
|
locale: 'de-DE',
|
||||||
timezone: 'Europe/Berlin',
|
timezone: 'Europe/Berlin',
|
||||||
|
@ -176,18 +145,16 @@ const vbbProfile = {
|
||||||
|
|
||||||
transformReqBody,
|
transformReqBody,
|
||||||
|
|
||||||
products: modes.allProducts,
|
products: products,
|
||||||
|
|
||||||
parseStationName: shorten,
|
parseStationName: shorten,
|
||||||
parseLocation,
|
parseLocation,
|
||||||
parseLine: createParseLine,
|
parseLine: createParseLine,
|
||||||
parseProducts: createParseBitmask(modes.allProducts, defaultProducts),
|
|
||||||
parseJourney: createParseJourney,
|
parseJourney: createParseJourney,
|
||||||
parseDeparture: createParseDeparture,
|
parseDeparture: createParseDeparture,
|
||||||
parseStopover: createParseStopover,
|
parseStopover: createParseStopover,
|
||||||
|
|
||||||
formatStation,
|
formatStation,
|
||||||
formatProducts,
|
|
||||||
|
|
||||||
journeysNumF: false,
|
journeysNumF: false,
|
||||||
journeyLeg: true,
|
journeyLeg: true,
|
||||||
|
|
112
p/vbb/modes.js
112
p/vbb/modes.js
|
@ -1,112 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
// todo: remove useless keys
|
|
||||||
const m = {
|
|
||||||
suburban: {
|
|
||||||
category: 0,
|
|
||||||
bitmask: 1,
|
|
||||||
name: 'S-Bahn',
|
|
||||||
mode: 'train',
|
|
||||||
short: 'S',
|
|
||||||
product: 'suburban'
|
|
||||||
},
|
|
||||||
|
|
||||||
subway: {
|
|
||||||
category: 1,
|
|
||||||
bitmask: 2,
|
|
||||||
name: 'U-Bahn',
|
|
||||||
mode: 'train',
|
|
||||||
short: 'U',
|
|
||||||
product: 'subway'
|
|
||||||
},
|
|
||||||
|
|
||||||
tram: {
|
|
||||||
category: 2,
|
|
||||||
bitmask: 4,
|
|
||||||
name: 'Tram',
|
|
||||||
mode: 'train',
|
|
||||||
short: 'T',
|
|
||||||
product: 'tram'
|
|
||||||
},
|
|
||||||
|
|
||||||
bus: {
|
|
||||||
category: 3,
|
|
||||||
bitmask: 8,
|
|
||||||
name: 'Bus',
|
|
||||||
mode: 'bus',
|
|
||||||
short: 'B',
|
|
||||||
product: 'bus'
|
|
||||||
},
|
|
||||||
|
|
||||||
ferry: {
|
|
||||||
category: 4,
|
|
||||||
bitmask: 16,
|
|
||||||
name: 'Fähre',
|
|
||||||
mode: 'watercraft',
|
|
||||||
short: 'F',
|
|
||||||
product: 'ferry'
|
|
||||||
},
|
|
||||||
|
|
||||||
express: {
|
|
||||||
category: 5,
|
|
||||||
bitmask: 32,
|
|
||||||
name: 'IC/ICE',
|
|
||||||
mode: 'train',
|
|
||||||
short: 'E',
|
|
||||||
product: 'express'
|
|
||||||
},
|
|
||||||
|
|
||||||
regional: {
|
|
||||||
category: 6,
|
|
||||||
bitmask: 64,
|
|
||||||
name: 'RB/RE',
|
|
||||||
mode: 'train',
|
|
||||||
short: 'R',
|
|
||||||
product: 'regional'
|
|
||||||
},
|
|
||||||
|
|
||||||
unknown: {
|
|
||||||
category: null,
|
|
||||||
bitmask: 0,
|
|
||||||
name: 'unknown',
|
|
||||||
mode: null,
|
|
||||||
short: '?',
|
|
||||||
product: 'unknown'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.bitmasks = []
|
|
||||||
m.bitmasks[1] = m.suburban
|
|
||||||
m.bitmasks[2] = m.subway
|
|
||||||
m.bitmasks[4] = m.tram
|
|
||||||
m.bitmasks[8] = m.bus
|
|
||||||
m.bitmasks[16] = m.ferry
|
|
||||||
m.bitmasks[32] = m.express
|
|
||||||
m.bitmasks[64] = m.regional
|
|
||||||
|
|
||||||
m.categories = [
|
|
||||||
m.suburban,
|
|
||||||
m.subway,
|
|
||||||
m.tram,
|
|
||||||
m.bus,
|
|
||||||
m.ferry,
|
|
||||||
m.express,
|
|
||||||
m.regional,
|
|
||||||
m.unknown
|
|
||||||
]
|
|
||||||
|
|
||||||
m.allProducts = [
|
|
||||||
m.suburban,
|
|
||||||
m.subway,
|
|
||||||
m.tram,
|
|
||||||
m.bus,
|
|
||||||
m.ferry,
|
|
||||||
m.express,
|
|
||||||
m.regional
|
|
||||||
]
|
|
||||||
|
|
||||||
// m.parseCategory = (category) => {
|
|
||||||
// return m.categories[parseInt(category)] || m.unknown
|
|
||||||
// }
|
|
||||||
|
|
||||||
module.exports = m
|
|
60
p/vbb/products.js
Normal file
60
p/vbb/products.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
id: 'suburban',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [1],
|
||||||
|
name: 'S-Bahn',
|
||||||
|
short: 'S',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'subway',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [2],
|
||||||
|
name: 'U-Bahn',
|
||||||
|
short: 'U',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'tram',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [4],
|
||||||
|
name: 'Tram',
|
||||||
|
short: 'T',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'bus',
|
||||||
|
mode: 'bus',
|
||||||
|
bitmasks: [8],
|
||||||
|
name: 'Bus',
|
||||||
|
short: 'B',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ferry',
|
||||||
|
mode: 'watercraft',
|
||||||
|
bitmasks: [16],
|
||||||
|
name: 'Fähre',
|
||||||
|
short: 'F',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'express',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [32],
|
||||||
|
name: 'IC/ICE',
|
||||||
|
short: 'E',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'regional',
|
||||||
|
mode: 'train',
|
||||||
|
bitmasks: [64],
|
||||||
|
name: 'RB/RE',
|
||||||
|
short: 'R',
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
]
|
|
@ -2,8 +2,14 @@
|
||||||
|
|
||||||
const slugg = require('slugg')
|
const slugg = require('slugg')
|
||||||
|
|
||||||
// todo: are p.number and p.line ever different?
|
|
||||||
const createParseLine = (profile, operators) => {
|
const createParseLine = (profile, operators) => {
|
||||||
|
const byBitmask = []
|
||||||
|
for (let product of profile.products) {
|
||||||
|
for (let bitmask of product.bitmasks) {
|
||||||
|
byBitmask[bitmask] = product
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const parseLine = (p) => {
|
const parseLine = (p) => {
|
||||||
if (!p) return null // todo: handle this upstream
|
if (!p) return null // todo: handle this upstream
|
||||||
const res = {
|
const res = {
|
||||||
|
@ -13,8 +19,9 @@ const createParseLine = (profile, operators) => {
|
||||||
public: true
|
public: true
|
||||||
}
|
}
|
||||||
// todo: what is p.prodCtx && p.prodCtx.num?
|
// todo: what is p.prodCtx && p.prodCtx.num?
|
||||||
|
// todo: what is p.number?
|
||||||
|
|
||||||
// This is terrible, but FPTF demands an ID. Let's pray for VBB to expose an ID.
|
// This is terrible, but FPTF demands an ID. Let's pray for HaCon to expose an ID.
|
||||||
// todo: find a better way
|
// todo: find a better way
|
||||||
if (p.line) res.id = slugg(p.line.trim())
|
if (p.line) res.id = slugg(p.line.trim())
|
||||||
else if (p.name) res.id = slugg(p.name.trim())
|
else if (p.name) res.id = slugg(p.name.trim())
|
||||||
|
@ -24,7 +31,12 @@ const createParseLine = (profile, operators) => {
|
||||||
res.productCode = +p.prodCtx.catCode
|
res.productCode = +p.prodCtx.catCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: parse mode, remove from profiles
|
if ('class' in res) {
|
||||||
|
// todo: what if `res.class` is the sum of two bitmasks?
|
||||||
|
const product = byBitmask[parseInt(res.class)]
|
||||||
|
res.mode = product && product.mode || null
|
||||||
|
res.product = product && product.id || null
|
||||||
|
}
|
||||||
|
|
||||||
if ('number' === typeof p.oprX) {
|
if ('number' === typeof p.oprX) {
|
||||||
res.operator = operators[p.oprX] || null
|
res.operator = operators[p.oprX] || null
|
||||||
|
|
|
@ -1,25 +1,23 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const createParseBitmask = (allProducts, defaultProducts) => {
|
const createParseBitmask = (profile) => {
|
||||||
allProducts = allProducts.sort((p1, p2) => p2.bitmask - p1.bitmask) // desc
|
const defaultProducts = {}
|
||||||
if (allProducts.length === 0) throw new Error('allProducts is empty.')
|
let withBitmask = []
|
||||||
for (let product of allProducts) {
|
for (let product of profile.products) {
|
||||||
if ('string' !== typeof product.product) {
|
defaultProducts[product.id] = false
|
||||||
throw new Error('allProducts[].product must be a string.')
|
for (let bitmask of product.bitmasks) {
|
||||||
}
|
withBitmask.push([bitmask, product])
|
||||||
if ('number' !== typeof product.bitmask) {
|
|
||||||
throw new Error(product.product + '.bitmask must be a number.')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
withBitmask.sort((a, b) => b[0] - a[0]) // descending
|
||||||
|
|
||||||
const parseBitmask = (bitmask) => {
|
const parseBitmask = (bitmask) => {
|
||||||
const res = Object.assign({}, defaultProducts)
|
const res = Object.assign({}, defaultProducts)
|
||||||
|
|
||||||
for (let product of allProducts) {
|
for (let [pBitmask, product] of withBitmask) {
|
||||||
if (bitmask === 0) break
|
if ((pBitmask & bitmask) > 0) {
|
||||||
if ((product.bitmask & bitmask) > 0) {
|
res[product.id] = true
|
||||||
res[product.product] = true
|
bitmask -= pBitmask
|
||||||
bitmask -= product.bitmask
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ const isRoughlyEqual = require('is-roughly-equal')
|
||||||
const co = require('./co')
|
const co = require('./co')
|
||||||
const createClient = require('..')
|
const createClient = require('..')
|
||||||
const dbProfile = require('../p/db')
|
const dbProfile = require('../p/db')
|
||||||
const {allProducts} = require('../p/db/modes')
|
const allProducts = require('../p/db/products')
|
||||||
const {
|
const {
|
||||||
assertValidStation,
|
assertValidStation,
|
||||||
assertValidPoi,
|
assertValidPoi,
|
||||||
|
@ -73,7 +73,7 @@ const assertIsJungfernheide = (t, s) => {
|
||||||
// todo: DRY with other tests
|
// todo: DRY with other tests
|
||||||
const assertValidProducts = (t, p) => {
|
const assertValidProducts = (t, p) => {
|
||||||
for (let product of allProducts) {
|
for (let product of allProducts) {
|
||||||
product = product.product // wat
|
product = product.id
|
||||||
t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean')
|
t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ const validateFptf = require('validate-fptf')
|
||||||
const co = require('./co')
|
const co = require('./co')
|
||||||
const createClient = require('..')
|
const createClient = require('..')
|
||||||
const insaProfile = require('../p/insa')
|
const insaProfile = require('../p/insa')
|
||||||
const {allProducts} = require('../p/insa/products')
|
const allProducts = require('../p/insa/products')
|
||||||
const {
|
const {
|
||||||
assertValidStation,
|
assertValidStation,
|
||||||
assertValidPoi,
|
assertValidPoi,
|
||||||
|
@ -58,7 +58,7 @@ const assertIsMagdeburgHbf = (t, s) => {
|
||||||
// todo: DRY with other tests
|
// todo: DRY with other tests
|
||||||
const assertValidProducts = (t, p) => {
|
const assertValidProducts = (t, p) => {
|
||||||
for (let product of allProducts) {
|
for (let product of allProducts) {
|
||||||
product = product.product // wat
|
product = product.id
|
||||||
t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean')
|
t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ const validateLineWithoutMode = require('./validate-line-without-mode')
|
||||||
const co = require('./co')
|
const co = require('./co')
|
||||||
const createClient = require('..')
|
const createClient = require('..')
|
||||||
const oebbProfile = require('../p/oebb')
|
const oebbProfile = require('../p/oebb')
|
||||||
const {allProducts} = require('../p/oebb/products')
|
const allProducts = require('../p/oebb/products')
|
||||||
const {
|
const {
|
||||||
assertValidStation,
|
assertValidStation,
|
||||||
assertValidPoi,
|
assertValidPoi,
|
||||||
|
@ -77,7 +77,7 @@ const assertIsSalzburgHbf = (t, s) => {
|
||||||
// todo: DRY with other tests
|
// todo: DRY with other tests
|
||||||
const assertValidProducts = (t, p) => {
|
const assertValidProducts = (t, p) => {
|
||||||
for (let product of allProducts) {
|
for (let product of allProducts) {
|
||||||
product = product.product // wat
|
product = product.id
|
||||||
t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean')
|
t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue