mirror of
https://github.com/public-transport/db-vendo-client.git
synced 2025-02-23 07:09:35 +02:00
parse trip.scheduledDays ✅
This commit is contained in:
parent
b6900a3ddb
commit
a60083f8d1
7 changed files with 126 additions and 42 deletions
3
index.js
3
index.js
|
@ -490,7 +490,8 @@ const createClient = (profile, userAgent, opt = {}) => {
|
||||||
polyline: false, // return a track shape?
|
polyline: false, // return a track shape?
|
||||||
subStops: true, // parse & expose sub-stops of stations?
|
subStops: true, // parse & expose sub-stops of stations?
|
||||||
entrances: true, // parse & expose entrances of stops/stations?
|
entrances: true, // parse & expose entrances of stops/stations?
|
||||||
remarks: true // parse & expose hints & warnings?
|
remarks: true, // parse & expose hints & warnings?
|
||||||
|
scheduledDays: false, // parse & expose dates trip is valid on?
|
||||||
}, opt)
|
}, opt)
|
||||||
|
|
||||||
const req = profile.formatTripReq({profile, opt}, id, lineName)
|
const req = profile.formatTripReq({profile, opt}, id, lineName)
|
||||||
|
|
|
@ -19,6 +19,7 @@ const parseProductsBitmask = require('../parse/products-bitmask')
|
||||||
const parseIcon = require('../parse/icon')
|
const parseIcon = require('../parse/icon')
|
||||||
const parseWhen = require('../parse/when')
|
const parseWhen = require('../parse/when')
|
||||||
const parsePrognosisType = require('../parse/prognosis-type')
|
const parsePrognosisType = require('../parse/prognosis-type')
|
||||||
|
const parseScheduledDays = require('../parse/scheduled-days')
|
||||||
const parseDeparture = require('../parse/departure')
|
const parseDeparture = require('../parse/departure')
|
||||||
const parseArrival = require('../parse/arrival')
|
const parseArrival = require('../parse/arrival')
|
||||||
const parseTrip = require('../parse/trip')
|
const parseTrip = require('../parse/trip')
|
||||||
|
@ -85,6 +86,7 @@ const defaultProfile = {
|
||||||
parseIcon,
|
parseIcon,
|
||||||
parseWhen,
|
parseWhen,
|
||||||
parsePrognosisType,
|
parsePrognosisType,
|
||||||
|
parseScheduledDays,
|
||||||
parseDeparture,
|
parseDeparture,
|
||||||
parseArrival,
|
parseArrival,
|
||||||
parseTrip,
|
parseTrip,
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const {DateTime} = require('luxon')
|
|
||||||
const findRemarks = require('./find-remarks')
|
const findRemarks = require('./find-remarks')
|
||||||
|
|
||||||
// todo: DRY with parse/date-time.js
|
|
||||||
const parseDate = (date) => {
|
|
||||||
const res = {
|
|
||||||
year: parseInt(date.substr(-8, 4)),
|
|
||||||
month: parseInt(date.substr(-4, 2)),
|
|
||||||
day: parseInt(date.substr(-2, 2)),
|
|
||||||
}
|
|
||||||
if (!Number.isInteger(res.year) || !Number.isInteger(res.month) || !Number.isInteger(res.day)) {
|
|
||||||
throw new Error('invalid date format: ' + date)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseScheduledDays = (sDaysB, fpB, fpE, profile) => {
|
|
||||||
sDaysB = Buffer.from(sDaysB, 'hex')
|
|
||||||
const res = Object.create(null)
|
|
||||||
|
|
||||||
const _fpB = parseDate(fpB)
|
|
||||||
let d = DateTime.fromObject({
|
|
||||||
zone: profile.timezone, locale: profile.locale,
|
|
||||||
year: _fpB.year, month: _fpB.month, day: _fpB.day,
|
|
||||||
hour: 0, minute: 0, second: 0, millisecond: 0
|
|
||||||
})
|
|
||||||
for (let b = 0; b < sDaysB.length; b++) {
|
|
||||||
for (let i = 0; i < 8; i++) {
|
|
||||||
res[d.toISODate()] = (sDaysB[b] & Math.pow(2, 7 - i)) > 0
|
|
||||||
d = d.plus({days: 1})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: c.conSubscr (e.g. `F`)
|
// todo: c.conSubscr (e.g. `F`)
|
||||||
// todo: c.trfRes x vbb-parse-ticket
|
// todo: c.trfRes x vbb-parse-ticket
|
||||||
// todo: c.sotRating, c.isSotCon, c.sotCtxt
|
// todo: c.sotRating, c.isSotCon, c.sotCtxt
|
||||||
|
@ -70,13 +37,9 @@ const parseJourney = (ctx, j) => { // j = raw jouney
|
||||||
res.remarks = findRemarks(j.msgL).map(([remark]) => remark)
|
res.remarks = findRemarks(j.msgL).map(([remark]) => remark)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.scheduledDays) {
|
if (opt.scheduledDays && j.sDays) {
|
||||||
// sDaysB is a bitmap mapping all days from fpB (first date of schedule) to fpE (last date in schedule).
|
// todo [breaking]: rename to scheduledDates
|
||||||
const {sDaysB} = j.sDays
|
res.scheduledDays = profile.parseScheduledDays(ctx, j.sDays)
|
||||||
const {fpB, fpE} = ctx.res
|
|
||||||
if (sDaysB && fpB && fpE) {
|
|
||||||
res.scheduledDays = parseScheduledDays(sDaysB, fpB, fpE, profile)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
43
parse/scheduled-days.js
Normal file
43
parse/scheduled-days.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const {DateTime} = require('luxon')
|
||||||
|
|
||||||
|
// todo: DRY with parse/date-time.js
|
||||||
|
const parseDate = (date) => {
|
||||||
|
const res = {
|
||||||
|
year: parseInt(date.substr(-8, 4)),
|
||||||
|
month: parseInt(date.substr(-4, 2)),
|
||||||
|
day: parseInt(date.substr(-2, 2)),
|
||||||
|
}
|
||||||
|
if (!Number.isInteger(res.year) || !Number.isInteger(res.month) || !Number.isInteger(res.day)) {
|
||||||
|
throw new Error('invalid date format: ' + date)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseScheduledDays = (ctx, sDays) => {
|
||||||
|
const {profile} = ctx
|
||||||
|
|
||||||
|
// sDaysB is a bitmap mapping all days from fpB (first date of schedule) to fpE (last date in schedule).
|
||||||
|
const {fpB, fpE} = ctx.res
|
||||||
|
if (!sDays.sDaysB || !fpB || !fpE) return null
|
||||||
|
|
||||||
|
const sDaysB = Buffer.from(sDays.sDaysB, 'hex')
|
||||||
|
const res = Object.create(null)
|
||||||
|
|
||||||
|
const _fpB = parseDate(fpB)
|
||||||
|
let d = DateTime.fromObject({
|
||||||
|
zone: profile.timezone, locale: profile.locale,
|
||||||
|
year: _fpB.year, month: _fpB.month, day: _fpB.day,
|
||||||
|
hour: 0, minute: 0, second: 0, millisecond: 0
|
||||||
|
})
|
||||||
|
for (let b = 0; b < sDaysB.length; b++) {
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
res[d.toISODate()] = (sDaysB[b] & Math.pow(2, 7 - i)) > 0
|
||||||
|
d = d.plus({days: 1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = parseScheduledDays
|
|
@ -5,7 +5,7 @@ const maxBy = require('lodash/maxBy')
|
||||||
const last = require('lodash/last')
|
const last = require('lodash/last')
|
||||||
|
|
||||||
const parseTrip = (ctx, t) => { // t = raw trip
|
const parseTrip = (ctx, t) => { // t = raw trip
|
||||||
const {profile, res} = ctx
|
const {profile, opt, res} = ctx
|
||||||
|
|
||||||
// pretend the trip is a leg in a journey
|
// pretend the trip is a leg in a journey
|
||||||
const fakeLeg = {
|
const fakeLeg = {
|
||||||
|
@ -29,6 +29,20 @@ const parseTrip = (ctx, t) => { // t = raw trip
|
||||||
delete trip.tripId
|
delete trip.tripId
|
||||||
// todo [breaking]: delete trip.reachable
|
// todo [breaking]: delete trip.reachable
|
||||||
|
|
||||||
|
if (opt.scheduledDays) {
|
||||||
|
const nrOfStopovers = t.stopL.length
|
||||||
|
// trips seem to use sDaysL[], journeys use sDays
|
||||||
|
const sDaysL = Array.isArray(t.sDaysL) ? t.sDaysL : []
|
||||||
|
const matchingSDays = sDaysL.filter((sDays) => {
|
||||||
|
return sDays.fLocIdx === 0 && sDays.tLocIdx === (nrOfStopovers - 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
// if there are >1 sDays, we don't know how to interpret them
|
||||||
|
const sDays = matchingSDays.length === 1 ? matchingSDays[0] : null
|
||||||
|
// todo [breaking]: rename to scheduledDates
|
||||||
|
trip.scheduledDays = profile.parseScheduledDays(ctx, sDays)
|
||||||
|
}
|
||||||
|
|
||||||
if (res.planrtTS) {
|
if (res.planrtTS) {
|
||||||
// todo [breaking]: remove here
|
// todo [breaking]: remove here
|
||||||
trip.realtimeDataUpdatedAt = parseInt(res.planrtTS)
|
trip.realtimeDataUpdatedAt = parseInt(res.planrtTS)
|
||||||
|
|
|
@ -16,6 +16,7 @@ const opt = {
|
||||||
subStops: false,
|
subStops: false,
|
||||||
entrances: true,
|
entrances: true,
|
||||||
remarks: true,
|
remarks: true,
|
||||||
|
scheduledDays: true,
|
||||||
when: '2021-10-28T09:28:00+02:00',
|
when: '2021-10-28T09:28:00+02:00',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
60
test/fixtures/bvg-trip-with-occupancy.js
vendored
60
test/fixtures/bvg-trip-with-occupancy.js
vendored
|
@ -44,6 +44,66 @@ module.exports = {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
occupancy: 'medium',
|
occupancy: 'medium',
|
||||||
|
|
||||||
|
scheduledDays: {
|
||||||
|
'2021-10-22': true,
|
||||||
|
'2021-10-23': false,
|
||||||
|
'2021-10-24': false,
|
||||||
|
'2021-10-25': true,
|
||||||
|
'2021-10-26': true,
|
||||||
|
'2021-10-27': true,
|
||||||
|
'2021-10-28': true,
|
||||||
|
'2021-10-29': true,
|
||||||
|
'2021-10-30': false,
|
||||||
|
'2021-10-31': false,
|
||||||
|
'2021-11-01': true,
|
||||||
|
'2021-11-02': true,
|
||||||
|
'2021-11-03': true,
|
||||||
|
'2021-11-04': true,
|
||||||
|
'2021-11-05': true,
|
||||||
|
'2021-11-06': false,
|
||||||
|
'2021-11-07': false,
|
||||||
|
'2021-11-08': true,
|
||||||
|
'2021-11-09': true,
|
||||||
|
'2021-11-10': true,
|
||||||
|
'2021-11-11': true,
|
||||||
|
'2021-11-12': true,
|
||||||
|
'2021-11-13': false,
|
||||||
|
'2021-11-14': false,
|
||||||
|
'2021-11-15': true,
|
||||||
|
'2021-11-16': true,
|
||||||
|
'2021-11-17': true,
|
||||||
|
'2021-11-18': true,
|
||||||
|
'2021-11-19': true,
|
||||||
|
'2021-11-20': false,
|
||||||
|
'2021-11-21': false,
|
||||||
|
'2021-11-22': true,
|
||||||
|
'2021-11-23': true,
|
||||||
|
'2021-11-24': true,
|
||||||
|
'2021-11-25': true,
|
||||||
|
'2021-11-26': true,
|
||||||
|
'2021-11-27': false,
|
||||||
|
'2021-11-28': false,
|
||||||
|
'2021-11-29': true,
|
||||||
|
'2021-11-30': true,
|
||||||
|
'2021-12-01': true,
|
||||||
|
'2021-12-02': true,
|
||||||
|
'2021-12-03': true,
|
||||||
|
'2021-12-04': false,
|
||||||
|
'2021-12-05': false,
|
||||||
|
'2021-12-06': true,
|
||||||
|
'2021-12-07': true,
|
||||||
|
'2021-12-08': true,
|
||||||
|
'2021-12-09': true,
|
||||||
|
'2021-12-10': true,
|
||||||
|
'2021-12-11': false,
|
||||||
|
'2021-12-12': false,
|
||||||
|
'2021-12-13': false,
|
||||||
|
'2021-12-14': false,
|
||||||
|
'2021-12-15': false,
|
||||||
|
'2021-12-16': false,
|
||||||
|
},
|
||||||
|
|
||||||
realtimeDataUpdatedAt: 1635406146,
|
realtimeDataUpdatedAt: 1635406146,
|
||||||
|
|
||||||
origin: {
|
origin: {
|
||||||
|
|
Loading…
Add table
Reference in a new issue