Files
grok-botandCommandCodeBot b061210872
CI / ubuntu-latest · Clang · C++17 (push) Has been cancelled
Code Quality / cppcheck (push) Has been cancelled
docs: Projekt-Status nach Phase 5 (Session 4) aktualisiert
Aktualisiert ARCHITECTURE.md, REFACTORING.md, TESTPLAN.md, FORTSCHRITT.md,
README.md und improvements.md mit den Ergebnissen der Session 4:

- Phase 5 (Sicherheit & Stabilität): 6 Commits
  - Dangling-Pointer gFallMemObject → std::make_unique
  - Thread-sichere Singleton-Init via std::atomic
  - 13 strcpy → Tools::strncpy (8 Domain-Dateien + 2 Actions)
  - 2 static-Caches → thread_local
  - sRegelnAusfuehren → std::atomic<bool>
- Cleanup: 6 tote Perl-Tools + kvai.ini gelöscht (266 Zeilen)
- Tests: 12 neue Test Cases (Ist_Gueltiges_Datum, Ist_Gueltige_Uhrzeit)
- Build: 23/23 Tests grün

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-06-13 08:15:13 +02:00

25 KiB
Raw Permalink Blame History

Architektur — Regelwerk (RW)

Systemuebersicht

flowchart TB
    subgraph External["Externe Systeme"]
        KVAI["KVAI Host<br/>(Abrechnungssystem)"]
        DB[("Oracle/Sybase<br/>Stammdaten + Abrechnungsdaten")]
    end

    subgraph RW["Regelwerk DLL (rw_core)"]
        direction TB

        subgraph Interface["Schnittstelle"]
            API["rw_implementation.hpp<br/>RegelWerkImpl / RegelWerkDatenImpl"]
            XMLIn["XML-Parser<br/>rw_smallxml"]
            XMLOut["XML-Serialisierung<br/>convert2xml"]
        end

        subgraph Core["Kern"]
            Config["Config<br/>(KVAI-Konfiguration)"]
            Init["initAllRW<br/>(LE-Daten, Stammdaten)"]
            PaketLader["PaketLader<br/>(DB → Entity-Graph)"]
            RegelMaschine["RegelMaschine<br/>(2-Stufen-Pipeline)"]
        end

        subgraph Engine["Rule Engine"]
            MSRegelwerk["MSRegelwerk<br/>(Regelwerk-Lader + regelFall)"]
            Praedikate["87 Praedikate<br/>(Bedingungen)"]
            Aktionen["30+ Aktionen<br/>(Beanstanden, Streichen, Ersetzen)"]
            Methoden["50+ Methoden<br/>(UR1..601, SB20..414)"]
        end

        subgraph Domain["Domain-Modell"]
            Entities["Paket → Patientenfall → BHF<br/>→ Schein → Tag → Leistung"]
            StateMachine["Zustandsautomat<br/>(R00..R01, AII, RFS, RW0)"]
            Memory["Speichermodell<br/>(Arena-Allokator, Flyweight)"]
        end
    end

    KVAI -->|"XML-Auftrag"| XMLIn
    XMLIn --> Config
    Config --> Init
    Init --> PaketLader
    DB --> PaketLader
    PaketLader --> Entities
    Entities --> RegelMaschine
    RegelMaschine --> MSRegelwerk
    MSRegelwerk --> Praedikate
    MSRegelwerk --> Aktionen
    MSRegelwerk --> Methoden
    Praedikate --> StateMachine
    Aktionen --> StateMachine
    RegelMaschine --> XMLOut
    XMLOut -->|"XML-Ergebnis"| KVAI

    style External fill:#f0f0f0,stroke:#666,color:#333
    style RW fill:#1a1a2e,stroke:#e94560,color:#fff
    style Interface fill:#2d2d44,stroke:#533483,color:#ccc
    style Core fill:#2d2d44,stroke:#533483,color:#ccc
    style Engine fill:#2d2d44,stroke:#533483,color:#ccc
    style Domain fill:#2d2d44,stroke:#533483,color:#ccc

1. Entity-Hierarchie

