meldestelle/docs/03_Domain/02_Reference/TURNIER_KLASSEN.md

182 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
type: RULE_SPEC
status: DRAFT
owner: Rulebook Expert
last_update: 2026-04-02
---
# Turnier-Klassen und Abteilungs-Zwangsteilung (ÖTO)
Ziel: Einheitliche, maschinenlesbare Spezifikation der Klassensystematik und der verpflichtenden Abteilungs-Teilungsregeln ("Zwangsteilung") gemäß ÖTO. Diese Regeln steuern Backend-Validierungen, Frontend-UX (Hinweise/Warnungen) und Exportlogik.
Quellen/Verweise:
- Roadmap: `docs/04_Agents/Roadmaps/Rulebook_Roadmap.md` (A-2)
- DomänenModell: `docs/03_Domain/01_Core_Model/Domain_Model_Veranstaltung_Turnier_Bewerb_Abteilung.md`
- Validierungsregeln (Lizenz/Alter): `docs/03_Domain/02_Reference/Validierungsregeln.md`
- ÖTO Referenzstellen (ParagraphenPins zur Nachverfolgung):
- Springen: ÖTO 2026, Kapitel „Springen“, § 231 Abs. 13 (CSNCNEU Teilungsregeln) [PIN: OETO-SPR-231]
- Dressur: ÖTO 2026, Kapitel „Dressur“, § 103 Abs. 25 (Teilnahme/Leistungsstufen) [PIN: OETO-DRS-103]
- Vielseitigkeit: ÖTO 2026, Kapitel „Vielseitigkeit“, §§ 3xx (Teilnahme/Abteilungen) [PIN: OETO-VS-3XX]
Hinweis Rechtslage: Die obigen „ParagraphenPins“ verankern die Stellen im ÖTO. Exakte Absatz-/Ziffernangaben werden nach juristischer Finalisierung ergänzt. Inhaltliche Logik entspricht dem Stand der Praxis (CSNCNEU) und wird bei Abweichungen angepasst.
---
## 1. Begriffe (Auszug)
- Bewerb: Sportliche Ausschreibungseinheit innerhalb eines Turniers (z. B. Springen 95 cm, Stilspringen). Enthält 1..N Abteilungen.
- Abteilung: Startgruppe innerhalb eines Bewerbs. Kann organisatorische oder regelbedingte Gründe haben (Zwangsteilung, Lizenz, Jugend usw.).
- Zwangsteilung: Verpflichtende Abteilungsbildung anhand lizenz-/leistungsbezogener Kriterien gemäß ÖTO.
---
## 2. CSN (Springen national) — Zwangsteilung CNEU
Gültig für Bewerbe der Kategorie „CSNCNEU“.
### 2.1 Regelübersicht (Zwangsteilung)
- Rechtsgrundlage: ÖTO § 231 (vgl. [PIN: OETO-SPR-231])
- Bewerbe mit Höhe ≤ 95 cm:
- Abteilung A: Label: „ohne Lizenz“ — Key: `LZF_ONLY` — Allowed: `LZF`
- Abteilung B: Label: „mit Lizenz“ — Key: `R1_PLUS` — Allowed: `R1|R2|R3|R4`
- Bewerbe mit Höhe ≥ 100 cm:
- Abteilung A: Label: „R1“ — Key: `R1_ONLY` — Allowed: `R1`
- Abteilung B: Label: „R2 und höher“ — Key: `R2_PLUS` — Allowed: `R2|R3|R4`
Erläuterungen:
- Die Abteilungsbezeichnungen dienen dem Frontend (Label) und der Preisgeld-/Siegerehrungslogik. Technisch werden die Abteilungen per Attribut „LizenzGruppe“ markiert.
- Veranstalter dürfen enger teilen (z. B. zusätzliche Jugendabteilungen), nicht jedoch lockern (PflichtZweiteilung muss bestehen bleiben).
### 2.2 Maschinenlesbare Spezifikation
Tabelle: CSNCNEU Zwangsteilung nach Höhe
| Höhe (cm) | Abteilung 1 (Label · Key) | Abteilung 2 (Label · Key) | Bemerkung |
|---|---|---|---|
| ≤ 95 | „ohne Lizenz“ · `LZF_ONLY` | „mit Lizenz“ · `R1_PLUS` | `R1_PLUS` umfasst `R1|R2|R3|R4` |
| ≥ 100 | „R1“ · `R1_ONLY` | „R2 und höher“ · `R2_PLUS` | `R2_PLUS` umfasst `R2|R3|R4` |
Pseudocode (Ableitung der PflichtAbteilungen):
```kotlin
data class ForcedDivision(val label: String, val allowedLicenses: Set<String>)
fun forcedDivisionsCsnCNeu(heightCm: Int): List<ForcedDivision> =
if (heightCm <= 95) listOf(
ForcedDivision(label = DivisionLabels.OHNE_LIZENZ, allowedLicenses = setOf("LZF")),
ForcedDivision(label = DivisionLabels.MIT_LIZENZ, allowedLicenses = setOf("R1","R2","R3","R4"))
) else listOf(
ForcedDivision(label = DivisionLabels.R1, allowedLicenses = setOf("R1")),
ForcedDivision(label = DivisionLabels.R2_UND_HOEHER, allowedLicenses = setOf("R2","R3","R4"))
)
```
Validierung (vereinfachte Regel):
- Wenn Bewerbskategorie = `CSN-C-NEU`, dann müssen genau zwei Abteilungen gemäß obiger Ableitung vorhanden sein. Jede Nennung muss in einer Abteilung landen, deren `allowedLicenses` die Lizenz des Reiters enthält.
Fehlermeldungen (UX):
- „Für CSNCNEU Bewerbe ist eine Zwangsteilung nach Lizenz vorgeschrieben (ÖTO § 231). Bitte beide Abteilungen anlegen.“
- „Die Abteilung R2 und höher darf nur Lizenzen R2/R3/R4 enthalten.“
- Hinweistext (Quelle): „Rechtsgrundlage: ÖTO § 231 (CSNCNEU).“
---
## 3. CDN (Dressur national) — Prüfung weiterer Zwangsteilungen
Status: geprüft. Nach aktuellem Stand bestehen in den Einsteiger/NiedrigKlassen keine zwingenden LizenzZwangsteilungen analog zu CSNCNEU. Übliche Praxis ist die optionale Teilung nach Leistungsklassen/Jahrgängen (z. B. Jugendliche), jedoch keine verpflichtende Zweiteilung „ohne/mit Lizenz“.
- Ergebnis: Keine allgemeine, disziplinweite Zwangsteilung identifiziert. Veranstalter können freiwillig teilen (z. B. RD1 vs. RD2+), sofern ÖTO konform. Bezug: ÖTO § 103 (vgl. [PIN: OETO-DRS-103]).
Folgeaktion: Bei Veröffentlichung der finalen DressurAbschnitte erneut prüfen. Bis dahin: Keine systemweite Pflichtregel hinterlegen.
---
## 4. CCN (Vielseitigkeit national) — Prüfung weiterer Zwangsteilungen
Status: vorläufig geprüft. In den nationalen Vielseitigkeitsklassen (CCN) ist keine generische Zwangsteilung nach Lizenzgruppen („ohne/mit“ bzw. `R1` vs. `R2+`) als Pflicht verankert. Teilungen erfolgen eher nach Leistungsniveau, Altersklassen oder organisatorischen Gründen.
- Ergebnis: Keine disziplinweiten PflichtTeilungsregeln identifiziert. Konkrete Ausnahmen sind turnierspezifisch. Bezug: ÖTO Kapitel „Vielseitigkeit“, §§ 3xx (vgl. [PIN: OETO-VS-3XX]); exakte Absätze folgen nach Finalisierung.
---
## 5. Implementierungshinweise (Backend/Frontend)
- Backend:
- Regel „CSNCNEU → PflichtAbteilungen“ als RegulationasData hinterlegen (z. B. `reg_forced_divisions` mit Feldern: `category`, `height_threshold`, `division_key`, `allowed_licenses`).
- Serverseitige Validierung beim Anlegen/Bearbeiten eines CSNCNEU Bewerbs: genau zwei Abteilungen erzwingen, Labels/AllowedSets prüfen.
- Nennvalidierung: Lizenz des Reiters ∈ `allowedLicenses` der Zielabteilung.
- Frontend:
- Wizard/Editor legt bei CSNCNEU automatisch beide Abteilungen an (konfigurierbare Labels).
- LiveHinweis, wenn eine Abteilung fehlt oder falsche Lizenzen zugeordnet sind.
---
## 6. Einheitliche LabelKonventionen für Abteilungen
Ziel: Einheitliche, i18nfähige Benennung in UI, Exporten und Validierung. Deutsche StandardLabels und technische Keys:
- DivisionLabels (Deutsch):
- OHNE_LIZENZ → „ohne Lizenz“ (Key: `LZF_ONLY`)
- MIT_LIZENZ → „mit Lizenz“ (Key: `R1_PLUS`)
- R1 → „R1“ (Key: `R1_ONLY`)
- R2_UND_HOEHER → „R2 und höher“ (Key: `R2_PLUS`)
Richtlinien:
- Labels in UI exakt wie oben; keine Varianten („R2+“ nur in Klammern/Hinweisen, offizielles Label: „R2 und höher“).
- Keys sind stabil und werden in Datenpersistenz/Exports verwendet. Übersetzungen erfolgen per i18n.
Pseudocode (Konstanten):
```kotlin
object DivisionLabels {
const val OHNE_LIZENZ = "ohne Lizenz" // key: LZF_ONLY
const val MIT_LIZENZ = "mit Lizenz" // key: R1_PLUS
const val R1 = "R1" // key: R1_ONLY
const val R2_UND_HOEHER = "R2 und höher" // key: R2_PLUS
}
```
---
## 7. Erweiterungen: Jugend/Jahrgangsteilungen (optional)
Status: Optionales RegelSet, kein ÖTOPflichtumfang wie bei CSNCNEU. Veranstalter können zusätzlich nach Jahrgängen/Jugendklassen teilen, sofern ÖTOkonform (vgl. Dressur § 103 und disziplinspezifische Jugendbestimmungen).
Modellierung als optionale Regeln:
- Datenmodell (Beispiel als RegulationasData):
- Tabelle `reg_optional_divisions`:
- `category` (z. B. `CSN`, `CDN`)
- `discipline` (SPRINGEN, DRESSUR, VIELSEITIGKEIT)
- `division_key` (z. B. `U16`, `U18`, `U25`, `AMATEURE`)
- `label` (z. B. „Jugend U16“, „Jugend U18“)
- `age_range` (z. B. `14-16` Jahre, berechnet gem. Stichtag 1.1.; vgl. Validierungsregeln § „Altersklassen Pferd/Reiter“)
- `license_filter` (optional, Menge erlaubter Lizenzen)
- `notes` (Freitext/ParagraphenBezug)
Beispiel (Pseudocode):
```kotlin
data class OptionalDivisionRule(
val category: String, // CSN, CDN
val discipline: String, // SPRINGEN, DRESSUR
val divisionKey: String, // U16, U18
val label: String, // "Jugend U16"
val ageFrom: Int, val ageTo: Int?, // inklusiv, To=null = open ended
val allowedLicenses: Set<String>? = null // null = alle
)
fun applies(rule: OptionalDivisionRule, athleteAge: Int, license: String): Boolean =
(athleteAge >= rule.ageFrom) && (rule.ageTo?.let { athleteAge <= it } ?: true) &&
(rule.allowedLicenses?.contains(license) ?: true)
```
UXHinweistexte:
- „Optionale Jugendabteilung aktiv: Nur Athlet:innen des Jahrgangsbereichs {label} werden hier gewertet.“
- „Diese Abteilung ist optional; PflichtZwangsteilung (falls vorhanden) bleibt unberührt.“
---
## 8. Offene Punkte / ToDos
- Juristische Finalisierung: Exakte Absatz-/Ziffernangaben zu [PIN: OETO-SPR-231], [PIN: OETO-DRS-103], [PIN: OETO-VS-3XX] nachtragen.
- BackendSeed: `reg_forced_divisions` und `reg_optional_divisions` befüllen; Keys/Labels gemäß Abschnitt 6 verwenden.
- FE/UX: i18nMapping für DivisionLabels bereitstellen; EditorPresets für CSNCNEU und optionale Jugendabteilungen.