2026-02-27 12:01:02 +01:00
|
|
|
|
from nicegui import ui, app
|
2026-03-02 16:17:50 +01:00
|
|
|
|
from gui import gui_style
|
2026-03-04 16:08:45 +01:00
|
|
|
|
from data import data_api
|
2026-03-12 09:34:22 +01:00
|
|
|
|
from gui.info_text import info_system
|
2026-02-27 12:01:02 +01:00
|
|
|
|
|
2026-03-03 15:49:40 +01:00
|
|
|
|
def setup_routes():
|
2026-02-27 12:01:02 +01:00
|
|
|
|
# 1. Die {}-Klammern definieren eine dynamische Variable in der URL
|
2026-03-08 16:23:39 +01:00
|
|
|
|
@ui.page('/statistic/{systemname}', dark=True)
|
2026-02-27 12:01:02 +01:00
|
|
|
|
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
|
|
|
|
|
|
|
2026-03-02 16:17:50 +01:00
|
|
|
|
gui_style.apply_design()
|
2026-03-04 16:08:45 +01:00
|
|
|
|
|
|
|
|
|
|
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'):
|
2026-03-12 09:34:22 +01:00
|
|
|
|
ui.button(icon="arrow_back", on_click=lambda: ui.navigate.to('/')).props("round")
|
2026-03-04 16:08:45 +01:00
|
|
|
|
ui.button("Spiel eintragen", on_click=lambda: ui.navigate.to(f'/add-match/{systemname}'))
|
|
|
|
|
|
|
2026-03-12 15:23:09 +01:00
|
|
|
|
with ui.column().classes('w-full items-center justify-center mt-10'):
|
|
|
|
|
|
ui.label(f'Deine Statistik in {systemname}').classes('text-3xl justify-center font-bold text-normaltext')
|
2026-03-04 16:08:45 +01:00
|
|
|
|
|
|
|
|
|
|
# --- BLOCK 1 (2 Karten) ---
|
2026-03-06 12:01:58 +01:00
|
|
|
|
# 1. Daten für die Rangliste holen
|
|
|
|
|
|
leaderboard_data = data_api.get_leaderboard(systemname)
|
2026-03-04 16:08:45 +01:00
|
|
|
|
|
2026-03-06 12:01:58 +01:00
|
|
|
|
# 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
|
2026-03-08 20:56:54 +01:00
|
|
|
|
'name': f"{player['display_name']} 'aka' {player['discord_name']}",
|
2026-03-06 12:01:58 +01:00
|
|
|
|
'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"):
|
|
|
|
|
|
with ui.column().classes("w-full gap-4"):
|
|
|
|
|
|
with ui.card().classes("w-full items-center justify-center text-center"):
|
2026-03-11 20:43:30 +01:00
|
|
|
|
with ui.row().classes("w-full items-center text-center"):
|
2026-03-12 15:23:09 +01:00
|
|
|
|
ui.label("MMR Punkte: ").classes('justify-center text-2xl font-bold text-normaltext')
|
2026-03-11 20:43:30 +01:00
|
|
|
|
ui.space()
|
2026-03-12 09:34:22 +01:00
|
|
|
|
info_system.create_info_button("mmr_info")
|
|
|
|
|
|
ui.label(str(stats["mmr"])).classes('text-4xl font-bold text-accent')
|
2026-03-04 16:08:45 +01:00
|
|
|
|
|
2026-03-06 12:01:58 +01:00
|
|
|
|
with ui.card().classes("w-full items-center justify-center text-center"):
|
2026-03-04 16:08:45 +01:00
|
|
|
|
ui.label("Rang: ").classes('text-2xl font-bold')
|
2026-03-06 12:01:58 +01:00
|
|
|
|
# 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')
|
|
|
|
|
|
|
2026-03-02 16:17:50 +01:00
|
|
|
|
|
2026-03-04 16:08:45 +01:00
|
|
|
|
# --- 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')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-02-27 12:01:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-02 16:17:50 +01:00
|
|
|
|
|