@startuml
title "Detailliertes Datenmodell: Ergebnis_Context"

!theme vibrant

' Externe Referenzen werden der Übersichtlichkeit halber als vereinfachte Entitäten dargestellt.
package "Externe Referenzen (Andere Kontexte)" {
    class Nennungs_Context_API
    class Veranstaltungs_Context_API
    class Personen_Context_API
}

package "Ergebnisdienst" as ErgebnisContext {

    ' #################### Aggregate Root: Bewerbsergebnis ####################
    ' Bündelt alle Ergebnisse einer Prüfungsabteilung zu einer konsistenten Einheit.
    class Bewerbsergebnis <<(A,red) Aggregate Root>> {
        + bewerbsergebnisId : UUID <<PK>>
        --
        ' Referenz zur Prüfung, für die dieses Ergebnis gilt.
        + pruefung : PruefungsReferenzVO
        ' Liste der eingesetzten Richter/Funktionäre gem. C-Satz
        + eingesetzteOffizielle : List<OffiziellerReferenzVO>
        ' Der aktuelle Zustand des Gesamtergebnisses.
        + status : ErgebnisStatusVO
    }

    ' #################### Entitäten und VOs innerhalb des Aggregates ####################
    ' Repräsentiert die Teilnahme und das Ergebnis eines einzelnen Starters.
    entity Einzelergebnis {
        + einzelergebnisId : UUID <<PK>>
        --
        ' Referenz zur Nennung, zu der dieses Ergebnis gehört.
        + nennung : NennungsReferenzVO
        ' Die berechnete finale Platzierung.
        ' D-Satz, Stelle 2-4
        + platz : integer
        ' Status des einzelnen Starters.
        ' Abgeleitet aus PLATZ und AUSSCHLUSS (D-Satz)
        + teilnahmeStatus: TeilnahmeStatusVO
        ' D-Satz, Stelle 145 ('*')
        + istPlatziert : boolean
        ' D-Satz, Stelle 136-141
        + geldpreis : GeldbetragVO
        ' D-Satz, Stelle 176-183
        + link_id_ergebnis : VARCHAR(8)
        ' Die konkrete, spartenspezifische Leistung.
        + leistung : LeistungVO
    }

    ' Polymorphes Value Object für die eigentliche Leistung
    abstract class LeistungVO <<VO>> {
    }
    ' Konkrete Ausprägungen der Leistung je nach Sparte
    LeistungVO <|-- DressurLeistungVO
    LeistungVO <|-- SpringenLeistungVO
    LeistungVO <|-- VielseitigkeitLeistungVO
    LeistungVO <|-- ReitervierkampfLeistungVO

    class DressurLeistungVO {
        ' D-Satz, Stelle 121-126
        + wertnote : decimal
        ' D-Satz, Stelle 127-131
        + prozent : decimal
    }

    class SpringenLeistungVO {
        ' D-Satz, Stelle 121-126
        + fehlerpunkte : decimal
        ' D-Satz, Stelle 127-131
        + zeit : decimal
        ' D-Satz, Stelle 132-135
        + stechen_info : string
    }

    class VielseitigkeitLeistungVO {
      + minuspunkte_dressur : decimal
      + minuspunkte_gelaende_hindernis : decimal
      + minuspunkte_gelaende_zeit : decimal
      + minuspunkte_springen : decimal
      + gesamt_minuspunkte : decimal
    }

    class ReitervierkampfLeistungVO {
      + punkte_dressur : INTEGER
      + punkte_springen : INTEGER
      + punkte_laufen : INTEGER
      + punkte_schwimmen : INTEGER
      + gesamt_punkte : INTEGER
    }


    ' #################### Value Objects für Referenzen und Beschreibungen ####################
    class PruefungsReferenzVO <<VO>> {
        ' Referenz zur originalen Abteilung
        + pruefungAbteilungDbId : UUID
        ' Relevante Daten zum Zeitpunkt der Ergebniserfassung
        + bewerbBezeichnung : string
        + abteilungBezeichnung: string
    }

    class NennungsReferenzVO <<VO>> {
        ' Referenz zur originalen Nennung
        + nennungDbId : UUID
        ' Redundante Daten für die Ergebnisliste, wie im D-Satz spezifiziert
        + reiterName : string
        + pferdName : string
        + kopfnummer : string
        + nationCode : string ' D-Satz, Stelle 142-144
    }

    class OffiziellerReferenzVO <<VO>> {
      ' Referenz zur Person
      + oepsSatzNrPerson: VARCHAR(6)
      ' Rolle gemäß C-Satz
      + rolle: string ' z.B. "Richter-1", "Parcoursbau"
    }

    class GeldbetragVO <<VO>> {
        + wert : decimal
        + waehrung : string
    }

    enum ErgebnisStatusVO {
        IN_ERFASSUNG
        VORLAEUFIG
        FINAL
        KORRIGIERT
    }

    enum TeilnahmeStatusVO {
        GESTARTET_GEWERTET
        AUSGESCHIEDEN ' Code "A" aus D-Satz, Stelle 120
        DISQUALIFIZIERT ' Code "D" aus D-Satz, Stelle 120
        TEILNAHMEVERZICHT ' Code "T" aus D-Satz, Stelle 120
    }

    ' #################### Beziehungen ####################
    ' Ein Bewerbsergebnis besteht aus vielen Einzelergebnissen (Komposition)
    Bewerbsergebnis "1" *-- "1..*" Einzelergebnis : "enthält"

    ' Jedes Einzelergebnis hat genau eine spezifische Leistung (Komposition)
    Einzelergebnis "1" *-- "1" LeistungVO : "hat Leistung"
}

' Beziehungen zu externen Kontexten (dargestellt als API-Aufrufe oder Events)
ErgebnisContext.Bewerbsergebnis ..> Nennungs_Context_API : "holt Starterliste"
ErgebnisContext.Bewerbsergebnis ..> Veranstaltungs_Context_API : "holt Prüfungsdetails"
ErgebnisContext.Bewerbsergebnis ..> Personen_Context_API : "holt Details zu Offiziellen"


note right of Bewerbsergebnis
  **Aggregate Root: Bewerbsergebnis**
  * **Verantwortung:** Dieses Aggregat garantiert die Konsistenz der gesamten Rangliste einer Abteilung.
  * **Logik:** Eine Methode `berechneRangliste()` würde alle zugehörigen `Einzelergebnis`-Objekte anhand der Regeln der jeweiligen Sparte sortieren und die `platz`-Attribute neu vergeben.
  * **Datenherkunft:** Die Liste der `eingesetzteOffizielle` wird aus dem C-Satz der Ergebnisdatei befüllt.
end note

note bottom of LeistungVO
  **Polymorphe Leistung**
  Das abstrakte `LeistungVO` ermöglicht eine saubere Modellierung der unterschiedlichen Ergebnisstrukturen. Je nach Disziplin der Prüfung (Information aus `PruefungsReferenzVO`) wird ein `Einzelergebnis` mit einem der konkreten Leistungs-Objekte (`DressurLeistungVO`, `SpringenLeistungVO` etc.) instanziiert. Die Daten dafür stammen primär aus den Feldern `PUNKTE/WERTNOTE`, `ZEIT/PROZENT` und `STECHEN` des D-Satzes.
end note
@enduml
