lsa-planer

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

/ tests domain koordinierungImUmlauf.test.ts

4,2 KB Rohdatei
tests/domain/koordinierungImUmlauf.test.ts — 99 Zeilen
1 import { describe, expect, it } from 'vitest';
2 import { RILSA_DEFAULTS } from '@/domain/rilsa/constants';
3 import { computeCoordination } from '@/domain/rilsa/coordination';
4
5 /*
6 * Befunde S2 und S4, behoben in Fassung 5.10.0.
7 *
8 * Der Versatz wurde zyklisch gebildet (modulo Umlaufzeit), die Bandbreite
9 * dagegen auf der Geraden: "greenStart - Reisezeit" wurde ohne Faltung in den
10 * Umlauf gegen die uebrigen Fenster geschnitten. Ein Signalprogramm wiederholt
11 * sich aber mit jedem Umlauf; die Fenster liegen auf einem Kreis der Laenge tU.
12 * Sobald "greenStart - Reisezeit" unter den Umlaufbeginn fiel, meldete die
13 * Rechnung "keine Bandbreite" - und zwar fuer genau die Versaetze, die sie in
14 * intersections[i].offset selbst empfiehlt.
15 *
16 * Fuer Fassung 5 ist gegenueber 4.x zugesagt, die Rechnung
17 * ermittle "die tatsächliche Schnittmenge der Freigabefenster". Sie wird von
18 * keiner Ansicht aufgerufen, gehoert aber ueber src/domain/rilsa/index.ts zur
19 * oeffentlichen Schnittstelle des Fachkerns.
20 */
21
22 describe('Bandbreite der Koordinierung auf dem Umlauf (Befunde S2 und S4)', () => {
23 it('faltet Freigabefenster in den Umlauf, wenn die Reisezeit den Umlauf uebersteigt', () => {
24 // tU 60 s, 50 km/h, 1000 m -> Reisezeit 72,0 s, empfohlener Versatz 12,0 s.
25 // Mit genau diesem Versatz decken sich beide Fenster vollstaendig.
26 const result = computeCoordination(
27 [
28 { id: 'a', name: 'Knoten A', distanceToPrevious: 0, greenStart: 0, greenDuration: 30 },
29 { id: 'b', name: 'Knoten B', distanceToPrevious: 1000, greenStart: 12, greenDuration: 30 },
30 ],
31 60,
32 50,
33 );
34
35 expect(result.intersections[1]!.travelTime).toBeCloseTo(72, 1);
36 expect(result.intersections[1]!.offset).toBeCloseTo(12, 1);
37 expect(result.bandwidth).toBe(30);
38 expect(result.bandwidthRatio).toBe(0.5);
39 expect(result.quality).toBe('gut');
40 expect(result.notes.some((n) => n.code === 'keine-bandbreite')).toBe(false);
41 });
42
43 it('faltet auch, wenn nur der Umlaufbeginn ueberschritten wird', () => {
44 // tU 60 s, 60 km/h, 500 m -> Reisezeit 30,0 s. A ab 40 s, B ab 10 s: der
45 // Versatz passt, das zurueckgerechnete Fenster von B liegt bei 40 s.
46 const result = computeCoordination(
47 [
48 { id: 'a', name: 'Knoten A', distanceToPrevious: 0, greenStart: 40, greenDuration: 20 },
49 { id: 'b', name: 'Knoten B', distanceToPrevious: 500, greenStart: 10, greenDuration: 20 },
50 ],
51 60,
52 60,
53 );
54
55 expect(result.intersections[1]!.travelTime).toBeCloseTo(30, 1);
56 expect(result.bandwidth).toBe(20);
57 expect(result.notes.some((n) => n.code === 'keine-bandbreite')).toBe(false);
58 });
59
60 it('nimmt den laengsten zusammenhaengenden Bogen, nicht die Summe der Teilbogen', () => {
61 // tU 60 s, 60 km/h, 1000 m -> Reisezeit 60,0 s, also ein voller Umlauf.
62 // A [0; 50), B zurueckgerechnet [20; 70) = [20; 60) und [0; 10). Die
63 // Schnittmenge zerfaellt in zwei Boegen von 30 s und 10 s; nutzbar ist der
64 // laengere, nicht die Summe von 40 s - und nicht der ungefaltete Rest von
65 // 10 s, den die geradlinige Rechnung uebrig liess.
66 const result = computeCoordination(
67 [
68 { id: 'a', name: 'Knoten A', distanceToPrevious: 0, greenStart: 0, greenDuration: 50 },
69 { id: 'b', name: 'Knoten B', distanceToPrevious: 1000, greenStart: 20, greenDuration: 50 },
70 ],
71 60,
72 60,
73 );
74
75 expect(result.intersections[1]!.travelTime).toBeCloseTo(60, 1);
76 expect(result.bandwidth).toBe(30);
77 });
78
79 it('nimmt die Progressionsgeschwindigkeit aus den Projektvorgaben, nicht aus den Regelwerten', () => {
80 const vorgaben = {
81 ...RILSA_DEFAULTS,
82 coordination: { ...RILSA_DEFAULTS.coordination, defaultSpeed: 40 },
83 };
84 const result = computeCoordination(
85 [
86 { id: 'a', name: 'Knoten A', distanceToPrevious: 0, greenStart: 0, greenDuration: 30 },
87 { id: 'b', name: 'Knoten B', distanceToPrevious: 400, greenStart: 36, greenDuration: 30 },
88 ],
89 90,
90 undefined,
91 vorgaben,
92 );
93
94 expect(RILSA_DEFAULTS.coordination.defaultSpeed).toBe(50);
95 expect(result.speed).toBe(40);
96 // 400 m bei 40 km/h = 11,111 m/s -> 36,0 s, nicht 28,8 s wie bei 50 km/h.
97 expect(result.intersections[1]!.travelTime).toBeCloseTo(36, 1);
98 });
99 });