classDiagram
    class Paket {
        +int paketId
        +PatfallIDs patFaelle
        +ladePaket()
        +regeln()
        +serialisieren()
    }

    class Patientenfall {
        +int patfallId
        +Status zustand
        +List~Behandlungsfall~ bhfs
        +regeln()
        +rfsPropagieren()
    }

    class Behandlungsfall {
        +int bhfId
        +List~Krankenschein~ scheine
        +List~BHD~ bhds
        +KHF khf
        +zaehlerAbhaengig
        +zkennzeichen
    }

    class Krankenschein {
        +int scheinId
        +ScheinStatus status
        +List~Tag~ tage
        +tagIterator()
    }

    class Tag {
        +Datum datum
        +List~Leistung~ leistungen
    }

    class Leistung {
        +string gop
        +string lg
        +string lug
        +string farbe
        +LeistungStatus status
        +double wert
        +TaetigkeitOrt taetigkeitOrt
        +List~LeistungWert~ werte
        +List~LeistungBegruendung~ begruendungen
        +List~RegelAenderung~ aenderungen
    }

    class LeistungWert {
        +int wert
        +string waehrung
    }

    class LeistungBegruendung {
        +string feldkennung
        +string wert
    }

    class RegelAenderung {
        +string regelId
        +string status
    }

    class BHD {
        +Datum von
        +Datum bis
        +List~Tag~ tage
    }

    class KHF {
        +string khfId
        +List~Behandlungsfall~ bhfs
    }

    class TaetigkeitOrt {
        +string lanr9
        +int leistungsort
    }

    Paket "1" --> "*" Patientenfall
    Patientenfall "1" --> "*" Behandlungsfall
    Behandlungsfall "1" --> "*" Krankenschein
    Behandlungsfall "1" --> "*" BHD
    Behandlungsfall "1" --> "1" KHF
    Krankenschein "1" --> "*" Tag
    Tag "1" --> "*" Leistung
    Leistung "1" --> "*" LeistungWert
    Leistung "1" --> "*" LeistungBegruendung
    Leistung "1" --> "*" RegelAenderung
    Leistung "1" --> "1" TaetigkeitOrt

Entity-Zusammenfassung

Entity Bedeutung Enthaelt
Paket Abrechnungspaket pro Praxis/Quartal 1..n Patientenfaelle
Patientenfall Alle BHFs eines Patienten 1..n BHFs, Status, Rueckgabedaten
Behandlungsfall (BHF) Zusammenfassung aller Kranken­scheine eines Patienten im Quartal Scheine, BHDs, KHF, Kennzeichen
Krankenschein Ein Abrechnungsdokument 1..n Tage mit Leistungen
BHD BehandlungZeitraumDatum Datumsbezogene Gruppierung von Tagen
KHF Krankheitsfall (quartalsuebergreifend) Abstraktion ueber BHFs hinweg
Tag Ein Behandlungstag 1..n Leistungen
Leistung Aerztliche Einzelleistung (GOP) Werte, Begruendungen, Regel-Aenderungen
LeistungWert Punktwert/Waehrungsbetrag Wert + Waehrungskennzeichen
LeistungBegruendung Feldkennung + Wert (z.B. OP-Datum, Uhrzeit) feldkennung, wert
RegelAenderung Protokolleintrag einer Regel-Anwendung regelId, status, text

2. Zustandsautomat

stateDiagram-v2
    direction LR

    state "Paket-Zustand" as PaketState {
        [*] --> R00: Paket angelegt
        R00 --> RVF: PaketLader.ladePaket
        RVF --> RWF: REGELWERK_VOR
        RWF --> RNF: RegelMaschine.regelFaelle
        RNF --> R01: REGELWERK_NACH
    }

    state "Schein-Zustand" as ScheinState {
        [*] --> AII: Default OK
        [*] --> RW0: Fehlerhafter Schein
        [*] --> DA0: Ungeregelt
        [*] --> DAP: Trennwerk
        [*] --> L00: Gelöscht

        AII --> RFS: RFS-Fehler entdeckt
        RW0 --> RFS: RFS-Fehler entdeckt
        DA0 --> RFS: RFS-Fehler entdeckt
    }

    state "Leistung-Zustand" as LeistungState {
        [*] --> State0: Normal = 0
        [*] --> State2: RW-geloescht = 2
        [*] --> State3: Spurlos geloescht = 3
        [*] --> State4: RW-eingefuegt = 4
        [*] --> State5: Unsichtbar = 5
        [*] --> StateI: Manuell hinzu = I
        [*] --> StateG: Manuell geloescht = G
    }

