Compare commits
3 Commits
master
...
dev_league
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b1031a5e7 | ||
|
|
e281160ec7 | ||
| 85e0b57833 |
|
|
@ -182,41 +182,75 @@ def get_player_statistics(player_id):
|
|||
return rows
|
||||
|
||||
|
||||
def get_player_statistic(player_id, system_id):
|
||||
def get_player_statistic(player_id, system_id, season_id=None):
|
||||
"""
|
||||
- Wenn season_id angegeben: Daten für diese Season.
|
||||
- Wenn season_id = None: Aggregierte Gesamtstatistik.
|
||||
"""
|
||||
connection = db_connection()
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
query = """
|
||||
SELECT
|
||||
sys.id AS gamesystem_id,
|
||||
sys.name AS gamesystem_name,
|
||||
sys.description,
|
||||
stat.mmr,
|
||||
stat.games_in_system,
|
||||
stat.points,
|
||||
stat.avv_points,
|
||||
stat.last_played,
|
||||
stat.win_rate,
|
||||
stat.trend,
|
||||
stat.tyrann_id,
|
||||
stat.pushover_id,
|
||||
stat.nemesis_id
|
||||
FROM gamesystems sys
|
||||
LEFT JOIN player_game_statistic stat
|
||||
ON sys.id = stat.gamesystem_id AND stat.player_id = %s
|
||||
WHERE sys.id = %s
|
||||
"""
|
||||
if season_id:
|
||||
query = """
|
||||
SELECT
|
||||
sys.name AS gamesystem_name,
|
||||
stat.mmr, stat.games_in_system, stat.points,
|
||||
stat.avv_points, stat.last_played, stat.win_rate,
|
||||
stat.trend, stat.tyrann_id, stat.pushover_id, stat.nemesis_id
|
||||
FROM gamesystems sys
|
||||
LEFT JOIN player_game_statistic stat
|
||||
ON sys.id = stat.gamesystem_id
|
||||
AND stat.player_id = %s
|
||||
AND stat.season_id = %s
|
||||
WHERE sys.id = %s
|
||||
"""
|
||||
cursor.execute(query, (player_id, season_id, system_id))
|
||||
else:
|
||||
query = """
|
||||
SELECT
|
||||
sys.name AS gamesystem_name,
|
||||
SUM(stat.mmr) / COUNT(stat.season_id) AS mmr, -- Durchschnitt MMR über Seasons
|
||||
SUM(stat.games_in_system) AS games_in_system,
|
||||
SUM(stat.points) AS points,
|
||||
SUM(stat.points) / SUM(stat.games_in_system) AS avv_points,
|
||||
MAX(stat.last_played) AS last_played
|
||||
FROM gamesystems sys
|
||||
LEFT JOIN player_game_statistic stat
|
||||
ON sys.id = stat.gamesystem_id
|
||||
AND stat.player_id = %s
|
||||
WHERE sys.id = %s
|
||||
GROUP BY sys.id
|
||||
"""
|
||||
cursor.execute(query, (player_id, system_id))
|
||||
|
||||
cursor.execute(query, (player_id, system_id))
|
||||
row = cursor.fetchone()
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return row
|
||||
|
||||
|
||||
def get_player_rank(player_id, system_id):
|
||||
"""Holt den Rang eines Spielers in einem System basierend auf MMR (absteigend)."""
|
||||
def get_seasons_by_system(gamesystem_id):
|
||||
"""Holt alle Seasons eines Spielsystems, sortiert nach Nummer absteigend."""
|
||||
connection = db_connection()
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
query = """
|
||||
SELECT id, name, season_number
|
||||
FROM seasons
|
||||
WHERE gamesystem_id = %s
|
||||
ORDER BY season_number DESC
|
||||
"""
|
||||
|
||||
cursor.execute(query, (gamesystem_id,))
|
||||
seasons = cursor.fetchall()
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return seasons
|
||||
|
||||
|
||||
def get_player_rank(player_id, system_id, season_id):
|
||||
"""Holt den Rang eines Spielers in einem System für eine spezifische Season."""
|
||||
connection = db_connection()
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
|
|
@ -224,23 +258,24 @@ def get_player_rank(player_id, system_id):
|
|||
SELECT COUNT(*) + 1 AS rank
|
||||
FROM player_game_statistic stat
|
||||
WHERE stat.gamesystem_id = %s
|
||||
AND stat.season_id = %s
|
||||
AND stat.games_in_system > 0
|
||||
AND stat.mmr > (
|
||||
SELECT stat2.mmr
|
||||
FROM player_game_statistic stat2
|
||||
WHERE stat2.player_id = %s
|
||||
AND stat2.gamesystem_id = %s
|
||||
AND stat2.season_id = %s
|
||||
)
|
||||
"""
|
||||
cursor.execute(query, (system_id, player_id, system_id))
|
||||
# Parameter: gamesystem, season, player, gamesystem, season
|
||||
cursor.execute(query, (system_id, season_id, player_id, system_id, season_id))
|
||||
row = cursor.fetchone()
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
if row and row['rank'] is not None:
|
||||
return row['rank']
|
||||
return None
|
||||
return row['rank'] if row and row['rank'] is not None else 1
|
||||
|
||||
|
||||
|
||||
|
|
@ -548,7 +583,7 @@ def get_player_name(player_id):
|
|||
return "Gelöschter Spieler"
|
||||
|
||||
|
||||
def get_system_name(sys_id):
|
||||
def get_system_name_by_id(sys_id):
|
||||
if sys_id is None:
|
||||
return "Unbekanntes System"
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,8 @@ def db_connection():
|
|||
password=os.getenv("DB_PASSWORD"),
|
||||
database=os.getenv(f"{prefix}NAME")
|
||||
)
|
||||
|
||||
return connection
|
||||
if is_prod:
|
||||
print("Verbindung mit Test DB")
|
||||
|
||||
except mariadb.Error as e:
|
||||
raise RuntimeError(f"Fehler beim Verbinden mit {'Prod' if is_prod else 'Test'}-DB: {e}")
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from data import database, data_api
|
|||
from gui import gui_style
|
||||
from wood import logger
|
||||
from gui import main_gui
|
||||
from utils.season_scheduler import check_new_seasons
|
||||
|
||||
def setup_routes():
|
||||
@ui.page('/admin', dark=True)
|
||||
|
|
@ -15,7 +16,13 @@ def setup_routes():
|
|||
if app.storage.user.get('authenticated', False):
|
||||
with ui.row().classes("w-full"):
|
||||
ui.button(text= "test", on_click=lambda: data_api.create_random_dummy_match(2))
|
||||
ui.button(icon="refresh", on_click= lambda: ui.navigate.to("/admin") )
|
||||
ui.button(icon="refresh", on_click= lambda: ui.navigate.to("/admin") )
|
||||
def handle_manual_check():
|
||||
ui.notify('Starte Season-Check...', type='info')
|
||||
check_new_seasons()
|
||||
ui.notify('Season-Check abgeschlossen!', type='positive')
|
||||
ui.button('Admin: Season-Check erzwingen', on_click=handle_manual_check)
|
||||
|
||||
with ui.card().classes("w-full"):
|
||||
ui.label("System Audit Log").classes('text-2xl font-bold text-white mb-4')
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ from gui.templates.leaderboard import Leaderboard
|
|||
def setup_routes():
|
||||
@ui.page('/statistic/{system_name}', dark=True)
|
||||
def gamesystem_statistic_page(system_name: str):
|
||||
|
||||
if not app.storage.user.get('authenticated', False):
|
||||
ui.navigate.to('/')
|
||||
return
|
||||
|
|
@ -16,76 +15,5 @@ def setup_routes():
|
|||
|
||||
player_id = app.storage.user.get('db_id')
|
||||
system_id = data_api.get_gamesystem_id_by_name(system_name)
|
||||
print(player_id, system_id)
|
||||
|
||||
player_stats = data_api.get_player_statistic(player_id, system_id)
|
||||
|
||||
# Header
|
||||
with ui.header().classes('items-center justify-between bg-zinc-900 p-4 shadow-lg'):
|
||||
ui.button(icon="arrow_back", on_click=lambda: ui.navigate.to('/')).props("round")
|
||||
ui.button("Spiel eintragen", on_click=lambda: ui.navigate.to(f'/add-match/{system_name}'))
|
||||
|
||||
with ui.column().classes('w-full items-center justify-center mt-10'):
|
||||
ui.label(f'Deine Statistik in {system_name}').classes('text-3xl justify-center font-bold text-normaltext')
|
||||
|
||||
# --- BLOCK 1 (MMR & Rang | Rangliste) ---
|
||||
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"):
|
||||
with ui.row().classes("w-full items-center text-center"):
|
||||
ui.label("MMR Punkte: ").classes('justify-center text-2xl font-bold text-normaltext')
|
||||
ui.space()
|
||||
info_system.create_info_button("mmr_info")
|
||||
ui.label(str(player_stats["mmr"])).classes('text-4xl font-bold text-accent')
|
||||
|
||||
with ui.card().classes("w-full items-center justify-center text-center"):
|
||||
with ui.row().classes("w-full items-center text-center"):
|
||||
ui.label("Rang: ").classes('justify-center text-2xl font-bold text-normaltext')
|
||||
ui.space()
|
||||
info_system.create_info_button("rang_info")
|
||||
ui.label(str(data_api.get_player_rank(player_id,system_id))).classes('text-4xl font-bold text-blue-100')
|
||||
|
||||
|
||||
with ui.card().classes("w-full lg:col-span-2 max-h-[50vh] overflow-y-auto"):
|
||||
ui.label("Liga Rangliste").classes("text-xl font-bold text-white mb-2 top-0 bg-zinc-900 z-10")
|
||||
Leaderboard(system_name)
|
||||
|
||||
# --- 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(player_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(player_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')
|
||||
ui.label(str(player_stats["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(str(player_stats["nemesis_id"])).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(str(player_stats["nemesis_id"])).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(str(player_stats["pushover_id"])).classes('text-4xl font-bold text-blue-100')
|
||||
|
||||
|
|
@ -72,7 +72,6 @@ def setup_routes(admin_discord_id):
|
|||
new_name = name_input.value
|
||||
# Nur speichern, wenn ein Name drinsteht und er anders ist als vorher
|
||||
if new_name and new_name != display_name:
|
||||
print("save")
|
||||
data_api.change_display_name(player_id, new_name) # Deine DB Funktion
|
||||
app.storage.user['display_name'] = new_name
|
||||
ui.notify('Name gespeichert!', color='positive')
|
||||
|
|
|
|||
|
|
@ -1,26 +1,88 @@
|
|||
import schedule
|
||||
import time
|
||||
from datetime import date
|
||||
from data import database
|
||||
|
||||
from data import database, data_api
|
||||
from wood import logger
|
||||
|
||||
def check_new_seasons():
|
||||
print("Season mach brrrrr")
|
||||
today = date.today()
|
||||
|
||||
conn = database.db_connection()
|
||||
cursor = conn.cursor(dictionary=True)
|
||||
|
||||
# 1. Prüfen, ob für heute ein Start geplant ist
|
||||
cursor.execute(
|
||||
"SELECT id, gamesystem_id FROM season_schedule "
|
||||
"WHERE start_month = %s AND start_day = %s",
|
||||
(today.month, today.day)
|
||||
)
|
||||
triggers = cursor.fetchall()
|
||||
print(triggers)
|
||||
|
||||
print(f"[Season Check] {today} – {len(triggers)} Treffer gefunden")
|
||||
for trigger in triggers:
|
||||
gamesystem_id = trigger['gamesystem_id']
|
||||
|
||||
# 2. Prüfen, ob heute schon eine Season für das System erstellt wurde
|
||||
cursor.execute(
|
||||
"SELECT id FROM seasons WHERE gamesystem_id = %s AND start_date = %s",
|
||||
(gamesystem_id, today)
|
||||
)
|
||||
if cursor.fetchone():
|
||||
continue
|
||||
|
||||
# 3. Alte Season beenden (end_date = gestern)
|
||||
cursor.execute(
|
||||
"UPDATE seasons SET end_date = DATE_SUB(CURDATE(), INTERVAL 1 DAY) "
|
||||
"WHERE gamesystem_id = %s AND end_date IS NULL",
|
||||
(gamesystem_id,)
|
||||
)
|
||||
|
||||
# 4. Neue Season anlegen
|
||||
cursor.execute(
|
||||
"SELECT MAX(season_number) as last_num FROM seasons WHERE gamesystem_id = %s",
|
||||
(gamesystem_id,)
|
||||
)
|
||||
result = cursor.fetchone()
|
||||
last_num = result['last_num'] if result['last_num'] else 0
|
||||
new_season_number = last_num + 1
|
||||
|
||||
cursor.execute(
|
||||
"INSERT INTO seasons (gamesystem_id, name, start_date, season_number) "
|
||||
"VALUES (%s, %s, %s, %s)",
|
||||
(gamesystem_id, f"{data_api.get_system_name_by_id(gamesystem_id)} - Season{new_season_number}", today, new_season_number)
|
||||
)
|
||||
new_season_id = cursor.lastrowid
|
||||
|
||||
logger.log(f"new Season for {data_api.get_system_name_by_id(gamesystem_id)}, Season ID:{new_season_id}")
|
||||
|
||||
# 5. AUTO-JOIN: Spieler der alten Season in die neue Season kopieren
|
||||
cursor.execute(
|
||||
"SELECT id FROM seasons WHERE gamesystem_id = %s AND id != %s ORDER BY id DESC LIMIT 1",
|
||||
(gamesystem_id, new_season_id)
|
||||
)
|
||||
old_season = cursor.fetchone()
|
||||
|
||||
if old_season:
|
||||
old_season_id = old_season['id']
|
||||
|
||||
# Der Auto-Join Befehl
|
||||
# Wir nehmen player_id und gamesystem_id aus der alten Season
|
||||
# und setzen die neue season_id ein.
|
||||
cursor.execute("""
|
||||
INSERT INTO player_game_statistic (player_id, gamesystem_id, season_id, wins, loss, draws, games_in_system)
|
||||
SELECT player_id, gamesystem_id, %s, 0, 0, 0, 0
|
||||
FROM player_game_statistic
|
||||
WHERE season_id = %s
|
||||
""", (new_season_id, old_season_id))
|
||||
|
||||
logger.log(f"Player copied from SeasonID {old_season_id} to SeasonID {new_season_id}")
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
|
||||
|
||||
|
||||
def run_scheduler():
|
||||
"""Läuft in einem Hintergrund-Thread."""
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user