import { readFileSync } from 'node:fs'; import { describe, expect, it } from 'vitest'; import { buildSignalPlan } from '@/domain/plan/signalPlan'; import { parseProject } from '@/domain/model/schema'; import { RILSA_DEFAULTS } from '@/domain/rilsa/constants'; /* * Die Beispieldatei beispiele/vierarmiger-knotenpunkt.lsap unter der Furtregel * (Befund C1). * * Die VORLAGE (createStandardIntersectionProject, Furten 12 m) bleibt bei 5 s * - das prueft fehlendePruefungen.test.ts. Die BEISPIELDATEI ist eine andere * Planung: Ihre Fussgaengergruppen raeumen bis zu 14,39 m (F Nord gegen K Ost), * die halbe Furt braucht 7,20 m / 1,2 m/s = 5,996 s, und daraus werden 6 s * statt der bisherigen 5 s. Wer die Datei oeffnet, sieht also eine * Verhaltensaenderung, und die steht in den Unterlagen der Fassung ("Achtung * bei bestehenden Projekten") - dieser Test haelt fest, dass die dort * genannten Zahlen die der Datei sind. Gegen den Altstand schlaegt er fehl * (dort 5 s, kein Hinweis). */ const DATEI = 'beispiele/vierarmiger-knotenpunkt.lsap'; const DATUM = new Date('2026-01-01T00:00:00Z'); function beispiel(): ReturnType { return parseProject(JSON.parse(readFileSync(DATEI, 'utf8')), DATUM); } describe('Beispieldatei vierarmiger-knotenpunkt.lsap unter der Furtregel', () => { it('liest sich ohne Fehler ein - Schema 7, ohne das Feld blindenzusatz', () => { const ergebnis = beispiel(); expect(ergebnis.issues.filter((i) => i.severity === 'fehler')).toEqual([]); for (const gruppe of ergebnis.project.signalGroups.filter((g) => g.mode === 'fuss')) { // Altdatei: kein Zusatz erfasst, gerechnet wird die halbe Furt. expect(gruppe.blindenzusatz).toBeUndefined(); } }); it('gibt allen vier Fussgaengergruppen 6 s statt 5 s: laengster Raeumweg 14,39 m, halbe Furt 7,20 m / 1,2 m/s = 5,996 s', () => { const { project } = beispiel(); const plan = buildSignalPlan(project); const fussgruppen = plan.groups.filter((g) => g.mode === 'fuss'); expect(fussgruppen).toHaveLength(4); for (const gruppe of fussgruppen) { const mfz = gruppe.mindestfreigabezeit; expect(mfz.regelwert).toBe(RILSA_DEFAULTS.minGreen.fuss); expect(mfz.furt).not.toBeNull(); expect(mfz.furt!.furtlaenge).toBeCloseTo(14.39, 6); expect(mfz.furt!.ganzeFurt).toBe(false); expect(mfz.furt!.vr).toBe(1.2); expect(mfz.furt!.zeitbedarf).toBeCloseTo(5.996, 3); expect(mfz.furt!.zeitbedarfGerundet).toBe(6); expect(mfz.massgebend).toBe('furt'); expect(mfz.wert).toBe(6); expect(gruppe.times.minGreen).toBe(6); // Der Plan haelt die neue Untergrenze ein - kein "unterschritten". expect(gruppe.totalGreen).toBeGreaterThanOrEqual(6); } expect(plan.notes.some((n) => n.code === 'mindestfreigabezeit-unterschritten')).toBe(false); }); it('nennt zu jeder Fussgaengergruppe den Rechenweg als Hinweis', () => { const { project } = beispiel(); const plan = buildSignalPlan(project); const hinweise = plan.notes.filter((n) => n.code === 'mindestfreigabezeit-aus-furtlaenge'); expect(hinweise).toHaveLength(4); for (const hinweis of hinweise) { expect(hinweis.severity).toBe('hinweis'); expect(hinweis.message).toContain('Furt von 14,39 m'); expect(hinweis.message).toContain('die halbe Furt'); expect(hinweis.message).toContain('7,20 m / 1,2 m/s = 5,996 s, aufgerundet 6 s'); expect(hinweis.message).toContain('betrÃĪgt deshalb 6 s statt des Regelwerts von 5 s'); } // Keine Gruppe mit unbekannter Furtlaenge: Jede raeumt gegen Kfz-Stroeme. expect(plan.notes.some((n) => n.code === 'mindestfreigabezeit-ohne-furtlaenge')).toBe(false); }); });