shinkan-jinkendo/backend/scripts/parse_matrix.py

150 lines
5.3 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""
Parse Fähigkeitsmatrix und extrahiere vollständige Kategorisierung.
"""
import sys
import httpx
from bs4 import BeautifulSoup
def parse_matrix():
"""Parse die Fähigkeitsmatrix und gib CSV-Mapping aus."""
# Wiki-Login
api_url = 'https://karatetrainer.net/api.php'
username = 'Jinkendo'
password = 'Jinkendo6970'
# Synchroner Client
with httpx.Client(timeout=30) as client:
# Schritt 1: Login-Token holen
r1 = client.get(api_url, params={
'action': 'query',
'meta': 'tokens',
'type': 'login',
'format': 'json',
})
r1.raise_for_status()
data1 = r1.json()
token = data1.get('query', {}).get('tokens', {}).get('logintoken', '')
if not token:
print("ERROR: Kein Login-Token erhalten", file=sys.stderr)
return
# Schritt 2: Login durchführen
r2 = client.post(api_url, data={
'action': 'login',
'lgname': username,
'lgpassword': password,
'lgtoken': token,
'format': 'json',
})
r2.raise_for_status()
data2 = r2.json()
if data2.get('login', {}).get('result') != 'Success':
print(f"ERROR: Login fehlgeschlagen: {data2}", file=sys.stderr)
return
# Hole Matrix-Seite als HTML
page_url = 'https://karatetrainer.net/index.php?title=Fähigkeitsmatrix'
r3 = client.get(page_url)
r3.raise_for_status()
html = r3.text
if not html:
print("ERROR: Konnte Matrix-HTML nicht abrufen", file=sys.stderr)
return
# Parse HTML
soup = BeautifulSoup(html, 'html.parser')
table = soup.find('table', {'class': 'wikitable'})
if not table:
print("ERROR: Tabelle nicht gefunden", file=sys.stderr)
return
rows = table.find_all('tr')
# Extrahiere Struktur
# Default: KARATE Fähigkeiten (bis Row 49 wo ALLGEMEINE beginnt)
current_main_cat = 'karate'
current_sub_cat = None
skills_data = []
for idx, row in enumerate(rows):
cells = row.find_all(['td', 'th'])
if len(cells) == 1:
# Kategorie-Header (1 Zelle)
text = cells[0].get_text(strip=True)
# Überspringe Inhaltsverzeichnis (Row 4)
if 'Inhaltsverzeichnis' in text:
continue
# Haupt-Kategorie Wechsel erkennen (nur bei "ALLGEMEINE sportliche Fähigkeiten")
if 'ALLGEMEINE' in text and 'sportliche' in text:
current_main_cat = 'allgemeine'
current_sub_cat = None
# print(f"DEBUG: Row {idx} - Wechsel zu allgemeine", file=sys.stderr)
else:
# Alle anderen 1-Zellen-Rows sind Unterkategorien
# Bereinige Text (entferne Sonderzeichen, Leerzeichen)
current_sub_cat = text.replace('­', '').strip() # soft hyphen entfernen
# print(f"DEBUG: Row {idx} - Unterkategorie '{current_sub_cat}' (main_cat={current_main_cat})", file=sys.stderr)
elif len(cells) == 6:
# Skill-Zeile (6 Zellen: Name + 5 Level-Beschreibungen)
skill_name = cells[0].get_text(strip=True).replace('­', '') # soft hyphen entfernen
# Nur Skills mit Hauptkategorie UND Unterkategorie erfassen
if skill_name and current_main_cat and current_sub_cat:
# Fokusbereich bestimmen
focus = 'karate' if current_main_cat == 'karate' else 'universal'
skills_data.append({
'skill': skill_name,
'sub_cat': current_sub_cat,
'main_cat': current_main_cat,
'focus': focus,
'row': idx
})
# Duplikat-Handling: Bevorzuge spezifischere Kategorien
# Bei Duplikaten: Kondition/Koordination > Kumite (für allgemeine Fähigkeiten)
# Kumite > Rest (für Kampf-spezifische wie "Timing", "Antizipation")
duplicates_to_remove = {
('Anaerobe Ausdauer', 'Kumite'), # Behalte Kondition
('Bewegungsschnelligkeit', 'Kumite'), # Behalte Kondition
('Flexibilität', 'Kumite'), # Behalte Kondition
('Reaktionsschnelligkeit', 'Kumite'), # Behalte Kondition
('Schnelligkeitsausdauer', 'Kumite'), # Behalte Kondition
('Antizipation', 'Koordination'), # Behalte Kumite (kampfspezifisch)
('Timing', 'Koordination'), # Behalte Kumite (kampfspezifisch)
}
# Filtere Duplikate
filtered_skills = []
for s in skills_data:
if (s['skill'], s['sub_cat']) not in duplicates_to_remove:
filtered_skills.append(s)
# Ausgabe als CSV (UTF-8)
import sys
# Force UTF-8 output
sys.stdout.reconfigure(encoding='utf-8')
print('skill_name,sub_category,main_category,focus_areas')
for s in filtered_skills:
# Escape Kommas in Namen
skill = s['skill'].replace(',', ';')
sub_cat = s['sub_cat'].replace(',', ';')
print(f"{skill},{sub_cat},{s['main_cat']},{s['focus']}")
print(f"\n# Total: {len(filtered_skills)} Skills (von {len(skills_data)} Zeilen, {len(skills_data) - len(filtered_skills)} Duplikate entfernt)", file=sys.stderr)
if __name__ == '__main__':
parse_matrix()