Zustands-Propagation

flowchart LR
    L["Leistung"] --> T["Tag"] --> S["Schein"] --> B["BHF"] --> P["Patientenfall"]

    subgraph BottomUp["Bottom-up: Aggregation"]
        L2["Leistung<br/>(Status, Flags)"] --> T2["Tag<br/>(Status aggregiert)"]
        T2 --> S2["Schein<br/>(AII, RW0, RFS, DA0)"]
        S2 --> B2["BHF<br/>(Kennzeichen, Zaehler)"]
        B2 --> P2["Patientenfall<br/>(Gesamt-Status)"]
    end

    subgraph TopDown["Top-down: Propagation"]
        P3["Patientenfall"] -.->|"Aenderungen<br/>propagieren"| B3["BHF"]
        B3 -.-> S3["Schein"]
        S3 -.->|"wirkt auf alle<br/>Leistungen"| L3["Leistung"]
    end

    style BottomUp fill:#16213e,stroke:#0f3460,color:#ccc
    style TopDown fill:#0f3460,stroke:#533483,color:#ccc

RFS-Propagation (Regelwerk-Fehler-Stop):

  • RFS in einer Leistung → gesamter Patientenfall erhaelt RFS-Status
  • RFS ueberschreibt alle anderen Stati (hoechste Prioritaet)
  • Bottom-up: Leistung → Tag → Schein → BHF → Patientenfall

Leistungs-Flags

Flag Bedeutung
unsichtbar Leistung wird nicht ausgegeben
plausibel Nur plausible Regeln duerfen aendern
hinweis Regelwirkung als Hinweis (nicht aktiv)
loeschend_wirksam Loeschung wurde bereits durchgefuehrt

3. Regel-Pipeline (Detail)

flowchart TB
    subgraph Input["Eingabe"]
        XML["XML-Auftrag<br/>(<RWCMD>...</RWCMD>)"]
    end

    subgraph Phase0["Phase 0: Initialisierung"]
        Cfg["Config laden<br/>(KVAI-Konfiguration)"]
        LE["LE-Daten laden<br/>(LANR, BSNR, Arztgruppen)"]
        GO["GOAE-Stammdaten<br/>(GOP-Kataloge, Farben)"]
        KHF["KHF-Daten<br/>(Krankheitsfall-Daten)"]
    end

    subgraph Phase1["Phase 1: Laden"]
        PL["PaketLader::ladePaket()"]
        DB[("Datenbank<br/>Oracle/Sybase")]
        EG["Entity-Graph aufbauen<br/>(Paket → Patientenfall → ... → Leistung)"]
    end

    subgraph Phase2["Phase 2: BILDUNG (ruleFaelle)"]
        RM1["RegelMaschine::regelFaelle()"]
        BL["Pro Patientenfall:<br/>MSRegelwerk::regelFall()"]
        ZK["Zaehler deklarieren<br/>und inkrementieren"]
    end

    subgraph Phase3["Phase 3: AUSWERTUNG (zaehlerAbhaengigeFaelleRegeln)"]
        RM2["RegelMaschine::zaehlerAbhaengigeFaelleRegeln()"]
        AL["Nur zaehler-abhaengige Faelle<br/>erneut beregeln"]
        ZF["Mit fertigen Zaehlerstaenden<br/>Regeln ausfuehren"]
    end

    subgraph Phase4["Phase 4: Ausgabe"]
        SER["Entity-Graph → XML serialisieren"]
        OUT["XML-Ergebnis<br/>(<RWRESULT>...</RWRESULT>)"]
    end

    XML --> Cfg
    Cfg --> LE
    LE --> GO
    GO --> KHF
    KHF --> PL
    DB --> PL
    PL --> EG
    EG --> RM1
    RM1 --> BL
    BL --> ZK
    ZK --> RM2
    RM2 --> AL
    AL --> ZF
    ZF --> SER
    SER --> OUT

    style Input fill:#f0f0f0,stroke:#666,color:#333
    style Phase0 fill:#2d2d44,stroke:#533483,color:#ccc
    style Phase1 fill:#2d2d44,stroke:#533483,color:#ccc
    style Phase2 fill:#16213e,stroke:#0f3460,color:#ccc
    style Phase3 fill:#0f3460,stroke:#533483,color:#ccc
    style Phase4 fill:#2d2d44,stroke:#533483,color:#ccc

