LSTtraining – Simulationstool für Leitstellen-Training

Hey zusammen,

ich arbeite aktuell wieder intensiver an meinem Projekt LSTtraining – ein Open-Source-Framework zur realitätsnahen Simulation von Einsätzen im Rettungsdienst- und Feuerwehrbereich.
Ziel ist die Ausbildung und Fortbildung von Leitstellen-Disponent:innen mithilfe realer Karten, Fahrzeugdaten, Einsatzszenarien und Geoinformationen.


:puzzle_piece: Was gibt’s aktuell?

  • WordPress-Plugin mit eigenem Admin-Interface
  • Verwaltung von Leitstellen inkl. Koordinaten und voll interaktivem Einsatzgebiet-Editor
  • Kartenanzeige via OpenLayers
  • Routing und Fahrzeugbewegung über OpenRouteService
  • Formularbasierte Erstellung und Bearbeitung von Objekten
  • REST-APIs für Wachen, Fahrzeuge und Routing
  • GeoJSON-Import und Bearbeitung (Punkte hinzufügen/entfernen per Maus)
  • Automatischer Zoom, Live-Vorschau und bidirektionale Synchronisation mit der Hauptkarte
  • Plugin-Demo: https://frief.de

:package: Code & Projektseite:
:right_arrow: GitHub - Frief84/LSTtraining: Realistische, trainingsorientierte Einsatzsimulation für Feuerwehr- und Rettungsdienst-Disponent:innen – mit Echtzeitkarte, Einsatzgenerator und flexibler Szenarienlogik. · GitHub


:white_check_mark: Neu: Einsatzgebiet-Editor (fertig)

  • Polygon zeichnen, bearbeiten, löschen
  • Koordinaten via GeoJSON importieren
  • Bearbeitung über Mausklicks:
    • Linksklick fügt Punkte hinzu
    • Rechtsklick entfernt letzte Punkte
  • Automatischer Zoom aufs Gebiet
  • Speicherung direkt in der Datenbank (GeoJSON)

:round_pushpin: Unterstützungsleitstellen (in Arbeit)

Aktuell beginne ich mit dem Sammeln und Einpflegen von sogenannten Unterstützungsleitstellen – also angrenzenden, nicht direkt bespielbaren Leitstellen, aus denen Fahrzeuge zur Unterstützung angefordert werden können.
Ziel ist ein realistisches Nachbarsystem analog zum echten Dispositionsablauf.


:wrench: Roadmap (Auswahl)

  • Benutzerrollen (Admin, Ausbilder, Teilnehmer)
  • Verwaltung von Wachen, Fahrzeugen, Einsätzen
  • Zufällige Einsatzgenerierung (Ort, POIs, Uhrzeit, etc.)
  • Gruppenübungen / Echtzeit-Mehrspieler
  • Logging, Auswertung, Fortschrittsanzeige
  • Integration eines eigenen Routingservers

:man_raising_hand: Wer möchte mitmachen?

Ich suche Mitstreiter:innen, die Lust haben auf:

  • Frontend (OpenLayers, Leaflet, Kartenlogik, UI)
  • Backend (PHP, Datenmodell, Pluginlogik)
  • UX/UI (Design, Struktur, einfache Bedienung)
  • Doku, Testing, Feedback
  • Oder einfach nur Interesse und Ideen!

Ob zur Mitentwicklung, fürs eigene Training, als Tool für Ausbildung oder einfach zum Lernen – meldet euch gerne im Thread oder direkt bei mir.

Ich freu mich über jede Unterstützung – auch moralische!

2 „Gefällt mir“

Update zum Backend & Nebenleitstellen

Aktuell kümmere ich mich intensiv um das Backend – insbesondere um die Datenstruktur und Logik rund um die sogenannten Nebenleitstellen.

Dabei handelt es sich um reale BOS-Leitstellen in Deutschland, die z. B. für Landkreise oder kreisfreie Städte zuständig sind. Sie koordinieren Einsätze von Feuerwehr, Rettungsdienst, Katastrophenschutz usw.

Warum Nebenleitstellen?
Im Spiel stehen diese Leitstellen neben der vom Spieler aktiv gespielten Hauptleitstelle.
Sie sind selbst nicht direkt steuerbar, können aber zur Unterstützung angefragt werden – z. B. für Nachalarmierungen, Rettungsmittel, spezielle Fahrzeuge oder bei Großschadenslagen.
Sie agieren also eigenständig im Spiel, beeinflussen die Dynamik, stehen aber nicht dauerhaft unter Spielersteuerung – daher der Begriff „Nebenleitstellen“.

Jede Nebenleitstelle hat ein fest definiertes Zuständigkeitsgebiet, zugeordnete Wachen und Fahrzeuge. Die dafür nötigen Daten werden derzeit aus verschiedenen Quellen wie GeoJSON, Overpass API, LSTSim & Co. aufbereitet und strukturiert.

Geplante Spielmodi:

1. Einzelleitstellenmodus

[]Einsätze werden dynamisch generiert
[
]Eine Person übernimmt allein die Verantwortung für eine Leitstelle
[*]Einsätze, Fahrzeugbewegungen und Wachen sind nur für diese eine Instanz sichtbar und steuerbar

2. Zufriedenstellende

[]Einsätze werden dynamisch generiert oder gezielt getriggert
[
]Eine Person fungiert als Spielleiter
[]Mehrere Spieler:innen betreiben gemeinsam eine Leitstelle
[
]Aufgabenteilung z. B. nach Disziplinen (Feuerwehr/Rettung) oder Bereichen (z. B. Nord-/Süd-Wache)
Alle Aktionen synchronisieren sich in Echtzeit

Langfristiges Ziel:
Mehrere Leitstelleninstanzen sollen parallel und unabhängig voneinander laufen können – mit jeweils eigenem dynamischen Status für Fahrzeuge, Wachen, Einsätze etc.
Dafür entsteht derzeit eine erweiterbare Backend-Struktur, die parallele Spielwelten, Kooperationsspiel und individuelle Ausbildungsszenarien unterstützt.

Wenn ihr Ideen, Feedback oder Wünsche für den Multiplayer- oder Ausbildungsbereich abt immer her damit

Hallo zusammen,

ich möchte Euch kurz auf den neuesten Stand zum LSTtraining-Plugin bringen, das wir aktuell als WordPress-Extension entwickeln.

:magnifying_glass_tilted_left: Was ist neu?

  1. Wachen-Editor Modal
  • Klick auf „Bearbeiten“ in der Tabelle oder auf den Stift-Button im Karten-Tooltip öffnet jetzt ein Popup-Formular
  • Formular lädt Wache-Daten via AJAX (lsttraining_get_wache) und speichert Änderungen wieder per lsttraining_save_wache
  • Felder: ID (unveränderbar), Name, Typ (FW, FFW, FFRD, RD, FRRD), Koordinaten, optional Bild
  1. Interaktive Karte mit OpenLayers
  • Marker für jede Wache, farblich codiert nach Typ
    • FW (Feuerwache) = Rot
    • FFW (Freiw. Feuerwehr) = Hellrot
    • RD (Rettungswache) = Blau
    • FRRD (Rettungsdienst + Feuer) = Rosa
    • FFRD (Freiw. Feuerwehr + RD) = Hellblau
  • Tooltip mit Wachen-Name und Stift-Icon
  • Lazy Load der Wachen per Filter (Leitstelle oder Nebenleitstelle)
  1. Verbesserte Filter-UI
  • Suche/Live-Filter für Leitstellen und Nebenleitstellen
  • Wechsel eines Filters setzt den jeweils anderen zurück
  • Only one filter active at a time

:card_index_dividers: Was steht an?

  • Funktionen Zum hinzufügen von Leistellen
  • Funktionen Zum hinzufügen von Nebenleistellen
  • Funktionen zum Hinzufügen von Wachen
  • Funktionen zum Hinzufügen von Fahrzeugen
  • Erstellen einer Datenbankstruktur für Krankenhäuser
  • Editor für Krankenhäuser
  • Editor für Fahrzeuge
  • Aufräumen des Adminmenües

:hammer_and_wrench: Feedback & Mitmachen

Falls Ihr Anregungen habt, Fehler findet oder selbst beitragen möchtet, hinterlasst bitte ein Kommentar hier im Thread oder eröffnet ein Issue auf GitHub:
:link: GitHub - Frief84/LSTtraining: Realistische, trainingsorientierte Einsatzsimulation für Feuerwehr- und Rettungsdienst-Disponent:innen – mit Echtzeitkarte, Einsatzgenerator und flexibler Szenarienlogik. · GitHub

Vielen Dank und viele Grüße

Neuerungen im LSTtraining-Plugin

1. Krankenhäuser importiert

Alle Krankenhäuser deutschlandweit wurden als statische „Hospitalkatalog“-Tabelle in die Simulation übernommen.

