Files
WrestleDesk/docs/superpowers/specs/2026-03-24-leistungstest-statistiken-design.md
Andrej Spielmann 3fefc550fe Initial commit: WrestleDesk full project
- Django backend with DRF (clubs, wrestlers, trainers, exercises, templates, trainings, homework, locations, leistungstest)
- Next.js 16 frontend with React, Shadcn UI, Tailwind
- JWT authentication
- Full CRUD for all entities
- Calendar view for trainings
- Homework management system
- Leistungstest tracking
2026-03-26 13:24:57 +01:00

4.0 KiB

Leistungstest Statistiken — Design

Overview

Erweiterung des Leistungstest-Bereichs um Statistiken und Ranglisten auf zwei Ebenen: Vorlagen und Übungen. Filterbar nach Zeitraum (Monat / Alle Zeiten).

Features

1. Ranglisten pro Vorlage

  • Rangliste aller Wrestler nach score_percent (absteigend)
  • Optional: Sortierung nach total_time_seconds (aufsteigend = schnellste Zeit)
  • Zeitraum-Filter: "Alle Zeiten" | "Dieser Monat" | "Letzte 3 Monate" | "Dieses Jahr"
  • Anzeige: Rank, Wrestler-Name, Score %, Gesamtzeit, Datum

2. Ranglisten pro Übung

  • Für jede Übung: Rangliste nach elapsed_seconds (schnellste Zeit)
  • Berechnung: Beste Zeit (niedrigste elapsed_seconds) pro Wrestler pro Übung
  • Zeitraum-Filter wie oben
  • Anzeige: Rank, Wrestler-Name, Übungsname, Bestzeit, Datum

3. Ringer-Statistik (optional)

  • Pro Wrestler: Durchschnitts-Score, Anzahl Tests, Trend (besser/schlechter)

Datenmodell

Keine neuen Modelle — Berechnung erfolgt on-the-fly aus LeistungstestResult und LeistungstestResultItem.

API Endpoints (Backend)

GET /api/v1/leistungstest/stats/leaderboard/

Query-Parameter:

  • type: "template" | "exercise"
  • template_id: number (für template-Typ)
  • period: "all" | "month" | "3months" | "year"
  • limit: number (default: 10)

Response für type=template:

{
  "template_id": 1,
  "template_name": "Krafttest Februar",
  "period": "all",
  "results": [
    {
      "rank": 1,
      "wrestler_id": 1,
      "wrestler_name": "Max Mustermann",
      "score_percent": 100.0,
      "total_time_seconds": 342,
      "completed_at": "2026-03-24"
    }
  ]
}

Response für type=exercise:

{
  "exercise_id": 1,
  "exercise_name": "Liegestütze",
  "period": "all",
  "results": [
    {
      "rank": 1,
      "wrestler_id": 1,
      "wrestler_name": "Max Mustermann",
      "best_time_seconds": 75,
      "completed_at": "2026-03-24"
    }
  ]
}

GET /api/v1/leistungstest/stats/exercises/

Liste aller Übungen die jemals in einem Leistungstest verwendet wurden (für Dropdown).

Frontend

Neuer Tab: "📊 Statistiken"

Tabs im Leistungstest:

  1. Vorlagen (existiert)
  2. Zuweisen (existiert)
  3. Ergebnisse (existiert, jetzt Karten-Ansicht)
  4. 📊 Statistiken (NEU)

Statistiken-Tab Layout:

[Tab: Vorlagen | Zuweisen | Ergebnisse | 📊 Statistiken]

📊 Statistiken

[Dropdowns: Vorlage auswählen | Zeitraum: Alle Zeiten ▾]

-tabs-
[⊞ Nach Vorlage] [📋 Nach Übung]

--- Nach Vorlage ---
Rangliste: Krafttest Februar
1. 🥇 Max Mustermann — 100% (5:42)
2. 🥈 Anna Schmidt — 87% (6:20)  
3. 🥉 Tom Klein — 65% (8:15)

--- Nach Übung ---
Rangliste: Liegestütze
1. 🥇 Max Mustermann — 1:15
2. 🥈 Anna Schmidt — 1:30
3. 🥉 Tom Klein — 2:00

Rangliste: Kniebeugen
1. 🥇 Max Mustermann — 2:30
...

Backend-Implementierung

Neue Datei: leistungstest/stats.py

def get_template_leaderboard(template_id, period="all", limit=10):
    # Filter results by template and period
    # Order by score_percent DESC, total_time_seconds ASC
    # Return top N with rank

def get_exercise_leaderboard(exercise_id, period="all", limit=10):
    # For each wrestler, find their BEST (lowest) elapsed_seconds
    # Filter by period
    # Order by best_time ASC
    # Return top N

Neue URL: leistungstest/stats.py ViewSet

  • GET /leaderboard/ — Template oder Exercise Leaderboard
  • GET /exercises/ — Liste verwendeter Übungen

Zeitraum-Filter Logik

def get_date_range(period):
    today = date.today()
    if period == "month":
        return today.replace(day=1)
    elif period == "3months":
        return today - timedelta(days=90)
    elif period == "year":
        return today.replace(month=1, day=1)
    return None  # "all"

Implementierungs-Reihenfolge

  1. Backend: stats.py mit ViewSet + URLs
  2. Frontend: Neuer "Statistiken" Tab
  3. Toggle zwischen Vorlagen/Übungs-Ansicht
  4. Zeitraum-Filter
  5. Ranglisten-Anzeige mit Medaillen-Icons