Files
linusandClaude Sonnet 5 03f6fdb0d9 Erstumsetzung: OAMC Turnierauswertung (AP 0–7, 9)
* Datenmodell + Alembic-Initialmigration (Plan §4), Seed Saison 2026
* Wertungs-Engine (Plan §3.3), regelbasiert je Kategorie/Saison
  - Abnahmetest gegen die Ergebnisliste 2026-05-31
* Meisterschaftsberechnung mit Streichresultaten + Tie-Break
  (PLATZHALTER-Punktetabelle, O-1 offen)
* Ingest-API (idempotent, dry_run) inkl. Excel-Leser und Fahrer-Matching/Merge
* Zeitmessungs-Endpoint (Batch, idempotent, unzugeordnet/unplausibel) + SSE-Anzeige
  - Mess-Pi-Client bewusst NICHT enthalten (docs/zeitmessung-endpoint.md)
* Frontend: öffentliche Seiten + internes Backend (Jinja2/HTMX, kein Build)
* Auslieferung: Docker (multi-arch) + docker-compose sowie Debian-Paket/APT-Repo
* 57 Tests grün gegen echte PostgreSQL-Testdatenbank

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 18:49:00 +02:00

45 KiB
Raw Permalink Blame History

Plan: OAMC Turnierauswertung — Webanwendung

Stand: 2026-09-05 · Status: Entwurf, noch nicht freigegeben Änderung 05.09.: Zeitmessung per Lichtschranke aufgenommen (§3.6, §5.4, §6.2, AP 5)


1. Ausgangslage

1.1 Der Verein und die Sportart

Der OAMC Reinheim e.V. im ADAC (Odenwälder Automobil- und Motorsportclub) richtet ADAC Motorrad-Turniere aus. Diese laufen nach der ADAC-Turnierordnung im Bereich des ADAC Hessen-Thüringen (HTH).

Motorrad-Turniersport ist kein Rennsport, sondern ein Geschicklichkeitswettbewerb: Die Fahrer durchfahren einen Parcours mit festen Aufgaben, dabei zählen Fehlerpunkte und Fahrzeit.

Aufgaben im Parcours (laut Sportbeschreibung auf oamc.de):

Fahrzeugabnahme · Schätzen (im Stand und in Fahrt) · Slalom · Acht-Figur · Spurgasse · Kreisel · Tor · Schrägbrett · Wippe (mit und ohne Spurbrett) · Gummiringe · Dose umsetzen · Fahrgasse · Stop Haltelinie · Langsamfahrstrecke

1.2 Aktueller Ist-Zustand der Website

Die bestehende Seite oamc.de (Zweitdomain: oamc-reinheim.de) ist eine statische HTML-4.01-Frameset-Website:

  • Aufbau: indexoben.htm (Navigation) + hauptfenster.htm, jede Rubrik wieder ein eigenes Frameset (m/frame-m.htmm1.htm Menü + m2.htm Inhalt)
  • Rubriken: Verein · VÜP ADAC-Platz · Kartgruppe · Motorradgruppe · Fahrrad JVS · Anfahrt · Download · Weblinks · Flohmarkt · BikerSafetyDay
  • Alle Ergebnisse liegen ausschließlich als PDF unter /datei/ und werden auf d/d-mot-turnier.htm verlinkt — Tagesergebnisse, Meisterschaftsstände (HTH 20022026), Bundesturnier-Ergebnisse, Protokolle
  • Die Seite m/m-fahrer.htm ist eine „BAUSTELLE" — es gibt aktuell keine Fahrerdatenbank. Genau das ist die Lücke, die dieses Projekt schließt.
  • m-ergebnisse.htm und m-ausschreibung.htm verweisen nur auf die PDF-Downloadseite

1.3 Wie heute ausgewertet wird

Die Rahmenausschreibung 2026 nennt als Anforderung an den Veranstalter:

„Auswertungscomputer mit MSOffice (Excel) und Drucker sollte zeitgemäß vorhanden sein."

Es existieren Vorlagen als .xlsx (z. B. MT-NENNLISTE-5-2025.xlsx). Die Auswertung läuft also heute in Excel, das Ergebnis wird als PDF exportiert und manuell auf die Website gelegt. Meisterschaftsstände werden separat fortgeschrieben.

Schmerzpunkte:

Problem Auswirkung
Ergebnisse nur als PDF nicht durchsuchbar, nicht verlinkbar, nicht mobil lesbar
Meisterschaftsstand manuell fehleranfällig, spät verfügbar
Keine Fahrerhistorie „Wie oft war X schon dabei?" nicht beantwortbar
Fahrerstammdaten pro Turnier neu erfasst Tippfehler, Dubletten, Namensvarianten
Frameset-Website kein Deep-Link, schlechtes SEO, unbrauchbar auf dem Handy

2. Ziel

