From b7c1ee3b0589c455c3134d918dfffdb2de73aa53 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 16 Mar 2018 14:23:27 +0100 Subject: [PATCH 01/11] new products markup --- p/db/index.js | 10 ++-- p/db/modes.js | 108 ------------------------------------- p/db/products.js | 85 +++++++++++++++++++++++++++++ p/insa/products.js | 94 +++++++++++++------------------- p/oebb/products.js | 130 ++++++++++++++++++--------------------------- p/vbb/index.js | 10 ++-- p/vbb/modes.js | 112 -------------------------------------- p/vbb/products.js | 60 +++++++++++++++++++++ 8 files changed, 242 insertions(+), 367 deletions(-) delete mode 100644 p/db/modes.js create mode 100644 p/db/products.js delete mode 100644 p/vbb/modes.js create mode 100644 p/vbb/products.js diff --git a/p/db/index.js b/p/db/index.js index d8cc5e6f..2f6870c5 100644 --- a/p/db/index.js +++ b/p/db/index.js @@ -7,10 +7,10 @@ const createParseBitmask = require('../../parse/products-bitmask') const createFormatBitmask = require('../../format/products-bitmask') const {bike} = require('../../format/filters') -const modes = require('./modes') +const products = require('./products') const formatLoyaltyCard = require('./loyalty-cards').format -const formatBitmask = createFormatBitmask(modes) +const formatBitmask = createFormatBitmask(products) const transformReqBody = (body) => { body.client = {id: 'DB', v: '16040000', type: 'IPH', name: 'DB Navigator'} @@ -47,7 +47,7 @@ const createParseLine = (profile, operators) => { res.mode = res.product = null if ('class' in res) { - const data = modes.bitmasks[parseInt(res.class)] + const data = products.bitmasks[parseInt(res.class)] if (data) { res.mode = data.mode res.product = data.product @@ -137,11 +137,11 @@ const dbProfile = { transformReqBody, transformJourneysQuery, - products: modes.allProducts, + products: products.allProducts, // todo: parseLocation parseLine: createParseLine, - parseProducts: createParseBitmask(modes.allProducts, defaultProducts), + parseProducts: createParseBitmask(products.allProducts, defaultProducts), parseJourney: createParseJourney, formatStation, diff --git a/p/db/modes.js b/p/db/modes.js deleted file mode 100644 index dcca851f..00000000 --- a/p/db/modes.js +++ /dev/null @@ -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 diff --git a/p/db/products.js b/p/db/products.js new file mode 100644 index 00000000..d1e26771 --- /dev/null +++ b/p/db/products.js @@ -0,0 +1,85 @@ +'use strict' + +// todo: https://gist.github.com/anonymous/d3323a5d2d6e159ed42b12afd0380434#file-haf_products-properties-L1-L95 +module.exports = [ + { + product: 'nationalExp', + mode: 'train', + bitmasks: [1], + name: 'InterCityExpress', + short: 'ICE', + default: true + }, + { + product: 'national', + mode: 'train', + bitmasks: [2], + name: 'InterCity & EuroCity', + short: 'IC/EC', + default: true + }, + { + product: 'regionalExp', + mode: 'train', + bitmasks: [4], + name: 'RegionalExpress & InterRegio', + short: 'RE/IR', + default: true + }, + { + product: 'regional', + mode: 'train', + bitmasks: [8], + name: 'Regio', + short: 'RB', + default: true + }, + { + product: 'suburban', + mode: 'train', + bitmasks: [16], + name: 'S-Bahn', + short: 'S', + default: true + }, + { + product: 'bus', + mode: 'bus', + bitmasks: [32], + name: 'Bus', + short: 'B', + default: true + }, + { + product: 'ferry', + mode: 'watercraft', + bitmasks: [64], + name: 'Ferry', + short: 'F', + default: true + }, + { + product: 'subway', + mode: 'train', + bitmasks: [128], + name: 'U-Bahn', + short: 'U', + default: true + }, + { + product: 'tram', + mode: 'tram', + bitmasks: [256], + name: 'Tram', + short: 'T', + default: true + }, + { + product: 'taxi', + mode: 'taxi', + bitmasks: [512], + name: 'Group Taxi', + short: 'Taxi', + default: true + } +] diff --git a/p/insa/products.js b/p/insa/products.js index d6b343e5..66bd63ec 100644 --- a/p/insa/products.js +++ b/p/insa/products.js @@ -1,82 +1,60 @@ 'use strict' -// TODO Jannis R.: DRY -const p = { - nationalExp: { - bitmask: 1, +module.exports = [ + { + product: 'nationalExp', + mode: 'train', + bitmasks: [1], name: 'InterCityExpress', short: 'ICE', - mode: 'train', - product: 'nationalExp' + default: true }, - national: { - bitmask: 2, + { + product: 'national', + mode: 'train', + bitmasks: [2], name: 'InterCity & EuroCity', short: 'IC/EC', - mode: 'train', - product: 'national' + default: true }, - regional: { - bitmask: 8, + { + product: 'regional', + mode: 'train', + bitmasks: [8], name: 'RegionalExpress & RegionalBahn', short: 'RE/RB', - mode: 'train', - product: 'regional' + default: true }, - suburban: { - bitmask: 16, + { + product: 'suburban', + mode: 'train', + bitmasks: [16], name: 'S-Bahn', short: 'S', - mode: 'train', - product: 'suburban' + default: true }, - tram: { - bitmask: 32, + { + product: 'tram', + mode: 'train', + bitmasks: [32], name: 'Tram', short: 'T', - mode: 'train', - product: 'tram' + default: true }, - bus: { - bitmask: 64+128, + { + product: 'bus', + mode: 'bus', + bitmasks: [64, 128], name: 'Bus', short: 'B', - mode: 'bus', - product: 'bus' + default: true }, - tourismTrain: { - bitmask: 256, + { + product: 'tourismTrain', + mode: 'train', + bitmasks: [256], name: 'Tourism Train', short: 'TT', - mode: 'train', - product: 'tourismTrain' - }, - unknown: { - bitmask: 0, - name: 'unknown', - short: '?', - product: 'unknown' + default: true } -} - -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 diff --git a/p/oebb/products.js b/p/oebb/products.js index 646d4588..1c0fd223 100644 --- a/p/oebb/products.js +++ b/p/oebb/products.js @@ -1,112 +1,84 @@ 'use strict' -const p = { - nationalExp: { - bitmask: 1, +module.exports = [ + { + product: 'nationalExp', + mode: 'train', + bitmasks: [1], name: 'InterCityExpress & RailJet', short: 'ICE/RJ', - mode: 'train', - product: 'nationalExp' + default: true }, - national: { - bitmask: 2 + 4, + { + product: 'national', + mode: 'train', + bitmasks: [2, 4], name: 'InterCity & EuroCity', short: 'IC/EC', - mode: 'train', - product: 'national' + default: true }, - interregional: { - bitmask: 8 + 4096, + { + product: 'interregional', + mode: 'train', + bitmasks: [8, 4096], name: 'Durchgangszug & EuroNight', short: 'D/EN', - mode: 'train', - product: 'interregional' + default: true }, - regional: { - bitmask: 16, + { + product: 'regional', + mode: 'train', + bitmasks: [16], name: 'Regional & RegionalExpress', short: 'R/REX', - mode: 'train', - product: 'regional' + default: true }, - suburban: { - bitmask: 32, + { + product: 'suburban', + mode: 'train', + bitmasks: [32], name: 'S-Bahn', short: 'S', - mode: 'train', - product: 'suburban' + default: true }, - bus: { - bitmask: 64, + { + product: 'bus', + mode: 'bus', + bitmasks: [64], name: 'Bus', short: 'B', - mode: 'bus', - product: 'bus' + default: true }, - ferry: { - bitmask: 128, + { + product: 'ferry', + mode: 'watercraft', + bitmasks: [128], name: 'Ferry', short: 'F', - mode: 'watercraft', - product: 'ferry' + default: true }, - subway: { - bitmask: 256, + { + product: 'subway', + mode: 'train', + bitmasks: [256], name: 'U-Bahn', short: 'U', - mode: 'train', - product: 'subway' + default: true }, - tram: { - bitmask: 512, + { + product: 'tram', + mode: 'train', + bitmasks: [512], name: 'Tram', short: 'T', - mode: 'train', - product: 'tram' + default: true }, - onCall: { - bitmask: 2048, + { + product: 'onCall', + mode: null, // todo + bitmasks: [2048], name: 'On-call transit', short: 'on-call', - mode: null, // todo - product: 'onCall' - }, - unknown: { - bitmask: 0, - name: 'unknown', - short: '?', - product: 'unknown' + default: true } -} - -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 diff --git a/p/vbb/index.js b/p/vbb/index.js index 3f9f9ecd..10b5e743 100644 --- a/p/vbb/index.js +++ b/p/vbb/index.js @@ -15,9 +15,9 @@ 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 formatBitmask = createFormatBitmask(products) const transformReqBody = (body) => { body.client = {type: 'IPA', id: 'VBB', name: 'vbbPROD', v: '4010300'} @@ -36,7 +36,7 @@ const createParseLine = (profile, operators) => { res.mode = res.product = null if ('class' in res) { - const data = modes.bitmasks[parseInt(res.class)] + const data = products.bitmasks[parseInt(res.class)] if (data) { res.mode = data.mode res.product = data.product @@ -176,12 +176,12 @@ const vbbProfile = { transformReqBody, - products: modes.allProducts, + products: products.allProducts, parseStationName: shorten, parseLocation, parseLine: createParseLine, - parseProducts: createParseBitmask(modes.allProducts, defaultProducts), + parseProducts: createParseBitmask(products.allProducts, defaultProducts), parseJourney: createParseJourney, parseDeparture: createParseDeparture, parseStopover: createParseStopover, diff --git a/p/vbb/modes.js b/p/vbb/modes.js deleted file mode 100644 index 3e771793..00000000 --- a/p/vbb/modes.js +++ /dev/null @@ -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 diff --git a/p/vbb/products.js b/p/vbb/products.js new file mode 100644 index 00000000..678972ac --- /dev/null +++ b/p/vbb/products.js @@ -0,0 +1,60 @@ +'use strict' + +module.exports = [ + { + product: 'suburban', + mode: 'train', + bitmasks: [1], + name: 'S-Bahn', + short: 'S', + default: true + }, + { + product: 'subway', + mode: 'train', + bitmasks: [2], + name: 'U-Bahn', + short: 'U', + default: true + }, + { + product: 'tram', + mode: 'train', + bitmasks: [4], + name: 'Tram', + short: 'T', + default: true + }, + { + product: 'bus', + mode: 'bus', + bitmasks: [8], + name: 'Bus', + short: 'B', + default: true + }, + { + product: 'ferry', + mode: 'watercraft', + bitmasks: [16], + name: 'Fähre', + short: 'F', + default: true + }, + { + product: 'express', + mode: 'train', + bitmasks: [32], + name: 'IC/ICE', + short: 'E', + default: true + }, + { + product: 'regional', + mode: 'train', + bitmasks: [64], + name: 'RB/RE', + short: 'R', + default: true + } +] From ce43f15ad50181455f1efe8bfd0db304d677bc6f Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 16 Mar 2018 15:38:16 +0100 Subject: [PATCH 02/11] parseProducts: move factory from profiles into main code --- index.js | 4 +++- lib/validate-profile.js | 5 +++++ p/db/index.js | 2 -- p/insa/index.js | 2 -- p/oebb/index.js | 2 -- p/vbb/index.js | 2 -- parse/products-bitmask.js | 30 +++++++++++++++++++----------- 7 files changed, 27 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index 158d0151..44a296d1 100644 --- a/index.js +++ b/index.js @@ -3,8 +3,9 @@ const minBy = require('lodash/minBy') const maxBy = require('lodash/maxBy') -const validateProfile = require('./lib/validate-profile') const defaultProfile = require('./lib/default-profile') +const createParseBitmask = require('./parse/products-bitmask') +const validateProfile = require('./lib/validate-profile') const _request = require('./lib/request') const isObj = o => o !== null && 'object' === typeof o && !Array.isArray(o) @@ -12,6 +13,7 @@ const isNonEmptyString = str => 'string' === typeof str && str.length > 0 const createClient = (profile, request = _request) => { profile = Object.assign({}, defaultProfile, profile) + profile.parseProducts = createParseBitmask(profile) validateProfile(profile) const departures = (station, opt = {}) => { diff --git a/lib/validate-profile.js b/lib/validate-profile.js index 19465c3f..2a8ac81b 100644 --- a/lib/validate-profile.js +++ b/lib/validate-profile.js @@ -47,6 +47,11 @@ const validateProfile = (profile) => { 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.') } module.exports = validateProfile diff --git a/p/db/index.js b/p/db/index.js index 2f6870c5..d6fb2708 100644 --- a/p/db/index.js +++ b/p/db/index.js @@ -3,7 +3,6 @@ const _createParseLine = require('../../parse/line') const _createParseJourney = require('../../parse/journey') const _formatStation = require('../../format/station') -const createParseBitmask = require('../../parse/products-bitmask') const createFormatBitmask = require('../../format/products-bitmask') const {bike} = require('../../format/filters') @@ -141,7 +140,6 @@ const dbProfile = { // todo: parseLocation parseLine: createParseLine, - parseProducts: createParseBitmask(products.allProducts, defaultProducts), parseJourney: createParseJourney, formatStation, diff --git a/p/insa/index.js b/p/insa/index.js index 8b7bea1b..948da700 100644 --- a/p/insa/index.js +++ b/p/insa/index.js @@ -2,7 +2,6 @@ const _createParseLine = require('../../parse/line') const products = require('./products') -const createParseBitmask = require('../../parse/products-bitmask') const createFormatBitmask = require('../../format/products-bitmask') const defaultProducts = { @@ -70,7 +69,6 @@ const insaProfile = { transformReqBody, products: products.allProducts, - parseProducts: createParseBitmask(products.allProducts, defaultProducts), formatProducts, parseLine: createParseLine, diff --git a/p/oebb/index.js b/p/oebb/index.js index 5196ab49..c0da7427 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -3,7 +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-L47-L234 -const createParseBitmask = require('../../parse/products-bitmask') const createFormatBitmask = require('../../format/products-bitmask') const _createParseLine = require('../../parse/line') const _parseLocation = require('../../parse/location') @@ -113,7 +112,6 @@ const oebbProfile = { products: products.allProducts, - parseProducts: createParseBitmask(products.allProducts, defaultProducts), parseLine: createParseLine, parseLocation, parseMovement: createParseMovement, diff --git a/p/vbb/index.js b/p/vbb/index.js index 10b5e743..b58d819b 100644 --- a/p/vbb/index.js +++ b/p/vbb/index.js @@ -12,7 +12,6 @@ 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') const createFormatBitmask = require('../../format/products-bitmask') const products = require('./products') @@ -181,7 +180,6 @@ const vbbProfile = { parseStationName: shorten, parseLocation, parseLine: createParseLine, - parseProducts: createParseBitmask(products.allProducts, defaultProducts), parseJourney: createParseJourney, parseDeparture: createParseDeparture, parseStopover: createParseStopover, diff --git a/parse/products-bitmask.js b/parse/products-bitmask.js index 5dc5e8bc..f8522dc6 100644 --- a/parse/products-bitmask.js +++ b/parse/products-bitmask.js @@ -1,25 +1,33 @@ 'use strict' -const createParseBitmask = (allProducts, defaultProducts) => { - allProducts = allProducts.sort((p1, p2) => p2.bitmask - p1.bitmask) // desc - if (allProducts.length === 0) throw new Error('allProducts is empty.') - for (let product of allProducts) { +const createParseBitmask = (profile) => { + const defaultProducts = {} + let withBitmask = [] + for (let product of profile.products) { if ('string' !== typeof product.product) { - throw new Error('allProducts[].product must be a string.') + throw new Error('profile.products[].product must be a string.') } - if ('number' !== typeof product.bitmask) { - throw new Error(product.product + '.bitmask must be a number.') + + defaultProducts[product.product] = false + if (!Array.isArray(product.bitmasks)) { + throw new Error(product.product + '.bitmasks must be an array.') + } + for (let bitmask of product.bitmasks) { + if ('number' !== typeof bitmask) { + throw new Error(product.product + '.bitmasks[] must be a number.') + } + withBitmask.push([bitmask, product]) } } + withBitmask.sort((a, b) => b[0] - a[0]) // descending const parseBitmask = (bitmask) => { const res = Object.assign({}, defaultProducts) - for (let product of allProducts) { - if (bitmask === 0) break - if ((product.bitmask & bitmask) > 0) { + for (let [pBitmask, product] of withBitmask) { + if ((pBitmask & bitmask) > 0) { res[product.product] = true - bitmask -= product.bitmask + bitmask -= pBitmask } } From 83248785e50bb0b42776d055689f952b3fdb8219 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 16 Mar 2018 16:11:32 +0100 Subject: [PATCH 03/11] formatProducts: move factory from profiles into main code and rename to `formatProductsFilter` --- format/products-bitmask.js | 16 ---------------- format/products-filter.js | 34 ++++++++++++++++++++++++++++++++++ index.js | 8 +++++--- p/db/index.js | 27 +-------------------------- p/insa/index.js | 27 --------------------------- p/oebb/index.js | 25 ------------------------- p/vbb/index.js | 22 ---------------------- 7 files changed, 40 insertions(+), 119 deletions(-) delete mode 100644 format/products-bitmask.js create mode 100644 format/products-filter.js diff --git a/format/products-bitmask.js b/format/products-bitmask.js deleted file mode 100644 index b3baab87..00000000 --- a/format/products-bitmask.js +++ /dev/null @@ -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 diff --git a/format/products-filter.js b/format/products-filter.js new file mode 100644 index 00000000..90b1d06b --- /dev/null +++ b/format/products-filter.js @@ -0,0 +1,34 @@ +'use strict' + +const isObj = o => o !== null && 'object' === typeof o && !Array.isArray(o) +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.product] = product + defaultProducts[product.product] = 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 diff --git a/index.js b/index.js index 44a296d1..4ea95c84 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,7 @@ const maxBy = require('lodash/maxBy') 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') @@ -14,6 +15,7 @@ const isNonEmptyString = str => 'string' === typeof str && str.length > 0 const createClient = (profile, request = _request) => { profile = Object.assign({}, defaultProfile, profile) profile.parseProducts = createParseBitmask(profile) + profile.formatProductsFilter = createFormatProductsFilter(profile) validateProfile(profile) const departures = (station, opt = {}) => { @@ -26,7 +28,7 @@ const createClient = (profile, request = _request) => { duration: 10 // show departures for the next n minutes }, opt) 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 return request(profile, { @@ -92,7 +94,7 @@ const createClient = (profile, request = _request) => { opt.when = opt.when || new Date() const filters = [ - profile.formatProducts(opt.products || {}) + profile.formatProductsFilter(opt.products || {}) ] if ( opt.accessibility && @@ -319,7 +321,7 @@ const createClient = (profile, request = _request) => { perStep: Math.round(durationPerStep), ageOfReport: true, // todo: what is this? jnyFltrL: [ - profile.formatProducts(opt.products || {}) + profile.formatProductsFilter(opt.products || {}) ], trainPosMode: 'CALC' // todo: what is this? what about realtime? } diff --git a/p/db/index.js b/p/db/index.js index d6fb2708..cd79befb 100644 --- a/p/db/index.js +++ b/p/db/index.js @@ -3,14 +3,11 @@ const _createParseLine = require('../../parse/line') const _createParseJourney = require('../../parse/journey') const _formatStation = require('../../format/station') -const createFormatBitmask = require('../../format/products-bitmask') const {bike} = require('../../format/filters') const products = require('./products') const formatLoyaltyCard = require('./loyalty-cards').format -const formatBitmask = createFormatBitmask(products) - const transformReqBody = (body) => { body.client = {id: 'DB', v: '16040000', type: 'IPH', name: 'DB Navigator'} body.ext = 'DB.R15.12.a' @@ -102,27 +99,6 @@ const 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 const dbProfile = { @@ -142,8 +118,7 @@ const dbProfile = { parseLine: createParseLine, parseJourney: createParseJourney, - formatStation, - formatProducts + formatStation } module.exports = dbProfile diff --git a/p/insa/index.js b/p/insa/index.js index 948da700..11709ca1 100644 --- a/p/insa/index.js +++ b/p/insa/index.js @@ -2,18 +2,6 @@ const _createParseLine = require('../../parse/line') const products = require('./products') -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) => { body.client = { @@ -50,18 +38,6 @@ const createParseLine = (profile, operators) => { 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 = { locale: 'de-DE', timezone: 'Europe/Berlin', @@ -69,9 +45,6 @@ const insaProfile = { transformReqBody, products: products.allProducts, - formatProducts, - - parseLine: createParseLine, journeyLeg: true, radar: true diff --git a/p/oebb/index.js b/p/oebb/index.js index c0da7427..a3c73a0d 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -3,7 +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-L47-L234 -const createFormatBitmask = require('../../format/products-bitmask') const _createParseLine = require('../../parse/line') const _parseLocation = require('../../parse/location') const _createParseMovement = require('../../parse/movement') @@ -81,28 +80,6 @@ const createParseMovement = (profile, locations, lines, remarks) => { 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', @@ -116,8 +93,6 @@ const oebbProfile = { parseLocation, parseMovement: createParseMovement, - formatProducts, - journeyLeg: true, radar: true } diff --git a/p/vbb/index.js b/p/vbb/index.js index b58d819b..cb926e9d 100644 --- a/p/vbb/index.js +++ b/p/vbb/index.js @@ -12,12 +12,9 @@ const _createParseJourney = require('../../parse/journey') const _createParseStopover = require('../../parse/stopover') const _createParseDeparture = require('../../parse/departure') const _formatStation = require('../../format/station') -const createFormatBitmask = require('../../format/products-bitmask') const products = require('./products') -const formatBitmask = createFormatBitmask(products) - const transformReqBody = (body) => { body.client = {type: 'IPA', id: 'VBB', name: 'vbbPROD', v: '4010300'} body.ext = 'VBB.1' @@ -145,24 +142,6 @@ const 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 = { locale: 'de-DE', timezone: 'Europe/Berlin', @@ -185,7 +164,6 @@ const vbbProfile = { parseStopover: createParseStopover, formatStation, - formatProducts, journeysNumF: false, journeyLeg: true, From 08357dfa9d8f37b0e6046848173ef2574857a5eb Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 16 Mar 2018 17:00:06 +0100 Subject: [PATCH 04/11] parseLine: move mode & products parsing from profiles into main code --- p/db/index.js | 24 +----------------------- p/insa/index.js | 23 +---------------------- p/oebb/index.js | 24 +----------------------- p/vbb/index.js | 15 +++------------ parse/line.js | 27 ++++++++++++++++++++++++--- 5 files changed, 30 insertions(+), 83 deletions(-) diff --git a/p/db/index.js b/p/db/index.js index cd79befb..812cb94d 100644 --- a/p/db/index.js +++ b/p/db/index.js @@ -1,6 +1,5 @@ 'use strict' -const _createParseLine = require('../../parse/line') const _createParseJourney = require('../../parse/journey') const _formatStation = require('../../format/station') const {bike} = require('../../format/filters') @@ -35,26 +34,6 @@ const transformJourneysQuery = (query, opt) => { 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 = products.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 parseJourney = _createParseJourney(profile, stations, lines, remarks) @@ -112,10 +91,9 @@ const dbProfile = { transformReqBody, transformJourneysQuery, - products: products.allProducts, + products: products, // todo: parseLocation - parseLine: createParseLine, parseJourney: createParseJourney, formatStation diff --git a/p/insa/index.js b/p/insa/index.js index 11709ca1..ed562dee 100644 --- a/p/insa/index.js +++ b/p/insa/index.js @@ -1,6 +1,5 @@ 'use strict' -const _createParseLine = require('../../parse/line') const products = require('./products') const transformReqBody = (body) => { @@ -18,33 +17,13 @@ const transformReqBody = (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 insaProfile = { locale: 'de-DE', timezone: 'Europe/Berlin', endpoint: 'http://reiseauskunft.insa.de/bin/mgate.exe', transformReqBody, - products: products.allProducts, + products: products, journeyLeg: true, radar: true diff --git a/p/oebb/index.js b/p/oebb/index.js index a3c73a0d..99496761 100644 --- a/p/oebb/index.js +++ b/p/oebb/index.js @@ -3,7 +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-L47-L234 -const _createParseLine = require('../../parse/line') const _parseLocation = require('../../parse/location') const _createParseMovement = require('../../parse/movement') @@ -26,26 +25,6 @@ const transformReqBody = (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) => { // ÖBB has some 'stations' **in austria** with no departures/products, // like station entrances, that are actually POIs. @@ -87,9 +66,8 @@ const oebbProfile = { endpoint: 'http://fahrplan.oebb.at/bin/mgate.exe', transformReqBody, - products: products.allProducts, + products: products, - parseLine: createParseLine, parseLocation, parseMovement: createParseMovement, diff --git a/p/vbb/index.js b/p/vbb/index.js index cb926e9d..534c93d6 100644 --- a/p/vbb/index.js +++ b/p/vbb/index.js @@ -27,18 +27,9 @@ const transformReqBody = (body) => { const createParseLine = (profile, operators) => { const parseLine = _createParseLine(profile, operators) - const parseLineWithMode = (l) => { + const parseLineWithMoreDetails = (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 - } - } - const details = parseLineName(l.name) res.symbol = details.symbol res.nr = details.nr @@ -48,7 +39,7 @@ const createParseLine = (profile, operators) => { return res } - return parseLineWithMode + return parseLineWithMoreDetails } const parseLocation = (profile, l, lines) => { @@ -154,7 +145,7 @@ const vbbProfile = { transformReqBody, - products: products.allProducts, + products: products, parseStationName: shorten, parseLocation, diff --git a/parse/line.js b/parse/line.js index 79300c08..99e8c293 100644 --- a/parse/line.js +++ b/parse/line.js @@ -2,8 +2,23 @@ const slugg = require('slugg') -// todo: are p.number and p.line ever different? const createParseLine = (profile, operators) => { + const byBitmask = [] + for (let product of profile.products) { + if ('string' !== typeof product.product) { + throw new Error('profile.products[].product must be a string.') + } + if (!Array.isArray(product.bitmasks)) { + throw new Error(product.product + '.bitmasks must be an array.') + } + for (let bitmask of product.bitmasks) { + if ('number' !== typeof bitmask) { + throw new Error(product.product + '.bitmasks[] must be a number.') + } + byBitmask[bitmask] = product + } + } + const parseLine = (p) => { if (!p) return null // todo: handle this upstream const res = { @@ -13,8 +28,9 @@ const createParseLine = (profile, operators) => { public: true } // 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 if (p.line) res.id = slugg(p.line.trim()) else if (p.name) res.id = slugg(p.name.trim()) @@ -24,7 +40,12 @@ const createParseLine = (profile, operators) => { 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 data = byBitmask[parseInt(res.class)] + res.mode = data && data.mode || null + res.product = data && data.product || null + } if ('number' === typeof p.oprX) { res.operator = operators[p.oprX] || null From bbb68d86d52fe99676db5908d657fae84861a4eb Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 16 Mar 2018 17:03:13 +0100 Subject: [PATCH 05/11] validate products in lib/validate-profile --- lib/validate-profile.js | 16 ++++++++++++++++ parse/line.js | 9 --------- parse/products-bitmask.js | 10 ---------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/lib/validate-profile.js b/lib/validate-profile.js index 2a8ac81b..8c05ebdb 100644 --- a/lib/validate-profile.js +++ b/lib/validate-profile.js @@ -52,6 +52,22 @@ const validateProfile = (profile) => { 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.product) { + throw new Error('profile.products[].product 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.product + '.bitmasks must be an array.') + } + for (let bitmask of product.bitmasks) { + if ('number' !== typeof bitmask) { + throw new Error(product.product + '.bitmasks[] must be a number.') + } + } + } } module.exports = validateProfile diff --git a/parse/line.js b/parse/line.js index 99e8c293..36da3f26 100644 --- a/parse/line.js +++ b/parse/line.js @@ -5,16 +5,7 @@ const slugg = require('slugg') const createParseLine = (profile, operators) => { const byBitmask = [] for (let product of profile.products) { - if ('string' !== typeof product.product) { - throw new Error('profile.products[].product must be a string.') - } - if (!Array.isArray(product.bitmasks)) { - throw new Error(product.product + '.bitmasks must be an array.') - } for (let bitmask of product.bitmasks) { - if ('number' !== typeof bitmask) { - throw new Error(product.product + '.bitmasks[] must be a number.') - } byBitmask[bitmask] = product } } diff --git a/parse/products-bitmask.js b/parse/products-bitmask.js index f8522dc6..3ebdb7d7 100644 --- a/parse/products-bitmask.js +++ b/parse/products-bitmask.js @@ -4,18 +4,8 @@ const createParseBitmask = (profile) => { const defaultProducts = {} let withBitmask = [] for (let product of profile.products) { - if ('string' !== typeof product.product) { - throw new Error('profile.products[].product must be a string.') - } - defaultProducts[product.product] = false - if (!Array.isArray(product.bitmasks)) { - throw new Error(product.product + '.bitmasks must be an array.') - } for (let bitmask of product.bitmasks) { - if ('number' !== typeof bitmask) { - throw new Error(product.product + '.bitmasks[] must be a number.') - } withBitmask.push([bitmask, product]) } } From 94bbe2361b7a405e5f781053ebbe82eab02e92cc Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 16 Mar 2018 17:06:32 +0100 Subject: [PATCH 06/11] products[].product -> products[].id --- format/products-filter.js | 4 ++-- lib/validate-profile.js | 8 ++++---- p/db/products.js | 20 ++++++++++---------- p/insa/products.js | 14 +++++++------- p/oebb/products.js | 20 ++++++++++---------- p/vbb/products.js | 14 +++++++------- parse/line.js | 6 +++--- parse/products-bitmask.js | 4 ++-- test/db.js | 2 +- test/insa.js | 2 +- test/oebb.js | 2 +- 11 files changed, 48 insertions(+), 48 deletions(-) diff --git a/format/products-filter.js b/format/products-filter.js index 90b1d06b..1305f501 100644 --- a/format/products-filter.js +++ b/format/products-filter.js @@ -7,8 +7,8 @@ const createFormatProductsFilter = (profile) => { const byProduct = {} const defaultProducts = {} for (let product of profile.products) { - byProduct[product.product] = product - defaultProducts[product.product] = product.default + byProduct[product.id] = product + defaultProducts[product.id] = product.default } const formatProductsFilter = (filter) => { diff --git a/lib/validate-profile.js b/lib/validate-profile.js index 8c05ebdb..21c86829 100644 --- a/lib/validate-profile.js +++ b/lib/validate-profile.js @@ -53,18 +53,18 @@ const validateProfile = (profile) => { } if (profile.products.length === 0) throw new Error('profile.products is empty.') for (let product of profile.products) { - if ('string' !== typeof product.product) { - throw new Error('profile.products[].product must be a string.') + 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.product + '.bitmasks must be an array.') + throw new Error(product.id + '.bitmasks must be an array.') } for (let bitmask of product.bitmasks) { if ('number' !== typeof bitmask) { - throw new Error(product.product + '.bitmasks[] must be a number.') + throw new Error(product.id + '.bitmasks[] must be a number.') } } } diff --git a/p/db/products.js b/p/db/products.js index d1e26771..fa683e2b 100644 --- a/p/db/products.js +++ b/p/db/products.js @@ -3,7 +3,7 @@ // todo: https://gist.github.com/anonymous/d3323a5d2d6e159ed42b12afd0380434#file-haf_products-properties-L1-L95 module.exports = [ { - product: 'nationalExp', + id: 'nationalExp', mode: 'train', bitmasks: [1], name: 'InterCityExpress', @@ -11,7 +11,7 @@ module.exports = [ default: true }, { - product: 'national', + id: 'national', mode: 'train', bitmasks: [2], name: 'InterCity & EuroCity', @@ -19,7 +19,7 @@ module.exports = [ default: true }, { - product: 'regionalExp', + id: 'regionalExp', mode: 'train', bitmasks: [4], name: 'RegionalExpress & InterRegio', @@ -27,7 +27,7 @@ module.exports = [ default: true }, { - product: 'regional', + id: 'regional', mode: 'train', bitmasks: [8], name: 'Regio', @@ -35,7 +35,7 @@ module.exports = [ default: true }, { - product: 'suburban', + id: 'suburban', mode: 'train', bitmasks: [16], name: 'S-Bahn', @@ -43,7 +43,7 @@ module.exports = [ default: true }, { - product: 'bus', + id: 'bus', mode: 'bus', bitmasks: [32], name: 'Bus', @@ -51,7 +51,7 @@ module.exports = [ default: true }, { - product: 'ferry', + id: 'ferry', mode: 'watercraft', bitmasks: [64], name: 'Ferry', @@ -59,7 +59,7 @@ module.exports = [ default: true }, { - product: 'subway', + id: 'subway', mode: 'train', bitmasks: [128], name: 'U-Bahn', @@ -67,7 +67,7 @@ module.exports = [ default: true }, { - product: 'tram', + id: 'tram', mode: 'tram', bitmasks: [256], name: 'Tram', @@ -75,7 +75,7 @@ module.exports = [ default: true }, { - product: 'taxi', + id: 'taxi', mode: 'taxi', bitmasks: [512], name: 'Group Taxi', diff --git a/p/insa/products.js b/p/insa/products.js index 66bd63ec..485c3f23 100644 --- a/p/insa/products.js +++ b/p/insa/products.js @@ -2,7 +2,7 @@ module.exports = [ { - product: 'nationalExp', + id: 'nationalExp', mode: 'train', bitmasks: [1], name: 'InterCityExpress', @@ -10,7 +10,7 @@ module.exports = [ default: true }, { - product: 'national', + id: 'national', mode: 'train', bitmasks: [2], name: 'InterCity & EuroCity', @@ -18,7 +18,7 @@ module.exports = [ default: true }, { - product: 'regional', + id: 'regional', mode: 'train', bitmasks: [8], name: 'RegionalExpress & RegionalBahn', @@ -26,7 +26,7 @@ module.exports = [ default: true }, { - product: 'suburban', + id: 'suburban', mode: 'train', bitmasks: [16], name: 'S-Bahn', @@ -34,7 +34,7 @@ module.exports = [ default: true }, { - product: 'tram', + id: 'tram', mode: 'train', bitmasks: [32], name: 'Tram', @@ -42,7 +42,7 @@ module.exports = [ default: true }, { - product: 'bus', + id: 'bus', mode: 'bus', bitmasks: [64, 128], name: 'Bus', @@ -50,7 +50,7 @@ module.exports = [ default: true }, { - product: 'tourismTrain', + id: 'tourismTrain', mode: 'train', bitmasks: [256], name: 'Tourism Train', diff --git a/p/oebb/products.js b/p/oebb/products.js index 1c0fd223..91bcf65e 100644 --- a/p/oebb/products.js +++ b/p/oebb/products.js @@ -2,7 +2,7 @@ module.exports = [ { - product: 'nationalExp', + id: 'nationalExp', mode: 'train', bitmasks: [1], name: 'InterCityExpress & RailJet', @@ -10,7 +10,7 @@ module.exports = [ default: true }, { - product: 'national', + id: 'national', mode: 'train', bitmasks: [2, 4], name: 'InterCity & EuroCity', @@ -18,7 +18,7 @@ module.exports = [ default: true }, { - product: 'interregional', + id: 'interregional', mode: 'train', bitmasks: [8, 4096], name: 'Durchgangszug & EuroNight', @@ -26,7 +26,7 @@ module.exports = [ default: true }, { - product: 'regional', + id: 'regional', mode: 'train', bitmasks: [16], name: 'Regional & RegionalExpress', @@ -34,7 +34,7 @@ module.exports = [ default: true }, { - product: 'suburban', + id: 'suburban', mode: 'train', bitmasks: [32], name: 'S-Bahn', @@ -42,7 +42,7 @@ module.exports = [ default: true }, { - product: 'bus', + id: 'bus', mode: 'bus', bitmasks: [64], name: 'Bus', @@ -50,7 +50,7 @@ module.exports = [ default: true }, { - product: 'ferry', + id: 'ferry', mode: 'watercraft', bitmasks: [128], name: 'Ferry', @@ -58,7 +58,7 @@ module.exports = [ default: true }, { - product: 'subway', + id: 'subway', mode: 'train', bitmasks: [256], name: 'U-Bahn', @@ -66,7 +66,7 @@ module.exports = [ default: true }, { - product: 'tram', + id: 'tram', mode: 'train', bitmasks: [512], name: 'Tram', @@ -74,7 +74,7 @@ module.exports = [ default: true }, { - product: 'onCall', + id: 'onCall', mode: null, // todo bitmasks: [2048], name: 'On-call transit', diff --git a/p/vbb/products.js b/p/vbb/products.js index 678972ac..6d091247 100644 --- a/p/vbb/products.js +++ b/p/vbb/products.js @@ -2,7 +2,7 @@ module.exports = [ { - product: 'suburban', + id: 'suburban', mode: 'train', bitmasks: [1], name: 'S-Bahn', @@ -10,7 +10,7 @@ module.exports = [ default: true }, { - product: 'subway', + id: 'subway', mode: 'train', bitmasks: [2], name: 'U-Bahn', @@ -18,7 +18,7 @@ module.exports = [ default: true }, { - product: 'tram', + id: 'tram', mode: 'train', bitmasks: [4], name: 'Tram', @@ -26,7 +26,7 @@ module.exports = [ default: true }, { - product: 'bus', + id: 'bus', mode: 'bus', bitmasks: [8], name: 'Bus', @@ -34,7 +34,7 @@ module.exports = [ default: true }, { - product: 'ferry', + id: 'ferry', mode: 'watercraft', bitmasks: [16], name: 'Fähre', @@ -42,7 +42,7 @@ module.exports = [ default: true }, { - product: 'express', + id: 'express', mode: 'train', bitmasks: [32], name: 'IC/ICE', @@ -50,7 +50,7 @@ module.exports = [ default: true }, { - product: 'regional', + id: 'regional', mode: 'train', bitmasks: [64], name: 'RB/RE', diff --git a/parse/line.js b/parse/line.js index 36da3f26..fddc66e6 100644 --- a/parse/line.js +++ b/parse/line.js @@ -33,9 +33,9 @@ const createParseLine = (profile, operators) => { if ('class' in res) { // todo: what if `res.class` is the sum of two bitmasks? - const data = byBitmask[parseInt(res.class)] - res.mode = data && data.mode || null - res.product = data && data.product || null + const product = byBitmask[parseInt(res.class)] + res.mode = product && product.mode || null + res.product = product && product.id || null } if ('number' === typeof p.oprX) { diff --git a/parse/products-bitmask.js b/parse/products-bitmask.js index 3ebdb7d7..6b836904 100644 --- a/parse/products-bitmask.js +++ b/parse/products-bitmask.js @@ -4,7 +4,7 @@ const createParseBitmask = (profile) => { const defaultProducts = {} let withBitmask = [] for (let product of profile.products) { - defaultProducts[product.product] = false + defaultProducts[product.id] = false for (let bitmask of product.bitmasks) { withBitmask.push([bitmask, product]) } @@ -16,7 +16,7 @@ const createParseBitmask = (profile) => { for (let [pBitmask, product] of withBitmask) { if ((pBitmask & bitmask) > 0) { - res[product.product] = true + res[product.id] = true bitmask -= pBitmask } } diff --git a/test/db.js b/test/db.js index 62f39074..1df50fd6 100644 --- a/test/db.js +++ b/test/db.js @@ -73,7 +73,7 @@ const assertIsJungfernheide = (t, s) => { // todo: DRY with other tests const assertValidProducts = (t, p) => { for (let product of allProducts) { - product = product.product // wat + product = product.id t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean') } } diff --git a/test/insa.js b/test/insa.js index 28679120..a5acfd04 100644 --- a/test/insa.js +++ b/test/insa.js @@ -58,7 +58,7 @@ const assertIsMagdeburgHbf = (t, s) => { // todo: DRY with other tests const assertValidProducts = (t, p) => { for (let product of allProducts) { - product = product.product // wat + product = product.id t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean') } } diff --git a/test/oebb.js b/test/oebb.js index 7427b6db..f40d0655 100644 --- a/test/oebb.js +++ b/test/oebb.js @@ -77,7 +77,7 @@ const assertIsSalzburgHbf = (t, s) => { // todo: DRY with other tests const assertValidProducts = (t, p) => { for (let product of allProducts) { - product = product.product // wat + product = product.id t.equal(typeof p[product], 'boolean', 'product ' + p + ' must be a boolean') } } From bc51d257fd1e9ee47dd6eb94461096b2f151d02e Mon Sep 17 00:00:00 2001 From: Jannis R Date: Fri, 16 Mar 2018 17:11:21 +0100 Subject: [PATCH 07/11] adapt tests to new products markup --- test/db.js | 2 +- test/insa.js | 2 +- test/oebb.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/db.js b/test/db.js index 1df50fd6..020ae236 100644 --- a/test/db.js +++ b/test/db.js @@ -8,7 +8,7 @@ const isRoughlyEqual = require('is-roughly-equal') const co = require('./co') const createClient = require('..') const dbProfile = require('../p/db') -const {allProducts} = require('../p/db/modes') +const allProducts = require('../p/db/products') const { assertValidStation, assertValidPoi, diff --git a/test/insa.js b/test/insa.js index a5acfd04..14dd9985 100644 --- a/test/insa.js +++ b/test/insa.js @@ -8,7 +8,7 @@ const validateFptf = require('validate-fptf') const co = require('./co') const createClient = require('..') const insaProfile = require('../p/insa') -const {allProducts} = require('../p/insa/products') +const allProducts = require('../p/insa/products') const { assertValidStation, assertValidPoi, diff --git a/test/oebb.js b/test/oebb.js index f40d0655..f424d071 100644 --- a/test/oebb.js +++ b/test/oebb.js @@ -12,7 +12,7 @@ const validateLineWithoutMode = require('./validate-line-without-mode') const co = require('./co') const createClient = require('..') const oebbProfile = require('../p/oebb') -const {allProducts} = require('../p/oebb/products') +const allProducts = require('../p/oebb/products') const { assertValidStation, assertValidPoi, From ad4d60f3ca63874fec4f490ab7428b9195fa97ed Mon Sep 17 00:00:00 2001 From: Jannis R Date: Sun, 18 Mar 2018 00:11:51 +0100 Subject: [PATCH 08/11] allow for overwriting parseProducts & formatProductsFilter --- index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 4ea95c84..395f4ab0 100644 --- a/index.js +++ b/index.js @@ -13,9 +13,10 @@ 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) - profile.parseProducts = createParseBitmask(profile) - profile.formatProductsFilter = createFormatProductsFilter(profile) + profile = Object.assign({ + parseProducts: createParseBitmask(profile), + formatProductsFilter: createFormatProductsFilter(profile) + }, defaultProfile, profile) validateProfile(profile) const departures = (station, opt = {}) => { From 854b0bd35ef75f85b5cb8eee108a3a53c01aa503 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Sun, 18 Mar 2018 00:13:44 +0100 Subject: [PATCH 09/11] homegrown isObj -> lodash/isObject --- format/products-filter.js | 3 ++- index.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/format/products-filter.js b/format/products-filter.js index 1305f501..8ee8ffca 100644 --- a/format/products-filter.js +++ b/format/products-filter.js @@ -1,6 +1,7 @@ 'use strict' -const isObj = o => o !== null && 'object' === typeof o && !Array.isArray(o) +const isObj = require('lodash/isObject') + const hasProp = (o, k) => Object.prototype.hasOwnProperty.call(o, k) const createFormatProductsFilter = (profile) => { diff --git a/index.js b/index.js index 395f4ab0..70f4ae2d 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const minBy = require('lodash/minBy') const maxBy = require('lodash/maxBy') +const isObj = require('lodash/isObject') const defaultProfile = require('./lib/default-profile') const createParseBitmask = require('./parse/products-bitmask') @@ -9,7 +10,6 @@ const createFormatProductsFilter = require('./format/products-filter') const validateProfile = require('./lib/validate-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) => { From ccd2dc078346007fe91f385fc9eb364993539b85 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Sun, 18 Mar 2018 00:17:10 +0100 Subject: [PATCH 10/11] let parseProducts and formatProductsFilter get the real profile :bug: --- index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 70f4ae2d..b6c82e3a 100644 --- a/index.js +++ b/index.js @@ -12,10 +12,14 @@ const _request = require('./lib/request') const isNonEmptyString = str => 'string' === typeof str && str.length > 0 -const createClient = (profile, request = _request) => { - profile = Object.assign({ - parseProducts: createParseBitmask(profile), - formatProductsFilter: createFormatProductsFilter(profile) +const createClient = (_profile, request = _request) => { + profile = Object.assign({}, defaultProfile, profile) + if (!profile.parseProducts) { + profile.parseProducts = createParseBitmask(profile) + } + if (!profile.formatProductsFilter) { + profile.formatProductsFilter = createFormatProductsFilter(profile) + } }, defaultProfile, profile) validateProfile(profile) From 94988d98c0af6991bf861204cdb064ca600eb172 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Sun, 18 Mar 2018 00:30:54 +0100 Subject: [PATCH 11/11] yet another fix :bug: --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index b6c82e3a..a51b805d 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,7 @@ const _request = require('./lib/request') const isNonEmptyString = str => 'string' === typeof str && str.length > 0 -const createClient = (_profile, request = _request) => { +const createClient = (profile, request = _request) => { profile = Object.assign({}, defaultProfile, profile) if (!profile.parseProducts) { profile.parseProducts = createParseBitmask(profile) @@ -20,7 +20,6 @@ const createClient = (_profile, request = _request) => { if (!profile.formatProductsFilter) { profile.formatProductsFilter = createFormatProductsFilter(profile) } - }, defaultProfile, profile) validateProfile(profile) const departures = (station, opt = {}) => {