Regel-Ausfuehrung im Detail

flowchart TD
    RF["MSRegelwerk::regelFall(Patientenfall)"] --> IT["Iteriere ueber alle<br/>Behandlungsfaelle (BHFs)"]
    IT --> BZ["Pro BHF: Iteriere ueber<br/>Behandlungs-Zeitraeume (BHZ)"]
    BZ --> RL["Pro BHZ: Fuehre alle Regeln aus"]

    RL --> PR{"Praedikat<br/>erfuellt?"}
    PR -->|"true"| AK["Aktion ausfuehren"]
    PR -->|"false"| NXT["Naechste Regel"]

    AK --> AT{".Aktionstyp?"}
    AT -->|"Beanstanden"| BEA["LeistungBeanstanden()"]
    AT -->|"Streichen"| STR["LeistungStreichen()"]
    AT -->|"Ersetzen"| ERS["LeistungErsetzen()"]
    AT -->|"Methode"| MTH["MethodeAusfuehren()"]
    AT -->|"Umfaerben"| UMF["UmfaerbeAktion()"]

    BEA --> NXT
    STR --> NXT
    ERS --> NXT
    MTH --> NXT
    UMF --> NXT

    style RF fill:#0a3a0a,stroke:#51cf66,color:#51cf66
    style PR fill:#3a3a0a,stroke:#ffd43b,color:#ffd43b
    style AK fill:#0a3a0a,stroke:#51cf66,color:#51cf66

Praedikate (Auszug der 87 Bedingungen)

Kategorie Beispiele
GOP-Selektoren gop_selector, gop_menge_selector, gop_im_stamm_selector
Mengen-Relationen ist_element_von, ist_teilmenge_von, ist_gop_abgerechnet
Datums-Praedikate ist_gueltiges_datum, hat_datum, am_sonntag
OPS-Praedikate go_ops_erfuellt_selector, falsche_ops_selector, ist_op_datum
Diagnosen diagnosen_erfuellt
Leistungserbringer le_hat_berechtigung, ist_bht_gueltigkeitstag_fuer_taetigkeitsort
Kennzeichen kennzeichen_ist_element_von, fallkzm_praedikat
Aussetzungen aussetzung_is_equal_to, genehmigt_am_ort_quartal
Berechtigungen berechtigungen_teilmenge_von
Kombinierte aktive_methode_praedikat, ausschliesslicher_ansatz_von_gops

Aktionen (Auszug der 30+ Aenderungen)

Kategorie Beispiele
Beanstanden LeistungBeanstanden, LeistungHinweis, LeistungRFSBeanstanden
Streichen LeistungStreichen, LeistungStreichenOhneAufheben
Ersetzen LeistungErsetzen, SetzeAlphaExtensionAktion, GopMengeHinzu
Wert-Aenderung WertaenderungAktion, ProzWertaenderungAktion
Umfaerben UmfaerbeAktion
Taetigkeit TaetigkeitUmsetzenAktion, LeistortUmsetzenAktion
LUG/LG SetzeLUGAktion, SetzeLGLUGAktion
Methode MethodeAusfuehren
Zaehlkennzeichen ZK-Framework (Deklaration + Inkrement)

Methoden (50+ komplexe Verfahren)

Ur-Methoden (UR):        UR01, UR14, UR21, UR29, UR41, UR42, UR43, UR44, UR45, UR46,
                         UR101, UR121, UR125, UR126, UR129, UR201, UR229, UR301, UR329,
                         UR401, UR501, UR601

SB-Methoden (Sonderbed.): SB20, SB34, SB46, SB314, SB414