Eine Webanwendung, die

  1. Turnierergebnisse auswertet — Fehlerpunkte + Zeit → Platzierung je Wertungsklasse
  2. Alle Daten in einer Datenbank hält statt in Excel und PDF
  3. Zeiten per API von der Lichtschranken-Zeitmessung entgegennimmt (zweiter Raspberry Pi am Parcours, siehe §3.6), in die Datenbank schreibt und live anzeigt
  4. Fahrer samt Stammdaten und Historie bereitstellt (die heutige „Baustelle")
  5. Die Meisterschafts-/Pokalwertung automatisch fortschreibt

Nicht-Ziele (bewusst außerhalb dieses Projekts)

  • Ablösung der kompletten oamc.de (Kart, Fahrrad, Flohmarkt, VÜP bleiben, wo sie sind)
  • Online-Nennung/Anmeldung durch Teilnehmer → Phase 2, siehe §9
  • Elektronische Erfassung der Fehlerpunkte — die bleiben beim Wertungspersonal im Parcours und werden manuell eingegeben (siehe §3.6)
  • Zahlungsabwicklung des Nenngelds (10 € je Start, wird vor Ort kassiert)

3. Fachliche Grundlagen

⚠️ Die folgenden Regeln wurden aus der Ergebnisliste 2026-05-31-MT-REIN-HAIN.PDF und der MT-Rahmenausschreibung-2026.pdf abgeleitet. Sie sind vor der Implementierung gegen die ADAC-Turnierordnung 2026 (MT-D2025.pdf) und mit dem Bereichsleiter zu verifizieren — siehe §10.

3.1 Veranstaltungsstruktur

  • Ein Renntag kann ein Doppelturnier sein: zwei Turniere zweier Ortsclubs laufen parallel auf einem Platz, z. B. „ADAC-Motorrad-Doppelturnier des MSC Hainstadt und des OAMC Reinheim".
  • Jeder Fahrer wird in beiden Turnieren getrennt gewertet — die Ergebnisliste vom 31.05.2026 enthält für dieselben Fahrer je einen Block „Reinheim" und einen Block „Hainstadt" mit eigenen Zeiten, Fehlern und Platzierungen.
  • ⇒ Datenmodell-Konsequenz: veranstaltung (Renntag) : turnier (Wertungslauf) = 1:n

3.2 Klassen

Jugendklassen (Einteilung strikt nach Jahrgang, Ausweispflicht bei der Nennung):

Klasse Jahrgang ~Alter Fahrzeug
J 1 2019 / 2018 / 2017 79 Kindermotorrad max. 110 ccm / 5,5 kW
J 2 2016 / 2015 1011 Kindermotorrad max. 110 ccm / 5,5 kW
J 3 2014 / 2013 1213 Mofa, Motorrad + Roller max. 125 ccm / 11 kW
J 4 2012 / 2011 1415 Mofa, Motorrad + Roller max. 125 ccm / 11 kW
J 5 2010 / 2009 / 2008 (bis 18. Geburtstag) 1618 Mofa, Motorrad + Roller max. 125 ccm / 11 kW

Für Klasse 1 muss der Teilnehmer am Veranstaltungstag bereits 7 Jahre alt sein. ⇒ Die Jahrgangstabelle ist jahresabhängig und muss versioniert in der DB liegen, nicht im Code (klassen_jahrgang mit saison).

Erwachsenenklassen: S 1S 9 (Stammfahrer) und A 1A 4 (Anfänger), unterteilt nach Fahrzeugtyp/Hubraum. Aus der Sportbeschreibung: Mokicks und Roller bis 80 ccm · bis 250 ccm · bis 650 ccm · über 650 ccm · Enduro (mehrere Hubraumklassen) · Seitenwagen · Pedelec / E-Bike · E-Scooter (neu).

Die genaue Zuordnung S 1S 9 / A 1A 4 → Fahrzeugtyp ist aus den öffentlichen Seiten nicht ersichtlich. Muss erfragt werden (§10).

Wertungsklasse ≠ Klasse: In der Ergebnisliste werden Klassen zu Wertungsklassen zusammengefasst, wenn zu wenige Starter da sind — z. B. eine gemeinsame Wertung „S 5, S 9, S 3, S 6, S 7" und „A 1, A 4". Das Zusammenlegen ist eine Entscheidung pro Turnier und gehört als Datum in die DB, nicht als Regel in den Code.

3.3 Wertungslogik ← Kernstück der Anwendung

Spalten der Ergebnisliste:

Start-Nr. · Voller Name · Regionalclub · Klasse · Geschlecht · Kategorie · Summe Zeit · Summe Fehler · Gesamt · Platzierung

Es gibt zwei verschiedene Berechnungen für Gesamt:

a) Erwachsene (Kategorie S, und A-Fahrer):

Gesamt = Summe Zeit + Summe Fehler
Platzierung = aufsteigend nach Gesamt

Belege aus der Liste vom 31.05.2026, Wertungsklasse „S 5, S 9, S 3, S 6, S 7":

Fahrer Klasse Zeit Fehler Gesamt Platz
Bernius Meik S 6 105,43 0 105,43 1
Schmunk Christian S 9 103,26 10 113,26 2
Krack Robin S 5 130,33 0 130,33 4
Steinbrech Nicolai S 5 65,71 1210 1275,71 11

b) Jugend (Kategorie J):

Gesamt = Summe Fehler          ← die Zeit geht NICHT in die Wertung ein
Platzierung = aufsteigend nach Fehler, bei Gleichstand aufsteigend nach Zeit

Das deckt sich mit der Sportbeschreibung:

„Bei den Turnieren kommt es in der Jugendklasse vorrangig auf die fehlerfreie Durchfahrt an, da die Zeit erst bei Punktgleichheit herangezogen wird."

Belege, Wertungsklasse J 3:

Fahrer Zeit Fehler Gesamt Platz Anmerkung
Freund Philipp 136,88 0 0 1 drei Fahrer mit 0 Fehlern …
D'Angelo Leandro 140,40 0 0 2 … Reihenfolge über die Zeit
Heil Luca 144,46 0 0 3
Mattes Flynn 160,05 10 10 4
Ratter Mitja 148,42 60 60 7 Gleichstand 60 Fehler …
Kemesies Finlay 165,39 60 60 8 … 148,42 < 165,39

⇒ Die Wertungsformel ist pro Kategorie konfigurierbar zu implementieren, nicht hart zu verdrahten (wertungsregel als Strategie/Enum je Kategorie und Saison).

Fehlerpunkte treten in Vielfachen von 10 auf (10/20/30/…/1210). Die Zuordnung „welcher Fehler an welcher Aufgabe kostet wie viele Punkte" steht in der ADAC-Turnierordnung und ist zu beschaffen (§10).

Mehrfachstarts: Ein Fahrer kann am selben Tag mehrfach starten (anderes Fahrzeug, andere Klasse). Beispiel 31.05.2026: Schmunk Christian startet in S 9 und S 3, Bernius Meik in S 6 und S 7 — jeweils mit eigener Startnummer und eigenem Ergebnis. ⇒ Der Schlüssel eines Ergebnisses ist nicht (Turnier, Fahrer), sondern (Turnier, Start), und Nenngeld fällt „für jeden Start" an.

3.4 Meisterschafts-/Pokalwertung (HTH)

  • Erwachsene: ein Gesamtklassement der A- und S-Fahrer/innen (klassenübergreifend)
  • Jugend: Pokalwertung klassenweise J 1 J 5

Streichresultate — nicht alle Läufe zählen:

Turniere in der Saison 12 11 10 9 8 7 6 5 4
davon gewertet 8 8 8 7 6 5 4 3 2

Nicht jede Veranstaltung zählt zur Meisterschaft — der Terminkalender markiert Läufe „mit Meisterschaftswertung" bzw. „o. M. = ohne Meisterschaft".

Endlaufqualifikation: die besten 10 Erwachsenen und 10 Jugendlichen der HTH-Meisterschaft (Jugend ohne Trennung Damen/Herren, Verteilung prozentual nach Teilnehmerzahl der 5 Jugendklassen). Bei Punktgleichheit zählt die Majorität der Siege. Endgültige Festlegung durch den Bereichsleiter ⇒ die Anwendung schlägt vor, sie entscheidet nicht.

Die Punktetabelle (Platz → Meisterschaftspunkte) ist noch nicht bekannt (§10).

3.5 Weitere Regeln aus der Rahmenausschreibung 2026

  • Nenngeld einheitlich 10 € je Start (S, A, Jugend, Mofa/Moped, E-Bike, Pedelec, E-Scooter)
  • Nennschluss: Klasse S + Jugendklassen 14:00 Uhr, A-Klasse + E-Bike/Pedelec/E-Scooter 15:00 Uhr
  • Pokalläufe bei Doppelveranstaltungen beginnen generell 09:00 Uhr
  • Gültiger Jugendausweis + unterschriebener Haftungsausschluss sind bei der Nennung vorzulegen
  • Eine nummerierte Nennungsliste ist zu führen, die Reihenfolge nach Möglichkeit einzuhalten
  • Für A-Klassen-Fahrer und Gelegenheitsfahrer wird z. B. jede 10. Startnummer freigehalten
  • Schlussbericht + Ergebnisliste müssen nach FFM gemeldet werden — der Veranstalter-Zuschuss wird erst überwiesen, wenn beide Dokumente dort sind ⇒ Export in genau diesen Formaten ist kein „nice to have", sondern zahlungsrelevant

