diff --git a/index.js b/index.js index d9b411a00..d29aefe0d 100644 --- a/index.js +++ b/index.js @@ -532,6 +532,9 @@ const createClient = (profile, userAgent, opt = {}) => { onlyCR: opt.onlyCurrentlyRunning, jnyFltrL: [ profile.formatProductsFilter({profile}, opt.products), + // these don't work: + // {mode: 'INC', type: 'ROUTE', value: 'R::10::Schiff::B3012287613::de:aac:05358|obersee:rs::1'}, + // {mode: 'INC', type: 'CAT', value: 'G::4::Fähre::B*::*::*'}, ], // todo: passing `tripId` yields a `CGI_READ_FAILED` error // todo: passing a stop ID as `extId` yields a `PARAMETER` error @@ -597,6 +600,66 @@ const createClient = (profile, userAgent, opt = {}) => { } } + // todo: rename to tripsAsTree? how do we obtain actual trips? + const pidFiltersAsTree = async (opt = {}) => { + const { + pidFilter, + } = Object.assign({ + pidFilter: null, + }, opt) + + const {res, common} = await profile.request({profile, opt}, userAgent, { + meth: 'JourneyTree', + req: { + pid: pidFilter, + // https://github.com/marudor/BahnhofsAbfahrten/blob/f32da187ef3306345674ea4665c97135f6f4c20f/packages/types/HAFAS/JourneyTree.ts#L3-L13 + // getChilds?: number; + getHIM: false, + getParent: true, + getStatus: true, + // todo: https://github.com/marudor/BahnhofsAbfahrten/blob/41b0bfcc450acf154b5c3476d26658072ca3f038/packages/types/HAFAS/index.ts#L89-L109 + // himFltrL?: HimFilter[]; + // todo: https://github.com/marudor/BahnhofsAbfahrten/blob/41b0bfcc450acf154b5c3476d26658072ca3f038/packages/types/HAFAS/index.ts#L20-L45 + // see also https://github.com/derhuerst/BahnhofsAbfahrten/pull/1 + jnyFltrL: [ + // { + // mode: 'INC', + // type: 'JID', + // value: '1|18357|19|86|21102021', + // } + ], + // rect?: GeoRect; + // ring?: GeoRing; + }, + }) + + if (!Array.isArray(res.jnyTreeNodeL)) return null + + const ctx = {profile, opt, common, res} + return profile.parsePidFiltersTree(ctx, res.jnyTreeNodeL) + } + + // todo: rename + const foo = async (opt = {}) => { + const {res, common} = await profile.request({profile, opt}, userAgent, { + meth: 'JourneyGraph', + req: { + // https://github.com/marudor/BahnhofsAbfahrten/blob/f32da187ef3306345674ea4665c97135f6f4c20f/packages/types/HAFAS/JourneyGraph.ts#L3-L11 + date: '20211021', + getPasslist: true, + getProductStartEndInfo: true, + // todo: https://github.com/marudor/BahnhofsAbfahrten/blob/41b0bfcc450acf154b5c3476d26658072ca3f038/packages/types/HAFAS/index.ts#L20-L45 + // see also https://github.com/derhuerst/BahnhofsAbfahrten/pull/1 + jnyFltrL: [{ + mode: 'INC', + type: 'JID', + value: '1|18357|19|86|21102021', + }], + }, + }) + return null // todo + } + const radar = async ({north, west, south, east}, opt) => { if ('number' !== typeof north) throw new TypeError('north must be a number.') if ('number' !== typeof west) throw new TypeError('west must be a number.') @@ -789,6 +852,8 @@ const createClient = (profile, userAgent, opt = {}) => { locations, stop, nearby, + pidFiltersAsTree, + foo, // todo serverInfo, } if (profile.trip) client.trip = trip diff --git a/lib/default-profile.js b/lib/default-profile.js index 2578bd704..b8c7b37c2 100644 --- a/lib/default-profile.js +++ b/lib/default-profile.js @@ -33,6 +33,7 @@ import {parseOperator} from '../parse/operator.js' import {parseHint} from '../parse/hint.js' import {parseWarning} from '../parse/warning.js' import {parseStopover} from '../parse/stopover.js' +import {parsePidFiltersTree} from '../parse/pid-filters-tree.js' import {formatAddress} from '../format/address.js' import {formatCoord} from '../format/coord.js' @@ -102,6 +103,7 @@ const defaultProfile = { parseHint, parseWarning, parseStopover, + parsePidFiltersTree, formatAddress, formatCoord, diff --git a/parse/pid-filters-tree.js b/parse/pid-filters-tree.js new file mode 100644 index 000000000..703032488 --- /dev/null +++ b/parse/pid-filters-tree.js @@ -0,0 +1,57 @@ +const nodeKinds = new Map() +// todo: are these correct? +nodeKinds.set('P', 'product') // usually level 0, pid filter begins with `P:` "Produkt"? +nodeKinds.set('C', 'category') // usually level 1, pid filter begins with `G:` "Gruppe"? +nodeKinds.set('O', 'operator') // usually level 2, pid filter begins with `B:` "Betreiber"? +nodeKinds.set('L', 'line') // usually level 3, pid filter begins with `L:` "Linie"? +nodeKinds.set('D', 'direction') // usually level 4, pid filter begins with `R:` "Richtung"? + +const parsePidFiltersTree = (ctx, jnyTreeNodeL) => { + const parsedNodes = new WeakMap() // raw node -> parsed node + const parseNode = (idx) => { + const _ = jnyTreeNodeL[idx] + if (!_) throw new Error(`missing node ${idx}`) // todo: don't let this happen + if (parsedNodes.has(_)) return parsedNodes.get(_) + + // todo: what is _.stat.rt? nr of children with realtime data? + // todo: what is _.stat.ont? + // todo: what is _.stat.cncl? nr of canceled children? + // todo: what is _.stat.delGrpL & _.stat.delCntL? + // todo: what is _.stat.him? nr of children with HIM messages? + const node = { + kind: nodeKinds.has(_.type) ? nodeKinds.get(_.type) : null, + name: _.name, + pidFilter: _.pid, // todo [breaking]: rename field? + // todo [breaking]: rename field? + // todo: parse differently? most tree nodes have a sparse common.prodL[_.prodX] + product: _.line, + // nrOfTrips: _.stat ? _.stat.cnt : null, // todo: is this wrong + // todo: _.icon? + } + parsedNodes.set(_, node) + + if (Array.isArray(_.childRefL)) { + node.children = _.childRefL.map(parseNode) + } + + return node + } + + const rootChildren = jnyTreeNodeL + .map((node, idx) => [idx, node]) + .filter(([_, node]) => !jnyTreeNodeL[node.parRefX]) // keep nodes without parent + .map(([idx]) => parseNode(idx)) + + return { + // mock root node + kind: 'root', + name: null, + pid: null, + product: null, + children: rootChildren, + } +} + +export { + parsePidFiltersTree, +} diff --git a/tools/debug-cli/cli.js b/tools/debug-cli/cli.js index b6ee4c69b..ef5fccb9a 100755 --- a/tools/debug-cli/cli.js +++ b/tools/debug-cli/cli.js @@ -46,6 +46,8 @@ const methodsAndTheirArgs = [ ['lines', 0, toString], ['lines', 1, parseJsObject], ['serverInfo', 0, parseJsObject], + ['pidFiltersAsTree', 0, parseJsObject], + ['foo', 0, parseJsObject], ] const {