lsa-planer

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

/ tests domain signalbilder.test.ts

2,9 KB Rohdatei
tests/domain/signalbilder.test.ts — 78 Zeilen
1 import { describe, expect, it } from 'vitest';
2 import { aspectAt, aspectSegments, aspectTotals, isGreenAt } from '@/domain/plan/aspects';
3 import type { PlannedSignalGroup } from '@/domain/plan/signalPlan';
4
5 /*
6 * Befund F33: Reichte das Gelb des einen Freigabefensters ueber den Beginn des
7 * naechsten hinweg, kuerzte aspectSegments die FREIGABE statt das Gelb.
8 *
9 * Der Anwender sah dadurch in derselben Tabellenzeile zwei einander
10 * widersprechende Zahlen: In der Spalte "Freigabezeit (Summe)" stand die volle
11 * Freigabezeit aus dem Plan, in den Spalten Rot-Gelb/Gelb/Rot die um die
12 * Ueberschneidung gekuerzte Summe aus den Signalbildern - und der gezeichnete
13 * Balken zeigte Gelb, wo die Simulation Freigabe meldete.
14 */
15
16 type Pruefgruppe = Pick<PlannedSignalGroup, 'greens' | 'times'>;
17
18 /** Zwei Freigabefenster ohne Abstand; das Gelb des ersten faellt ins zweite. */
19 const OHNE_ABSTAND: Pruefgruppe = {
20 greens: [
21 { start: 0, duration: 20 },
22 { start: 20, duration: 15 },
23 ],
24 times: { minGreen: 5, yellow: 3, redYellow: 1 },
25 };
26
27 /** Drei Sekunden Abstand bei fuenf Sekunden Gelbzeit. */
28 const KUERZER_ALS_GELB: Pruefgruppe = {
29 greens: [
30 { start: 0, duration: 20 },
31 { start: 23, duration: 15 },
32 ],
33 times: { minGreen: 5, yellow: 5, redYellow: 1 },
34 };
35
36 const UMLAUF = 60;
37
38 describe('Signalbilder bei dicht aufeinanderfolgenden Freigabefenstern', () => {
39 it('zeigt die volle Freigabezeit, wenn zwei Fenster ohne Abstand aufeinanderfolgen', () => {
40 const totals = aspectTotals(OHNE_ABSTAND, UMLAUF);
41 const freigabe = OHNE_ABSTAND.greens.reduce((summe, g) => summe + g.duration, 0);
42
43 expect(totals.gruen).toBeCloseTo(freigabe, 3);
44 });
45
46 it('kuerzt das Gelb und nicht die Freigabe, wenn der Abstand kleiner als die Gelbzeit ist', () => {
47 const totals = aspectTotals(KUERZER_ALS_GELB, UMLAUF);
48 const freigabe = KUERZER_ALS_GELB.greens.reduce((summe, g) => summe + g.duration, 0);
49
50 expect(totals.gruen).toBeCloseTo(freigabe, 3);
51 // Von den 5 s Gelb des ersten Fensters bleiben die 3 s bis zum naechsten
52 // Freigabebeginn; das zweite Fenster behaelt seine vollen 5 s.
53 expect(totals.gelb).toBeCloseTo(8, 3);
54 });
55
56 it('sagt dasselbe wie die Freigabezeitfenster - Signalbild gegen isGreenAt', () => {
57 for (const gruppe of [OHNE_ABSTAND, KUERZER_ALS_GELB]) {
58 for (let t = 0; t < UMLAUF; t += 0.5) {
59 expect(aspectAt(gruppe, t, UMLAUF) === 'gruen', `t=${t}s`).toBe(
60 isGreenAt(gruppe, t, UMLAUF),
61 );
62 }
63 }
64 });
65
66 it('zerlegt den Umlauf weiterhin lueckenlos und ueberschneidungsfrei', () => {
67 for (const gruppe of [OHNE_ABSTAND, KUERZER_ALS_GELB]) {
68 const segmente = aspectSegments(gruppe, UMLAUF);
69 let cursor = 0;
70 for (const segment of segmente) {
71 expect(segment.start).toBeCloseTo(cursor, 3);
72 expect(segment.duration).toBeGreaterThan(0);
73 cursor += segment.duration;
74 }
75 expect(cursor).toBeCloseTo(UMLAUF, 3);
76 }
77 });
78 });