2. Wachen-Editor jetzt als Modal

  • Klick auf das „Bearbeiten“-Icon im Tooltip öffnet ein Pop-up statt einer neuen Seite
  • Lade- und Speicher-Routine über AJAX-Endpoints lsttraining_get_wache und lsttraining_save_wache in includes/nebenstellen_editor.php bzw. includes/leitstellen_editor.php
  • Bearbeitbare Felder:
    • Name, Typ (FW, FFW, FFRD, RD, FRRD)
    • Koordinaten (Latitude/Longitude) mit interaktivem Marker
    • Bilddatei (optional)
    • ID ist schreibgeschützt

3. Interaktive OpenLayers-Karte

  • Neuer Layer mit Markern für alle Wachen in js/app.js
  • Farbkodierung der Marker nach Wachen-Typ (Rot=FW, Hellrot=FFW, Blau=RD etc.)
  • Tooltips zeigen Wachen-Name plus Stift-Icon zum Editieren
  • Karte initialisiert in openlayers/ol.js & ol.css, Konfiguration in js/app.js

4. Lazy Loading & Filter-UI

  • Wachen werden nur für die aktuell ausgewählte Leitstelle geladen (get_wachen.php)
  • Live-Suche für Leitstellen und Nebenleitstellen im Admin-Panel (js/admin-ui.js)
  • Beim Wechsel eines Filters wird der jeweils andere zurückgesetzt (immer nur ein aktiver Filter)

5. Neue Editor-Module

  • Einsatzgebiet-Editor (js/einsatzgebiet-editor.js + includes/einsatzgebiet-editor.php)
  • Leitstellen-Editor (includes/leitstellen_editor.php)
  • Nebenleitstellen-Editor (includes/nebenstellen_editor.php)
  • Krankenhaus-Editor: SQL-Import in database/insert_hospitals.sql und Template includes/hospitals_editor.php

6. Ausbau der API-Endpoints

  • get_route.php: Wegberechnung über OpenRouteService
  • get_wachen.php: Liefert Wachen-Daten als GeoJSON
  • Registriert als WordPress AJAX-Actions in includes/map-override.php und includes/schema_import.php

7. Verbesserungen an den Einstellungen

  • Neue Optionen in der Settings-Page (includes/settings.php)
  • Konfigurierbare Defaults für Karten-Zoom, OpenRouteService-Key und Standard-Leitstelle

:brick: Datenbank

Das Schema in database/schema.sql definiert diese acht Tabellen:

Tabelle Beschreibung
leitstellen Dispositionszentren mit Polygon-GeoJSON und Metadaten
wachen Feuerwachen/Rettungswachen mit Name, Koordinaten, Typ und optionalem Bild
fahrzeuge Zuweisung zu Wachen, Typ (ENUM), letzte bekannte Position
fahrzeug_status Live-Status und Positions-Tracking von Fahrzeugen
spielinstanzen Multi-User-Instanzen für Trainingsszenarien
instanz_wachen Zuordnung Wachen ↔ Spielinstanzen
instanz_user Zuordnung User ↔ Spielinstanzen
einsatzvorlagen Vorlagen für wiederkehrende Übungen

:hospital: Krankenhäuser

Wir haben eine vollständige statische „Hospitalkatalog“-Tabelle definiert. Die SQL-Definition dient als Referenz; in der README findest du alle Feld-Beschreibungen.

Feld Typ Beschreibung
id INT, PK, AUTO_INCREMENT Interner Primärschlüssel
name VARCHAR(255) Name des Krankenhauses
latitude DOUBLE Breitengrad
longitude DOUBLE Längengrad
versorgungsstufe ENUM Versorgungsstufe: Grundversorgung ‖ Schwerpunktversorger ‖ Maximalversorger
trauma_level TINYINT Trauma-Level (0 = keiner, 1–3)
helipad BOOLEAN Hubschrauberlandeplatz vorhanden? (true / false)
departments JSON Liste der Fachabteilungen als JSON-Array (siehe unten)
last_update TIMESTAMP Zeitpunkt der letzten Änderung (automatisch aktualisiert)
created_at TIMESTAMP Erstellungszeitpunkt (automatisch gesetzt)

Fachabteilungen (departments JSON)

Das Feld departments ist ein Array aus Objekten:

json

KopierenBearbeiten

[
  {
    "code":     "CHIR",
    "name":     "Chirurgie",
    "priority": 2,
    "capacity": 24
  },
  {
    "code":     "CT",
    "name":     "Computertomographie",
    "priority": 3
  }
  // …
]

Nur diese Codes sind zulässig:

Code Name
NOTF Innere Notaufnahme
KINA Kinder-Notaufnahme
CHIR Chirurgie
ISTX Chirurgische Intensivstation
CT Computertomographie
DERM Dermatologie
DRAM Druckkammer
VASG Gefäßchirurgie
GYNO Gynäkologie
HNOK HNO-Heilkunde
INTX Innere Intensivstation
CARD Kardiologie
KESS Kreißsaal
MRT Magnetresonanztomographie
MKGC MKG-Chirurgie
NECH Neurochirurgie
NEUR Neurologie
NOTO Notoperation
NUKL Nuklearmedizin
ONKO Onkologie
PSYC Psychiatrie
PED Pädiatrie
KKH Kinderkrankenhaus
STRK Stroke Unit
UROL Urologie
BURN Brandverletzten-Station
CAT Herzkatheteruntersuchung

Hinweis: Die Felder versorgungsstufe, trauma_level und helipad sollen später das Routing und Handling in der Simulation beeinflussen


  • Editor für Krankenhäuser:
    Im Admin-Bereich gibt es jetzt einen eigenen Hospitals-Editor, über den du alle Parameter (Name, Versorgungsstufe, Trauma-Level, Helipad) sowie die Position (Latitude/Longitude) interaktiv anpassen kannst.
  • Editor für Fachbereiche:
    Ein Departments-Editor zur Pflege des departments-JSON (Fachabteilungen) befindet sich aktuell in Arbeit und wird bald verfügbar sein.

:building_construction: Architektur und Aufbau

  1. Bootstrap (lsttraining-plugin.php)
    Lädt alle Module und initialisiert das Plugin.
  2. Datenbank-Layer
  • includes/schema_import.php: Importiert database/schema.sql
  • includes/db.php: Helferfunktion lsttraining_get_connection()
  1. Einstellungen & Admin-Menü
  • includes/settings.php: Plugin-Optionen (DB-Modus, API-Key)
  • includes/admin-menu.php: Menüs und Subpages
  1. Admin-UI & Editor-Module
  • includes/admin-ui.php: Enqueue von CSS/JS (OpenLayers, Admin-UI, wachen.js etc.)
  • Templates: leitstellen_editor.php, nebenstellen_editor.php, wachen.php, hospitals_editor.php

CRUD & AJAX-Endpunkte (includes/ajax-handlers.php)

Action Zweck
lsttraining_get_einsatzgebiet GeoJSON einer Leitstelle laden
lsttraining_save_einsatzgebiet GeoJSON einer Leitstelle speichern
lsttraining_get_neben_einsatzgebiet GeoJSON einer Nebenleitstelle laden
lsttraining_save_neben_einsatzgebiet GeoJSON einer Nebenleitstelle speichern
lsttraining_get_wachen Alle Wachen als GeoJSON (Filter: Leitstelle/Neben)
lsttraining_get_wache Daten für eine einzelne Wache laden
lsttraining_save_wache Änderungen einer Wache speichern






