Liga-System/gui/league_statistic.py

172 lines
8.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from nicegui import ui, app
from gui import gui_style
from data import data_api
def setup_routes():
# 1. Die {}-Klammern definieren eine dynamische Variable in der URL
@ui.page('/statistic/{systemname}', dark=True)
def gamesystem_statistic_page(systemname: str): # <--- WICHTIG: Hier fangen wir das Wort aus der URL auf!
# Sicherheitscheck: Ist der User eingeloggt?
if not app.storage.user.get('authenticated', False):
ui.navigate.to('/')
return
gui_style.apply_design()
player_id = app.storage.user.get('db_id')
stats = data_api.get_player_system_stats(player_id, systemname)
if stats:
with ui.header().classes('items-center justify-between bg-zinc-900 p-4 shadow-lg'):
ui.button('Zurück zur Übersicht', on_click=lambda: ui.navigate.to('/'))
ui.button("Spiel eintragen", on_click=lambda: ui.navigate.to(f'/add-match/{systemname}'))
with ui.column().classes('w-full items-center mt-10'):
ui.label(f'Deine Statistik in {systemname}').classes('text-5xl font-bold text-blue-400')
# --- BLOCK 1 (2 Karten) ---
# 1. Daten für die Rangliste holen
leaderboard_data = data_api.get_leaderboard(systemname)
# 2. Tabelle vorbereiten und den EIGENEN Rang herausfinden
table_rows = []
my_rank = "-"
for index, player in enumerate(leaderboard_data):
current_rank = index + 1
# Wenn wir in der Liste über uns selbst stolpern, merken wir uns den Rang für unsere Karte!
if player['id'] == player_id:
my_rank = current_rank
table_rows.append({
'rank': current_rank,
'trend': '', # Platzhalter für später
'name': f"{player['display_name']} aka {player['discord_name']}",
'mmr': player['mmr']
})
table_columns = [
{'name': 'rank', 'label': '#', 'field': 'rank', 'align': 'left'},
{'name': 'trend', 'label': 'Trend', 'field': 'trend', 'align': 'center'},
{'name': 'name', 'label': 'Spieler', 'field': 'name', 'align': 'left'},
{'name': 'mmr', 'label': 'MMR', 'field': 'mmr', 'align': 'left'}
]
# --- BLOCK 1 (Links: MMR & Rang | Rechts: Rangliste) ---
# lg:grid-cols-3 teilt den Bildschirm auf großen Monitoren in 3 gleich große unsichtbare Spalten
with ui.element('div').classes("w-full grid grid-cols-1 lg:grid-cols-3 gap-4 mt-4"):
# LINKE SEITE (Belegt 1 Spalte)
# flex-col setzt die beiden Karten exakt übereinander
with ui.column().classes("w-full gap-4"):
with ui.card().classes("w-full items-center justify-center text-center"):
ui.label("MMR Punkte: ").classes('text-2xl font-bold')
ui.label(str(stats["mmr"])).classes('text-4xl font-bold text-blue-100')
with ui.card().classes("w-full items-center justify-center text-center"):
ui.label("Rang: ").classes('text-2xl font-bold')
# Hier tragen wir jetzt unsere gefundene Platzierung ein!
ui.label(str(my_rank)).classes('text-4xl font-bold text-blue-100')
# RECHTE SEITE (Belegt 2 Spalten -> lg:col-span-2)
with ui.card().classes("w-full lg:col-span-2"):
ui.label("Liga Rangliste").classes("text-xl font-bold text-white mb-2")
ui.table(columns=table_columns, rows=table_rows, row_key='rank').classes('w-full bg-zinc-900 text-white')
# --- BLOCK 2 (5 Karten) ---
with ui.card().classes("w-full"):
with ui.element('div').classes("w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"):
with ui.card().classes("items-center justify-center text-center"):
ui.label("Spiele: ").classes('text-2xl font-bold')
ui.label(str(stats["games_in_system"])).classes('text-4xl font-bold text-blue-100')
with ui.card().classes("items-center justify-center text-center"):
ui.label("Ø Punkte pro Spiel: ").classes('text-2xl font-bold')
ui.label(str(stats["avv_points"])).classes('text-4xl font-bold text-blue-100')
with ui.card().classes("items-center justify-center text-center"):
ui.label("Win-Rate: ").classes('text-2xl font-bold')
ui.label("-").classes('text-4xl font-bold text-blue-100')
with ui.card().classes("items-center justify-center text-center"):
ui.label("Letztes Spiel am: ").classes('text-2xl font-bold')
# Schneidet die Zeit vom Datum ab, falls eins existiert
last_played = str(stats["last_played"])[:10] if stats["last_played"] else "-"
ui.label(last_played).classes('text-4xl font-bold text-blue-100')
with ui.card().classes("items-center justify-center text-center"):
ui.label("Win-Streak: ").classes('text-2xl font-bold')
ui.label("-").classes('text-4xl font-bold text-blue-100')
# --- BLOCK 3 (3 Karten) ---
with ui.card().classes("w-full"):
with ui.element('div').classes("w-full grid grid-cols-1 md:grid-cols-3 lg:grid-cols-3 gap-4"):
with ui.card().classes("items-center justify-center text-center"):
ui.label("Dein Nemesis: ").classes('text-2xl font-bold')
ui.label("-").classes('text-4xl font-bold text-blue-100')
with ui.card().classes("items-center justify-center text-center"):
ui.label("Meisten Spiele mit: ").classes('text-2xl font-bold')
ui.label("-").classes('text-4xl font-bold text-blue-100')
with ui.card().classes("items-center justify-center text-center"):
ui.label("Dein 'Prügelknabe': ").classes('text-2xl font-bold')
ui.label("-").classes('text-4xl font-bold text-blue-100')
# --- BLOCK 4 (Diagramm der letzten 20 Spiele) ---
with ui.card().classes("w-full items-center"):
ui.label("Punkte in den letzten 20 Spielen").classes('text-2xl font-bold mb-4')
# 1. Daten aus der API holen
chart_data = data_api.get_last_20_match_scores(player_id, systemname)
# 2. Nur zeichnen, wenn es überhaupt schon Spiele gibt!
if len(chart_data['points']) > 0:
ui.echart({
'xAxis': {
'type': 'category',
'data': chart_data['labels'],
'axisLabel': {'color': '#e5e7eb'}
},
'yAxis': {
'type': 'value',
'axisLabel': {'color': '#e5e7eb'},
'splitLine': {'lineStyle': {'color': '#3f3f46'}}
},
'series': [
{
'name': 'Punkte', # Zeigt im Tooltip "Punkte: 76" statt einer unbenannten Zahl
'type': 'line',
'data': chart_data['points'],
'smooth': True,
'color': '#60a5fa'
}
],
'tooltip': {
'trigger': 'axis',
'backgroundColor': '#27272a',
'textStyle': {'color': '#ffffff'},
'borderColor': '#3f3f46' # Ein feiner Rand für den Kasten
}
}).classes('w-full h-64')
else:
ui.label("Keine Statistiken für dieses System gefunden.").classes('text-red-500 mt-4')