3.6 Zeitmessung per Lichtschranke (Vorgabe des Auftraggebers)

Die API wird von einem zweiten Raspberry Pi am Parcours bespielt. Dieser ist an eine Lichtschranke angeschlossen, misst die Fahrzeiten, sendet sie an die Anwendung und zeigt die Daten des aktuellen Fahrzeugs/Starters an.

Damit gibt es zwei Datenquellen pro Ergebnis:

Wert Quelle Weg
Summe Zeit Lichtschranke (Messgerät) automatisch per API
Summe Fehler Wertungspersonal im Parcours manuell im internen Frontend

Ein Ergebnis ist also erst vollständig, wenn beide Seiten geliefert haben. Das Datenmodell muss einen Start mit Zeit, aber ohne Fehlerpunkte (und umgekehrt) sauber abbilden können — ein „halbes" Ergebnis ist der Normalzustand während der Veranstaltung, kein Fehler.

Konsequenzen für den Entwurf

a) Rohmessungen statt Summen speichern. Die Spalte heißt in der Ergebnisliste Summe Zeit — die Zeit ist also vermutlich eine Summe mehrerer Messungen (mehrere Durchgänge oder mehrere gemessene Abschnitte, z. B. Langsamfahrstrecke und Gesamtdurchfahrt). Die Anwendung speichert deshalb jede Einzelmessung (zeitmessung) und bildet die Summe selbst. Rückweg gibt es nicht: aus einer gespeicherten Summe lassen sich Einzelmessungen nie wieder herstellen, aus Einzelmessungen die Summe jederzeit. → offene Frage O-13

b) Das Messgerät ist ein eigenständiger API-Client, kein Teil der Anwendung. Es bekommt einen Geräte-Token (nicht den Auswerter-Login), darf nur Messungen schreiben und Starter-Daten lesen, und wird in der DB als geraet geführt. Ein Gerät am offenen Platz muss man notfalls einzeln sperren können.

c) Netzausfall ist der Normalfall, nicht die Ausnahme. Am ADAC-Platz kann das Netz wegbrechen. Der Mess-Pi muss lokal puffern (SQLite oder Datei-Queue) und nach Wiederverbindung nachliefern. Deshalb gilt zwingend:

  • jede Messung bekommt eine UUID vom Messgerät → Server ist idempotent, doppelt gesendete Messungen erzeugen keine Dubletten
  • die Messung trägt zwei Zeitstempel: Wanduhr (gemessen_am) und monotone Gerätezeit (monotonic_ns). Die Wanduhr eines Pi ohne Netz und ohne RTC springt beim NTP-Sync — die Dauer zwischen zwei Lichtschranken-Ereignissen darf davon nicht abhängen. Der Pi berechnet die Dauer selbst und sendet sie, der Server rechnet keine Differenz aus zwei Wanduhr-Zeitstempeln.
  • der Server nimmt Messungen rückwirkend an (gemessen_am in der Vergangenheit) und markiert sie als nachgeliefert

d) Zuordnung Messung → Starter ist der kritische Punkt. Eine Lichtschranke misst eine Zeit, sie weiß nicht, wer durchgefahren ist. Die Zuordnung muss irgendwo herkommen — Eingabe der Startnummer am Mess-Pi, eine Warteschlange „nächster Starter" aus der Nennliste, oder ein Transponder/RFID. → offene Frage O-14. Bis zur Klärung wird konservativ geplant:

  • der Mess-Pi holt sich per API die Startreihenfolge des laufenden Turniers
  • er sendet die Messung mit der Startnummer, die er gerade anzeigt
  • eine Messung ohne zuordenbare Startnummer wird nicht verworfen, sondern als zeitmessung ohne start_id gespeichert und im Frontend zur manuellen Zuordnung angeboten. Eine gemessene Zeit ist nicht reproduzierbar — sie darf nie verloren gehen, nur weil die Zuordnung fehlte.

e) Fehlmessungen sind Betriebsrealität. Zuschauer, Helfer oder ein zurücksetzendes Motorrad lösen die Lichtschranke aus. Nötig sind: Entprellung/Mindestabstand zwischen zwei Triggern auf dem Pi, ein Verwerfen-Knopf in der Erfassung, sowie Plausibilitätsprüfung serverseitig (eine Fahrzeit von 3 s oder 900 s ist zu markieren, nicht stillschweigend zu übernehmen). Jede verworfene Messung bleibt mit Grund gespeichert.

f) Die Anzeige am Parcours ist ein eigener Anwendungsfall. Der Mess-Pi zeigt Starter- und Fahrzeugdaten an, zieht sie also lesend aus der API. Das braucht einen schlanken, schnellen Endpunkt und eine Live-Aktualisierung (SSE), und er muss auch bei Netzausfall die zuletzt geladene Startliste weiter anzeigen.

Was genau angezeigt werden soll (Startnummer, Name, Klasse, Fahrzeug, laufende Zeit, letzte Zeit?) und auf welcher Hardware (HDMI-Monitor, kleines Display, LED-Tafel) ist noch offen → O-15.


4. Datenmodell

verein ──┐
         ├──< fahrer ──< start >── turnier >── veranstaltung
saison ──┤              │  │          │
         ├──< klasse ───┘  │          └──< wertungsklasse
         │                 ├──< ergebnis        (Zeit + Fehler, berechnet)
         │                 └──< zeitmessung >── geraet   (Lichtschranke)
         └──< meisterschaft ──< meisterschaft_stand

Tabellen

verein — Regionalclub / Ortsclub id · name („OAMC Reinheim", „MSC Schotten", „PMS Kassel", „Hainstadt") · kurzname · adac_gau · aktiv

