lsa-planer

LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.

/ tests domain gelbzeitImBericht.test.ts

4,7 KB Rohdatei
tests/domain/gelbzeitImBericht.test.ts — 101 Zeilen
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 });