lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ tests domain rechenlaengenUndRotgelb.test.ts
| 1 | import { describe, expect, it } from 'vitest'; |
| 2 | import { RILSA_DEFAULTS, SAFETY_FLOORS } from '@/domain/rilsa/constants'; |
| 3 | import { resolveRilsaSettings, settingFields } from '@/domain/rilsa/settings'; |
| 4 | import { computeIntergreen } from '@/domain/rilsa/intergreen'; |
| 5 | import { QUELLEN } from '@/domain/rilsa/quellen'; |
| 6 | import type { ClearingStream, EnteringStream } from '@/domain/rilsa/types'; |
| 7 | |
| 8 | /* |
| 9 | * Befunde B5 und B6. |
| 10 | * |
| 11 | * B5: Lkw/Bus 12 m und Lastzug 18,75 m waren die Hoechstlaengen nach Par. 32 |
| 12 | * StVZO, keine RiLSA-Rechenwerte - und standen als "gesichert nach RiLSA |
| 13 | * 2015" in der Planunterlage. Die RiLSA rechnet mit 6 m fuer Kraftfahrzeuge |
| 14 | * (Fall 3 woertlich fuer Linienbusse; Lkw/Lastzug nach Sekundaerquellen). |
| 15 | * |
| 16 | * B6: Das Vorgabenfeld Rot-Gelb liess 3 s zu; 2,5 oder 3 s ergaben nur einen |
| 17 | * Abweichungshinweis. VwV-StVO zu Par. 37 Rn. 17: "soll ... eine Sekunde |
| 18 | * dauern, darf aber nicht laenger als zwei Sekunden sein". |
| 19 | */ |
| 20 | |
| 21 | const kfz = (vehicleClass: ClearingStream['vehicleClass']): ClearingStream => ({ |
| 22 | mode: 'kfz', |
| 23 | movement: 'geradeaus', |
| 24 | clearingDistance: 24, |
| 25 | vehicleClass, |
| 26 | vZul: 50, |
| 27 | }); |
| 28 | const einfahrend: EnteringStream = { mode: 'kfz', movement: 'geradeaus', enteringDistance: 10 }; |
| 29 | |
| 30 | describe('Fahrzeuglaengen sind RiLSA-Rechenlaengen (Befund B5)', () => { |
| 31 | it('setzt fuer Pkw, Lkw, Bus und Lastzug dieselben 6 m an, fuer die Strassenbahn 15 m', () => { |
| 32 | expect(RILSA_DEFAULTS.vehicleLength).toMatchObject({ |
| 33 | pkw: 6, |
| 34 | lkw: 6, |
| 35 | bus: 6, |
| 36 | lastzug: 6, |
| 37 | strassenbahn: 15, |
| 38 | rad: 0, |
| 39 | }); |
| 40 | }); |
| 41 | |
| 42 | it('rechnet Lastzug und Pkw dieselbe Zwischenzeit - der Unterschied war eine erfundene Verschaerfung', () => { |
| 43 | // 24 m + 6 m bei 10 m/s = 3,0 s Raeumzeit; mit 18,75 m waren es 4,275 s - |
| 44 | // eine Sekunde mehr Zwischenzeit, die kein Pruefer aus der RiLSA herleiten konnte. |
| 45 | const pkw = computeIntergreen(kfz('pkw'), einfahrend); |
| 46 | const lastzug = computeIntergreen(kfz('lastzug'), einfahrend); |
| 47 | expect(lastzug.vehicleLength).toBe(6); |
| 48 | expect(lastzug.intergreen).toBe(pkw.intergreen); |
| 49 | expect(lastzug.clearingTime).toBeCloseTo(3.0, 6); |
| 50 | }); |
| 51 | |
| 52 | it('haelt die 6 m als harte Untergrenze und laesst laengere Zuschlaege als Vorgabe zu', () => { |
| 53 | const zuKurz = resolveRilsaSettings({ vehicleLengthLastzug: 4 }); |
| 54 | expect(zuKurz.defaults.vehicleLength.lastzug).toBe(SAFETY_FLOORS.minVehicleLengthKfz); |
| 55 | expect(zuKurz.notes.some((n) => n.code === 'vorgabe-unterschritten:vehicleLengthLastzug')).toBe( |
| 56 | true, |
| 57 | ); |
| 58 | const verschaerft = resolveRilsaSettings({ vehicleLengthLastzug: 18.75 }); |
| 59 | expect(verschaerft.defaults.vehicleLength.lastzug).toBe(18.75); |
| 60 | expect(verschaerft.deviations.map((d) => d.key)).toContain('vehicleLengthLastzug'); |
| 61 | }); |
| 62 | |
| 63 | it('nennt im Fundstellenverzeichnis die RiLSA-Rechenlaenge fuer alle Kraftfahrzeuge', () => { |
| 64 | const quelle = QUELLEN['rilsa-fahrzeuglaengen']; |
| 65 | expect(quelle.hinweis).toContain('6 m für Kraftfahrzeuge einschließlich Lkw, Lastzug'); |
| 66 | // Der Hinweis nennt den frueheren Stand mit der Fassung, bis zu der er galt. |
| 67 | expect(quelle.hinweis).toContain('Vor der Fassung 5.4.0 standen hier Lkw/Bus 12 m'); |
| 68 | }); |
| 69 | }); |
| 70 | |
| 71 | describe('Rot-Gelb-Zeit hoechstens 2 s (Befund B6)', () => { |
| 72 | it('deckelt das Vorgabenfeld bei 2 s mit Begruendung aus der VwV-StVO', () => { |
| 73 | const feld = settingFields().find((f) => f.key === 'redYellow')!; |
| 74 | expect(feld.max).toBe(2); |
| 75 | expect(feld.min).toBe(1); |
| 76 | expect(feld.schrankenBegruendung).toContain('VwV-StVO'); |
| 77 | expect(SAFETY_FLOORS.maxRedYellow).toBe(2); |
| 78 | }); |
| 79 | |
| 80 | it('kappt eine gespeicherte Rot-Gelb-Zeit von 3 s mit Fehler auf 2 s statt sie still zu uebernehmen', () => { |
| 81 | // Bis hierher lief 3 s als blosser Abweichungshinweis in den Plan. |
| 82 | const { defaults, notes } = resolveRilsaSettings({ redYellow: 3 }); |
| 83 | expect(defaults.redYellow).toBe(2); |
| 84 | const fehler = notes.find((n) => n.code === 'vorgabe-ueberschritten:redYellow'); |
| 85 | expect(fehler?.severity).toBe('fehler'); |
| 86 | expect(fehler?.message).toContain('höchstens 2 s'); |
| 87 | expect(fehler?.message).toContain('VwV-StVO'); |
| 88 | }); |
| 89 | |
| 90 | it('nimmt 2 s als zulaessige Abweichung an', () => { |
| 91 | const { defaults, notes, deviations } = resolveRilsaSettings({ redYellow: 2 }); |
| 92 | expect(defaults.redYellow).toBe(2); |
| 93 | expect(notes).toHaveLength(0); |
| 94 | expect(deviations.map((d) => d.key)).toContain('redYellow'); |
| 95 | }); |
| 96 | }); |