Weitere Methoden:         AB, AK, BP, EB, FL, FZ, GS, HA, HB, HL, HW, HZ, KA,
                         MA, MS, NW, O3, PX, PY, PZ, SB, ST, TA, TH, ZA

4. Speichermodell

flowchart LR
    subgraph Global["Globaler Speicher"]
        GPM["gPersistParamMemObject<br/>16 MB<br/>(Stammdaten)"]
    end

    subgraph PerFall["Pro Patientenfall"]
        FMO["gFallMemObject<br/>1 MB Stack-Allokator"]
        MSM["MSMem (Bump-Allokator)<br/>32-KB-Bloecke<br/>placement-new"]
    end

    subgraph Flyweight["String-Interning (Flyweight)"]
        MG["Menge / IntMenge<br/>(GOPs, Diagnosen, LANRs)"]
        MP["Map<br/>(Key-Value-Paare)"]
    end

    subgraph Listen["Intrusive Listen"]
        DL["dlink → List~T~<br/>(Entity-Verkettung)"]
        CT["CntList<br/>(ref-counted)"]
    end

    GPM --> MG
    FMO --> MSM
    MSM --> MG
    MG --> DL
    MP --> MG

    style Global fill:#0a3a0a,stroke:#51cf66,color:#51cf66
    style PerFall fill:#2d2d44,stroke:#533483,color:#ccc
    style Flyweight fill:#16213e,stroke:#0f3460,color:#ccc
    style Listen fill:#3a3a0a,stroke:#ffd43b,color:#ffd43b

Speicher-Strategie

Komponente Groesse Zweck
gPersistParamMemObject 16 MB Stammdaten (GOP-Kataloge, LE-Daten), persistent ueber alle Faelle
gFallMemObject 1 MB/Fall Stack-Allokator, wird nach jedem Fall zurueckgesetzt
MSMem 32-KB-Bloecke Bump-Allokator, verwaltet Bloecke aus gFallMemObject
Menge / IntMenge variabel String-Interning fuer GOPs, Diagnosen, LANR9
Map variabel Key-Value-Speicher (Konfiguration, Aussetzungen)
dlink / List<T> 0 Overhead Intrusive doppelt-verkettete Liste, keine Heap-Allokation

Wichtig: Alle Entities werden per placement-new in Arena-Allokatoren erstellt. Kein Heap-Overhead pro Entity. Flyweight-Pattern vermeidet String-Duplikation bei haeufig wiederkehrenden Werten wie GOPs, Diagnose-ICDs und LANR9.


5. XML-Schnittstelle

sequenceDiagram
    participant KVAI as KVAI Host
    participant DLL as rw_core (DLL)
    participant PL as PaketLader
    participant RM as RegelMaschine
    participant S as Serializer

    KVAI->>DLL: RegelWerkImpl(xmlAuftrag)
    DLL->>DLL: XML parsen (rw_smallxml)
    DLL->>PL: ladePaket(paketId)
    PL-->>DLL: Entity-Graph
    DLL->>RM: regelFaelle() + zaehlerAbhaengigeFaelleRegeln()
    RM-->>DLL: regulierte Faelle
    DLL->>S: Entity-Graph → XML
    S-->>DLL: XML-Ergebnis
    DLL-->>KVAI: XML-Ergebnis-String

Auftrag (Eingabe)

<?xml version="1.0" standalone="yes"?>
<RWCMD>
    <CMD Aktion="regeln"/>
    <DATA>
        <KS_PRAXIS_AUSSETZUNG PRAXIS_ID="123456789" AUSS_REGELGRP="UV9000"/>
        <KS_BEHANDLUNGSFALL BHF_ID="42" PRAXIS_ID="123456789" QUARTAL="20101"
                            PAT_ID="99" KT="08150" BA="1">
            <KS_KRANKENSCHEIN SK_ID="1" DATUM="01.01.2010">
                <KS_LEISTUNG LST_ID="1" GOP="01430" LG="01" LUG="00"
                             PM="P" WERT="100"/>
            </KS_KRANKENSCHEIN>
        </KS_BEHANDLUNGSFALL>
    </DATA>
</RWCMD>

Ergebnis (Ausgabe)

