lsa-planer

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

/ tests domain konfliktkennungWegeuebernahme.test.ts

5,7 KB Rohdatei
tests/domain/konfliktkennungWegeuebernahme.test.ts — 191 Zeilen
1 import { describe, expect, it } from 'vitest';
2 import { leiteAb, uebernimmWege, wegSchluessel } from '@/domain/geometrie/ableitung';
3 import type { Haltlinie, Lageplan, Planlinie } from '@/domain/geometrie/lageplan';
4 import { REGELBREITE } from '@/domain/geometrie/vermessung';
5 import { createEmptyProject } from '@/domain/model/factory';
6 import {
7 WEGNACHWEIS_UNBESTIMMT,
8 type Conflict,
9 type Project,
10 type SignalGroup,
11 } from '@/domain/model/project';
12
13 /**
14 * Rest aus Befund 2 (Fassung 5.9.0): `uebernimmWege` sucht die Beziehung
15 * ueber das Paar (fromId, toId), schreibt sie aber ueber `c.id`.
16 *
17 * WAS DER ANWENDER SONST ERLEBT
18 *
19 * Er uebernimmt die Wege eines Knotenpunkts aus dem Lageplan. Traegt eine
20 * zweite Konfliktbeziehung dieselbe Kennung - eine von Hand zusammengefuegte
21 * Projektdatei, ein Stand aus einer aelteren Fassung -, bekommt sie beim
22 * Schreiben Raeumweg, Einfahrweg und Bemerkung der ersten mit. Sie gehoert zu
23 * ganz anderen Signalgruppen, und niemand hat sie angefasst: Der Raeumweg
24 * dieser zweiten Beziehung wird stillschweigend auf einen fremden Wert gesetzt,
25 * und ist er kuerzer als der wahre, faellt ihre Zwischenzeit zu kurz aus - die
26 * gefaehrliche Richtung.
27 *
28 * Die erste Behebung hat die Neuvergabe der Kennungen beim Einlesen eingebaut
29 * (`schema.ts`). Das entschaerft nur Daten, die durch `parseProject` laufen -
30 * im Arbeitsstand entstandene Doppelungen nicht. Geschrieben wird deshalb ueber
31 * dasselbe Paar, ueber das auch gesucht wird.
32 */
33
34 const FIXED_DATE = new Date('2026-01-01T00:00:00Z');
35
36 /** 1 Bildpunkt = 1 m, damit sich die Masse unmittelbar ablesen lassen. */
37 const KALIBRIERUNG = {
38 von: { x: 0, y: 0 },
39 bis: { x: 100, y: 0 },
40 laengeMeter: 100,
41 herkunft: 'gemessen',
42 } as const;
43
44 const HL_NORD = 'hl-nord';
45 const HL_OST = 'hl-ost';
46
47 const HALTLINIEN: readonly Haltlinie[] = [
48 {
49 id: HL_NORD,
50 name: 'Zufahrt Nord',
51 art: 'zufahrt',
52 armId: 'arm-nord',
53 von: { x: 0, y: 0 },
54 bis: { x: 20, y: 0 },
55 },
56 {
57 id: HL_OST,
58 name: 'Furt Ost',
59 art: 'querung',
60 armId: 'arm-ost',
61 von: { x: 0, y: 30 },
62 bis: { x: 30, y: 30 },
63 },
64 ];
65
66 /** Geradeaus aus der Nordzufahrt - kreuzt die Furt bei (10 | 30). */
67 const GERADEAUS: Planlinie = {
68 id: 'l-gerade',
69 name: 'L1 geradeaus',
70 mode: 'kfz',
71 movement: 'geradeaus',
72 breiteMeter: REGELBREITE.kfz,
73 punkte: [
74 { x: 10, y: 0 },
75 { x: 10, y: 60 },
76 ],
77 haltlinieId: HL_NORD,
78 startT: 0.5,
79 signalGroupId: 'sg-a',
80 };
81
82 /** Fussgaengerfurt quer ueber die Nordzufahrt. */
83 const FURT: Planlinie = {
84 id: 'l-furt',
85 name: 'L2 Furt',
86 mode: 'fuss',
87 movement: 'querung',
88 breiteMeter: REGELBREITE.fuss,
89 punkte: [
90 { x: 0, y: 30 },
91 { x: 30, y: 30 },
92 ],
93 haltlinieId: HL_OST,
94 startT: 0,
95 signalGroupId: 'sg-b',
96 };
97
98 const LAGEPLAN: Lageplan = {
99 arbeitsbereiche: [],
100 signalgeber: [],
101 bild: null,
102 kalibrierung: KALIBRIERUNG,
103 haltlinien: HALTLINIEN,
104 linien: [GERADEAUS, FURT],
105 };
106
107 const gruppe = (id: string, patch: Partial<SignalGroup> = {}): SignalGroup => ({
108 id,
109 name: id,
110 mode: 'kfz',
111 movement: 'geradeaus',
112 armId: null,
113 vZul: 50,
114 lanes: 1,
115 vehicleClass: 'pkw',
116 minGreenOverride: null,
117 maxGreenOverride: null,
118 reducedMobility: false,
119 color: '#2f6fd0',
120 ...patch,
121 });
122
123 /**
124 * Zwei Beziehungen mit DERSELBEN Kennung.
125 *
126 * Die eine steht zwischen den Gruppen der gezeichneten Stroeme, die andere
127 * zwischen zwei ganz anderen. Nur die erste wird uebernommen.
128 */
129 const DOPPELTE_KENNUNG = 'cf-doppelt';
130
131 const konflikt = (fromId: string, toId: string, patch: Partial<Conflict> = {}): Conflict => ({
132 id: DOPPELTE_KENNUNG,
133 fromId,
134 toId,
135 clearingDistance: 99,
136 enteringDistance: 88,
137 clearingSpeedOverride: null,
138 enteringSpeedOverride: null,
139 crossingTimeOverride: null,
140 manualIntergreen: null,
141 wegnachweis: WEGNACHWEIS_UNBESTIMMT,
142 note: '',
143 ...patch,
144 });
145
146 function projekt(): Project {
147 const leer = createEmptyProject('Kennungen', FIXED_DATE);
148 return {
149 ...leer,
150 signalGroups: [
151 gruppe('sg-a'),
152 gruppe('sg-b', { mode: 'fuss', movement: 'querung', vehicleClass: 'keine' }),
153 gruppe('sg-c'),
154 gruppe('sg-d'),
155 ],
156 conflicts: [konflikt('sg-a', 'sg-b'), konflikt('sg-c', 'sg-d')],
157 lageplan: LAGEPLAN,
158 };
159 }
160
161 describe('Wege aus dem Lageplan uebernehmen bei doppelter Konfliktkennung', () => {
162 it('schreibt nur die Beziehung des uebernommenen Gruppenpaares', () => {
163 const p = projekt();
164 const ableitung = leiteAb(p, LAGEPLAN);
165 const weg = ableitung.wege.find(
166 (w) => w.vonLinieId === GERADEAUS.id && w.nachLinieId === FURT.id,
167 );
168 // Grundlage des Falls: Es gibt ueberhaupt einen Weg zu uebernehmen.
169 expect(weg, 'die beiden Stroeme kreuzen sich nicht').toBeDefined();
170
171 const ergebnis = uebernimmWege(p, LAGEPLAN, ableitung, [wegSchluessel(weg!)]);
172
173 const geschrieben = ergebnis.project.conflicts.find(
174 (c) => c.fromId === 'sg-a' && c.toId === 'sg-b',
175 );
176 const fremd = ergebnis.project.conflicts.find((c) => c.fromId === 'sg-c' && c.toId === 'sg-d');
177
178 expect(ergebnis.uebernommen).toBe(1);
179 expect(geschrieben?.clearingDistance, 'die gemeinte Beziehung wurde nicht geschrieben').toBe(
180 weg!.raeumweg,
181 );
182 // Der Kern des Falls: Die zweite Beziehung teilt nur die Kennung. Sie
183 // gehoert zu sg-c/sg-d, wurde nicht gewaehlt und muss unberuehrt bleiben.
184 expect(fremd?.clearingDistance, 'die fremde Beziehung wurde mitgeschrieben').toBe(99);
185 expect(fremd?.enteringDistance, 'die fremde Beziehung wurde mitgeschrieben').toBe(88);
186 expect(fremd?.note, 'die fremde Beziehung trägt jetzt eine fremde Bemerkung').toBe('');
187 expect(fremd?.wegnachweis, 'die fremde Beziehung behauptet jetzt den Lageplan').toBe(
188 WEGNACHWEIS_UNBESTIMMT,
189 );
190 });
191 });