- Implemented a new SQL migration for wiki import tracking tables. - Created an import router for handling MediaWiki imports of exercises, skills, and methods. - Developed a Semantic MediaWiki API client for direct API interactions. - Added a mapper to convert SMW properties to local database fields. - Introduced background tasks for asynchronous import processing. - Implemented logging and error handling for import operations. - Added endpoints for previewing imports, checking import status, and managing import references.
16 KiB
Fähigkeitsmatrix / Reifegradmodell – Specification
Version: 1.0 Datum: 2026-04-24 Status: DRAFT Autor: Claude Code Basis: shinkan_anforderungsdokument_entwurf.md §8 + DOMAIN_MODEL.md
1. Konzept
1.1 Was ist die Fähigkeitsmatrix?
Die Fähigkeitsmatrix verbindet globale Fähigkeiten (Skills) mit kontextspezifischen Reifegradmodellen. Sie beantwortet pro Kontext die Frage:
„Was muss ein Schüler auf Stufe X dieser Fähigkeit können, und welche Übungen trainieren ihn von Stufe A auf Stufe B?"
Drei Ebenen:
1. Globale Fähigkeit (skill)
"Distanzgefühl" – gilt überall, für alle Stile und Zielgruppen
2. Reifegradmodell (maturity_model)
"Karate / Shotokan / Breitensport" – definiert WIE VIELE Stufen es gibt
und wie die Stufen heißen
3. Modell-Fähigkeitsstufe (model_skill_level)
"Stufe 3 von Distanzgefühl im Shotokan-Breitensport-Modell" –
beschreibt KONKRET was auf Stufe 3 erwartet wird
1.2 Warum kontextabhängig?
Dieselbe Fähigkeit (z.B. „Distanzgefühl") hat in verschiedenen Kontexten unterschiedliche Bedeutungen:
| Kontext | Stufe 3 Bedeutung |
|---|---|
| Karate / Shotokan / Breitensport | Distanzkontrolle in einfachen Partnerübungen |
| Karate / Shotokan / Leistungssport | Stabile Distanz im freien Kumite |
| Selbstverteidigung / Erwachsene | Sicherheitsabstand in Alltagssituationen einschätzen |
Ein Modell hat variable Stufenanzahl (3-7, nicht fest 5):
Shotokan Breitensport → 5 Stufen (Einsteiger bis Experte)
Kinder-Karate → 4 Stufen (Kinder-gerecht vereinfacht)
Leistungssport → 7 Stufen (feiner granuliert)
1.3 Abgrenzung zu exercise_skills
exercise_skills: Übung trainiert Fähigkeit mit Intensität und
suggested required/target Stufe
→ kontextunabhängig (gilt für alle Modelle)
model_skill_levels: Für dieses Modell bedeutet "Stufe 3" von Fähigkeit X:
"[konkrete Beschreibung]"
→ kontextspezifisch
2. Datenmodell
2.1 Entity-Übersicht
focus_areas (global, existiert)
└─ style_directions (existiert, früher training_styles)
└─ target_groups (M:N, existiert)
maturity_models (NEU)
├─ focus_area_id FK (optional, NULL = gilt für alle Fokusbereiche)
├─ style_direction_id FK (optional)
├─ target_group_id FK (optional)
└─ level_count (INT) – wie viele Stufen hat das Modell?
model_levels (NEU) – Stufen-Definitionen
├─ maturity_model_id FK
├─ level_number (1 bis level_count)
├─ name (z.B. "Einsteiger", "Grundlagen", ...)
└─ description
model_skill_levels (NEU) – Was bedeutet Stufe X für Fähigkeit Y im Modell Z?
├─ maturity_model_id FK
├─ skill_id FK
├─ level_number (muss in maturity_model.level_count liegen)
├─ description (Pflicht-Text: was soll der Lernende können?)
├─ observable_criteria (Beobachtungskriterien für Trainer)
└─ example_exercises JSONB (Empfohlene Übungs-Typen, keine FK)
2.2 Vollständige Migration (019_maturity_models.sql)
-- Migration 019: Fähigkeitsmatrix / Reifegradmodelle
-- Autor: Claude Code
-- Datum: 2026-04-24
DO $$
BEGIN
-- ============================================================================
-- MATURITY MODELS (Reifegradmodelle)
-- ============================================================================
CREATE TABLE IF NOT EXISTS maturity_models (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description TEXT,
-- Kontext-Bindung (alle optional – NULL bedeutet "gilt allgemein")
-- Je mehr gesetzt, desto spezifischer das Modell
focus_area_id INT REFERENCES focus_areas(id) ON DELETE RESTRICT,
style_direction_id INT REFERENCES style_directions(id) ON DELETE RESTRICT,
target_group_id INT REFERENCES target_groups(id) ON DELETE RESTRICT,
-- Stufenanzahl (flexibel, nicht fest auf 5)
level_count INT NOT NULL DEFAULT 5 CHECK (level_count BETWEEN 3 AND 10),
-- Sichtbarkeit & Freigabe
-- 'draft': in Bearbeitung | 'active': in Nutzung | 'archived': nicht mehr aktiv
status VARCHAR(20) DEFAULT 'draft' CHECK (status IN ('draft', 'active', 'archived')),
-- Versionierung
version VARCHAR(20) DEFAULT '1.0',
-- Ownership
created_by INT REFERENCES profiles(id) ON DELETE SET NULL,
club_id INT REFERENCES clubs(id) ON DELETE SET NULL,
-- Import-Tracking (für Semantic MediaWiki Import)
import_source VARCHAR(50),
import_id VARCHAR(200),
-- Timestamps
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
-- Constraint: Name + Kontext eindeutig
UNIQUE(name, focus_area_id, style_direction_id, target_group_id)
);
-- ============================================================================
-- MODEL LEVELS (Stufendefinitionen pro Modell)
-- ============================================================================
CREATE TABLE IF NOT EXISTS model_levels (
id SERIAL PRIMARY KEY,
maturity_model_id INT NOT NULL REFERENCES maturity_models(id) ON DELETE CASCADE,
level_number INT NOT NULL CHECK (level_number >= 1),
name VARCHAR(100) NOT NULL, -- z.B. "Einsteiger", "Grundlagen", "Aufbau"
description TEXT, -- Was zeichnet diese Stufe generell aus?
sort_order INT NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(maturity_model_id, level_number)
);
-- ============================================================================
-- MODEL SKILL LEVELS
-- Was bedeutet "Stufe X der Fähigkeit Y im Modell Z"?
-- ============================================================================
CREATE TABLE IF NOT EXISTS model_skill_levels (
id SERIAL PRIMARY KEY,
maturity_model_id INT NOT NULL REFERENCES maturity_models(id) ON DELETE CASCADE,
skill_id INT NOT NULL REFERENCES skills(id) ON DELETE RESTRICT,
level_number INT NOT NULL CHECK (level_number >= 1),
-- Was wird auf dieser Stufe erwartet? (Pflichtfeld)
description TEXT NOT NULL,
-- Konkrete Beobachtungskriterien für Trainer
-- z.B. "Kann Distanz in ruhigen Partnerübungen halten (3/3 Versuchen)"
observable_criteria TEXT,
-- Empfohlene Übungs-Typen (keine FK, nur Hinweise)
-- z.B. {"types": ["Grundübung", "Partnerübung"], "max_duration_min": 15}
example_exercise_hints JSONB,
-- KI-generiert?
ai_generated BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE(maturity_model_id, skill_id, level_number),
-- level_number muss im Bereich des Modells liegen
-- (wird per Trigger oder Backend-Validierung geprüft)
CONSTRAINT ck_level_positive CHECK (level_number > 0)
);
-- ============================================================================
-- SKILL CATALOG: Felder für Matrix-Nutzung (falls noch nicht vorhanden)
-- ============================================================================
-- Fähigkeiten können einem bestimmten Fokusbereich "zugehören" (primär)
-- bleiben aber global nutzbar (secondary assignments über M:N)
ALTER TABLE skills
ADD COLUMN IF NOT EXISTS primary_focus_area_id INT REFERENCES focus_areas(id) ON DELETE SET NULL,
ADD COLUMN IF NOT EXISTS is_cross_domain BOOLEAN DEFAULT false; -- gilt für alle Fokusbereiche
-- ============================================================================
-- INDEXES
-- ============================================================================
CREATE INDEX IF NOT EXISTS idx_maturity_models_focus ON maturity_models(focus_area_id);
CREATE INDEX IF NOT EXISTS idx_maturity_models_style ON maturity_models(style_direction_id);
CREATE INDEX IF NOT EXISTS idx_maturity_models_target ON maturity_models(target_group_id);
CREATE INDEX IF NOT EXISTS idx_maturity_models_status ON maturity_models(status);
CREATE INDEX IF NOT EXISTS idx_model_levels_model ON model_levels(maturity_model_id);
CREATE INDEX IF NOT EXISTS idx_model_skill_levels_model ON model_skill_levels(maturity_model_id);
CREATE INDEX IF NOT EXISTS idx_model_skill_levels_skill ON model_skill_levels(skill_id);
CREATE INDEX IF NOT EXISTS idx_model_skill_levels_combo ON model_skill_levels(maturity_model_id, skill_id);
-- ============================================================================
-- TRIGGERS
-- ============================================================================
DROP TRIGGER IF EXISTS maturity_models_update ON maturity_models;
CREATE TRIGGER maturity_models_update
BEFORE UPDATE ON maturity_models
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
DROP TRIGGER IF EXISTS model_skill_levels_update ON model_skill_levels;
CREATE TRIGGER model_skill_levels_update
BEFORE UPDATE ON model_skill_levels
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
RAISE NOTICE 'Migration 019 completed successfully (Maturity Models / Fähigkeitsmatrix)';
END $$;
3. Beispiel-Daten
3.1 Beispiel-Modell: Karate Shotokan Breitensport (5 Stufen)
INSERT INTO maturity_models (name, focus_area_id, style_direction_id, target_group_id, level_count, status)
VALUES ('Karate Shotokan Breitensport', 1, 1, 1, 5, 'active');
-- Stufennamen
INSERT INTO model_levels (maturity_model_id, level_number, name, description, sort_order) VALUES
(1, 1, 'Einsteiger', 'Erste Begegnung – keine Vorkenntnisse erforderlich', 1),
(1, 2, 'Grundlagen', 'Grundprinzipien bekannt, in ruhigen Situationen anwendbar', 2),
(1, 3, 'Aufbau', 'Semi-intuitiver Einsatz, mit gelegentlicher Korrektur', 3),
(1, 4, 'Fortgeschritten', 'Intuitiver Einsatz auch unter Druck', 4),
(1, 5, 'Experte', 'Vollständig automatisiert, stabile Leistung auf Spitzenniveau', 5);
-- Fähigkeitsstufen: Distanzgefühl im Shotokan-Breitensport-Modell
INSERT INTO model_skill_levels (maturity_model_id, skill_id, level_number, description, observable_criteria)
VALUES
(1, 10, 1, 'Versteht das Konzept "Distanz" und kann erklären warum es wichtig ist.',
'Kann auf Frage benennen, was Maai bedeutet.'),
(1, 10, 2, 'Hält in langsamen, geführten Partnerübungen die Angriffsdistanz.',
'In 3 von 3 langsamen Wiederholungen korrekte Distanz eingenommen.'),
(1, 10, 3, 'Kontrolliert Distanz in mittlerer Geschwindigkeit bei Standardtechniken.',
'Trainer bewertet Distanzkontrolle mit "gut" in Kihon-Ippon-Kumite.'),
(1, 10, 4, 'Stabiler Einsatz im Jiyu-Ippon-Kumite, selten vom Partner überrascht.',
'In freiem Jiyu-Kumite hält Schüler Linie in >70% der Aktionen.'),
(1, 10, 5, 'Feingefühl für minimale Distanzveränderungen, taktischer Einsatz im Shiai.',
'Wettkampferfolge durch bewusstes Distanzmanagement nachweisbar.');
4. API-Endpoints
4.1 Übersicht
| Method | Endpoint | Beschreibung |
|---|---|---|
| GET | /maturity-models |
Liste aller Modelle (mit Filter) |
| GET | /maturity-models/{id} |
Modell-Detail mit Stufen + Skills |
| POST | /maturity-models |
Neues Modell erstellen (Admin) |
| PUT | /maturity-models/{id} |
Modell bearbeiten (Admin) |
| DELETE | /maturity-models/{id} |
Modell löschen (Admin) |
| GET | /maturity-models/{id}/skills |
Alle Fähigkeiten + Stufen dieses Modells |
| PUT | /maturity-models/{id}/skills/{skill_id}/levels |
Stufen-Beschreibungen setzen (Admin) |
| GET | /maturity-models/resolve |
Bestes Modell für Kontext finden |
4.2 GET /maturity-models/resolve
Findet das spezifischste Modell für einen gegebenen Kontext. Wird von der KI und vom Frontend verwendet.
Query Parameters:
focus_area_id(int, optional)style_direction_id(int, optional)target_group_id(int, optional)
Response:
{
"model": {
"id": 1,
"name": "Karate Shotokan Breitensport",
"level_count": 5,
"match_specificity": "full"
},
"fallback_used": false
}
Auflösungslogik (Most Specific First):
- Alle drei passen (focus + style + target) →
match_specificity: "full" - focus + style passen →
match_specificity: "style" - Nur focus passt →
match_specificity: "focus" - Allgemeines Modell (alle FK = NULL) →
match_specificity: "generic" - Kein Modell vorhanden →
match_specificity: null, 404
5. Verbindung zu Übungen
5.1 Wie exercise_skills das Modell referenziert
exercise_skills speichert required_level und target_level als Stufen-Namen
(einsteiger/grundlagen/aufbau/fortgeschritten/experte), die modellunabhängig sind.
Das Frontend kann bei Bedarf die konkrete Modell-Beschreibung nachladen:
exercise_skills.required_level = "grundlagen"
→ GET /maturity-models/resolve?focus_area_id=1
→ Model: Karate Shotokan Breitensport (level_count=5)
→ model_levels: level_number=2, name="Grundlagen"
→ model_skill_levels für skill_id=10: "Hält in ruhigen Partnerübungen Distanz"
5.2 Darstellung in der Übungsdetail-Ansicht
Fähigkeiten
─────────────────────────────────────────────
★ Distanzgefühl (primär)
Voraussetzung: Grundlagen → Ziel: Aufbau
Intensität: Hoch
────────────────────────────────
Grundlagen: "Hält in ruhigen Partnerübungen
Distanz"
Aufbau: "Kontrolle in mittlerer
Geschwindigkeit"
[Kontext: Shotokan Breitensport ▼]
─────────────────────────────────────────────
◦ Reaktionsschnelligkeit (sekundär)
Voraussetzung: Einsteiger → Ziel: Grundlagen
Intensität: Mittel
Kontext-Dropdown: Trainer kann Modell wechseln um kontextspezifische Beschreibungen zu sehen.
6. KI-Unterstützung für Modell-Pflege
Die KI kann model_skill_levels-Beschreibungen vorschlagen.
Prompt-Placeholder:
{{skill_name}}– Name der Fähigkeit{{model_name}}– Name des Reifegradmodells{{level_count}}– Anzahl der Stufen{{level_names}}– Namen der Stufen (z.B. "Einsteiger, Grundlagen, Aufbau..."){{focus_area}}– Fokusbereich{{target_group}}– Zielgruppe
Endpoint: POST /maturity-models/{id}/ai/suggest-skill-levels
// Request
{
"skill_id": 10,
"regenerate_existing": false
}
// Response
{
"skill": {"id": 10, "name": "Distanzgefühl"},
"suggestions": [
{
"level_number": 1,
"level_name": "Einsteiger",
"description": "...",
"observable_criteria": "...",
"ai_generated": true
},
...
]
}
7. Semantic MediaWiki Import
Die bestehende Fähigkeitsmatrix im SMW enthält bereits Stufen-Beschreibungen.
Erweiterung der MEDIAWIKI_IMPORT_SPEC.md:
| Wiki-Feld | Ziel-Tabelle | Transformation |
|---|---|---|
SMW Property: Stufe 1 Beschreibung |
model_skill_levels.description (level=1) |
Direkt |
SMW Property: Stufe N Beschreibung |
model_skill_levels.description (level=N) |
Direkt |
SMW Property: Modell |
maturity_models.name |
Lookup/Create |
SMW Property: Fokusbereich |
maturity_models.focus_area_id |
Name → ID |
Import-Endpoint: POST /import/mediawiki/execute mit import_type: "maturity_model"
8. Admin-Workflow
8.1 Modell anlegen (Admin)
1. Admin wählt: Fokusbereich + Stil + Zielgruppe
2. Admin legt Stufenanzahl + Stufennamen fest
3. Admin weist Fähigkeiten dem Modell zu (Pflicht-/Optional-Skills)
4. Für jede Fähigkeit × Stufe: Beschreibung eingeben
→ Optional: KI-Vorschlag generieren
5. Modell auf "active" stellen
8.2 SMW-Migration-Workflow
1. SMW-Import: Bestehende Modelle und Beschreibungen importieren
2. Review: Trainer prüft importierte Beschreibungen
3. KI-Ergänzung: Für fehlende Stufen KI-Vorschläge generieren
4. Freigabe: status → 'active'
Version: 1.0 Datum: 2026-04-24 Status: DRAFT Nächste Schritte:
- SMW-Struktur analysieren (User legt Daten ins Repo)
- Migration 019 implementieren
- Admin-UI für Modellpflege spezifizieren (UI_COMPONENTS_SPEC.md ergänzen)