<?xml version="1.0" standalone="yes"?>
<RWRESULT>
    <SUCCESS RESULT="TRUE"/>
    <DATA>
        <KS_BEHANDLUNGSFALL BHF_ID="42" ...>
            <KS_BHF_KENNZEICHEN KZ="ZK01" WERT="3"/>
            <KS_KRANKENSCHEIN SK_ID="1" ...>
                <KS_SK_KENNZEICHEN KZ="STATUS" WERT="AII"/>
                <KS_LEISTUNG LST_ID="1" GOP="01430" .../>
                <KS_LEISTUNG_REGELAENDERUNG SK_ID="1" LST_ID="1"
                    REGEL_ID="SB414" STATUS="HINWEIS"
                    TEXT="Mindestanzahl Behandlungstage nicht erreicht"/>
            </KS_KRANKENSCHEIN>
        </KS_BEHANDLUNGSFALL>
    </DATA>
</RWRESULT>

Aktionen der XML-Schnittstelle

Aktion Beschreibung
regeln Hauptaktion: Patientenfall beregeln
aussetzung_status Prueft, ob eine Aussetzung aktiv ist
set_le LE-Daten initialisieren
set_konfiguration KVAI-Konfiguration laden
gop_bewertung GOP-Bewertung abfragen

6. Subsysteme im Detail

6.1 Leistungserbringer (LE) — src/le/

Verwaltet alle Daten zu Aerzten und Betriebsstaetten:

Klasse Beschreibung
le_dblader Laedt LE-Daten aus der Datenbank
le_arztgruppe Arztgruppen-Zuordnung (Hausarzt, Facharzt, …)
le_hausfacharzt Hausarzt-Pruefung
le_gopkatalog GOP-Katalog pro Arztgruppe
le_relationen Beziehungen zwischen LE-Entitaeten
le_okz Ortskennzahl-Verwaltung
le_vars Globale LE-Variablen (thread-safe)
le_utilities Hilfsfunktionen (lanr9t-Extraktion, etc.)

6.2 GOAE-Katalog — src/goae/

Verwaltet die Gebuehrenordnungs-Stammdaten:

Klasse Beschreibung
gostamm GOP-Stammdaten (Farbe, LG, LUG, Beschreibung)
gopvergleich GOP-Vergleichsoperationen
gobeding GOAE-Bedingungen (z.B. "nur bei Ueberweisung")
goabw Abrechnungswert-Berechnung

6.3 Datenbank — src/db/

Abstrahiert den Datenbankzugriff:

Klasse Beschreibung
MSDBConnection Interface fuer DB-Verbindungen
DummyDBConnection No-Op-Implementierung fuer Build/Test
msora_connection Oracle-Implementierung (Produktion)
mssyb_connection Sybase-Implementierung (Produktion)
SQL_Updater SQL-Statement-Executor
stm_kvai_konfig KVAI-Konfigurations-Tabelle
class_rwstoredproc Regelwerk-Stored-Procedures

6.4 XML — src/xml/

Eigenbau-XML-Parser und Serialisierung:

Klasse Beschreibung
rw_smallxml Leichtgewichtiger XML-Parser
convert2xml Entity-Graph → XML
rw_xml_cache XML-Template-Cache
xmltools XML-Hilfsfunktionen

6.5 Statistik — src/statistik/

Sammelt und exportiert Regel-Statistiken:

Klasse Beschreibung
rw_statistik Statistik-Sammler
rw_statistikdata Statistik-Datencontainer
rw_sinks Ausgabe-Sinks (CSV, etc.)

7. Thread-Modell