1. Tooltip‐Click und Edit‐Modal für Krankenhäuser

  • Tooltip‐Click-Listener repariert
    • In der CSS-Klasse .hospital-tooltip wurde pointer-events: none entfernt (bzw. nur auf das Wrapper-div angewendet), sodass Klicks auf das ✎-Icon nicht mehr blockiert werden.
    • Der tooltipContainer.addEventListener('click', …)-Handler liest jetzt korrekt zuerst die id aus (const id = btn.dataset.id;) und loggt anschließend die Erkennung, bevor openEditForm(id) aufgerufen wird.
    • Dadurch wird garantiert, dass openEditForm(…) tatsächlich ausgelöst wird, sobald der Benutzer im Tooltip auf das Bearbeiten-Symbol klickt.
  • Modal-Editor öffnet sich direkt als Overlay
    • Klick auf das ✎-Icon im Tooltip öffnet nun konsistent das Bearbeitungs-Modal (#hospital-edit-modal) anstatt einer neuen Seite.
    • Das HTML-Template für das Modal (wp.template('hospital-edit-form')) wird via AJAX nachgeladen (get_krankenhaus) und in den Container .hospital-edit-content eingefügt.

2. Interaktive Karte im Hospital-Editor

  • Initialisierung der OpenLayers-Karte im Edit-Modal
    • Innerhalb von openEditForm() wird bei jedem Öffnen ein neuer ol.Map-Container (target: 'hospital-map-edit') erzeugt.
    • Ein Vector-Layer mit genau einem Marker (new ol.Feature({ … new ol.geom.Point( ol.proj.fromLonLat([lon, lat]) ) })) markiert die aktuelle Position des Krankenhauses (Eingang/RTW-Haltezone).
    • Der Marker ist mit einem Custom-Icon (hospital_icon.png) gestylt.
  • Drag‐Interaction für den Marker
    • Eine ol.interaction.Modify({ source: editSource })-Interaktion erlaubt es, den Marker direkt per Drag&Drop zu verschieben.
    • Beim modifyend-Event werden die neuen Koordinaten in die Felder #h-lat, #h-lon und das Textfeld #h-coords geschrieben (auf sechs Dezimalstellen gerundet).
  • Koordinaten-Input synchronisiert Karte und Marker
    • Direkt unterhalb der Map wurde ein <input id="h-coords"> ergänzt, in dem der Benutzer „Breitengrad, Längengrad“ eingeben kann.
    • Wenn sich der Wert in #h-coords ändert (via coordsInput.addEventListener('change', …)), wird geprüft, ob das Format „lat, lon“ gültig ist.
    • Anschließend wird der OL-Marker (marker.getGeometry().setCoordinates(newCoords)) auf die neue Position verschoben.
    • Optional wird die View der Karte auf die neuen Koordinaten zentriert (editMap.getView().animate({ center: newCoords, duration: 300 })).
  • Hinweistext unter der Karte
    • Direkt unter dem <div id="hospital-map-edit"> wurde ein <p class="hospital-map-hint">…</p> eingefügt, der den Benutzer auffordert, den Marker genau dort zu platzieren, „wo die Rettungswagen (RTWs) halten bzw. am Haupteingang der Notaufnahme“.
    • In css/admin-ui.css wurde die Klasse .hospital-map-hint ergänzt (z. B. kleinere Schriftgröße, Grauton, ausreichender Abstand nach oben).

3. Änderungen in der Krankenhaus‐Übersicht & Tabelle

  • Live-Suchfeld für Krankenhäuser
    • Ein Eingabe-Feld <input id="hospital-search" type="search" placeholder="Suche nach ID oder Name…"> wurde oberhalb der Tabelle (.widefat.fixed) eingefügt, sobald die Seite geladen wird.
    • Bei jeder Eingabe (input-Event) wird fetchHospitals() erneut aufgerufen, und die Liste filtert clientseitig nach ID oder Name (alles kleingeschrieben).
  • Sortier-Indikatoren in den Tabellen-Headern
    • Jede <th data-field="…"> erhält beim Klick (via th.addEventListener('click', …)) einen auf- oder ab-Pfeil (▲ / ▼), wenn nach diesem Feld sortiert wird. Die Sortierreihenfolge wechselt zwischen aufsteigend/absteigend, wenn derselbe Header wieder angeklickt wird.
    • In updateSortIndicators() werden alle bestehenden Pfeile entfernt, und nur im aktuell sortierten Feld je nach sortAsc ein ▲ (aufsteigend) oder ▼ (absteigend) ergänzt.
  • „Bearbeiten“-Button in jeder Tabellenzeile
    • Neben dem „Bearbeiten“-Stift im Tooltip gibt es in jeder Zeile der Krankenhaus-Tabelle (<button class="button edit-krankenhaus" data-id="${kh.id}">Bearbeiten</button>), der beim Klick ebenfalls openEditForm(id) aufruft (delegiert über $(document).on('click', '.edit-krankenhaus', …)).
  • „Löschen“-Button in jeder Tabellenzeile
    • <button class="button button-link-delete delete-krankenhaus" data-id="${kh.id}">Löschen</button> wurde ergänzt.
    • Klick-Handler fragt per confirm('Krankenhaus wirklich löschen?') ab. Bei Bestätigung wird via AJAX (action=delete_krankenhaus) gelöscht und anschließend fetchHospitals() neu aufgerufen.

4. Department‐Editor für jedes Krankenhaus

  • Neues Modal für Fachbereiche
    • openDepartmentEditor(hospitalId) öffnet einen separaten Modal-Container #departments-edit-modal. Per AJAX (action=get_departments) werden alle vorhandenen Departments + erlaubte Departments geladen.
    • Das Template wp.template('departments-editor') rendert das Formular mit Checkboxen/Inputs für jeden Fachbereich.
  • OpenLayers-Map für Departments
    • Unterhalb des Formulars wird eine Karte #dept-map initialisiert, ähnlich wie bei den Krankenhäusern:
      • window.deptSource = new ol.source.Vector(); und window.deptMap = new ol.Map({ …, layers: [… Vector({ source: deptSource })] … });
      • Ein fester Marker für das Krankenhaus selbst (type: 'hospital') wird ebenfalls in deptSource gezeichnet, damit der Benutzer die relative Position erkennt.
  • Translate-Interaction für Dept-Marker
    • In initDeptTranslateInteraction() wird eine globale Sammlung window.deptDragCollection = new ol.Collection() erzeugt und window.deptTranslate = new ol.interaction.Translate({ features: dragCollection }) hinzugefügt.
    • Das translateend-Event liest nach dem Verschieben eines Department-Markers (e.features.forEach(f => { … })) die neuen Koordinaten aus, sucht in der Tabelle (#departments-details-table tbody tr[data-code="${code}"]) die entsprechende Zeile und schreibt lat / lon direkt in die Input-Felder (.lat-input, .lon-input).
    • Damit kann der Nutzer jeden Department-Standort genau per Drag&Drop setzen, und die zugehörigen Formularfelder werden automatisch aktualisiert.
  • Toggle-Checkboxen für mögliche Departments
    • In bindDepartmentForm() (nicht vollständig im Changelog, sondern im Code) werden vorhandene Departments pro Krankenhaus vorgewählt: data.existing.forEach(dep => { … $('.dept-toggle[value="${code}"]').prop('checked', true).trigger('change'); }).
    • Damit wird beim Öffnen des Editors angezeigt, welche Fachbereiche aktuell aktiv sind, und unerwünschte können per Checkbox entfernt oder hinzugefügt werden.
  • Speichern der Fachbereiche
    • Beim Submit (#departments-edit-form) wird das Formular per Fetch/POST an action=save_departments geschickt (JSON-Serialisierung der Departments-Objekte), und nach erfolgreichem Speichern (res.success) wird das Modal geschlossen und fetchHospitals() erneut ausgeführt, damit eventuelle Änderungen in der Hauptübersicht reflektiert werden.

5. Kleinere CSS- und UI-Verbesserungen

  • CSS-Anpassungen
    • In css/admin-ui.css wurde .hospital-tooltip angepasst, sodass Klicks nicht mehr unterdrückt werden (bzw. nur der Wrapper-Container pointer-events: none behält, während .hospital-tooltip .button per pointer-events: auto wieder klickbar ist).
    • Neue CSS-Klasse .hospital-map-hint für den Hinweistext unter der Karte (kleinere Schrift, Grauton, etwas Abstand nach oben).
  • Button-Klassen konsistent gestellt
    • Statt verschiedener Klassen-Mischungen (edit-krankenhaus, button-secondary, button-link-delete etc.) wurden alle Buttons CSS-seitig so definiert, dass sie im Backend einheitlich aussehen und dieselbe button-Grundklasse erben.
    • Die title="Bearbeiten"-Attribute für das Tooltip-Icon wurden beibehalten, damit Screenreader und Hover-Texte korrekt arbeiten.

6. Backend-Anpassungen (PHP/SQL, nur stichpunktartig)

(Diese Punkte sind zwar im Forum-Post größtenteils genannt, hier aber nochmal kontrolliert und ergänzt, was wir tatsächlich umgesetzt haben)

  • AJAX-Handler erweitert
    • lsttraining_get_krankenhaus (liefert einzelne Krankenhausdaten) inklusive Feldern: id, name, versorgungsstufe, trauma_level, helipad, latitude, longitude, departments.
    • lsttraining_save_krankenhaus (speichert alle Änderungen inkl. Departments, Standort, Meta-Felder).
    • lsttraining_delete_krankenhaus (löscht einen Datensatz, wenn mit gültiger id aufgerufen).
    • lsttraining_get_departments + lsttraining_save_departments (wie oben beschrieben).
  • Template-Erweiterungen
    • In includes/hospitals_editor.php wurden neue Input-Felder hinzugefügt:
      • <input id="h-lat" name="latitude" …>
      • <input id="h-lon" name="longitude" …>
      • <input id="h-coords" name="coords" …>
      • Checkboxen und Textfelder für die JSON-Felder departments[…].
    • Unterhalb der Map in hospital-edit-form wurde das <p class="hospital-map-hint">…</p> hinzugefügt.
    • Das bestehende SQL-Schema (database/insert_hospitals.sql) wurde erweitert, sodass jetzt die Felder last_update, created_at automatisch gesetzt werden, falls noch nicht das aktuelle Timestamp-Verhalten abbildet.

7. Zusammenfassung der wichtigsten Punkte, die im Forum noch fehlen

  1. Tooltip-Click-Fix: CSS-Änderung (pointer-events) + Korrektur der id-Reihenfolge im Listener, damit openEditForm() tatsächlich aufgerufen wird.
  2. Koordinaten-Input ↔ Marker-Sync: Das neue Feld #h-coords synchronisiert jetzt beide Richtungen, nicht nur Drag&Drop.
  3. Hinweistext unter der Edit-Karte: Benutzeranweisung, den Marker beim RTW-Halt/Eingang zu positionieren.
  4. Sortieren+Filtern in der Krankenhausliste: Suchfeld für Live-Filter und Pfeil-Indikatoren in den Tabellen-Headings.
  5. „Löschen“-Button für Krankenhaus: mit AJAX-Endpoint und Bestätigungsdialog.
  6. Dept-Editor Verbesserung: Drag&Drop für Fachbereichs-Marker, automatische Tabellen-Updates bei Verschieben, Checkbox-Toggling für erlaubte Departments.
  7. CSS-Feinschliff: Einheitliche Button-Klassen, farbliche Anpassungen, Abstände in admin-ui.css.

Spannende Idee. Hab ja selbst mal mit an der Waldbrand-App mitgewirkt. Vielleicht kann man das irgendwie verzahnen oder Daten hin und her schicken. So als Idee für den Hinterkopf und damit man was auf dem mobilen Gerät hat.

https://waldbrand-app.de/

danke für deinen Input und den Hinweis auf die Waldbrand-App. Für unsere Leitstellen-Simulation sehe ich aktuell allerdings keine Notwendigkeit, Hydranten- oder Saugstellendaten zu importieren – das ist eher für die Einsatzkräfte vor Ort relevant. Für die Einsatzgenerierung in der Simulation könnten hingegen Waldbrand-Hotspots spannend sein, um realitätsnahe Notrufe und Einsatzszenarien abzuleiten.

ChatGPT:

Kurzanleitung: Profil- und Passwort­änderung

  1. Profil öffnen
    Nach dem Einloggen findest du links in der WordPress-Seitenleiste den Punkt „Profil“ (siehe Markierung 1 im Bild).
    Ein Klick darauf öffnet deine persönlichen Einstellungen.
  2. Persönliche Daten anpassen
    Im oberen Teil kannst du
    Vorname, Nachname, Spitzname
    – die öffentliche Anzeige­form deines Namens
    – und deine E-Mail-Adresse ändern.
    Vergiss nicht auf „Profil aktualisieren“ (ganz unten) zu klicken, damit die Änderungen gespeichert werden.
  3. Passwort ändern
    Scrolle zum Abschnitt „Kontoverwaltung“.
    Klicke auf „Neues Passwort erstellen“ (Pfeil 2). WordPress generiert automatisch einen sicheren Vorschlag.
    Du kannst ihn übernehmen oder ein eigenes Passwort eintippen.
    Bestätige anschließend wieder mit „Profil aktualisieren“.

Empfehlung beim ersten Login:
Setze gleich ein individuelles, starkes Passwort und prüfe, ob deine E-Mail korrekt hinterlegt ist – nur so kannst du später problemlos „Passwort vergessen“ nutzen.


Kurzanleitung – Krankenhäuser verwalten

  1. Vorhandene Häuser prüfen
  • Suchfeld (2)
    Gib einen Teil des Namens oder die ID ein. Die Tabelle darunter filtert sich sofort.
  • Karte
    Jeder blaue Marker steht für ein bereits erfasstes Krankenhaus. Zoome oder verschiebe die Karte, um doppelte Einträge zu vermeiden.
  1. Neues Krankenhaus anlegen (1)
  • Klicke auf „+ Neues Krankenhaus“.
  • Fülle alle Pflichtfelder aus – Name, Versorgungs­stufe, Trauma-Level, Koordinaten (Übersichtskarte im Formular hilft).
  • Speichern → das neue Haus erscheint sofort in Tabelle und Karte.
  1. Bestehende Häuser bearbeiten
  • In der Tabelle auf „Bearbeiten“ klicken.
  • Änderungen vornehmen, speichern – fertig.
  1. Fachbereiche pflegen
  • Button „Fachbereiche“ öffnet eine Liste von Abteilungen.
  • Gewünschte Bereiche anhaken, Speichern.
  • Tipp: Marker einzelner Fachbereiche lassen sich per Drag-&-Drop versetzen.
  1. Löschen
  • „Löschen“ entfernt das Krankenhaus dauerhaft aus Datenbank und Karte.
  • Vorgang ist endgültig – bitte mit Bedacht nutzen.

Hinweis: Leg ein neues Krankenhaus nur an, wenn es in Suche und Karte nicht bereits existiert.


Wenn du in der Krankenhaus-Tabelle auf „Bearbeiten“ klickst oder „+ Neues Krankenhaus“ wählst, erscheint das rechts gezeigte Pop-up-Formular.

Feld Erklärung
Name Offizieller Klinikname – bitte exakt schreiben, damit Dopplungen vermieden werden.
Versorgungsstufe Grundversorger – Basisfächer (Innere, Chirurgie).
Schwerpunktversorger – zusätzlich spezialisierte Abteilungen (z. B. Kardiologie, Neurologie).
Maximalversorger – nahezu alle Fachgebiete, häufig Unikliniken.
Trauma-Level 0 = kein Traumazentrum
1 = lokales Zentrum (Erstversorgung, leichte Verletzungen)
2 = regionales Zentrum (auch schwere Verletzungen)
3 = überregionales Zentrum (Polytrauma, 24/7-Schockraum)
Koordinaten (lat, lon) Breiten- und Längengrad. Tipp: In Google Maps Rechtsklick → Koordinaten kopieren. Marker lässt sich alternativ per Drag & Drop verschieben.
Fachbereiche Button „Fachbereiche bearbeiten“ öffnet ein eigenes Pop-up, in dem du Abteilungen anhaken und ggf. deren Marker auf der Karte positionieren kannst.
Helipad Häkchen setzen, wenn ein Hubschrauber­landeplatz verfügbar ist (wichtig für Luftrettung).

Speichern übernimmt alle Änderungen, Abbrechen schließt ohne zu speichern, Löschen entfernt das Krankenhaus endgültig (inklusive Marker und Fachbereiche) – bitte nur nutzen, wenn wirklich erforderlich.

Kurzanleitung – „Fachbereiche bearbeiten“

  1. Fachbereich suchen / filtern
  • Oben im Pop-up findest du das Feld „Fachbereich suchen…“.
    Tipp ein Stichwort (z. B. „Herz“, „Neuro“) – die Checkbox-Liste darunter wird sofort gefiltert.
  • Hintergrund: Jede Leitstelle nutzt leicht andere Begriffe, deshalb steht hier eine breite Auswahl; die Liste kann später beliebig ergänzt werden.
  1. Fachbereiche aktivieren
  • Setze bei den gewünschten Abteilungen ein Häkchen.
  • Jeder aktivierte Fachbereich erscheint sofort in der Tabelle unterhalb („Aktiv / Koordinaten“).
  1. Koordinaten bearbeiten
  • Klicke in der Tabelle auf eine Zeile – der zugehörige Marker wird auf der Karte hervorgehoben.
  • Ziehe den Marker per Drag-&-Drop an den exakten Standort:
    4.Beispiel:* Herzkatheterlabor liegt in einem extra Gebäude → Marker dorthin verschieben, damit der Rettungsdienst die richtige Anfahrt sieht.
  • Die Textfelder „Koordinaten“ aktualisieren sich automatisch; du kannst Werte dort auch manuell anpassen.
  1. Speichern / Abbrechen
  • Speichern schreibt die aktive Liste (inkl. Marker-Positionen) als JSON in die Datenbank.
  • Abbrechen schließt das Pop-up ohne Änderungen.

Hinweis: Die Fachbereichs-Liste ist nicht fix. Wenn für deine Leitstelle ein Kürzel fehlt, melde es dem Admin – neue Einträge können jederzeit hinzugefügt werden.

Nebenstellen & Einsatzgebiete im LSTtraining verwalten

1) Nebenstellen-Übersicht

In der Übersicht siehst du alle Nebenstellen mit Name, Zuständigkeit, Einwohnerzahl, Fläche, Standort und ob ein Einsatzgebiet vorhanden ist.

  • Bearbeiten: öffnet das Formular zum Ändern von Daten/Einsatzgebiet
  • Löschen: entfernt die Nebenstelle (mit Bestätigung)
  • + Nebenstelle erstellen: legt eine neue Nebenstelle an

2) Neue Nebenstelle anlegen

  1. + Nebenstelle erstellen klicken
  2. Felder ausfüllen:
  • Name (z. B. „Leitstelle Oberpfalz-Nord“)
  • Zuständigkeit (Landkreis(e)/Städte)
  • Einwohner (realistische Angabe empfohlen)
  • Fläche (km²) (kann automatisch berechnet werden)
  • Standort als Breite,Länge (z. B. 49.44,11.86)

Wichtig: Die Werte für Einwohner und Fläche fließen später in die statistische Einsatzhäufigkeit ein.
Eine Nebenstelle mit mehr Einwohnern und/oder größerer Fläche wird im Simulationsbetrieb häufiger Einsätze erhalten als eine kleine Nebenstelle.
Deshalb möglichst echte und korrekte Werte verwenden.

  1. Speichern um Einsatzgebiet anzulegen klicken → das Modal bleibt offen, der Button Einsatzgebiet bearbeiten wird aktiv.

3) Nebenstelle bearbeiten

  • In der Tabelle Bearbeiten wählen

  • Daten anpassen und Speichern

  • Mit Einsatzgebiet bearbeiten den Editor öffnen

  • Leitstelle übernehmen

  • Mit diesem Button kannst du Einsatzgebiet, Wachen, Fahrzeuge, Standort und alle Stammdaten einer bestehenden Leitstelle in die aktuell bearbeitete Nebenstelle übernehmen.
  • Hinweis: Aktuell gibt es nur eine Leitstelle im System, daher ist diese Funktion im Moment noch nicht besonders relevant – wird aber wichtig, sobald mehrere Leitstellen vorhanden sind.


