3fefc550fe
- 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
155 lines
4.0 KiB
Markdown
155 lines
4.0 KiB
Markdown
# 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`:
|
|
```json
|
|
{
|
|
"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`:
|
|
```json
|
|
{
|
|
"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`
|
|
```python
|
|
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
|
|
```python
|
|
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
|