flowchart TB
    subgraph Threads["Thread-Modell"]
        Main["Haupt-Thread<br/>(KVAI Host)"]
        T1["Paket 1"]
        T2["Paket 2"]
        T3["Paket N"]
    end

    subgraph TLS["Thread-Local Storage"]
        Sys["System::exemplar()<br/>(aktuelles Paket, Regelwerk, BHF)"]
        Mem["gFallMemObject<br/>(1 MB Stack-Allokator)"]
        LM["LeistungMerker::exemplar()"]
        TOE["TaetigkeitOrtErmittler::exemplar()"]
    end

    Main --> T1
    Main --> T2
    Main --> T3

    T1 --> Sys
    T2 --> Sys
    T3 --> Sys

    T1 --> Mem
    T2 --> Mem
    T3 --> Mem

    style Threads fill:#f0f0f0,stroke:#666,color:#333
    style TLS fill:#2d2d44,stroke:#533483,color:#ccc
  • Kein thread_local → static Rueckbau: Die thread_local-Makros (MACRO_EMPTY_MENGE, System-Singletons) sind essenziell fuer parallele Paketverarbeitung. Jeder Thread hat seinen eigenen Entity-Graph und Speicher.
  • Paket-Isolation: Pakete werden parallel verarbeitet. Innerhalb eines Pakets laeuft alles single-threaded.

8. Build-System

flowchart LR
    subgraph Source["Quellen"]
        CPP["~230 .cpp"]
        HPP["~450 .hpp"]
    end

    subgraph CMake["CMakeLists.txt"]
        Core["rw_core<br/>(statische Bibliothek)"]
        Host["rw_host<br/>(Executable, optional)"]
        Tests["16 Test-Executables<br/>(optional)"]
    end

    subgraph Output["Output"]
        Lib["librw_core.a"]
        Bin["rw_host"]
        TestBin["*_test"]
    end

    CPP --> Core
    HPP --> Core
    Core --> Lib
    CPP --> Host
    Host --> Bin
    CPP --> Tests
    Tests --> TestBin

    style Source fill:#f0f0f0,stroke:#666,color:#333
    style CMake fill:#2d2d44,stroke:#533483,color:#ccc
    style Output fill:#0a3a0a,stroke:#51cf66,color:#51cf66

Die Quelldateien sind in sources.cmake ausgelagert um das CMakeLists.txt schlank zu halten. Fuer Produktion wird rw_core als DLL (RW_DLL-Flag) gebaut.


9. Verzeichnisstruktur (vollstaendig)

Verzeichnis Inhalt Dateien
src/core/ RegelMaschine, Config, Init, exportierte API 15
src/domain/ Entity-Klassen (Paket, Patientenfall, Leistung, …) ~90
src/datatypes/ Container: Menge, Map, List, IntMenge ~30
src/db/ Datenbank-Anbindung (Interface + Implementierungen) 28
src/interface/ IRWLeistung, IRWSchein (Interface-Abstraktion) 9
src/methods/ 50+ Methoden (ab, ak, eb, fl, gs, ha, sb, st, …) ~75
src/ur_meth/ 25+ Ur-Methoden (komplexe Verfahrensanweisungen) ~50
src/sb_meth/ 6 SB-Methoden (Sonderbedingungen) 11
src/rw_predicates/ 87 Praedikate (Bedingungen) ~80
src/rw_actions/ 59 Aktionen (eine pro .hpp, Beanstanden, Streichen, Ersetzen) 59
src/le/ Leistungserbringer-Subsystem (LANR, BSNR, Arztgruppen) ~50
src/goae/ GOAE-Katalog-Subsystem (Farben, GOP-Vergleich) ~40
src/statistik/ Statistik und Logging 8
src/taetigkeitort/ Taetigkeit-Ort-Berechnung ~5
src/json/ JSON-Parser und C++-Deserialisierung 9
src/xml/ XML-Serialisierung (rw_smallxml) 11
src/rest/ Host-Wrapper, Konstanten, Makros, Templates ~34
src/util/ Tools: Datumsberechnung, Speicher, Kompression ~50
src/zlib/ Statisch gelinkte ZLIB 1.2.3 ~20
src/libs/ Vorkompilierte ZLIB-Binaries (HP-UX, Solaris, Win) ~5
src/aktsource/ ⚠️ Generierte Stammdaten (~100MB) ~110

10. Beispiel: Ausfuehrungsfluss SB414