4) Fläche berechnen

Im Nebenstellen-Formular Berechnen klicken → die aktuelle Polygonfläche (km²) wird ins Feld übernommen.


5) Einsatzgebiet anlegen/bearbeiten (Editor)

Im Einsatzgebiet-Editor kannst du Polygone einzeichnen, ändern oder importieren:

Werkzeuge im Editor

  • Zeichnen/Anpassen: Linksklick setzt Punkte; Rechtsklick entfernt den letzten Punkt oder löscht die Fläche
  • Datei-Upload: GeoJSON auswählen → GeoJSON übernehmen & Vorschau
  • Manuell einfügen: GeoJSON in das Textfeld kopieren → GeoJSON übernehmen
  • Speichern: Einsatzgebiet dauerhaft sichern; die Karte in der Nebenstelle aktualisiert sich direkt

Externe Bearbeitung mit GeoJSON Utilities

Falls du offizielle Verwaltungsgrenzen (Gemeinden/Kreise/Bundesländer) als GeoJSON brauchst, nutze GeoJSON Utilities:

Was das Tool macht:

  • Exportiert Gemeindeflächen, Kreisflächen oder Bundeslandflächen als .geojson für Deutschland
  • Beinhaltet in den Eigenschaften auch Einwohnerzahlen und Flächenmaße
  • Simplify-Funktion zur Vereinfachung der Geometrie (0 = volle Genauigkeit, 20 = gut für den Einsatz, 200 = stark vereinfacht)
  • Zusatzdaten wie regionale Statistiken oder Wikipedia-Infos möglich

