FPTF location objects

see public-transport/friendly-public-transport-format@6481dee
This commit is contained in:
Jannis R 2017-12-11 19:25:29 +01:00
parent 14cdc77c0f
commit 3811b4553c
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
6 changed files with 78 additions and 66 deletions

View file

@ -40,6 +40,7 @@
"devDependencies": {
"co": "^4.6.0",
"db-stations": "^1.25.0",
"is-coordinates": "^2.0.2",
"is-roughly-equal": "^0.1.0",
"tap-spec": "^4.1.1",
"tape": "^4.8.0",

View file

@ -1,25 +1,31 @@
'use strict'
const types = Object.create(null)
types.P = 'poi'
types.S = 'station'
types.A = 'address'
const POI = 'P'
const STATION = 'S'
const ADDRESS = 'A'
// todo: what is s.rRefL?
// todo: is passing in profile necessary?
const parseLocation = (profile, l) => {
const type = types[l.type] || 'unknown'
const res = {
type,
name: l.name,
coordinates: l.crd ? {
latitude: l.crd.y / 1000000,
longitude: l.crd.x / 1000000
} : null
const res = {type: 'location'}
if (l.crd) {
res.latitude = l.crd.y / 1000000
res.longitude = l.crd.x / 1000000
}
if (type === 'poi' || type === 'station') res.id = l.extId
if ('pCls' in l) res.products = profile.parseProducts(l.pCls)
if (l.type === STATION) {
const station = {
type: 'station',
id: l.extId,
location: res
}
if ('pCls' in l) station.products = profile.parseProducts(l.pCls)
return station
}
if (type === POI) res.id = l.extId
else if (l.type === ADDRESS) res.address = l.name
else res.name = l.name
return res
}

View file

@ -27,7 +27,8 @@ const createParseMovement = (profile, locations, lines, remarks) => {
const res = {
direction: profile.parseStationName(m.dirTxt),
line: lines[m.prodX] || null,
coordinates: m.pos ? {
location: m.pos ? {
type: 'location',
latitude: m.pos.y / 1000000,
longitude: m.pos.x / 1000000
} : null,

View file

@ -53,18 +53,18 @@ const isJungfernheide = (s) => {
return s.type === 'station' &&
(s.id === '008011167' || s.id === '8011167') &&
s.name === 'Berlin Jungfernheide' &&
s.coordinates &&
isRoughlyEqual(s.coordinates.latitude, 52.530408, .0005) &&
isRoughlyEqual(s.coordinates.longitude, 13.299424, .0005)
s.location &&
isRoughlyEqual(s.location.latitude, 52.530408, .0005) &&
isRoughlyEqual(s.location.longitude, 13.299424, .0005)
}
const assertIsJungfernheide = (t, s) => {
t.equal(s.type, 'station')
t.ok(s.id === '008011167' || s.id === '8011167', 'id should be 8011167')
t.equal(s.name, 'Berlin Jungfernheide')
t.ok(s.coordinates)
t.ok(isRoughlyEqual(s.coordinates.latitude, 52.530408, .0005))
t.ok(isRoughlyEqual(s.coordinates.longitude, 13.299424, .0005))
t.ok(s.location)
t.ok(isRoughlyEqual(s.location.latitude, 52.530408, .0005))
t.ok(isRoughlyEqual(s.location.longitude, 13.299424, .0005))
}
const assertValidProducts = (t, p) => {
@ -170,8 +170,8 @@ test('Berlin Jungfernheide to Torfstraße 17', co.wrap(function* (t) {
const d = part.destination
assertValidAddress(t, d)
t.equal(d.name, 'Torfstraße 17')
t.ok(isRoughlyEqual(.0001, d.coordinates.latitude, 52.5416823))
t.ok(isRoughlyEqual(.0001, d.coordinates.longitude, 13.3491223))
t.ok(isRoughlyEqual(.0001, d.latitude, 52.5416823))
t.ok(isRoughlyEqual(.0001, d.longitude, 13.3491223))
t.end()
}))
@ -199,8 +199,8 @@ test('Berlin Jungfernheide to ATZE Musiktheater', co.wrap(function* (t) {
const d = part.destination
assertValidPoi(t, d)
t.equal(d.name, 'ATZE Musiktheater')
t.ok(isRoughlyEqual(.0001, d.coordinates.latitude, 52.542399))
t.ok(isRoughlyEqual(.0001, d.coordinates.longitude, 13.350402))
t.ok(isRoughlyEqual(.0001, d.latitude, 52.542399))
t.ok(isRoughlyEqual(.0001, d.longitude, 13.350402))
t.end()
}))

View file

@ -2,53 +2,57 @@
const isRoughlyEqual = require('is-roughly-equal')
const {DateTime} = require('luxon')
const isValidWGS84 = require('is-coordinates')
const assertValidStation = (t, s, coordsOptional = false) => {
t.equal(typeof s.type, 'string')
t.equal(s.type, 'station')
t.equal(typeof s.id, 'string')
t.ok(s.id)
t.equal(typeof s.name, 'string')
if (!coordsOptional) {
if (!s.coordinates) console.trace()
t.ok(s.coordinates)
}
if (s.coordinates) {
t.equal(typeof s.coordinates.latitude, 'number')
t.equal(typeof s.coordinates.longitude, 'number')
t.ok(s.name)
if (!coordsOptional || (s.location !== null && s.location !== undefined)) {
t.ok(s.location)
assertValidLocation(t, s.location, coordsOptional)
}
}
const assertValidPoi = (t, p) => {
t.equal(typeof p.type, 'string')
t.equal(p.type, 'poi')
t.equal(typeof p.id, 'string')
t.equal(typeof p.name, 'string')
t.ok(p.coordinates)
if (p.coordinates) {
t.equal(typeof p.coordinates.latitude, 'number')
t.equal(typeof p.coordinates.longitude, 'number')
}
t.equal(typeof a.address, 'string') // todo: do POIs always have an address?
assertValidLocation(t, a, true) // todo: do POIs always have coords?
}
const assertValidAddress = (t, a) => {
t.equal(typeof a.type, 'string')
t.equal(a.type, 'address')
t.equal(typeof a.name, 'string')
t.ok(a.coordinates)
if (a.coordinates) {
t.equal(typeof a.coordinates.latitude, 'number')
t.equal(typeof a.coordinates.longitude, 'number')
}
t.equal(typeof a.address, 'string')
assertValidLocation(t, a, true) // todo: do addresses always have coords?
}
const assertValidLocation = (t, l) => {
if (l.type === 'station') assertValidStation(t, l)
else if (l.type === 'poi') assertValidPoi(t, l)
else if (l.type === 'address') assertValidAddress(t, l)
else t.fail('invalid type ' + l.type)
const assertValidLocation = (t, l, coordsOptional = false) => {
t.equal(l.type, 'location')
if (l.name !== null && l.name !== undefined) {
t.equal(typeof l.name, 'string')
t.ok(l.name)
}
if (l.address !== null && l.address !== undefined) {
t.equal(typeof l.address, 'string')
t.ok(l.address)
}
const hasLatitude = l.latitude !== null && l.latitude !== undefined
const hasLongitude = l.longitude !== null && l.longitude !== undefined
if (!coordsOptional && hasLatitude) t.equal(typeof l.latitude, 'number')
if (!coordsOptional && hasLongitude) t.equal(typeof l.longitude, 'number')
if ((hasLongitude && !hasLatitude) || (hasLatitude && !hasLongitude)) {
t.fail('should have both .latitude and .longitude')
}
if (hasLatitude && hasLongitude) isValidWGS84([l.longitude, l.latitude])
if (!coordsOptional && l.altitude !== null && l.altitude !== undefined) {
t.equal(typeof l.altitude, 'number')
}
}
const isValidMode = (m) => {

View file

@ -204,8 +204,8 @@ test('journeys  station to address', co.wrap(function* (t) {
const dest = part.destination
assertValidAddress(t, dest)
t.strictEqual(dest.name, 'Torfstr. 17')
t.ok(isRoughlyEqual(.0001, dest.coordinates.latitude, 52.5416823))
t.ok(isRoughlyEqual(.0001, dest.coordinates.longitude, 13.3491223))
t.ok(isRoughlyEqual(.0001, dest.latitude, 52.5416823))
t.ok(isRoughlyEqual(.0001, dest.longitude, 13.3491223))
assertValidWhen(t, part.arrival)
t.end()
@ -231,8 +231,8 @@ test('journeys  station to POI', co.wrap(function* (t) {
const dest = part.destination
assertValidPoi(t, dest)
t.strictEqual(dest.name, 'ATZE Musiktheater')
t.ok(isRoughlyEqual(.0001, dest.coordinates.latitude, 52.543333))
t.ok(isRoughlyEqual(.0001, dest.coordinates.longitude, 13.351686))
t.ok(isRoughlyEqual(.0001, dest.latitude, 52.543333))
t.ok(isRoughlyEqual(.0001, dest.longitude, 13.351686))
assertValidWhen(t, part.arrival)
t.end()
@ -322,12 +322,12 @@ test('radar', co.wrap(function* (t) {
t.ok(findStation(v.direction))
assertValidLine(t, v.line)
t.equal(typeof v.coordinates.latitude, 'number')
t.ok(v.coordinates.latitude <= 55, 'vehicle is too far away')
t.ok(v.coordinates.latitude >= 45, 'vehicle is too far away')
t.equal(typeof v.coordinates.longitude, 'number')
t.ok(v.coordinates.longitude >= 9, 'vehicle is too far away')
t.ok(v.coordinates.longitude <= 15, 'vehicle is too far away')
t.equal(typeof v.location.latitude, 'number')
t.ok(v.location.latitude <= 55, 'vehicle is too far away')
t.ok(v.location.latitude >= 45, 'vehicle is too far away')
t.equal(typeof v.location.longitude, 'number')
t.ok(v.location.longitude >= 9, 'vehicle is too far away')
t.ok(v.location.longitude <= 15, 'vehicle is too far away')
t.ok(Array.isArray(v.nextStops))
for (let st of v.nextStops) {