flowchart TD
    subgraph SB414["SB414 — Mengenpruefung mit OPS-Filter"]
        A["Eingabe: gm1 (GOP-Menge), opsm (OPS-Menge),<br/>anzahl (Mindestanzahl Tage), gm4, gm5"]
    end

    A --> B{"diff_lanr9?"}
    B -->|"NO"| C["Pro Taetigkeit iterieren"]
    B -->|"YES"| D["Einmalig BHZ-weit pruefen"]

    C --> E
    D --> E

    E["Praedikat: SB314Praedikat"] --> F{"GOPs aus gm1<br/>vorhanden?"}
    F -->|"NO"| X["return false"]
    F -->|"YES"| G{"AKP-Pruefung<br/>(Arztgruppe, Kennzeichen,<br/>Alter, Geschlecht, ...)"}
    G -->|"NO"| X
    G -->|"YES"| H["Relevante Tage zaehlen<br/>(nicht in gm4, disjunkt zu gm5)"]
    H --> I{"|relevante Tage| < anzahl?"}
    I -->|"NO"| X
    I -->|"YES"| J["return true → Aktion"]

    J --> K{"Aktion: SB414Aktion"}
    K --> L{"opsm leer?"}
    L -->|"YES"| M["Alle gm1-Leistungen<br/>beanstanden"]
    L -->|"NO"| N{"vertausche_opsm?"}
    N -->|"YES"| O["Nur Leistungen MIT OPS<br/>in opsm beanstanden"]
    N -->|"NO"| P["Nur Leistungen MIT OPS<br/>die opsm erfuellen"]

    M --> Q["LeistungBeanstanden()"]
    O --> Q
    P --> Q

    style SB414 fill:#1a1a2e,stroke:#e94560,color:#fff
    style E fill:#16213e,stroke:#0f3460,color:#ccc
    style J fill:#0a3a0a,stroke:#51cf66,color:#51cf66
    style X fill:#3a0a0a,stroke:#ff6b6b,color:#ff6b6b
    style Q fill:#0a3a0a,stroke:#51cf66,color:#51cf66

11. Wartung und Erweiterung

Neue Regel hinzufuegen

  1. Praedikat definieren: In src/rw_predicates/ einen neuen Funktor erstellen
  2. Aktion definieren: Neue .hpp-Datei in src/rw_actions/ erstellen (besteht aus 59 Einzeldateien)
  3. Regel registrieren: In den Stammdaten (XML/DB) die neue Regel mit Praedikat+Aktion+Methoden-Parametern eintragen
  4. Testfaelle: XML-Testdaten in tests/sbXXX/ ablegen

Aenderungen an bestehenden Regeln

  • Immer gitnexus_impact auf das Ziel-Symbol ausfuehren
  • Bei HIGH/CRITICAL Risk: Aenderung mit Fachbereich abstimmen
  • Nach jeder Aenderung Build + Tests ausfuehren
  • gitnexus_detect_changes() vor Commit

12. Refactoring-Status (Juni 2026)

Phase Status Beschreibung
0 — Basis ✅ abgeschlossen Git-Init, UTF-8, unary_function → type-aliases, Boost→STL, Namespace maatini
1 — C++11 ✅ abgeschlossen BOOST_FOREACH, boost::bind, boost::function1, thread_local, nullptr, override
1 — rw_actions ✅ abgeschlossen Monolith → 59 Einzel-.hpp
— JSON ✅ abgeschlossen JSON-Parser + C++-Deserialisierung (src/json/, 9 Dateien)
2 — C++14/17 ✅ abgeschlossen enum → enum class (4 Typen), auto für Iteratoren (24 Deklarationen)
3 — Boost-Bereinigung ✅ abgeschlossen Nur bimap + lexical_cast verbleiben
4 — Speicher ✅ abgeschlossen gFallMemObject explizit (10 no-arg copy() entfernt)
5 — Sicherheit ✅ abgeschlossen Dangling-Pointer (25f9400), Thread-Safety (478062b, 5abfc85, ed4ba17), strcpy-Audit (a4aa685)
6 — Cleanup ✅ abgeschlossen 6 tote Perl-Tools, kvai.ini (2003), leeres Verzeichnis gelöscht
7 — Tests 🔄 laufend 23 Executables, 32+ standalone Prädikat-Tests, E2E-Pipeline, Catch2-Integration
8 — Container ⏳ geplant CountList → unordered_map, IntMenge → set (optional)

Siehe REFACTORING.md fuer Details.


Referenzen