So nutzt du es für LSTtraining:

  1. Gebiet(e) auf der Karte auswählen
  2. Im Bereich GeoJSON Export – Optionen gewünschte Ebene und Vereinfachung einstellen
  3. Export .geojson klicken und Datei speichern
  4. Im LSTtraining-Einsatzgebiet-Editor hochladen und bei Bedarf anpassen
  5. Speichern – die neue Fläche wird in der Nebenstelle übernommen

7) Tipps

  • Standort zuerst setzen → Karte zentriert sich automatisch
  • Realistische Einwohner- und Flächenwerte sorgen für realistische Einsatzverteilungen
  • Überlappungen zwischen Einsatzgebieten sind möglich
  • Mit GeoJSON Utilities kannst du schnell exakte Verwaltungsgrenzen importieren

Update: Wachen-Editor & Datenbereinigung

Ich arbeite gerade am neuen Wachen-Editor für das LST-Training.

Ausgangslage

  • Aus OSM wurden inzwischen rund 30.579 Wachen (Feuerwehr, Rettungswachen, DLRG, THW usw.) importiert.
  • Für die Nebenstellen gibt es bereits eine Zuordnungsmechanik, sodass Wachen den Leitstellen zugeordnet werden können.

Aktueller Schritt

Im Moment bereite ich die importierten Wachen-Daten auf:

  • Viele Einträge haben noch fehlerhafte oder unvollständige Namen (z. B. nur eine OSM-ID wie way/123456).
  • Diese werden jetzt automatisch soweit möglich korrigiert oder ergänzt – etwa durch Ortsangaben oder durch eine Unterscheidung, ob es sich um eine Freiwillige Feuerwehr, Berufsfeuerwehr oder Werkfeuerwehr handelt.
  • Ziel ist es, eine saubere Datengrundlage für den Editor zu schaffen.

Was danach wichtig wird

  • Nach dieser automatischen Bereinigung müssen die problematischen Wachen manuell überprüft werden – vor allem die, die für Nebenstellen in Frage kommen oder einer Leitstelle zugeordnet werden sollen.
  • Der Editor wird dann ermöglichen, diese Korrekturen direkt im Adminbereich vorzunehmen.

Ausblick

Wenn die Bereinigung abgeschlossen ist, haben wir eine stabile Grundlage, um die Wachen übersichtlich darzustellen, einfacher zu verwalten und den Leitstellen sauber zuzuordnen.



Update: Verlauf/Aktivität (Admin-Audit) & zielgerichtete Admin-Verbesserungen

Aufbauend auf dem Wachen-Editor/Datenbereinigungs-Schritt WiLaP gibt es jetzt Funktionen für Nachvollziehbarkeit und präzisere Admin-Workflows.

Neu

  • Verlauf / Aktivität (nur für Admins)

    • Menü: WP-Admin → LST Training → Verlauf / Aktivität

    • Protokolliert aktuell: Leitstellen, Nebenstellen, Wachen (Create/Update/Delete), Zuordnungen (z. B. Wache ↔ (Neben)Leitstelle) sowie Berechtigungs-Sammelereignisse nach dem Speichern.

    • Details mit Feld-Diffs: Bei Updates werden nur tatsächlich geänderte Felder als „alt → neu“ angezeigt; Create/Delete erscheinen als kompakte Key-Value-Blöcke; Relations-Änderungen als „alt → neu“.

    • Filter & Pagination: Zeitraum, User-ID, entity_type, action.

  • Benutzer-Übersicht erweitert

    • In der Admin-Tabelle ist jetzt die WP-User-ID als erste Spalte sichtbar (hilft bei Rechtepflege, Support & Verknüpfungen).
  • Zuordnungen direkt im Admin (Inline)

    • Das Inline-Modal für Zuordnungen (ohne iFrame) hängt an den relevanten Seiten – schnellere Wache↔(Neben)Leitstelle-Zuweisungen ohne Kontextwechsel.
  • Geo-Workflows geschärft

    • Einsatzgebiete (GeoJSON): Upload/Bearbeitung mit den bekannten Karten-Bausteinen; Geometrie-Hilfen über Turf/GeoJSON-Utilities.

    • Kartenbasis wie gehabt OpenLayers; Assets werden seitenbezogen geladen, damit Editoren schnell bleiben.

Feinheiten unter der Haube

  • Nebenstellen (AJAX-Speichern): Echte Feld-Diffs im Log (Name, Zuständigkeit, Einwohner, Fläche, GPS).

  • Leitstellen: Create/Update/Delete werden im Verlauf erfasst; GeoJSON-Änderungen werden markiert.

  • Wachen: Create/Update/Delete sowie Relation-Toggles landen im Verlauf (inkl. schlanker Meta-Infos).

  • Rechteverwaltung: Nach dem Speichern wird ein Sammel-Event geloggt (für transparente Nachverfolgung).

Als Nächstes

  • Fahrzeuge bearbeiten (CRUD) und Zuordnung zur Wache – inkl. Aufnahme in den Verlauf mit Feld-Diffs.

Update: interner Refactor der AJAX-Struktur

In den letzten Tagen habe ich die interne Architektur des Plugins deutlich aufgeräumt und stabilisiert.

Der bisher sehr große und schwer wartbare ajax-handlers.php wurde vollständig refaktoriert und nach Verantwortlichkeiten aufgeteilt. Ziel war bessere Lesbarkeit, geringere Fehleranfälligkeit und eine saubere Basis für zukünftige Erweiterungen.

