From fd6f5c5524a726488ffdff24b65154c53ac486bc Mon Sep 17 00:00:00 2001 From: Ridwan Aditama Date: Mon, 7 Sep 2026 10:23:28 +0200 Subject: [PATCH 1/2] fix: only negative transfer time as an "uncertain transfer" --- src/transfer-risk/__tests__/transfer-risk.test.ts | 12 ++++++++++-- src/transfer-risk/transfer-risk.ts | 15 +++++++-------- src/transfer-risk/types.ts | 5 ++--- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/transfer-risk/__tests__/transfer-risk.test.ts b/src/transfer-risk/__tests__/transfer-risk.test.ts index 4134358..68b5eb8 100644 --- a/src/transfer-risk/__tests__/transfer-risk.test.ts +++ b/src/transfer-risk/__tests__/transfer-risk.test.ts @@ -33,8 +33,8 @@ describe('getTransferRisk', () => { expect(getTransferRisk(600)).toBeUndefined(); }); - it('treats a zero gap as uncertain', () => { - expect(getTransferRisk(0)).toBe('uncertain'); + it('passes on a zero gap, which the planner treats as feasible', () => { + expect(getTransferRisk(0)).toBeUndefined(); }); it('is uncertain at any negative gap, however large', () => { @@ -81,6 +81,14 @@ describe('getLegTransferRisk', () => { expect(getLegTransferRisk(legs, 1)).toBeUndefined(); }); + it('passes when the connection leaves the instant you arrive', () => { + const legs = [ + transitLeg({expectedEndTime: '2024-01-01T10:10:00.000Z'}), + transitLeg({expectedStartTime: '2024-01-01T10:10:00.000Z'}), + ]; + expect(getLegTransferRisk(legs, 1)).toBeUndefined(); + }); + it('passes on the first leg, which nothing precedes', () => { expect(getLegTransferRisk([transitLeg(), transitLeg()], 0)).toBeUndefined(); }); diff --git a/src/transfer-risk/transfer-risk.ts b/src/transfer-risk/transfer-risk.ts index e073458..12ab2fc 100644 --- a/src/transfer-risk/transfer-risk.ts +++ b/src/transfer-risk/transfer-risk.ts @@ -2,13 +2,12 @@ import type {TransferLeg} from './types'; import {TransferRisk} from './types'; /** - * Classifies the gap between arriving and the next departure: any gap that is - * not positive is uncertain, however large. Zero counts, because arriving - * exactly as the service leaves is not a transfer you can rely on. A - * non-finite gap yields undefined. + * Classifies the gap between arriving and the next departure: a negative gap is + * uncertain, however small. Zero seconds transfer is considered valid by Entur and is + * returned by the trip planner, so it is considered not a "risky" transfer */ export const getTransferRisk = (seconds: number): TransferRisk | undefined => { - if (!Number.isFinite(seconds) || seconds > 0) { + if (!Number.isFinite(seconds) || seconds >= 0) { return undefined; } return TransferRisk.Uncertain; @@ -24,9 +23,9 @@ export const isTransitLeg = (leg: TransferLeg): boolean => * before, so an intervening walk counts. * * Undefined when the leg is not transit, when no transit leg precedes it, or - * when the transfer still holds. The transit check also keeps the warning off - * the leg leading *into* a walk: those gaps are commonly re-anchored to exactly - * zero, which would otherwise fire on every transfer. + * when the transfer still holds. The transit check keeps the warning off the leg + * leading *into* a walk, where it would sit on a leg clients are free to filter + * out of the display. */ export const getLegTransferRisk = ( legs: TransferLeg[], diff --git a/src/transfer-risk/types.ts b/src/transfer-risk/types.ts index e191047..d17f780 100644 --- a/src/transfer-risk/types.ts +++ b/src/transfer-risk/types.ts @@ -1,7 +1,6 @@ /** - * Transfer risk classification for transfers with no slack (0s) or already - * missed (negative gaps). Kept as a string (vs boolean) because additional - * levels (e.g. `shortWait`) may be added later. + * Transfer risk classification for transfers. Kept as a string (vs boolean) + * because additional level(s) will be added later (`shortWait` will be added soon). */ export const TransferRisk = { Uncertain: 'uncertain', From 1019852a5d13633d7449c95e8cce58184a6e94e2 Mon Sep 17 00:00:00 2001 From: Ridwan Aditama Date: Mon, 7 Sep 2026 10:34:18 +0200 Subject: [PATCH 2/2] Apply batched suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/transfer-risk/transfer-risk.ts | 4 ++-- src/transfer-risk/types.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transfer-risk/transfer-risk.ts b/src/transfer-risk/transfer-risk.ts index 12ab2fc..8c3d22d 100644 --- a/src/transfer-risk/transfer-risk.ts +++ b/src/transfer-risk/transfer-risk.ts @@ -3,8 +3,8 @@ import {TransferRisk} from './types'; /** * Classifies the gap between arriving and the next departure: a negative gap is - * uncertain, however small. Zero seconds transfer is considered valid by Entur and is - * returned by the trip planner, so it is considered not a "risky" transfer + * uncertain, however small. A zero-second transfer is treated as feasible by Entur and may be + * returned by the trip planner, so it is not treated as a risky transfer. Non-finite values yield undefined. */ export const getTransferRisk = (seconds: number): TransferRisk | undefined => { if (!Number.isFinite(seconds) || seconds >= 0) { diff --git a/src/transfer-risk/types.ts b/src/transfer-risk/types.ts index d17f780..b5d33ec 100644 --- a/src/transfer-risk/types.ts +++ b/src/transfer-risk/types.ts @@ -1,6 +1,6 @@ /** * Transfer risk classification for transfers. Kept as a string (vs boolean) - * because additional level(s) will be added later (`shortWait` will be added soon). + * because additional levels may be added later (e.g. `shortWait`). */ export const TransferRisk = { Uncertain: 'uncertain',