lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ tests domain negativeNull.test.ts
| 1 | import { describe, expect, it } from 'vitest'; |
| 2 | import { computeIntergreen } from '@/domain/rilsa/intergreen'; |
| 3 | import { ceilSeconds, roundTo } from '@/domain/units'; |
| 4 | import type { ClearingStream, EnteringStream } from '@/domain/rilsa/types'; |
| 5 | |
| 6 | /* |
| 7 | * Befund 60, behoben in Fassung 5.10.0. |
| 8 | * |
| 9 | * Math.ceil liefert fuer jeden Wert zwischen -1 und 0 die NEGATIVE Null. |
| 10 | * Sie rechnet sich wie 0, druckt sich aber nicht wie 0: Intl gibt "-0" aus, |
| 11 | * und damit stand in der Zwischenzeitenmatrix der Planunterlage, im |
| 12 | * Rechenweg und in der CSV-Ausgabe "-0" bzw. "-0 s" - eine Angabe, die vor |
| 13 | * der Anordnungsbehoerde wie eine negative Zwischenzeit aussieht. |
| 14 | */ |
| 15 | |
| 16 | const deutsch = new Intl.NumberFormat('de-DE', { maximumFractionDigits: 0 }); |
| 17 | |
| 18 | describe('Befund 60 - ceilSeconds liefert keine negative Null', () => { |
| 19 | it('rundet Werte zwischen -1 und 0 auf die positive Null auf', () => { |
| 20 | for (const wert of [-0.0001, -0.0937, -0.4505, -0.5, -0.999]) { |
| 21 | expect(Object.is(ceilSeconds(wert), 0), String(wert)).toBe(true); |
| 22 | } |
| 23 | }); |
| 24 | |
| 25 | it('druckt die aufgerundete Null als "0" und nicht als "-0"', () => { |
| 26 | expect(deutsch.format(ceilSeconds(-0.4505))).toBe('0'); |
| 27 | }); |
| 28 | |
| 29 | it('laesst Vorzeichen und Betrag jedes anderen Wertes unberuehrt', () => { |
| 30 | expect(ceilSeconds(-2.7)).toBe(-2); |
| 31 | expect(ceilSeconds(0)).toBe(0); |
| 32 | expect(ceilSeconds(3.0000000000000004)).toBe(3); |
| 33 | expect(ceilSeconds(5.079)).toBe(6); |
| 34 | }); |
| 35 | |
| 36 | it('belegt, dass roundTo die negative Null nicht abstreift - nur den Vorzeichenfall', () => { |
| 37 | /* |
| 38 | * NACHTRAG (Fassung 5.10.0): Der Docblock von ceilSeconds sagte, die |
| 39 | * Nachbarzeile roundTo behandle "denselben Sonderfall seit jeher". Sie |
| 40 | * behandelt einen anderen: Math.round(-0,5) ergibt -0, deshalb rundet |
| 41 | * roundTo ueber den Betrag und setzt das Vorzeichen danach. Die negative |
| 42 | * Null bleibt dabei stehen - dieser Fall haelt den berichtigten Satz fest. |
| 43 | */ |
| 44 | expect(Object.is(roundTo(-0.4, 0), -0)).toBe(true); |
| 45 | expect(deutsch.format(roundTo(-0.4, 0))).toBe('-0'); |
| 46 | expect(roundTo(-0.5, 0)).toBe(-1); |
| 47 | }); |
| 48 | |
| 49 | it('gibt die Zwischenzeit einer knapp negativen Rechnung als 0 s aus', () => { |
| 50 | /* |
| 51 | * Ausloeser aus dem Befund: raeumender Fussgaengerstrom ohne Raeumweg |
| 52 | * (tue = 0 s, tr = 0 s) gegen einen einfahrenden Kfz-Strom mit 5 m |
| 53 | * Einfahrweg (te = 5/11,1 = 0,4505 s). raw = -0,4505 s. |
| 54 | */ |
| 55 | const raeumt: ClearingStream = { |
| 56 | mode: 'fuss', |
| 57 | movement: 'querung', |
| 58 | clearingDistance: 0, |
| 59 | vehicleClass: 'keine', |
| 60 | vZul: 0, |
| 61 | }; |
| 62 | const faehrtEin: EnteringStream = { |
| 63 | mode: 'kfz', |
| 64 | movement: 'geradeaus', |
| 65 | enteringDistance: 5, |
| 66 | }; |
| 67 | const ergebnis = computeIntergreen(raeumt, faehrtEin); |
| 68 | expect(ergebnis.raw).toBeLessThan(0); |
| 69 | expect(ergebnis.intergreen).toBe(0); |
| 70 | expect(deutsch.format(ergebnis.intergreen)).toBe('0'); |
| 71 | }); |
| 72 | }); |