Was konkret geändert wurde:

  • Einführung eines dedizierten Ordners includes/ajax/

  • Aufteilung der bisherigen Logik nach Domänen:

    • Leitstellen

    • Nebenstellen

    • Wachen

    • Einsatzgebiete (GeoJSON)

    • Fahrzeuge (inkl. Uploads)

    • Krankenhäuser

    • Benutzer-/Rechteverwaltung

  • Einheitliches Namensschema mit ajax_*.php, um Namenskollisionen mit bestehenden Dateien zu vermeiden

  • Zentraler Guard (ajax_common.php) für:

    • Berechtigungsprüfungen

    • Leitstellen-Scope

    • optionale Nonce-Validierung

  • Der alte ajax-handlers.php fungiert jetzt nur noch als Loader

Ergebnis:

  • deutlich bessere Wartbarkeit

  • klarere Verantwortlichkeiten pro Modul

  • saubere Grundlage für weitere Security-Härtung

  • Vorbereitung für eine spätere parallele REST-API

Funktional hat sich für Anwender nichts geändert, der Umbau ist rein strukturell/technisch.

Kurzes Status-Update

Die Fahrzeugverwaltung ist jetzt sauber pro Wache angebunden.

Was neu ist:

  • Direkter Button in der Wachenansicht → öffnet die Fahrzeuge-Seite gefiltert auf die gewählte Wache

  • Fahrzeuge lassen sich dort vollständig bearbeiten (CRUD)
    Bearbeiten erfolgt über ein Modal mit AJAX

  • Datenfluss zwischen PHP und JS vereinheitlicht
    kein doppeltes Laden mehr, keine inkonsistenten Counts

  • AJAX-Endpoints für get_fahrzeug, save_fahrzeug, delete_fahrzeug stabilisiert

  • Modal-Editor funktioniert jetzt konsistent für:

    • bestehende Fahrzeuge

    • neue Fahrzeuge

    • korrektes Laden von Wache, FMS-Status, First-Responder-Flag etc.

Technisch:

  • Fahrzeuge-Seite akzeptiert jetzt wache_id als Kontext

  • Saubere Trennung zwischen Listenansicht und Modal-Editor

  • Vorbereitung für spätere Erweiterungen (z. B. Fahrzeug-Typen, Dienstzeiten, Medien)

Nächste Schritte:

  • Feinschliff UX im Modal

  • Validierung / Fehlermeldungen

  • optional: Bulk-Aktionen pro Wache

Feedback wie immer willkommen.

Updates

  • Wachen ↔ Fahrzeuge Navigation

    • Rücksprung von der Fahrzeuge-Seite zur Wachen-Übersicht öffnet automatisch wieder das Modal der zuvor bearbeiteten Wache (open_wache_id)

    • Konsistenter Workflow ohne Kontextverlust beim Wechsel zwischen Wache und Fahrzeugen

  • Fahrzeuge-Liste (Admin)

    • Neue Bild-Spalte in der Fahrzeugtabelle (logisch nach FMS einsortiert)

    • Anzeige einer Miniatur pro Fahrzeug

    • Sinnvolle, beschreibende Alt-Texte je Fahrzeug (Rufname, Typ, Wache)

    • Sauberes CSS-Styling über Klasse statt Inline-Styles

    • Einheitliche Tabellenhöhe, kein Layout-Springen

  • Default-Fahrzeugbild

    • Neues graues, reduziertes Standard-Fahrzeugbild (nur Konturen, nicht angeschnitten)

    • Wird automatisch genutzt, wenn einem Fahrzeug kein eigenes Bild zugewiesen ist

    • Fallback-Logik bleibt stabil, auch ohne gesetzte Option

  • LSTtraining Einstellungen

    • Neues Einstellungsfeld: Default-Fahrzeugbild

    • Auswahl über WordPress-Mediathek (inkl. Vorschau, Wechseln, Entfernen)

    • Speicherung als Attachment-ID, keine harten Dateipfade

    • Saubere Integration in bestehende Settings-Struktur

  • AJAX / Datenfluss

    • Korrektur und Vereinheitlichung der AJAX-Handler für Fahrzeuge

    • Stabile Nonce-Prüfung, keine 400/403-Fehler mehr

    • Fahrzeugdaten werden wachenbezogen geladen und gecacht

    • Fahrzeug-Count und Fahrzeugliste werden getrennt und performant geladen

  • Wachen-Modal

    • Fahrzeugpanel lädt Inhalte lazy beim Öffnen

    • Fahrzeug-Count wird sofort angezeigt

    • Toggle-Logik stabilisiert (kein mehrfaches Nachladen, kein Flackern)

    • Rückbau von Race-Conditions bei parallelen Requests

  • JavaScript-Struktur

    • openWacheModal sauber global verfügbar gemacht

    • URL-Parameter-Handling (open_wache_id) robust umgesetzt

    • Initialisierung klar getrennt zwischen Page-Load und Modal-Aktionen

  • Admin-UI & Codequalität

    • Reduktion von Inline-Styles zugunsten zentralem CSS

    • Bessere Trennung von Logik, Darstellung und Konfiguration

    • Vorbereitung für weitere Erweiterungen (z. B. echte Fahrzeugbilder pro Datensatz)

Update: Leitstellen-POI-Editor & Kartenintegration (Meilenstein erreicht)

Im LSTtraining-Simulationstool wurde der POI-Editor für Leitstellen in den letzten Schritten deutlich erweitert und stabilisiert. Der aktuelle Stand bringt folgende neue Funktionen und Verbesserungen:

POI-Editor im Vollbild-Kartenmodus

  • Eigenständiger POI-Editor direkt aus der Leitstellenbearbeitung heraus

  • Große Karte mit OpenLayers als zentrales Element

  • POI-Liste und POI-Editor als Overlays, ein- und ausblendbar

  • Kartenbedienung und Editieren ohne Seitenwechsel

Einsatzgebiet als Karten-Overlay

  • Das Einsatzgebiet der Leitstelle wird automatisch auf der POI-Karte angezeigt

  • Darstellung ausschließlich als blauer Umriss, keine Flächenfüllung

  • Einsatzgebiet stammt direkt aus dem Leitstellen-GeoJSON (DB)

  • POIs und Einsatzgebiet liegen sauber übereinander

Stabile Kartenansicht

  • Beim Bearbeiten, Speichern oder Löschen eines POIs bleibt der aktuelle Kartenausschnitt erhalten

  • Kein Zurückspringen auf Default-Zoom oder Mittelpunkt

  • Erleichtert präzises Arbeiten bei vielen POIs

POI-Verwaltung (CRUD)

  • Anlegen, Bearbeiten und Löschen von POIs pro Leitstelle

  • POI-Typen aus JSON-Definition (nicht mehr CSV)

  • Pro POI: Typ, Bezeichnung, Kommentar, Genus, Koordinaten

  • Auswahl per Tabelle oder direkt per Klick auf der Karte

Import-Funktion

  • POIs können aus einer LSTSim-POI-Liste importiert werden

  • IDs werden bewusst nicht übernommen, es entstehen neue POIs

  • Gedacht für schnelles Vorbefüllen realistischer Karten

Technische Stabilisierung

  • AJAX-Handling bereinigt

  • Klare Trennung zwischen Leitstellen-POIs und Einsatzgebiet

  • OpenLayers-Layer sauber strukturiert (Base / Einsatzgebiet / POIs)

  • UI-IDs und CSS wieder konsistent

Damit ist der POI-Bereich jetzt funktional geschlossen und praxisnah nutzbar.
Weitere Ausbaustufen (z. B. simulationsrelevante Nutzung der POIs) können darauf direkt aufsetzen.

Grundidee des Einsatzsystems

Das Einsatzsystem im LST-Training soll keine statische Liste von Einsätzen sein, sondern ein dynamisches System, das sich an Leitstelle, Umgebung und Situation anpasst.

Im Zentrum steht die Vorstellung, dass Einsätze nicht einfach „zufällig auftauchen“, sondern aus realistischen Rahmenbedingungen entstehen:

  • aus der Landschaft,

  • aus der vorhandenen Infrastruktur,

  • aus Wetter, Tageszeit und Kontext,

  • und immer innerhalb des Einsatzgebiets der aktuell gespielten Leitstelle.

Dabei wird bewusst zwischen Definition und Auftreten eines Einsatzes unterschieden.


Zwei Arten von Einsätzen

Das System kennt zwei grundlegende Quellen:

1. Einsatzvorlagen

Einsatzvorlagen beschreiben typische, wiederverwendbare Einsatzarten.

Sie beantworten Fragen wie:

  • Was ist grundsätzlich passiert?

  • Wer ruft an?

  • Von wo meldet sich der Anrufer?

  • Welche Informationen gibt es initial und welche können später folgen?

Vorlagen sind:

  • leitstellenübergreifend nutzbar,

  • nicht an feste Koordinaten gebunden,

  • optional an Landschaftstypen oder POI-Typen gekoppelt,

  • redaktionell pflegbar.

Eine Vorlage definiert also den Inhalt eines Einsatzes, nicht dessen Häufigkeit.


2. Regelbasierte Einsätze

Regelbasierte Einsätze entstehen zur Laufzeit aus Rahmenbedingungen.

