From ec8df01f855b305d8c1ef180e9ee7e8b84bb28cb Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 29 Oct 2026 12:10:54 +0100 Subject: [PATCH] feat(shared): name the Valhalla costing of each profile and the providers that route every day VALHALLA_COSTING maps driving, walking and cycling to auto, pedestrian and bicycle once for the planner and the server. valhallaRoutesEveryDay says whether the resolved provider carries every day: the TREK services and an own Valhalla do, FOSSGIS and no Valhalla leave the days to OSRM. --- .../routing-relay.schema.spec.ts | 28 ++++++++++++++++++- .../src/routing-relay/routing-relay.schema.ts | 1 + shared/src/routing-relay/valhalla-provider.ts | 25 ++++++++++++++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/shared/src/routing-relay/routing-relay.schema.spec.ts b/shared/src/routing-relay/routing-relay.schema.spec.ts index 8a57c58ea..3d4d65a8b 100644 --- a/shared/src/routing-relay/routing-relay.schema.spec.ts +++ b/shared/src/routing-relay/routing-relay.schema.spec.ts @@ -4,7 +4,13 @@ import { valhallaRouteRequestSchema, valhallaTraceRequestSchema, } from './routing-relay.schema'; -import { compactValhallaRequest, encodePolyline6, resolveValhallaProvider } from './valhalla-provider'; +import { + compactValhallaRequest, + encodePolyline6, + resolveValhallaProvider, + VALHALLA_COSTING, + valhallaRoutesEveryDay, +} from './valhalla-provider'; import { describe, expect, it } from 'vitest'; @@ -143,3 +149,23 @@ describe('resolveValhallaProvider', () => { expect(resolveValhallaProvider({ ...unset, provider: 'nonsense', valhallaUrl: ' ' })).toBe('trek'); }); }); + +describe('valhallaRoutesEveryDay', () => { + it('hands every day to the TREK services and an own Valhalla, never to FOSSGIS or no Valhalla', () => { + expect(valhallaRoutesEveryDay('trek')).toBe(true); + expect(valhallaRoutesEveryDay('custom')).toBe(true); + expect(valhallaRoutesEveryDay('fossgis')).toBe(false); + expect(valhallaRoutesEveryDay(null)).toBe(false); + }); +}); + +describe('VALHALLA_COSTING', () => { + it('asks each profile under a costing the relay takes', () => { + expect(VALHALLA_COSTING).toEqual({ driving: 'auto', walking: 'pedestrian', cycling: 'bicycle' }); + for (const costing of Object.values(VALHALLA_COSTING)) { + expect( + valhallaRouteRequestSchema.safeParse({ ...route, costing, costing_options: { [costing]: {} } }).success, + ).toBe(true); + } + }); +}); diff --git a/shared/src/routing-relay/routing-relay.schema.ts b/shared/src/routing-relay/routing-relay.schema.ts index 544e59495..0f05839a7 100644 --- a/shared/src/routing-relay/routing-relay.schema.ts +++ b/shared/src/routing-relay/routing-relay.schema.ts @@ -36,6 +36,7 @@ const point = z.object({ }); const costingSchema = z.enum(['auto', 'pedestrian', 'bicycle']); +export type ValhallaCosting = z.infer; const optionName = z.string().min(1).max(64); /** Per costing, its weightings and switches by name: a number, a word or a flag. */ diff --git a/shared/src/routing-relay/valhalla-provider.ts b/shared/src/routing-relay/valhalla-provider.ts index bdf599b74..63d4a2f4e 100644 --- a/shared/src/routing-relay/valhalla-provider.ts +++ b/shared/src/routing-relay/valhalla-provider.ts @@ -1,4 +1,16 @@ -import { valhallaProviderSchema, type ValhallaProvider, type ValhallaRelayAction } from './routing-relay.schema'; +import { + valhallaProviderSchema, + type ValhallaCosting, + type ValhallaProvider, + type ValhallaRelayAction, +} from './routing-relay.schema'; + +/** TREK's three route profiles against the Valhalla costing model each is asked under. */ +export const VALHALLA_COSTING = { + driving: 'auto', + walking: 'pedestrian', + cycling: 'bicycle', +} as const satisfies Record<'driving' | 'walking' | 'cycling', ValhallaCosting>; /** What decides which Valhalla an instance asks, as its settings hold it. */ export interface ValhallaChoice { @@ -32,6 +44,17 @@ export function resolveValhallaProvider(choice: ValhallaChoice): ValhallaProvide return choice.trekAvailable ? 'trek' : 'fossgis'; } +/** + * Whether this Valhalla routes every day, on foot, by bike and by car, or only + * what OSRM cannot answer. The TREK services and an own Valhalla carry the + * whole load; the public FOSSGIS one allows a request a second and ten + * locations, so there OSRM keeps the days and Valhalla answers the avoidances + * and the tours. + */ +export function valhallaRoutesEveryDay(provider: ValhallaProvider | null): boolean { + return provider === 'trek' || provider === 'custom'; +} + function encodeSigned(value: number): string { let rest = value < 0 ? ~(value << 1) : value << 1; let out = '';