fahrer — Stammdaten, einmalig, nicht pro Turnier id · nachname · vorname · geburtsjahr · geburtsdatum (nullable, für J1-Prüfung „am Veranstaltungstag 7 Jahre") · geschlecht (M/W/D) · verein_id · adac_mitgliedsnr (nullable) · jugendausweis_gueltig_bis · aktiv · notiz · erstellt_am / geaendert_amDublettenerkennung beim Import nötig, siehe §6.3

saison — Jahr, macht Regeln versionierbar jahr (PK) · turnierordnung_version · streichresultate_tabelle (JSONB) · nenngeld_cent · aktiv

klasse — Klassendefinition pro Saison id · saison_jahr · code („J 1", „S 6", „A 4") · kategorie (J/S/A) · bezeichnung · jahrgaenge (int[], nur Jugend) · ccm_max · kw_max · fahrzeugtyp · sortierung

veranstaltung — der Renntag id · datum · titel · ort · ausrichter_verein_id · ist_doppelturnier · veranstaltungsleiter · turnierleiter · status (geplant/laufend/vorlaeufig/final)

turnier — der einzelne Wertungslauf (bei Doppelturnier zwei pro Veranstaltung) id · veranstaltung_id · name („Reinheim" / „Hainstadt") · veranstalter_verein_id · zaehlt_meisterschaft (bool) · status

wertungsklasse — pro Turnier zusammengefasste Klassen id · turnier_id · bezeichnung („S 5, S 9, S 3, S 6, S 7") · klasse_ids (int[]) · sortierung

start — eine Teilnahme; ein Fahrer kann mehrere pro Turnier haben id · turnier_id · fahrer_id · klasse_id · wertungsklasse_id · startnummer · fahrzeug (Text) · nenngeld_bezahlt · status (genannt/gestartet/DNF/DNS/DSQ) → UNIQUE (turnier_id, startnummer)

ergebnis — 1:1 zum Start, getrennt für saubere Nachträge/Korrekturen start_id (PK) · summe_zeit (numeric(7,2), aus zeitmessung summiert) · summe_fehler (int, manuell erfasst) · gesamt (numeric(9,2), berechnet) · platzierung (int, berechnet) · zeit_vollstaendig (bool) · fehler_vollstaendig (bool) · erfasst_von · erfasst_am · korrigiert_am · korrektur_grund → Die beiden *_vollstaendig-Flags machen sichtbar, welche der zwei Quellen (§3.6) noch fehlt. Gewertet wird erst, wenn beide gesetzt sind.

geraet — Messgerät / Anzeige am Parcours id · bezeichnung („Lichtschranke Ziel", „Anzeige Start") · typ (lichtschranke/anzeige) · token_hash · aktiv · letzte_meldung_am · firmware_version · notizletzte_meldung_am ist der Heartbeat: das Frontend zeigt, ob die Messung noch lebt

zeitmessung — Einzelmessung, nicht die Summe id (UUID, vom Gerät vergeben → Idempotenz) · geraet_id · turnier_id · start_id (nullable — unzugeordnete Messungen gehen nicht verloren) · startnummer_gemeldet (int, was das Gerät angezeigt hat) · messpunkt (z. B. „Durchgang 1", „Langsamfahrstrecke") · dauer_sekunden (numeric(7,2), vom Gerät berechnet) · gemessen_am (timestamptz, Wanduhr) · monotonic_ns (bigint) · empfangen_am · nachgeliefert (bool) · status (gueltig/verworfen/unzugeordnet) · verworfen_grund · roh (JSONB, Rohereignisse der Lichtschranke) → UNIQUE (id); Index auf (turnier_id, status), (start_id)

aufgabe / ergebnis_aufgabeoptional, Phase 2: Einzelwertung je Parcours-Aufgabe (Slalom, Wippe, Kreisel …). Die heutigen PDFs enthalten nur Summen; die Struktur vorzusehen kostet jetzt nichts und erlaubt später Detailauswertungen. Sobald die Lichtschranke mehrere Messpunkte bedient, wächst zeitmessung.messpunkt natürlich in diese Struktur hinein.

meisterschaft — z. B. „HTH Erwachsene 2026", „HTH Jugend J 3 2026" id · saison_jahr · bezeichnung · kategorie · klasse_id (nullable) · regelwerk (JSONB)

meisterschaft_stand — materialisiert, nach jedem Turnier neu berechnet meisterschaft_id · fahrer_id · punkte_gesamt · punkte_je_lauf (JSONB) · gestrichene_laeufe (JSONB) · anzahl_siege (Tie-Break!) · platz · berechnet_am

import_job — Audit-Trail jedes API-/Datei-Imports id · quelle · dateiname · roh_payload (JSONB) · status · fehler · angelegt_von · angelegt_am

benutzer / rolle — Admin, Auswerter, Lesend

Kernprinzipien

  • gesamt und platzierung werden von der Anwendung berechnet, nicht importiert — importierte Werte werden gegen die Berechnung geprüft und Abweichungen gemeldet (fängt Excel-Fehler in Altdaten und Regelmissverständnisse auf beiden Seiten)
  • Alles saisonversioniert: Klassen, Jahrgänge, Streichresultate, Punktetabelle. Ergebnisse aus 2019 müssen 2030 noch korrekt reproduzierbar sein.
  • Ergebnisse sind append-only mit Korrektur-Historie, kein stilles UPDATE

5. Architektur & Technologie

5.1 Vorhandene Umgebung (geprüft auf diesem Gerät)

Hardware Raspberry Pi 4 Model B Rev 1.5, 8 GB RAM, 117 GB Speicher (94 GB frei)
OS Debian 13 (trixie), Linux 6.18 aarch64
PostgreSQL 17.10 installiert und aktiv
nginx installiert und aktiv
Python 3.13.5 + pip 25.1.1
Node.js / npm nicht installiert
Docker nicht installiert
git nicht installiert — vor Projektstart nachinstallieren

5.2 Empfohlener Stack

Der Stack folgt dem, was schon läuft — auf einem Pi 4 zählt jedes vermiedene Laufzeit-Ökosystem.

Schicht Wahl Begründung
Datenbank PostgreSQL 17 läuft bereits; JSONB für Regelwerke, saubere Constraints, echte Transaktionen
Backend Python 3.13 + FastAPI Python ist da; FastAPI liefert die API-Doku (OpenAPI/Swagger) automatisch mit — wichtig, weil Dritte die API bespielen sollen
ORM / Migration SQLAlchemy 2 + Alembic Schemaänderungen über Jahre nachvollziehbar
Validierung Pydantic v2 ein Schema für API-Validierung und Doku
Templates Jinja2, serverseitig gerendert Ergebnislisten sind Dokumente, keine App. Kein Build-Schritt, kein Node, sofort suchmaschinenlesbar
Interaktivität HTMX (~14 kB, per CDN oder lokal) Filter/Sortierung/Live-Nachladen ohne SPA-Apparat
Live-Updates SSE (Server-Sent Events), von FastAPI direkt unterstützt Anzeige am Parcours und Live-Ergebnisse; einseitiger Datenfluss, kein WebSocket-Zustand nötig, reconnectet von selbst
CSS handgeschrieben oder Pico.css keine Build-Pipeline
Excel/CSV-Import openpyxl + csv die Nennlisten sind .xlsx
PDF-Export WeasyPrint Schlussbericht + Ergebnisliste müssen nach FFM
Server uvicorn hinter dem vorhandenen nginx nginx macht TLS und liefert Statisches
Prozess systemd-Unit kein Docker nötig
TLS Let's Encrypt / certbot

Bewusst nicht gewählt: React/Vue-SPA (Build-Kette auf dem Pi, kein SEO, viel Aufwand für Tabellenanzeige) · Docker (Overhead ohne Nutzen bei einer App) · SQLite (Mehrbenutzerbetrieb am Turniertag, Postgres ist schon da)

5.3 Betrieb

        ╔═══ Am Parcours ═══════════════╗
        ║  Pi #2 „Mess-Pi"              ║
        ║   Lichtschranke → GPIO        ║
        ║   lokale Queue (SQLite)       ║──┐  POST Messungen (idempotent, gepuffert)
        ║   Anzeige Starter/Fahrzeug    ║<─┼─  GET Startliste + SSE Live
        ╚═══════════════════════════════╝  │
                                           │
  Internet / LAN ──> nginx (TLS, statisch) ┘
                       └→ uvicorn/FastAPI (systemd) → PostgreSQL 17 (lokal)
                                                    → /var/oamc/uploads (PDFs, Bilder)
  • Backup: täglicher pg_dump + wöchentliche Vollsicherung auf externes Medium. Auf einer SD-Karte/SSD im Pi ist das nicht optional.
  • Offline-Fähigkeit am Turniertag ist durch die Zeitmessung Pflicht geworden, nicht mehr optional (§3.6c). Zwei Ebenen:
    1. der Mess-Pi puffert lokal und liefert nach — deckt kurze Aussetzer ab
    2. bei Veranstaltungen ohne Internet muss der Anwendungs-Pi mit vor Ort und beide Geräte hängen an einem lokalen Netz (Router/Hotspot ohne Uplink). Die Synchronisation zum öffentlichen Server erfolgt danach. ⇒ Entscheidung dazu offen, siehe O-7.
  • Zeitserver: ohne Internet gibt es kein NTP. Der Anwendungs-Pi sollte im lokalen Netz selbst NTP anbieten, damit die Zeitstempel zusammenpassen. Für die Messung ist das unkritisch (der Mess-Pi rechnet monoton, §3.6c), für die Protokollierung nicht.

5.4 Software auf dem Mess-Pi

Bewusst klein und eigenständig — das Gerät muss auch dann sinnvoll weiterlaufen, wenn der Server nicht erreichbar ist.

Teil Wahl
GPIO / Lichtschranke gpiozero mit pigpio- oder lgpio-Backend; Trigger als Interrupt, nicht Polling
Zeitmessung time.monotonic_ns(), Entprellung/Mindestabstand konfigurierbar
Lokale Queue SQLite, Einträge bleiben bis vom Server quittiert
Versand HTTP + Geräte-Token, Retry mit Backoff, Batch-Nachlieferung
Anzeige Browser im Kiosk-Modus auf die Anzeige-Seite der Anwendung (§7), Daten per SSE, letzte Startliste im localStorage als Offline-Rückfall
Betrieb systemd-Unit, WatchdogSec, Autostart, read-only Root-FS erwägen (Stromausfall am Platz)

Für saubere Zeiten unter Last ist ein Interrupt-basierter Trigger Pflicht. Ob die Genauigkeit eines Linux-Userspace-Prozesses reicht, hängt von der geforderten Auflösung ab → O-16. Die Ergebnislisten führen 1/100 s (z. B. 159,16); das ist mit pigpio gut erreichbar, mit Polling in Python nicht zuverlässig.


6. API

Zwei Richtungen: Ingest (Daten kommen rein) und Read (Daten gehen raus).

6.1 Ingest — POST /api/v1/… (authentifiziert, API-Key)

Endpunkt Zweck
POST /api/v1/veranstaltungen Renntag anlegen
POST /api/v1/turniere Wertungslauf zum Renntag
POST /api/v1/fahrer · PUT /api/v1/fahrer/{id} Stammdaten
POST /api/v1/turniere/{id}/starts Nennliste (Bulk)
POST /api/v1/turniere/{id}/ergebnisse Ergebnis-Bulk-Upload ← Kernfall
POST /api/v1/import/xlsx Excel-Nennliste/Ergebnisliste als Datei
POST /api/v1/turniere/{id}/finalisieren Wertung rechnen, Meisterschaft fortschreiben

Beispiel-Payload Ergebnis-Upload:

{
  "quelle": "excel-auswertung-v3",
  "idempotenz_schluessel": "2026-05-31-reinheim-final",
  "ergebnisse": [
    { "startnummer": 32, "fahrer": { "nachname": "Gál-Szász", "vorname": "Péter",
      "geburtsjahr": 2015, "geschlecht": "M", "verein": "OAMC Reinheim" },
      "klasse": "J 2", "summe_zeit": 159.16, "summe_fehler": 10,
      "gesamt_erwartet": 10, "platzierung_erwartet": 1 }
  ]
}

Regeln für den Ingest:

  • Idempotent über idempotenz_schluessel — ein doppelt gesendeter Upload legt keine Dubletten an. Am Turniertag mit wackligem Netz ist das Pflicht, nicht Komfort.
  • Zweistufig: ?dry_run=true liefert eine Validierungsvorschau (welche Fahrer sind neu, welche werden gematcht, welche Werte weichen ab) — erst danach wird geschrieben.
  • gesamt_erwartet / platzierung_erwartet sind optional; wenn geliefert, rechnet der Server nach und meldet Abweichungen als Warnung, statt sie zu übernehmen.
  • Jeder Aufruf landet in import_job mit Roh-Payload — bei Streit über eine Platzierung ist rekonstruierbar, was wann ankam.

6.2 Geräte-API — Zeitmessung & Anzeige (Mess-Pi, Token-Auth)

Eigener Namensraum mit eigenem Rechteprofil: schreiben nur Messungen, lesen nur das, was die Anzeige braucht. Kompromittierung des Geräts am offenen Platz darf keine Ergebnisse manipulieren können.

Endpunkt Zweck
POST /api/v1/geraete/heartbeat „ich lebe" + Firmware/Queue-Länge → Statusanzeige im Frontend
GET /api/v1/geraete/konfiguration Entprellzeit, Messpunkte, aktives Turnier — zentral gepflegt statt auf dem Pi
GET /api/v1/turniere/aktiv/startliste Startreihenfolge für die Anzeige, ETag-fähig, offlinefest zwischenspeicherbar
GET /api/v1/turniere/aktiv/anzeige (SSE) Live-Stream: aktueller Starter, letzte Zeit
POST /api/v1/zeitmessungen Messungen (Batch, idempotent) ← Kernfall
POST /api/v1/zeitmessungen/{id}/verwerfen Fehlmessung markieren

Beispiel-Payload der Zeitmessung — bewusst als Batch, weil der Pi nach einem Netzausfall mehrere Messungen auf einmal nachliefert:

{
  "geraet": "lichtschranke-ziel-01",
  "messungen": [
    {
      "id": "9f2c1e7a-4d38-4b6e-9a11-5c0b2d7e8f30",
      "turnier_id": 42,
      "startnummer_gemeldet": 32,
      "messpunkt": "durchgang-1",
      "dauer_sekunden": 159.16,
      "gemessen_am": "2026-05-31T10:14:02.482+02:00",
      "monotonic_ns": 884213771004,
      "roh": { "trigger_start_ns": 884054611004, "trigger_ziel_ns": 884213771004 }
    }
  ]
}

Antwort quittiert jede Messung einzeln (angenommen / duplikat / unzugeordnet / unplausibel) — erst eine Quittung löscht den Eintrag aus der lokalen Queue des Pi.

Festlegungen:

  • Die id vergibt das Gerät (UUIDv4/v7). Nur so ist Nachliefern nach Timeout ohne Dubletten möglich — der Pi weiß nach einem abgebrochenen Request nicht, ob der Server ihn verarbeitet hat, und darf ihn deshalb gefahrlos wiederholen.
  • Die Dauer kommt fertig vom Gerät, der Server rechnet keine Differenz aus Wanduhr- Zeitstempeln (Begründung §3.6c).
  • startnummer_gemeldet ist ein Hinweis, kein Fremdschlüssel. Der Server löst sie gegen die Startliste auf; scheitert das, wird die Messung als unzugeordnet gespeichert und im Frontend zur Zuordnung angeboten — nie verworfen.
  • Plausibilitätsgrenzen (min/max Fahrzeit je Klasse) sind konfigurierbar; Verstöße werden markiert, nicht abgelehnt.
  • Der Geräte-Token ist nicht der Auswerter-Login und einzeln sperrbar.

6.3 Read — GET /api/v1/… (öffentlich, ohne Key)

GET /api/v1/veranstaltungen?saison=2026
GET /api/v1/turniere/{id}/ergebnisse?wertungsklasse=J3
GET /api/v1/fahrer?q=bernius&verein=OAMC+Reinheim
GET /api/v1/fahrer/{id}/historie
GET /api/v1/meisterschaften/{id}/stand
GET /api/v1/meisterschaften/{id}/endlauf-qualifikation

Zusätzlich iCal (/termine.ics) für den Terminkalender und CSV-Export je Liste.

6.4 Fahrer-Matching beim Import

Der heikelste Teil des Imports. Aus den Altdaten sichtbar: Namen mit Sonderzeichen (Gál-Szász), Vereinsangaben mal als „OAMC Reinheim", mal als „Hainstadt" (Ortsname statt Clubname), Namensgleichheiten in Familien (Gál-Szász Péter / Máté / János; Bernius Meik / Jörg; Krack Robin / Luca; Tinz Xenia / Enrique).

Vorgehen:

  1. Exakter Match auf (Nachname, Vorname, Geburtsjahr) — normalisiert (Unicode NFKD, Kleinschreibung, Bindestriche)
  2. Unscharfer Match (Levenshtein / pg_trgm) → Vorschlag, nie automatisch
  3. Kein Match → neuer Fahrer wird angelegt, aber im Import-Report als „NEU" markiert
  4. Merge-Funktion im Admin, um nachträglich erkannte Dubletten zusammenzuführen

7. Seiten (Frontend)

Öffentlich:

Seite Inhalt
Startseite Motorrad-Turnier nächster Termin, letzte Ergebnisse, aktueller Meisterschaftsstand
Termine Saisonkalender, mit/ohne Meisterschaftswertung, Ausrichter, iCal-Abo
Ergebnisse je Veranstaltung → Turnier → Wertungsklasse, sortierbar, mobil lesbar
Live (Turniertag) vorläufiger Stand, sobald Zeiten eintreffen — deutlich als vorläufig gekennzeichnet, solange Fehlerpunkte fehlen (§3.6)
Fahrer durchsuchbare Liste (löst die „BAUSTELLE" ab)
Fahrerprofil Stammdaten, alle Starts, Platzierungen, Bestzeiten, Saisonverlauf
Meisterschaft HTH-Stand Erwachsene + Jugend J 1J 5, inkl. Streichresultat-Kennzeichnung
Endlauf-Qualifikation aktueller Stand der Top-10-Plätze
Sportbeschreibung / Ausschreibung / Downloads bestehende Inhalte, sauber übernommen

Intern (Login):

Seite Inhalt
Nennungsannahme Fahrer suchen/anlegen, Klasse automatisch aus Jahrgang vorschlagen, Startnummer vergeben, Nenngeld quittieren
Ergebniserfassung schnelle Eingabe Zeit/Fehler je Startnummer, tastaturoptimiert
Auswertung Wertungsklassen bilden, rechnen, vorläufig/final setzen
Korrekturen mit Begründung, mit Historie
Exporte Ergebnisliste (PDF, ADAC-Layout), Schlussbericht, Nennliste, CSV
Messungen zuordnen unzugeordnete/unplausible Lichtschranken-Messungen einem Start zuweisen oder mit Grund verwerfen
Geräte Mess-Pi-Status (Heartbeat, Queue-Länge), Token vergeben/sperren, Entprellzeit und Messpunkte konfigurieren
Import-Monitor Import-Jobs, Warnungen, Fahrer-Dubletten mergen
Stammdaten Saison, Klassen, Vereine, Punktetabelle, Benutzer

Anzeige am Parcours (eigener, minimaler Modus für den Mess-Pi):

Seite Inhalt
/anzeige aktueller Starter groß (Nr., Name, Klasse, Fahrzeug), laufende/letzte Zeit, nächste Starter; SSE-Update; Kiosk-tauglich; behält bei Verbindungsverlust die letzte Startliste und zeigt den Offline-Zustand deutlich an

Anforderungen quer: responsiv (am Platz wird das Handy benutzt) · Deep-Links auf jede Ergebnisliste · druckbare Ansichten · Aushang-/Beamer-Modus (große Schrift, Autorefresh) · barrierearm (Kontrast, Tabellen-Semantik)


8. Arbeitspakete

AP 0 — Klärung & Setup (vor allem anderen)

  • Offene Fragen §10 mit dem Verein / Bereichsleiter klären
  • ADAC-Turnierordnung 2026 (MT-D2025.pdf) beschaffen und Wertungsregeln verifizieren
  • Punktetabelle Meisterschaft beschaffen
  • git installieren, Repository anlegen, Python-venv, Projektgerüst
  • Zugriff auf die Excel-Vorlagen und ein paar echte Nennlisten

AP 1 — Datenmodell & Migrationen

  • SQLAlchemy-Modelle + Alembic-Initialmigration
  • Stammdaten-Seed: Saison 2026, Klassen J 1J 5, S/A-Klassen, Vereine
  • Unit-Tests auf Constraints (Mehrfachstart erlaubt, Startnummer eindeutig je Turnier)

AP 2 — Wertungs-Engine (der Kern — zuerst und mit Tests)

  • Regelstrategien je Kategorie (Jugend: Fehler → Zeit; Erwachsene: Zeit + Fehler)
  • Platzierung inkl. Gleichstandsauflösung, DNF/DNS/DSQ-Behandlung
  • Regressionstest gegen die reale Ergebnisliste vom 31.05.2026 — alle 13 Wertungs- blöcke müssen exakt die publizierten Platzierungen reproduzieren. Das ist der Abnahmetest für die Engine.

AP 3 — Meisterschaftsberechnung

  • Punktevergabe, Streichresultate nach Tabelle §3.4
  • Tie-Break „Majorität der Siege"
  • Endlauf-Qualifikationsvorschlag Top 10 / Top 10 Jugend
  • Nachrechnen gegen einen veröffentlichten HTH-Jahresstand als Test

AP 4 — API

  • Read-Endpunkte + OpenAPI-Doku
  • Ingest-Endpunkte, Idempotenz, dry_run, API-Key-Auth, Rate-Limit
  • Import-Job-Protokollierung
  • Fahrer-Matching inkl. Merge

AP 5 — Zeitmessung: Geräte-API & Mess-Pi

  • Geräte-Registrierung, Token, Heartbeat, zentrale Konfiguration
  • POST /zeitmessungen mit Batch, Idempotenz, Einzelquittung, Plausibilitätsprüfung
  • Auflösung startnummer_gemeldet → Start; unzugeordnete Messungen im Frontend behandeln
  • Client auf dem Mess-Pi: GPIO-Trigger, Entprellung, monotone Zeitmessung, lokale SQLite-Queue, Retry mit Backoff, Kiosk-Anzeige mit Offline-Rückfall
  • SSE-Endpunkt und /anzeige-Seite
  • Abnahmetest: Netzstecker während der Messung ziehen — nach Wiederverbindung müssen alle Messungen genau einmal in der DB stehen. Ebenso: Batch doppelt senden → keine Dubletten.
  • Kalibrierung: gemessene Zeiten gegen eine Handstoppung/Referenz vergleichen, bevor produktiv damit gewertet wird

AP 6 — Öffentliches Frontend

  • Layout, Navigation, responsive Tabellen
  • Termine, Ergebnisse, Fahrerliste, Fahrerprofil, Meisterschaft
  • iCal, CSV, Druckansichten

AP 7 — Internes Frontend

  • Login/Rollen, Nennungsannahme, Ergebniserfassung, Auswertung, Korrekturen
  • Exporte (PDF-Ergebnisliste im ADAC-Layout, Schlussbericht)

AP 8 — Datenübernahme Altbestand

  • Import der PDF-Ergebnisse ab einem zu definierenden Jahr (⚠️ die PDFs nutzen Subset-Fonts mit eigener Kodierung — reine Textextraktion schlägt bei den Meisterschafts-PDFs fehl; realistisch ist ein halbautomatischer Import mit manueller Nacharbeit, ggf. direkt aus den Excel-Originalen statt aus den PDFs)
  • Vereinheitlichung Vereinsnamen, Dublettenbereinigung Fahrer

AP 9 — Deployment & Betrieb

  • systemd-Unit, nginx-vHost, TLS
  • Backup-Automatik + getesteter Restore
  • Monitoring, Logrotation
  • Einweisung der Auswerter, Kurzanleitung

AP 10 — Pilotbetrieb

  • Eine Veranstaltung parallel zu Excel auswerten und Ergebnisse vergleichen
  • Zeitmessung zunächst nur mitlaufen lassen, nicht werten: Lichtschranken-Zeit gegen die manuell gestoppte Zeit stellen. Erst wenn beide über eine ganze Veranstaltung übereinstimmen, wird die Messung wertungsrelevant.
  • Erst nach fehlerfreiem Parallellauf umstellen

9. Ausbaustufen nach dem Kern

  • Online-Voranmeldung — die Rahmenausschreibung wünscht ausdrücklich Voranmeldung größerer Teilnehmergruppen und eine Anmeldeliste; das ist die naheliegendste Erweiterung
  • Aufgaben-Einzelwertung (Tabellen aus §4 bereits vorgesehen) → „woran verliere ich Zeit?"
  • Bildarchiv mit Verknüpfung Foto ↔ Fahrer ↔ Veranstaltung
  • Automatische Meldung von Schlussbericht/Ergebnisliste an den ADAC
  • Mehrmandantenfähigkeit für andere Ortsclubs (MSC Schotten, MSC Hainstadt, PMS Kassel …)
  • Übernahme der übrigen oamc.de-Rubriken aus dem Frameset

10. Offene Fragen

# Frage Warum blockierend
O-1 Punktetabelle der Meisterschaft (Platz → Punkte) AP 3 nicht baubar
O-2 Zuordnung S 1S 9 und A 1A 4 → Fahrzeugtyp/Hubraum/kW Stammdaten-Seed
O-3 Zählen A-Fahrer zur Meisterschaft? Die Rahmenausschreibung sagt „Gesamtklassement der A- und S-Fahrer/innen", die Spalte Kategorie ist bei A-Fahrern in der Ergebnisliste jedoch leer (bei S steht „S", bei Jugend „J") AP 3
O-4 Gilt die Jugend-Wertung (nur Fehler) auch beim Bundesendlauf, oder dort Zeit+Fehler? AP 2
O-5 Behandlung von DNF / DNS / Disqualifikation in Tages- und Jahreswertung AP 2/3
O-6 Wer soll die API bespielen?beantwortet: ein zweiter Raspberry Pi an der Lichtschranke, der Zeiten sendet und Starter-/Fahrzeugdaten anzeigt (§3.6) erledigt
O-7 Ist am ADAC-Platz ein verlässliches Netz? Wenn nein: muss der Anwendungs-Pi mit vor Ort? WLAN, LTE oder Kabel zwischen Mess-Pi und Server? hoch — bestimmt die gesamte Betriebsarchitektur (§5.3)
O-8 Ab welchem Jahr sollen Altdaten übernommen werden (PDFs reichen bis 2002 zurück)? Aufwand AP 8
O-9 Wo wird gehostet — dieser Raspberry Pi, ein Server beim Verein, Webhosting? AP 9, Erreichbarkeit
O-10 Verhältnis zur bestehenden oamc.de: Unterseite, Subdomain (z. B. mt.oamc.de) oder Ablösung? Navigation, DNS
O-11 Wer bekommt Schreibrechte, wie viele Auswerter, gemeinsamer Account oder je Person? AP 7
O-12 Liegen die Excel-Originale der Altveranstaltungen noch vor? macht AP 8 um ein Vielfaches einfacher

Neue Fragen zur Zeitmessung

# Frage Warum blockierend
O-13 Was misst die Lichtschranke genau? Eine Gesamtdurchfahrt, mehrere Durchgänge oder einzelne Abschnitte (Langsamfahrstrecke …)? Woraus setzt sich Summe Zeit zusammen? bestimmt zeitmessung.messpunkt und die Summenbildung; AP 5
O-14 Woher weiß der Mess-Pi, wer gerade fährt? Startnummer manuell eintippen, Warteschlange „nächster Starter" aus der Nennliste, Transponder/RFID? kritischster Punkt der Zuordnung; AP 5
O-15 Was genau soll die Anzeige zeigen und auf welcher Hardware (HDMI-Monitor, kleines Display, LED-Tafel)? Für wen — Fahrer, Publikum, Wertungspersonal? Gestaltung /anzeige; AP 5
O-16 Geforderte Messgenauigkeit? Die Listen führen 1/100 s. Reicht Userspace-GPIO oder braucht es dedizierte Hardware? Ein oder zwei Lichtschranken (Start und Ziel)? Hardware-Auswahl, AP 5
O-17 Wie kommen die Fehlerpunkte in die Anwendung — Zettel vom Wertungspersonal und zentrale Eingabe, oder Tablets im Parcours? AP 7; Phase 2 könnte hier ansetzen
O-18 Löst die Lichtschranke automatisch aus (Fahrzeug unterbricht Strahl) oder gibt es zusätzlich einen manuellen Start-/Stopp-Taster als Rückfall? Ausfallkonzept, AP 5
O-19 Wer baut/betreut die Hardware (Lichtschranke, Verkabelung, Stromversorgung am Platz)? Existiert sie schon oder wird sie beschafft? Terminplanung

11. Datenschutz

Das ist hier kein Formalpunkt. Es werden Namen, Geburtsjahre, Geschlecht und Vereinszugehörigkeit von Kindern ab 7 Jahren verarbeitet und öffentlich im Internet angezeigt. Die heutige Praxis (Namen in öffentlichen PDFs) wird durch eine durchsuchbare Datenbank mit Personenprofilen qualitativ verändert — aus einer schwer auffindbaren PDF-Liste wird ein über Jahre verknüpftes Profil eines Minderjährigen. Das ist datenschutzrechtlich eine andere Kategorie und muss vor dem Livegang geklärt sein.

Zu klären und umzusetzen:

  • Rechtsgrundlage je Verarbeitung; Einwilligung der Erziehungsberechtigten für die Veröffentlichung von Jugenddaten (idealerweise in Nennformular/Haftungsausschluss aufnehmen — die Formulare werden ohnehin unterschrieben)
  • Datenminimierung öffentlich: Geburtsjahr statt Geburtsdatum, kein Wohnort, keine Kontaktdaten, keine ADAC-Mitgliedsnummer
  • robots.txt / noindex für Fahrerprofile — Ergebnislisten dürfen auffindbar sein, Personenprofile von Minderjährigen sollten es nicht sein
  • Opt-out: Anzeige als „Teilnehmer 12" oder Namenskürzel auf Wunsch
  • Löschkonzept / Aufbewahrungsfristen, Auskunfts- und Berichtigungsrecht
  • Verzeichnis von Verarbeitungstätigkeiten, TOMs (Backup-Verschlüsselung, TLS, Zugriffsrollen, Protokollierung)
  • Ggf. Auftragsverarbeitung mit dem Hoster

Empfehlung: Vor AP 6 (öffentliches Frontend) eine Entscheidung des Vorstands herbeiführen, wie Jugenddaten öffentlich dargestellt werden. Die technische Umsetzung ist einfach — die Entscheidung ist es nicht, und sie nachträglich zu ändern bedeutet, bereits indexierte Seiten wieder einzufangen.


12. Risiken

Risiko Auswirkung Gegenmaßnahme
Wertungsregeln in §3.3 sind aus PDFs abgeleitet, nicht bestätigt falsche Platzierungen, Vertrauensverlust AP 0: Turnierordnung beschaffen; AP 2: Regressionstest gegen echte Listen; AP 10: Parallellauf
Ausfall am Turniertag (Pi, Netz, Strom) Veranstaltung blockiert Excel-Fallback bereithalten, bis der Parallellauf sauber ist; Export vor Ort möglich halten
Lichtschranke fällt aus oder misst falsch Zeiten des laufenden Turniers fehlen — nicht nachholbar, die Fahrt ist vorbei manuelle Zeitnahme als Rückfall immer parallel bereithalten; manuelle Nacherfassung im Frontend; Plausibilitätsprüfung serverseitig; AP 10 misst zunächst nur mit
Fehlauslösung durch Zuschauer/Helfer/rangierendes Motorrad falsche Zeit im Ergebnis Entprellung auf dem Pi, Verwerfen-Funktion mit Grund, Plausibilitätsgrenzen, Vier-Augen-Prinzip vor „final"
Messung dem falschen Fahrer zugeordnet zwei Ergebnisse gleichzeitig falsch, schwer zu bemerken Zuordnung (O-14) früh und sauber klären; Anzeige am Parcours macht die Zuordnung für alle sichtbar → Fehler fällt sofort auf
Netzausfall zwischen Mess-Pi und Server Messungen gehen verloren lokale Queue + Idempotenz (§3.6c); Abnahmetest in AP 5 zieht bewusst den Netzstecker
Altdaten-Import aus PDFs scheitert an Font-Kodierung AP 8 wird teuer Excel-Originale beschaffen (O-12); Import zeitlich begrenzen; notfalls Start ab 2026
Fahrer-Dubletten durch Namensvarianten falsche Meisterschaftsstände Matching + Merge-Werkzeug in AP 4, Import-Report mit „NEU"-Markierung
Datenschutzthema Jugenddaten wird spät geklärt Livegang verzögert oder Rückbau §11 vor AP 6 entscheiden
Projekt hängt an einer Person keine Wartung Doku, sauberes Repo, zweite eingewiesene Person
Raspberry Pi: SD-Karte/Speicherausfall Datenverlust Backup extern + Restore testen, SSD statt SD-Karte erwägen; auf dem Mess-Pi read-only Root-FS erwägen
Scope-Ausweitung (Online-Nennung, Bildarchiv …) Kern wird nie fertig §9 ist bewusst nach dem Kern; AP 10 ist der Zielpunkt

13. Nächster Schritt

  1. Diesen Plan im Verein durchgehen, insbesondere §10 (offene Fragen) und §11 (Datenschutz)
  2. ADAC-Turnierordnung 2026 und Punktetabelle beschaffen — ohne die stehen AP 2 und AP 3
  3. Zeitmessung klären: O-13 (was wird gemessen), O-14 (Zuordnung zum Fahrer), O-16 (Genauigkeit/Hardware), O-19 (wer baut sie) — davon hängt AP 5 komplett ab
  4. Entscheidung zu O-7 (Netz am Platz) und O-9/O-10 (Hosting, Domain)
  5. Danach AP 0 → AP 1 → AP 2

Reihenfolge-Hinweis: Die Zeitmessung ist das sichtbarste, aber nicht das erste Arbeitspaket. Sie liefert nur die Hälfte eines Ergebnisses (§3.6) und braucht Turnier, Startliste und Wertungslogik als Unterbau. AP 13 zuerst, dann AP 5 — sonst hat der Mess-Pi nichts, wogegen er Startnummern auflösen könnte.


Quellen

  • www.oamc.de — Startseite, Navigation, Rubrik Motorradgruppe (m/m1.htm, m/m2.htm, m/m-sportbeschreibung.htm), Downloadseite d/d-mot-turnier.htm
  • www.oamc.de/datei/2026-05-31-MT-REIN-HAIN.PDF — Tagesergebnis Doppelturnier MSC Hainstadt / OAMC Reinheim, 13 Wertungsblöcke; Grundlage für §3.3
  • www.oamc.de/datei/MT-Rahmenausschreibung-2026.pdf (Stand 1.2.2026) — Nenngeld, Nennschluss, Streichresultate, Jugend-Klasseneinteilung, Endlaufqualifikation
  • Systemprüfung auf dem Zielgerät (Raspberry Pi 4B) für §5.1