Sie basieren auf Regeln wie:

  • bestimmte Wetterlagen,

  • Tageszeiten oder Zeitfenster,

  • Landschaftseigenschaften,

  • vorhandene POIs oder Gebäudearten,

  • Infrastruktur wie Autobahnen oder Industriegebiete.

Diese Einsätze werden nicht „abgespielt“, sondern berechnet.
Beispiele:

  • Verkehrsunfälle auf Autobahnen bei Regen

  • Waldbrände bei Trockenheit

  • Stürze in Parks

  • Industrieunfälle in Gewerbegebieten

Regeln definieren, unter welchen Umständen ein Einsatz entstehen darf, nicht dass er entstehen muss.


Ort und Raum als zentrales Element

Alle Einsätze müssen räumlich sinnvoll verortet sein.

Dazu gilt:

  • Jeder Einsatz findet ausschließlich innerhalb des Einsatzgebiets der jeweiligen Leitstelle statt.

  • Einsätze können entstehen:

    • frei im Gebiet,

    • in bestimmten Landschaften,

    • an POIs eines bestimmten Typs,

    • oder an festen Koordinaten.

  • Autobahnen werden als echte Linien betrachtet, nicht als Flächen.

  • Gebäudearten wie Wohnhäuser, Bürogebäude oder Industriehallen werden real aus OSM-Daten berücksichtigt.

Das Einsatzsystem nutzt dafür vorbereitete OSM-Daten pro Leitstelle und arbeitet nicht mit Live-Abfragen während der Simulation.


Häufigkeit und Wahrscheinlichkeit

Die Häufigkeit von Einsätzen wird nicht direkt in den Einsatzdefinitionen fest verdrahtet.

Stattdessen:

  • definieren Vorlagen und Regeln nur Basisgewichte und harte Bedingungen,

  • die tatsächliche Wahrscheinlichkeit ergibt sich im Spiel aus:

    • Wetter,

    • Tageszeit,

    • Jahreszeit,

    • Landschaftsanteilen,

    • POI-Dichte,

    • Leitstellenstruktur.

So bleibt das System:

  • realistisch,

  • skalierbar,

  • und auf mehrere Leitstellen übertragbar.


Ziel des Systems

Das Ziel ist ein Einsatzsystem, das:

  • reproduzierbar, aber nicht vorhersehbar ist,

  • für unterschiedliche Leitstellen funktioniert,

  • realitätsnah wirkt, ohne zu überfrachten,

  • und später schrittweise erweitert werden kann.

Auf dieser Grundlage basiert das nachfolgend dokumentierte Datenbankschema.
Datenbankschema – Einsatzsystem (LST-Training)

Dieser Beitrag dokumentiert das aktuelle Datenbankschema für das Einsatzsystem im LST-Training-Plugin und erklärt, wie die einzelnen Tabellen gedacht sind und zusammenspielen.

Das Schema ist leitstellenübergreifend, simulationsfähig und trennt klar zwischen:

  • redaktionellen Einsatzvorlagen

  • regelbasiert generierten Einsätzen

  • konkreten Einsätzen innerhalb einer Spielinstanz

Das Frontend ist dabei ausdrücklich nicht Teil dieser Beschreibung.


Grundprinzip

Ein Einsatz existiert in drei Ebenen:

  1. Vorlage oder Regel

    • beschreibt, was grundsätzlich passieren kann

    • unabhängig von einer konkreten Spielinstanz

  2. Auswahl- und Generierungslogik

    • entscheidet zur Laufzeit, ob und wo ein Einsatz auftreten darf

    • berücksichtigt Leitstelle, Einsatzgebiet, Wetter, Landschaft, POIs

  3. Konkreter Einsatz

    • entsteht in einer Spielinstanz

    • hat feste Koordinaten, Texte und einen Lebenszyklus

Alle Einsätze dürfen nur im Einsatzgebiet der aktuell gespielten Leitstelle auftreten.


Tabelle: einsaetze (Einsatz-Vorlagen)

Diese Tabelle ersetzt die frühere Version vollständig und enthält Einsatzvorlagen.

Vorlagen:

  • gelten grundsätzlich für alle Leitstellen

  • können aber gezielt für einzelne Leitstellen ausgeschlossen werden

  • enthalten keine festen Wahrscheinlichkeiten, sondern nur Basisgewichte und Bedingungen

Zentrale Inhalte:

  • Einsatzart (RD / FW)

  • Einsatztyp (frei als Text)

  • Wetter- und Zeitbedingungen

  • Orts-Scope:

    • anywhere

    • landscape

    • poi_type

    • fixed_point

  • strukturierter Anrufertext nach Wer / Wo / Was

  • optionale Folgekommunikation

  • Basisgewicht für die Auswahl-Engine

Diese Tabelle definiert was passieren kann, nicht wann es passiert.


Tabelle: einsatz_excluded_leitstellen

Diese Tabelle regelt explizite Ausschlüsse.

Wenn ein Eintrag existiert:

  • darf der entsprechende Einsatz in dieser Leitstelle niemals auftreten

Gedacht für:

  • regionale Besonderheiten

  • nicht passende Einsatzarten

  • Test- oder Schulungsszenarien

Ohne Eintrag gilt der Einsatz für alle Leitstellen.


Tabelle: einsatz_followups

Folgekommunikation zu einer Einsatzvorlage.

Beispiele:

  • Rückfragen des Disponenten

  • Antworten des Anrufers

  • spätere Updates

  • Rückmeldungen von Einsatzmitteln

Eigenschaften:

  • Reihenfolge über step_no

  • optionale zeitliche Bedingungen

  • optionale Abhängigkeiten (z. B. nur wenn NA angefordert)

Diese Texte werden später in konkrete Einsatz-Events überführt.


Tabelle: einsatz_rules (regelbasierte Generatoren)

Diese Tabelle beschreibt Regeln, aus denen Einsätze dynamisch erzeugt werden.

Unterschied zu Vorlagen:

  • keine festen Texte

  • Nutzung von Templates und Platzhaltern

  • stärker an Landschaft, POIs und Situation gebunden

Typische Nutzung:

  • Verkehrsunfälle auf Autobahnen

  • Waldbrände bei Trockenheit

  • Stürze in Parks

  • Industrieunfälle in Gewerbegebieten

Auch hier gilt:

  • keine harte Wahrscheinlichkeit

  • nur Basisgewicht und Bedingungen

Die finale Entscheidung trifft die Spiel-Engine.


Tabelle: instanz_einsaetze (konkrete Einsätze)

Diese Tabelle enthält die tatsächlich im Spiel existierenden Einsätze.

Eintrag entsteht:

  • wenn eine Vorlage oder Regel für eine Spielinstanz ausgewählt wurde

Enthält:

  • feste Koordinaten

  • gerenderte Texte

  • Bezug zur Leitstelle und Spielinstanz

  • Status (neu, aktiv, abgeschlossen)

Diese Tabelle ist die zentrale Arbeitsgrundlage für das Spiel.


Tabelle: instanz_einsatz_events

Zeitlich sortierte Ereignisse zu einem konkreten Einsatz.

Beispiele:

  • neuer Anruf

  • Rückfrage

  • Lageverschärfung

  • Meldung eines Fahrzeugs

Diese Events sind:

  • unabhängig von der Vorlage

  • ausschließlich instanzbezogen


Tabelle: leitstellen_osm_layers

Cache für OSM-Daten pro Leitstelle.

Gespeichert werden GeoJSON-Layer, z. B.:

  • Wohngebäude

  • Bürogebäude

  • Industrieanlagen

  • Wohngebiete

  • Industriegebiete

  • Parks

  • Autobahn-Linien (als echte Ways, kein Korridor)

Zweck:

  • schnelle Einsatzgenerierung

  • keine Live-OSM-Abfragen während der Simulation

Aktualisierung erfolgt bewusst manuell oder periodisch.


Wichtige Designentscheidungen

  • Keine festen Wahrscheinlichkeiten pro Einsatz

    • Häufigkeiten entstehen aus Wetter, Tageszeit, Landschaft und Leitstellenstruktur
  • Mehrere Leitstellen mit gleichen POI-Typen sind erlaubt

  • POI-ID ist optional

    • Einsätze können an POI-Typen oder frei im Raum entstehen
  • Autobahnen werden als Linien behandelt

    • Einsätze entstehen direkt auf der Autobahn, nicht in Puffern
  • Gebäude werden real berücksichtigt

    • Wohnhaus, Büro, Industrie sind echte OSM-Gebäude

Fazit

Das Schema trennt sauber zwischen:

  • Definition

  • Regel

  • Instanz

Es ist:

  • leitstellenübergreifend

  • erweiterbar

  • simulationsgeeignet

  • nicht auf eine einzelne Region beschränkt

Damit ist die Grundlage gelegt, um Einsätze realistisch, reproduzierbar und dennoch dynamisch zu erzeugen.

