import type { KilometersPerHour, Meters, MetersPerSecond, Ratio, Seconds, VehiclesPerHour, } from '../units'; /** Verkehrsart einer Signalgruppe bzw. eines Verkehrsstroms. */ export type TrafficMode = 'kfz' | 'rad' | 'fuss' | 'oepnv'; /** * Fahrbeziehung. Sie bestimmt nach RiLSA die anzusetzende Raeumgeschwindigkeit: * abbiegende Kraftfahrzeuge raeumen langsamer als geradeausfahrende. */ export type Movement = 'geradeaus' | 'rechts' | 'links' | 'querung'; /** * Fahrzeugart fuer den Laengenzuschlag beim Raeumweg. * * 'strassenbahn' kam mit Fassung 5.4.0 (Befund A2) hinzu: Die * RiLSA 2015 rechnet im Zwischenzeitfall 3 mit einer Fahrzeuglaenge von 15 m * fuer Strassenbahnen ("lFZ = 15 m bei Strassenbahnen", FGSV-Aenderungsblatt * vom 29.07.2015, Originalseite 24). Ohne die Fahrzeugart war eine Bahn nur * als 'bus' abbildbar und raeumte 9 m zu kurz. */ export type VehicleClass = 'pkw' | 'lkw' | 'bus' | 'lastzug' | 'strassenbahn' | 'rad' | 'keine'; /** * Art der Lichtsignalanlage. * * WARUM DIESE UNTERSCHEIDUNG NOETIG IST * * Die Kennwerte des Regelwerks gelten nicht fuer jede Anlage gleich. Die * Obergrenze der Umlaufzeit von 120 s stammt aus der RiLSA und gilt fuer * KNOTENPUNKTE: Laengere Umlaeufe fuehren dort zu Rotlichtverstoessen. * * Bei einer einstreifigen Verkehrsfuehrung ist der Raeumweg dagegen die GANZE * Engstelle und nicht ein Konfliktbereich von dreissig Metern. Nachgerechnet: * Bei 400 m Engstelle ergeben sich 44 s Zwischenzeit je Richtung, bei zwei * Uebergaengen je Umlauf und knapper Freigabezeit also rund 128 s Umlauf - ohne * dass daran etwas falsch waere. Mit einer einzigen Schranke fuer alles ist * entweder der Knotenpunkt zu lasch bemessen oder die Arbeitsstelle nicht * rechenbar; bis hierher war Letzteres der Fall. * * Die Art steuert deshalb Schranken UND Pruefregeln - und sie gehoert in den * Ausdruck: Zur verkehrsbehoerdlichen Anordnung nach Paragraf 45 StVO gehoert, * welche Art Anlage angeordnet wird. */ export type Anlagenart = 'knotenpunkt' | 'fussgaengerschutzanlage' | 'einstreifig'; /** * Rechenansatz fuer die Ueberfahrzeit des Kraftfahrzeugverkehrs * (seit Fassung 5.5.0). * * 'gelbzeit' Die Ueberfahrzeit IST die Gelbzeit dieser Signalgruppe * (3/4/5 s nach zulaessiger Hoechstgeschwindigkeit) - der Ansatz * dieses Programms und die VORGABE. Er ist der konservative Stand: * bei den Regelwerten beider Ansaetze faellt die Zwischenzeit beim * Abbiegen und bei 60/70 km/h laenger aus als mit festen Werten, * und kuerzer als die Regelwerte der RiLSA rechnet er nie. * 'fest' tue = 3 s geradeaus, 2 s abbiegend, unabhaengig von der * zulaessigen Hoechstgeschwindigkeit - der REGELWERKSANSATZ * (RiLSA 2015, Abschnitt 2.5.2, Faelle 1 und 2; seit 5.27.0 an der * gekauften Ausgabe abgeglichen). Er VERKUERZT die Zwischenzeit * gegenueber der Vorgabe dieses Programms und erscheint deshalb * als begruendungspflichtige Abweichung. * * BERICHTIGT (Fassung 5.43.0): Beim Ansatz 'fest' stand hier * "Praxisansatz nach behoerdlichen Leitfaeden" - der Stand bis 5.26.0, als der * Wortlaut zu den Faellen 1 und 2 nur als Umkehrschluss aus den * Zwischenzeitentafeln eines Leitfadens vorlag. Der Umkehrschluss traf zu; das * Druckwerk liegt inzwischen vor, und quellen.ts fuehrt beide Zahlen unter * 'gesichert' mit Fundstelle. Derselbe ueberholte Satz stand im Pruefbericht. * * BEIDE WERTE SIND EINSTELLBAR (1 bis 10 s). Richtung und Groessenordnung der * Wahl bildet deshalb ansaetze.ts aus den WIRKSAMEN Vorgaben * (`ueberfahrzeitAnsatzRichtungSatz`, `festeWerteZuschreibungSatz`) und keine * Ausgabe aus dem Text dieses Kommentars. * * Beleglage und Begruendung der Vorgabe: constants.ts, RilsaDefaults * .crossingTime. */ export type UeberfahrzeitAnsatz = 'gelbzeit' | 'fest'; /** Signalbild eines Signalgebers zu einem Zeitpunkt. */ export type SignalAspect = 'rot' | 'rotgelb' | 'gruen' | 'gelb' | 'dunkel' | 'gelb-blinkend'; /** Schweregrad einer Pruefmeldung. */ export type Severity = 'fehler' | 'warnung' | 'hinweis'; /** * Ein raeumender Verkehrsstrom im Sinne der Zwischenzeitberechnung. * * `clearingDistance` ist der Weg von der Haltlinie bis zum Ende des * Konfliktbereichs (ohne Fahrzeuglaenge). Der Laengenzuschlag wird aus * `vehicleClass` abgeleitet und getrennt ausgewiesen, damit im Pruefbericht * nachvollziehbar bleibt, wie der Raeumweg zustande kommt. */ export interface ClearingStream { readonly mode: TrafficMode; readonly movement: Movement; /** Weg Haltlinie -> Ende Konfliktbereich in Metern, ohne Fahrzeuglaenge. */ readonly clearingDistance: Meters; readonly vehicleClass: VehicleClass; /** Zulaessige Hoechstgeschwindigkeit des raeumenden Stroms (fuer die Gelbzeit). */ readonly vZul: KilometersPerHour; /** Ueberschreibt die Raeumgeschwindigkeit aus dem Regelwerk (m/s). */ readonly clearingSpeedOverride?: MetersPerSecond; /** Ueberschreibt die Ueberfahrzeit aus dem Regelwerk (s). */ readonly crossingTimeOverride?: Seconds; /** Erhoehter Zeitbedarf, z. B. Furt an Schule oder Senioreneinrichtung. */ readonly reducedMobility?: boolean; /** * Nur abbiegende Kfz-Stroeme: Der Strom durchfaehrt an DIESER Beziehung einen * engen Innenradius (Praxisansatz). Dann gilt * `clearingSpeed.kfzTurningEngerRadius` statt `clearingSpeed.kfzTurning`. * Fehlt das Merkmal, gilt der Regelwert - das Verhalten bis Schema 11. */ readonly engerRadius?: boolean; /** * Rechenansatz der Ueberfahrzeit fuer Kraftfahrzeuge. * * WARUM AM STROM UND NICHT ALS ARGUMENT DER RECHNUNG: Die Wahl steht im * Projekt (Project.settings.ueberfahrzeitAnsatz) und wird an genau einer * Stelle in den Strom uebernommen (plan/signalPlan.ts, raeumenderStrom). * Damit rechnet jeder Aufrufer von computeIntergreen - auch die Gegenprobe * zu einer von Hand gesetzten Zwischenzeit - mit demselben Ansatz, ohne dass * ihn jede Aufrufstelle einzeln durchreichen muesste. Fehlt das Feld, gilt * 'gelbzeit': der heutige Stand und die konservative Seite. */ readonly ueberfahrzeitAnsatz?: UeberfahrzeitAnsatz; /** * Nur OePNV: Der Strom haelt regelmaessig vor dem Knotenpunkt (z. B. * Haltestelle) und faehrt am Ende der Freigabezeit aus dem Stand an. * Dann gilt der Zwischenzeitfall 4 der RiLSA 2015: Ueberfahrzeit 0 s und * Raeumen mit Anfahransatz statt mit konstanter Geschwindigkeit. */ readonly haltVorKnoten?: boolean; } /** * Ein einfahrender Verkehrsstrom im Sinne der Zwischenzeitberechnung. * * `enteringDistance` ist der Weg von der Haltlinie bis zum Beginn des * Konfliktbereichs. Ein Laengenzuschlag entfaellt hier definitionsgemaess. */ export interface EnteringStream { readonly mode: TrafficMode; readonly movement: Movement; /** Weg Haltlinie -> Beginn Konfliktbereich in Metern. */ readonly enteringDistance: Meters; /** Ueberschreibt die Einfahrgeschwindigkeit aus dem Regelwerk (m/s). */ readonly enteringSpeedOverride?: MetersPerSecond; } /** Nachvollziehbares Ergebnis einer Zwischenzeitberechnung. */ export interface IntergreenResult { /** * Nach welchem Verfahren gerechnet wurde. * * 'knotenpunkt': tz = tue + tr - te nach RiLSA 2015, Abschnitt 2.5. * 'engstelle': tz = tue + sr/Vr * 3,6 nach Abschnitt 5.2.2 - mit fester * Ueberfahrzeit von 4 s, ohne Fahrzeuglaenge im Raeumweg und * OHNE Einfahrzeit. * * Als eigenes Feld, damit Ausdruck und Ansicht das Verfahren benennen * koennen: Zwei Zeilen mit derselben Spaltenueberschrift, aber * verschiedenen Formeln dahinter sind ohne diese Angabe nicht * nachzurechnen - dieselbe Begruendung wie bei `raeumansatz`. */ readonly verfahren: 'knotenpunkt' | 'engstelle'; /** Massgebende Zwischenzeit in ganzen Sekunden (aufgerundet, nie negativ). */ readonly intergreen: Seconds; /** Ungerundetes Zwischenergebnis tue + tr - te. */ readonly raw: Seconds; /** Ueberfahrzeit tue. */ readonly crossingTime: Seconds; /** Raeumweg sr einschliesslich Fahrzeuglaenge. */ readonly clearingPath: Meters; /** Beruecksichtigter Laengenzuschlag. */ readonly vehicleLength: Meters; /** * Angesetzte Raeumgeschwindigkeit vr. * * Beim Anfahransatz ('anfahren') ist das die Geschwindigkeit, auf die das * Fahrzeug hoechstens beschleunigt (Vmax/3,6 bzw. der Rueckfallwert) - die * Raeumzeit ist dann NICHT sr/vr, sondern folgt der Anfahrformel. */ readonly clearingSpeed: MetersPerSecond; /** * Rechenansatz der Raeumzeit. 'geschwindigkeit': tr = sr / vr. * 'anfahren' (OePNV mit Halt vor dem Knotenpunkt, RiLSA 2015 Fall 4): * tr = sqrt(2 * sr / a); wird dabei vr erreicht, faehrt das Fahrzeug den * Restweg mit vr: tr = vr/a + (sr - vr^2/(2*a)) / vr. * * Als eigenes Feld, damit Ausdruck und Ansicht die Formel benennen koennen, * statt eine Geschwindigkeit zu drucken, aus der sich tr nicht nachrechnen * laesst (Grundsatz: was gedruckt wird, muss sich aus den gedruckten Groessen * nachrechnen lassen). */ readonly raeumansatz: 'geschwindigkeit' | 'anfahren'; /** Anfahrbeschleunigung a in m/s2 beim Anfahransatz, sonst null. */ readonly anfahrbeschleunigung: number | null; /** Raeumzeit tr in Sekunden (ungerundet); Formel siehe `raeumansatz`. */ readonly clearingTime: Seconds; /** * Untergrenze der Ueberfahr- und Raeumzeit nach RiLSA 2015, Abschnitt 2.5.2 - * NUR gesetzt, wenn sie GREIFT, sonst null. * * Die RiLSA verlangt fuer geradeaus fahrende (Fall 1) und abbiegende * Kraftfahrzeuge (Fall 2): tue + tr >= tG + 1 s. Greift die Schranke, ist * `raw` NICHT tue + tr - te, sondern diese Untergrenze abzueglich te. Ohne * dieses Feld liesse sich die gedruckte Zeile nicht nachrechnen - deshalb * steht hier die Zahl und nicht bloss ein Schalter. */ readonly ueberfahrRaeumzeitUntergrenze: Seconds | null; /** Einfahrweg se. */ readonly enteringPath: Meters; /** Angesetzte Einfahrgeschwindigkeit ve. */ readonly enteringSpeed: MetersPerSecond; /** Einfahrzeit te = se / ve (ungerundet). */ readonly enteringTime: Seconds; /** Wurde das rechnerische Ergebnis durch die untere Schranke 0 s ersetzt? */ readonly clampedToZero: boolean; readonly notes: readonly CalculationNote[]; } /** Begruendeter Hinweis aus einer Berechnung. */ export interface CalculationNote { readonly severity: Severity; readonly code: string; readonly message: string; /** * Konfliktbeziehung, aus der die Meldung stammt. * * Nur gesetzt, wo es eine gibt. Meldungen aus dem Planaufbau zeigten im * Pruefbericht pauschal auf das Programm; der Sprungknopf fuehrte damit bei * einer Zwischenzeitmeldung in die Phasenansicht, wo sich nichts davon * aendern laesst. */ readonly konfliktId?: string; } /** Signalzeiten einer Signalgruppe. */ export interface SignalGroupTimes { /** Mindestfreigabezeit. */ readonly minGreen: Seconds; /** Gelbzeit (0 s bei Fussgaengern). */ readonly yellow: Seconds; /** Rot-Gelb-Zeit (0 s bei Fussgaengern). */ readonly redYellow: Seconds; } /** Eingangsgroessen der Umlaufzeitermittlung. */ export interface CycleTimeInput { /** Summe der Verlustzeiten je Umlauf in Sekunden. */ readonly lostTime: Seconds; /** * Massgebende Saettigungsgrade y = q/qS der Phasen (dimensionslos). * Ihre Summe Y muss kleiner als 1 sein, sonst ist der Knoten uebersaettigt. * * `undefined` heisst "Verkehrsstaerke nicht erfasst" und NICHT "kein * Verkehr". Die Unterscheidung ist der ganze Zweck des Feldes: 0 ist eine * Angabe - gezaehlt und kein Verkehr -, eine Luecke ist keine. Beide ergaeben * dieselbe Summe Y; nur die Luecke ist zu melden, weil die daraus ermittelte * Umlaufzeit zu kurz ausfaellt. */ readonly criticalFlowRatios: readonly (Ratio | undefined)[]; /** Untere Schranke aus Mindestfreigabe- und Zwischenzeiten. */ readonly minimumCycle?: Seconds; /** Rasterung des Ergebnisses in Sekunden (Regelfall 5 s). */ readonly step?: Seconds; } /** Ergebnis eines Umlaufzeitverfahrens. */ export interface CycleTimeResult { readonly method: CycleTimeMethod; /** Empfohlene Umlaufzeit nach Rasterung und Begrenzung. */ readonly cycleTime: Seconds; /** Rechnerischer Wert vor Rasterung und Begrenzung. */ readonly raw: Seconds; /** Summe der massgebenden Saettigungsgrade Y. */ readonly totalFlowRatio: Ratio; readonly lostTime: Seconds; /** * Wurde das Ergebnis durch eine Schranke ersetzt? * * GENAUER: Die Frage meint die Schranken, die auf den ERFORDERLICHEN Umlauf * wirken - den vor der Rasterung. 'maximum' sagt, dass er nicht unter den * Hoechstwert passt, und nicht, dass eine Aufrundung gekuerzt wurde. Fuehrt * allein die Rasterung ueber den Hoechstwert hinaus, wird `cycleTime` zwar * auf ihn gekappt, `bounded` bleibt aber bei 'keine': Der Bedarf war gedeckt. * Gemessen mit 119,48 s und Rasterung 7 s - cycleTime 120 s, bounded 'keine'. * * 'uebersaettigt' (KORREKTUR Fassung 5.4.0, Befund C11): Bei * Y >= 1 (bzw. >= Ziel-/Hoechstauslastung) gibt es KEINE Umlaufzeit; * `cycleTime` traegt dann nur die Obergrenze als Ersatzwert, damit der Plan * eine Zahl hat. Bis dahin stand hier 'maximum' - derselbe Zustand wie bei * einer rechenbaren, aber zu langen Umlaufzeit, und keine Ausgabe konnte * "nicht bemessbar" von "120 s" unterscheiden. Jede Ausgabe der Umlaufzeit * muss diesen Zustand am Wert vermerken (siehe umlaufzeitIstErsatzwert in * plan/signalPlan.ts). */ readonly bounded: 'keine' | 'minimum' | 'maximum' | 'mindestumlauf' | 'uebersaettigt'; readonly notes: readonly CalculationNote[]; } export type CycleTimeMethod = 'webster' | 'hbs' | 'akcelik' | 'hcm'; /** * Bewertungsverfahren fuer Kapazitaet, Wartezeit und Qualitaetsstufe. * * KORREKTUR (Fassung 5.4.0, Befund B2): Bis dahin schaltete der Wert * nur die Stufentafel um, waehrend immer dieselbe HCM-Formel gerechnet wurde - * und der Ausdruck "Bewertung nach HBS 2015" behauptete. Jetzt bezeichnet er * das ganze Verfahren: 'HBS' rechnet Kapazitaet und Wartezeit nach dem * HBS 2015 (Abflusszeit tA = tF + 1 s, Grundwartezeit und Reststau mit * Instationaritaetsfaktor, T = 1 h) und bewertet nach dessen Tafeln; 'HCM' * rechnet das Verfahren des Highway Capacity Manual (d1 + d2, T = 0,25 h) * und bewertet nach dessen Tafel. */ export type Bewertungsverfahren = 'HBS' | 'HCM'; /** Kapazitaetskennwerte einer Signalgruppe. */ export interface CapacityResult { /** Verfahren, nach dem die Kapazitaet gerechnet wurde. */ readonly verfahren: Bewertungsverfahren; /** Kapazitaet in Fahrzeugen je Stunde. */ readonly capacity: VehiclesPerHour; /** * Abflusszeit tA, mit der die Kapazitaet gerechnet wurde. Nach HBS 2015 ist * das die Freigabezeit zuzueglich 1 s je Freigabezeitfenster (der Abfluss * laeuft in die Gelbzeit hinein), gedeckelt auf die Umlaufzeit; nach HCM die * Freigabezeit selbst. */ readonly abflusszeit: Seconds; /** Abflusszeitanteil fA = tA/tU (HBS) bzw. Freigabezeitanteil g/tU (HCM). */ readonly greenRatio: Ratio; /** Saettigungsverkehrsstaerke. */ readonly saturationFlow: VehiclesPerHour; /** Auslastungsgrad x = q/c, sofern eine Verkehrsstaerke bekannt ist. */ readonly degreeOfSaturation?: Ratio; readonly notes: readonly CalculationNote[]; } /** * Qualitaetsstufe des Verkehrsablaufs. * * `kriterium` sagt, woran gemessen wurde. Das HBS 2015 bewertet Kfz- und * OePNV-Stroeme nach der MITTLEREN Wartezeit, Fussgaenger und Radverkehr nach * der MAXIMALEN Wartezeit (laengste Sperrzeit im Umlauf), und vergibt fuer * Kfz die Stufe F nicht ab einer Wartezeit, sondern genau dann, wenn die * Nachfrage die Kapazitaet uebersteigt (Ueberlastung). Ohne dieses Feld liesse * sich aus einer gedruckten Stufe nicht nachvollziehen, welcher Wert sie * begruendet. */ export interface ServiceLevel { readonly grade: 'A' | 'B' | 'C' | 'D' | 'E' | 'F'; readonly label: string; readonly scale: Bewertungsverfahren; readonly kriterium: 'mittlere-wartezeit' | 'maximale-wartezeit' | 'ueberlastung'; }