lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ tests domain gelbzeitImBericht.test.ts
| 1 | import { describe, expect, it } from 'vitest'; |
| 2 | import { validateProject } from '@/domain/validation/engine'; |
| 3 | import { hoechstgeschwindigkeitBefunde } from '@/domain/validation/rules'; |
| 4 | import { buildSignalPlan } from '@/domain/plan/signalPlan'; |
| 5 | import { |
| 6 | createConflict, |
| 7 | createPhase, |
| 8 | createSignalGroup, |
| 9 | createStandardIntersectionProject, |
| 10 | } from '@/domain/model/factory'; |
| 11 | import type { Project } from '@/domain/model/project'; |
| 12 | |
| 13 | /* |
| 14 | * Befund 39, behoben in Fassung 5.9.0 - zwei Meldungen des Pruefberichts |
| 15 | * behaupteten fest "5 s" Gelbzeit. |
| 16 | * |
| 17 | * Angesetzt wird in beiden Faellen die oberste Stufe der Gelbzeitstaffel, also |
| 18 | * der Vorgabenwert "Gelbzeit Kfz über 60 km/h". Er ist von 3 bis 10 s |
| 19 | * einstellbar. Weil die Ueberfahrzeit des Kraftfahrzeugverkehrs im Regelansatz |
| 20 | * DIE Gelbzeit ist, geht der Wert unmittelbar in jede Zwischenzeit ein: Mit |
| 21 | * 3 s rechnet der Plan 2 s kuerzer, als der Bericht behauptet - der Pruefer |
| 22 | * haelt den Plan fuer sicherer, als er ist. |
| 23 | */ |
| 24 | |
| 25 | const DATUM = new Date('2026-01-01T00:00:00Z'); |
| 26 | |
| 27 | /** Der Musterknotenpunkt mit einer abweichenden obersten Gelbzeitstufe. */ |
| 28 | function mitGelbzeit(oberste: number, aendereK1: (g: Project['signalGroups'][number]) => object) { |
| 29 | const roh = createStandardIntersectionProject('Gelbzeit', DATUM); |
| 30 | return { |
| 31 | ...roh, |
| 32 | settings: { ...roh.settings, rilsa: { ...roh.settings.rilsa, yellowKfzAbove60: oberste } }, |
| 33 | signalGroups: roh.signalGroups.map((g) => (g.name === 'K1' ? { ...g, ...aendereK1(g) } : g)), |
| 34 | } satisfies Project; |
| 35 | } |
| 36 | |
| 37 | describe('Befund 39 - Die genannte Gelbzeit stammt aus den wirksamen Vorgaben', () => { |
| 38 | it('nennt bei fehlender Hoechstgeschwindigkeit die angesetzte und nicht die fest eingeschriebene Gelbzeit', () => { |
| 39 | // Erreichbar ueber den Altdatei-Pfad: Eine 4.x-Datei mit |
| 40 | // "geschwindigkeit: 0" an einer Kfz-Gruppe wird ungeprueft uebernommen. |
| 41 | const project = mitGelbzeit(8, () => ({ vZul: 0 })); |
| 42 | const befund = validateProject(project, buildSignalPlan(project), DATUM).findings.find( |
| 43 | (f) => f.rule === 'signalgruppen.geschwindigkeit-fehlt', |
| 44 | ); |
| 45 | expect(befund?.message).toContain('8 s'); |
| 46 | expect(befund?.message).not.toContain('5 s'); |
| 47 | }); |
| 48 | |
| 49 | it('nennt ueber 70 km/h die angesetzte und nicht die fest eingeschriebene Gelbzeit', () => { |
| 50 | const project = mitGelbzeit(8, () => ({ vZul: 90 })); |
| 51 | const befund = validateProject(project, buildSignalPlan(project), DATUM).findings.find( |
| 52 | (f) => f.rule === 'signalgruppen.vzul-ueber-70', |
| 53 | ); |
| 54 | expect(befund?.message).toContain('8 s'); |
| 55 | expect(befund?.message).not.toContain('5 s'); |
| 56 | }); |
| 57 | |
| 58 | it('bleibt bei den Regelvorgaben bei 5 s', () => { |
| 59 | // Die Gegenprobe: Ohne Aenderung der Vorgaben darf sich am Wortlaut |
| 60 | // nichts verschieben. |
| 61 | const project = mitGelbzeit(5, () => ({ vZul: 90 })); |
| 62 | const befund = validateProject(project, buildSignalPlan(project), DATUM).findings.find( |
| 63 | (f) => f.rule === 'signalgruppen.vzul-ueber-70', |
| 64 | ); |
| 65 | expect(befund?.message).toContain('5 s'); |
| 66 | }); |
| 67 | |
| 68 | it('behauptet fuer eine OePNV-Gruppe keine Gelbzeit', () => { |
| 69 | // OePNV-Sondersignale (Balkensignale) kennen kein Gelb; yellowTime liefert |
| 70 | // dort 0 s. Der Satz "Die Gelbzeit ist mit 5 s angesetzt" war schon mit den |
| 71 | // Regelvorgaben falsch - und ohne jede Vorgabenaenderung erreichbar. |
| 72 | const roh = createStandardIntersectionProject('ÖPNV', DATUM); |
| 73 | const k1 = roh.signalGroups.find((g) => g.name === 'K1')!; |
| 74 | const bahn = { ...createSignalGroup({ name: 'B1', mode: 'oepnv', index: 6 }), vZul: 90 }; |
| 75 | const phase3 = createPhase('Phase 3 - ÖPNV', [bahn.id]); |
| 76 | const project: Project = { |
| 77 | ...roh, |
| 78 | signalGroups: [...roh.signalGroups, bahn], |
| 79 | phases: [...roh.phases, phase3], |
| 80 | program: { ...roh.program, phaseOrder: [...roh.program.phaseOrder, phase3.id] }, |
| 81 | conflicts: [ |
| 82 | ...roh.conflicts, |
| 83 | { ...createConflict(bahn.id, k1.id), clearingDistance: 20, enteringDistance: 8 }, |
| 84 | ], |
| 85 | }; |
| 86 | const befund = hoechstgeschwindigkeitBefunde(project, buildSignalPlan(project).defaults).find( |
| 87 | (f) => f.rule === 'signalgruppen.vzul-ueber-70' && f.target?.id === bahn.id, |
| 88 | ); |
| 89 | /* |
| 90 | * NACHGEZOGEN MIT 5.27.0: Der Satz sagte "haben keine Gelbzeit" und liess |
| 91 | * damit offen, dass ueberhaupt ein Uebergang geschaltet wird. Gesondert |
| 92 | * signalisierte Strassenbahnen bekommen ein Uebergangssignal nach |
| 93 | * Par. 51 BOStrab, dessen Dauer die RiLSA 2015 in Abschnitt 2.4 staffelt; |
| 94 | * oberhalb 70 km/h gilt die oberste Stufe von 8 s. |
| 95 | */ |
| 96 | expect(befund).toBeDefined(); |
| 97 | expect(befund?.message).not.toContain('Gelbzeit ist mit 5 s'); |
| 98 | expect(befund?.message).toContain('kein Gelb, sondern ein Übergangssignal'); |
| 99 | expect(befund?.message).toContain('8 s'); |
| 100 | }); |
| 101 | }); |