Aktueller Stand: OSM-Datenimport pro Leitstelle (Ist-Beschreibung)

Dieser Abschnitt beschreibt exakt den aktuellen technischen Ablauf des OSM-Datenimports im LSTtraining-Simulationstool.


Zweck des OSM-Imports

Für jede Leitstelle werden lokale, gecachte OSM-Daten erzeugt, um später mögliche Einsatzorte bestimmen zu können.

Die OSM-Daten dienen nicht dem Routing der Fahrzeuge.
Das Routing erfolgt separat über einen Routingdienst.

Die importierten OSM-Layer liefern ausschließlich:

  • befahrbare Straßen als potenzielle Unfallorte

  • Gebietstypen (Landnutzung), um Einsätze räumlich einzugrenzen


Grundprinzip des Imports

  • Der Import wird manuell pro Leitstelle über den Admin-Button gestartet.

  • Alle Daten werden vorab geladen und gespeichert, nicht live abgefragt.

  • Jeder Layer wird sequenziell verarbeitet.

  • Jeder Layer wird tile-basiert in kleinen räumlichen Kacheln abgearbeitet.

  • Pro Request werden nur kleine Datenmengen (Chunks) verarbeitet.


Cache-Regel (vor jedem Download)

Bevor ein Layer geladen wird, wird geprüft:

  • Existiert ein Eintrag in leitstellen_osm_layers für diese Leitstelle und diesen Layer

  • Ist updated_at nicht älter als 7 Tage

  • Hat der Layer FeatureCount > 0

Wenn alle drei Bedingungen erfüllt sind:

  • Der Layer wird nicht erneut heruntergeladen

  • Der Import springt direkt zum nächsten Layer

Wenn FeatureCount = 0:

  • Der Layer wird trotz frischem Cache neu geladen

Abbruchverhalten

Laufende Imports werden sofort beendet, wenn:

  • der Button „Abbrechen“ im Modal gedrückt wird

  • das Overlay geschlossen wird

  • die Seite neu geladen wird

Bereits gestartete Overpass-Requests werden client- und serverseitig sauber abgebrochen.


Verwendete Overpass-Endpoints

Der Import nutzt mehrere Overpass-Instanzen als Fallback-Kette:

Fällt ein Endpoint aus oder antwortet langsam, wird automatisch der nächste verwendet.


Importierte Layer (Reihenfolge)

1. roads_lines – befahrbare Straßen

Abfrage:

  • alle way mit highway=* innerhalb des Leitstellen-Einsatzgebietes

Verarbeitung:

  • Geometrie als LineString

  • Vereinfachung der Linien (Distanz-basiert)

  • Speicherung nur, wenn der Straßenabschnitt im Einsatzgebiet liegt

Gespeicherte Properties:

  • t → Highway-Typ (z. B. motorway, primary, residential, …)

  • oid → OSM-ID (w<ID>)

Zweck:

  • Platzierung von Verkehrsunfällen

  • Unterscheidung von Straßentypen


2. Landnutzung (einzeln nach Typ)

Jeder Landuse-Typ wird separat verarbeitet als eigener Layer
(landuse_<key>).

Pro Landuse-Typ:

  • Tile-basierte Abfrage

  • way[landuse=<key>]

  • relation[type=multipolygon][landuse=<key>] (Outer-Ringe)

  • Polygon-Geometrie

  • Schwerpunktprüfung (Centroid im Einsatzgebiet)

Gespeicherte Geometry:

  • Polygon (Outer-Ring, vereinfacht)

Gespeicherte Properties:

  • t → Landuse-Key

  • oid → OSM-ID (w<ID>)


Aktuell abgefragte Landuse-Keys

Die folgenden Landuse-Keys werden nacheinander, einzeln importiert:

residential
industrial
commercial
retail
construction
institutional
education
fairground
aquaculture
allotments
farmland
farmyard
animal_keeping
flowerbed
forest
logging
greenhouse_horticulture
meadow
orchard
plant_nursery
vineyard
depot
garages
highway
port
railway
basin
salt_pond
brownfield
cemetery
grass
greenfield
landfill
military
quarry
recreation_ground
religious
village_green
greenery
winter_sports

Jeder dieser Keys erzeugt einen eigenen Import-Durchlauf.


Gespeichertes Datenformat

Alle Layer werden in der bestehenden Tabelle gespeichert:

leitstellen_osm_layers

Pro Datensatz:

  • leitstelle_id

  • layer_key (z. B. roads_lines, landuse_residential)

  • komprimierte GeoJSON-FeatureCollection

  • created_at, updated_at

Die GeoJSON-Daten sind stark reduziert auf:

  • Geometrie

  • minimale, spielrelevante Properties


Zweck im weiteren Projektverlauf

Diese OSM-Layer dienen als räumliche Grundlage für:

  • spätere, regional basierte Einsatzgenerierung

  • Einschränkung von Einsatzorten nach Gebietstyp

  • Plausibilisierung von Einsatzarten (z. B. Industrie vs. Wohngebiet)

Routing, Fahrzeiten und Wegeführung sind nicht Teil dieses Imports.

Landuse-Layer (aktueller Stand)

Unter data/landuse/ liegen die aktuell verwendeten Landuse-Daten.
Die Layer sind nach Kategorien getrennt, je Datei ein Landuse-Typ.

Enthaltene Kategorien sind u. a.:

  • residential

  • commercial

  • industrial

  • retail

  • allotments

  • farmland

  • animal_keeping

  • forest

  • logging

  • meadow

  • railway

  • cemetery

  • landfill

  • quarry

  • recreation_ground

  • religious

Die Dateien liegen als GeoJSON Text Sequences (geojsonseq) vor, also eine Feature-Zeile pro Objekt.
Es handelt sich dabei um Roh-Exports aus OSM, d. h. die Dateien können gemischte Geometrietypen enthalten. Die fachliche Zuordnung erfolgt über den jeweiligen Layer-Namen, nicht über einzelne Property-Felder.

Die Landuse-Layer werden global für die Region vorgehalten und bei Bedarf zur Laufzeit räumlich ausgewertet (z. B. Umgebung, Nähe, Überschneidungen).

Aktueller Stand: OSM-Landuse Daten – Umstellung auf globale Tiles

Wir haben die Verarbeitung der OSM-Landuse-Daten grundlegend umgestellt.

Was wir gemacht haben

  • Die bisherigen leitstellenweisen Overpass-Abfragen für Landuse wurden aufgegeben.
    Stattdessen arbeiten wir jetzt mit global vorbereiteten OSM-Daten für den gesamten DACH-Raum.
  • Die Landuse-Layer liegen zunächst als große, thematisch getrennte Dateien vor
    (z. B. landuse_residential, landuse_forest, landuse_meadow usw.).
  • Diese Layer werden offline in Tiles zerlegt:
    • Geometrie bleibt vollständig erhalten (Polygon / MultiPolygon).
    • Tile-Zuordnung erfolgt über den Centroid des Polygons.
    • Dadurch gehört jedes Feature genau zu einer Tile, keine Duplikate, keine Explosion der Datenmenge.
  • Für jeden Landuse-Typ wird eine eigene Tile-Auflösung verwendet
    (dichte Layer fein, dünne Layer grob).
    Die Tile-Auflösung ist unabhängig vom Karten-Zoom und dient nur als räumlicher Index.
  • Die Tiles liegen als geojsonl.gz vor:
    • ein Feature pro Zeile
    • direkt streambar
    • keine Entpack-Schritte zur Laufzeit nötig
  • Zusätzlich wird ein Manifest erzeugt, das pro Tile enthält:
    • Layer
    • Tile-Koordinaten (z/x/y)
    • Hash (SHA1)
    • Dateigröße
    • relative Pfadangabe

Warum dieser Ansatz

  • Kein Overpass-Timeout mehr
  • Updates sind deterministisch und reproduzierbar
  • Mehrere Personen können parallel Leitstellen aktualisieren
  • Updates betreffen nur die Tiles, die ein Einsatzgebiet wirklich schneiden
  • Schnelle Abfragen wie
    „nächstes landuse=residential zu Punkt XY“
    ohne globale Scans

Was als Nächstes kommt

  • Umbau der bestehenden Tabelle leitstellen_osm_layers:
    • Sie wird künftig globales Tile-Manifest und Leitstellen-Status aufnehmen
    • Tiles gehören keiner Leitstelle
    • Leitstellen speichern nur, welche Tiles und welche Version sie zuletzt angewendet haben
  • Der Button „OSM Cache“ wird umgestellt:
    • zuerst Update-Check: Welche Tiles im Einsatzgebiet haben sich geändert?
    • dann gezieltes Aktualisieren nur dieser Tiles
    • kein vollständiger Rebuild mehr
  • Die bestehenden Layer (Straßen, Gebäude-Centroids) können später nach demselben Prinzip integriert werden.