commit
776171a07b
|
|
@ -1 +1 @@
|
||||||
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"DN","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}
|
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"Verwirrter Klebschnüffler","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{}
|
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"DN","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}
|
||||||
|
|
@ -54,7 +54,7 @@ def get_or_create_player(discord_id, discord_name, avatar_url):
|
||||||
# Random Silly Name Generator für neue Spieler. Damit sie angeregt werden ihren richtigen Namen einzutragen.
|
# Random Silly Name Generator für neue Spieler. Damit sie angeregt werden ihren richtigen Namen einzutragen.
|
||||||
silly_name = generate_silly_name()
|
silly_name = generate_silly_name()
|
||||||
cursor.execute("INSERT INTO players (discord_id, discord_name, display_name, discord_avatar_url) VALUES (?, ?, ?, ?)", (discord_id, discord_name, silly_name, avatar_url))
|
cursor.execute("INSERT INTO players (discord_id, discord_name, display_name, discord_avatar_url) VALUES (?, ?, ?, ?)", (discord_id, discord_name, silly_name, avatar_url))
|
||||||
logger.log("NEW PLAYER", str("Ein neuer Spieler wurde angelegt - " + discord_name))
|
logger.log("data_api.get_or_create_player", str("Ein neuer Spieler wurde angelegt - " + discord_name))
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.execute("SELECT id, discord_name, display_name, discord_avatar_url FROM players WHERE discord_id = ?", (discord_id,))
|
cursor.execute("SELECT id, discord_name, display_name, discord_avatar_url FROM players WHERE discord_id = ?", (discord_id,))
|
||||||
player = cursor.fetchone()
|
player = cursor.fetchone()
|
||||||
|
|
@ -178,7 +178,7 @@ def join_league(player_id, gamesystem_id):
|
||||||
INSERT INTO player_game_statistic (player_id, gamesystem_id)
|
INSERT INTO player_game_statistic (player_id, gamesystem_id)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
"""
|
"""
|
||||||
logger.log("DataAPI", f"{get_player_name(player_id)} joined {gamesystem_id}", player_id)
|
logger.log("data_api.join_league", f"{get_player_name(player_id)} joined {gamesystem_id}", player_id)
|
||||||
cursor.execute(query, (player_id, gamesystem_id))
|
cursor.execute(query, (player_id, gamesystem_id))
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
|
|
@ -250,7 +250,7 @@ def add_new_match(system_name, player1_id, player2_id, score_p1, score_p2):
|
||||||
cursor.execute(query, (sys_id, player1_id, player2_id, score_p1, score_p2))
|
cursor.execute(query, (sys_id, player1_id, player2_id, score_p1, score_p2))
|
||||||
new_match_id = cursor.lastrowid
|
new_match_id = cursor.lastrowid
|
||||||
|
|
||||||
logger.log("DataAPI", f"{get_player_name(player1_id)}:({score_p1}) posted Match. System: {system_name}, {get_player_name(player2_id)}:({score_p2})", player1_id)
|
logger.log("data_api.add_new_match", f"{get_player_name(player1_id)}:({score_p1}) posted Match. System: {system_name}, {get_player_name(player2_id)}:({score_p2})", player1_id)
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
@ -335,12 +335,12 @@ def save_calculated_match(calc_results: dict):
|
||||||
))
|
))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
logger.log("MATCH_CALC", f"Match ID {match_id} wurde komplett berechnet und verbucht.")
|
logger.log("pi.save_calculated_match", f"Match ID:{match_id} berechnet.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
connection.rollback()
|
connection.rollback()
|
||||||
print(f"KRITISCHER FEHLER beim Speichern des Matches: {e}")
|
logger.log("data_api.save_calculated_match", f"KRITISCHER FEHLER beim Speichern des Matches: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
|
@ -363,9 +363,6 @@ def get_gamesystem_data(system_id):
|
||||||
return dict(zip([col[0] for col in cursor.description], row)) if row else None
|
return dict(zip([col[0] for col in cursor.description], row)) if row else None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_gamesystems_data():
|
def get_gamesystems_data():
|
||||||
connection = sqlite3.connect(DB_PATH)
|
connection = sqlite3.connect(DB_PATH)
|
||||||
|
|
||||||
|
|
@ -572,7 +569,6 @@ def set_match_counted(match_id):
|
||||||
|
|
||||||
# Ändert nur die Spalte match_is_counted auf 1 (True)
|
# Ändert nur die Spalte match_is_counted auf 1 (True)
|
||||||
cursor.execute("UPDATE matches SET match_is_counted = 1 WHERE id = ?", (match_id,))
|
cursor.execute("UPDATE matches SET match_is_counted = 1 WHERE id = ?", (match_id,))
|
||||||
logger.log("data_api.set_match_counted", f"Match mit ID: {match_id} berechnet.")
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
|
|
@ -602,15 +598,20 @@ def get_submitted_matches(player_id):
|
||||||
|
|
||||||
|
|
||||||
def get_match_history_log(player_id):
|
def get_match_history_log(player_id):
|
||||||
"""Holt ALLE Matches eines Spielers inklusive der MMR-Änderungen für das Log."""
|
"""Holt ALLE Matches eines Spielers inklusive der MMR-Änderungen und Faktoren für das Log."""
|
||||||
connection = sqlite3.connect(DB_PATH)
|
connection = sqlite3.connect(DB_PATH)
|
||||||
connection.row_factory = sqlite3.Row
|
connection.row_factory = sqlite3.Row
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
SELECT m.played_at, sys.name AS gamesystem_name,
|
SELECT m.played_at, sys.name AS gamesystem_name,
|
||||||
m.player1_id, p1.display_name AS p1_display, p1.discord_name AS p1_discord, m.score_player1, m.player1_mmr_change,
|
m.player1_id, p1.display_name AS p1_display, p1.discord_name AS p1_discord,
|
||||||
m.player2_id, p2.display_name AS p2_display, p2.discord_name AS p2_discord, m.score_player2, m.player2_mmr_change,
|
m.score_player1, m.player1_mmr_change,
|
||||||
|
m.player1_khorne, m.player1_tzeentch, m.player1_slaanesh, m.player1_base_change,
|
||||||
|
m.player2_id, p2.display_name AS p2_display, p2.discord_name AS p2_discord,
|
||||||
|
m.score_player2, m.player2_mmr_change,
|
||||||
|
m.player2_khorne, m.player2_tzeentch, m.player2_slaanesh, m.player2_base_change,
|
||||||
|
m.elo_factor, m.rust_factor,
|
||||||
m.player2_check, m.match_is_counted
|
m.player2_check, m.match_is_counted
|
||||||
FROM matches m
|
FROM matches m
|
||||||
JOIN gamesystems sys ON m.gamesystem_id = sys.id
|
JOIN gamesystems sys ON m.gamesystem_id = sys.id
|
||||||
|
|
@ -629,6 +630,7 @@ def get_match_history_log(player_id):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------
|
# -----------------------------------------------------
|
||||||
# Testing and Prototyping
|
# Testing and Prototyping
|
||||||
# -----------------------------------------------------
|
# -----------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,15 @@
|
||||||
"Um einer Liga beizutreten einfach auf **BEITRETEN** drücken und bestätigen.",
|
"Um einer Liga beizutreten einfach auf **BEITRETEN** drücken und bestätigen.",
|
||||||
"Um deine Statistik in einer Liga zu sehen, klick auf eine Liga."
|
"Um deine Statistik in einer Liga zu sehen, klick auf eine Liga."
|
||||||
],
|
],
|
||||||
|
|
||||||
"mmr_info": [
|
"mmr_info": [
|
||||||
"**MMR Punkte** sind die Liga Punkte um die gespielt wird.",
|
"**MMR Punkte** sind die Liga Punkte um die gespielt wird.",
|
||||||
"Verliert man ein Spiel, verliert man Punkte. Und umgekehrt."
|
"Verliert man ein Spiel, verliert man Punkte. Und umgekehrt."
|
||||||
],
|
],
|
||||||
|
|
||||||
"match_form_info": [
|
"match_form_info": [
|
||||||
"Um ein Spiel einzutragen gibt einfach deine Punkte ein. Wähle deinen Gegner aus. Und gibt seine Punkte ein.",
|
"Um ein Spiel einzutragen gibt einfach deine Punkte ein. Wähle deinen Gegner aus. Und gibt seine Punkte ein.",
|
||||||
"**ACHTUNG:** Ein Spieler ist nur als Gegner auswählbar wenn er sich in der Liga angemeldet hat!"
|
"**ACHTUNG:** Ein Spieler ist nur als Gegner auswählbar wenn er sich in der Liga angemeldet hat!",
|
||||||
|
"Solltest du einen Fehler machen kannst du das 'falsche' Match auf der Hauptseite noch löschen bevor es bestätigt wurde."
|
||||||
],
|
],
|
||||||
|
"tyrann_info": [],
|
||||||
"tyrann_info":[
|
"prügelknabe_info": []
|
||||||
|
}
|
||||||
],
|
|
||||||
|
|
||||||
"prügelknabe_info":[
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -132,9 +132,10 @@ def setup_routes(admin_discord_id):
|
||||||
calc_match.calculate_match(m_id)
|
calc_match.calculate_match(m_id)
|
||||||
|
|
||||||
with ui.row().classes('w-full items-center justify-between bg-zinc-900 p-3 rounded shadow-inner'):
|
with ui.row().classes('w-full items-center justify-between bg-zinc-900 p-3 rounded shadow-inner'):
|
||||||
# Info-Text: Was wurde eingetragen?
|
info_text = f"{match['system_name']} - {match["played_at"]} "
|
||||||
info_text = f"[{match['system_name']}] {match['p1_name']} behauptet: Er hat {match['score_player1']} : {match['score_player2']} gegen dich gespielt."
|
detail_text = f"{match['p1_name']} behauptet: {match['p1_name']} ({match['score_player1']}) vs. Du ({match['score_player2']})"
|
||||||
ui.label(info_text).classes('text-lg text-gray-200')
|
ui.label(info_text).classes('text-bold text-lg text-normaltext')
|
||||||
|
ui.label(detail_text).classes('text-bold text-normaltext')
|
||||||
|
|
||||||
# Die Buttons (Funktion machen wir im nächsten Schritt!)
|
# Die Buttons (Funktion machen wir im nächsten Schritt!)
|
||||||
with ui.row().classes('gap-2'):
|
with ui.row().classes('gap-2'):
|
||||||
|
|
@ -143,7 +144,7 @@ def setup_routes(admin_discord_id):
|
||||||
ui.space()
|
ui.space()
|
||||||
# BESTÄTIGEN und spiel berechnen lassen
|
# BESTÄTIGEN und spiel berechnen lassen
|
||||||
ui.button(color="positive", icon="check", on_click=lambda e, m_id=match['match_id']: acccept_match(m_id))
|
ui.button(color="positive", icon="check", on_click=lambda e, m_id=match['match_id']: acccept_match(m_id))
|
||||||
|
ui.label("Bestätigen wenn die Angaben stimmen, ablehnen wenn sich ein Fehler eingeschlichen hat.")
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# --- Selbst eingetragene, offene Spiele ---
|
# --- Selbst eingetragene, offene Spiele ---
|
||||||
|
|
@ -152,7 +153,7 @@ def setup_routes(admin_discord_id):
|
||||||
if len(submitted_matches) > 0:
|
if len(submitted_matches) > 0:
|
||||||
# Eine etwas dezentere Karte (grau)
|
# Eine etwas dezentere Karte (grau)
|
||||||
with ui.card().classes('w-full bg-zinc-800 border border-gray-600 mb-6'):
|
with ui.card().classes('w-full bg-zinc-800 border border-gray-600 mb-6'):
|
||||||
ui.label(f"Warten auf Gegner: Du hast {len(submitted_matches)} offene(s) Spiel(e) eingetragen.").classes('text-xl font-bold text-gray-300 mb-2')
|
ui.label(f"Warten auf Gegner: Du hast {len(submitted_matches)} offene(s) Spiel(e).").classes('text-xl font-bold text-gray-300 mb-2')
|
||||||
|
|
||||||
for match in submitted_matches:
|
for match in submitted_matches:
|
||||||
# Die Lösch-Funktion, die beim Klick ausgeführt wird
|
# Die Lösch-Funktion, die beim Klick ausgeführt wird
|
||||||
|
|
@ -163,14 +164,13 @@ def setup_routes(admin_discord_id):
|
||||||
|
|
||||||
# Für jedes Match machen wir eine kleine Reihe
|
# Für jedes Match machen wir eine kleine Reihe
|
||||||
with ui.row().classes('w-full items-center justify-between bg-zinc-900 p-3 rounded shadow-inner'):
|
with ui.row().classes('w-full items-center justify-between bg-zinc-900 p-3 rounded shadow-inner'):
|
||||||
|
|
||||||
# Info-Text: Auf wen warten wir?
|
# Info-Text: Auf wen warten wir?
|
||||||
info_text = f"[{match['system_name']}] Warten auf Bestätigung von {match['p2_name']} ({match['score_player1']} : {match['score_player2']})"
|
info_text = f"{match['system_name']} - {match["played_at"]} "
|
||||||
ui.label(info_text).classes('text-lg text-gray-400')
|
detail_text = f"Du ({match["score_player1"]}) vs. {match["p2_name"]}({match["score_player2"]})"
|
||||||
|
ui.label(info_text).classes('text-bold text-lg text-normaltext')
|
||||||
# Der Zurückziehen-Button (wieder mit unserem lambda m_id=... Trick!)
|
ui.label(detail_text).classes('text-bold text-normaltext')
|
||||||
ui.button("Zurückziehen", color="warning", icon="delete", on_click=lambda e, m_id=match['match_id']: retract_match(m_id))
|
ui.button(color="warning", icon="delete", on_click=lambda e, m_id=match['match_id']: retract_match(m_id))
|
||||||
|
ui.label("Dein Gegner muss das Match noch bestätigen. Wenn du einen Fehler gemacht hast, kannst du es löschen.")
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# --- Spielsysteme ---
|
# --- Spielsysteme ---
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from nicegui import ui, app
|
||||||
from gui import gui_style
|
from gui import gui_style
|
||||||
from data import data_api
|
from data import data_api
|
||||||
from match_calculations import calc_match
|
from match_calculations import calc_match
|
||||||
|
from gui.info_text import info_system
|
||||||
|
|
||||||
def setup_routes():
|
def setup_routes():
|
||||||
|
|
||||||
|
|
@ -21,37 +22,31 @@ def setup_routes():
|
||||||
|
|
||||||
# Text-Center hinzugefügt, falls der Systemname sehr lang ist und auf dem Handy umbricht
|
# Text-Center hinzugefügt, falls der Systemname sehr lang ist und auf dem Handy umbricht
|
||||||
ui.label(f'Neues Spiel für {systemname} eintragen').classes('text-2xl font-bold text-center mb-6')
|
ui.label(f'Neues Spiel für {systemname} eintragen').classes('text-2xl font-bold text-center mb-6')
|
||||||
|
|
||||||
ui.label("Meine Punkte:").classes('text-xl font-bold w-full text-left')
|
ui.label("Meine Punkte:").classes('text-xl font-bold w-full text-left')
|
||||||
|
|
||||||
# ÄNDERUNG: h-60 entfernt, stattdessen gap-6 (Abstand zwischen den Elementen)
|
|
||||||
with ui.column().classes("w-full items-center gap-6"):
|
with ui.column().classes("w-full items-center gap-6"):
|
||||||
|
|
||||||
# 1. Daten aus der DB holen
|
# 1. Daten aus der DB holen
|
||||||
raw_players = data_api.get_all_players_from_system(systemname)
|
raw_players = data_api.get_all_players_from_system(systemname)
|
||||||
my_id = app.storage.user.get('db_id')
|
my_id = app.storage.user.get('db_id')
|
||||||
|
|
||||||
# 3. Eine saubere Optionen-Liste für NiceGUI bauen
|
|
||||||
dropdown_options = {}
|
dropdown_options = {}
|
||||||
|
|
||||||
for p in raw_players:
|
for p in raw_players:
|
||||||
if p['player_id'] == my_id:
|
if p['player_id'] == my_id:
|
||||||
continue
|
continue
|
||||||
dropdown_options[p['player_id']] = f"{p['display_name']} 'aka' {p['discord_name']}"
|
dropdown_options[p['player_id']] = f"{p['display_name']} 'aka' {p['discord_name']}"
|
||||||
|
|
||||||
# ÄNDERUNG: .classes('w-full') hinzugefügt, damit der Slider sich anpasst
|
with ui.row().classes("w-full items-center justify-between"):
|
||||||
p1_points = ui.slider(min=0, max=100, value=10).props("label-always").classes('w-full')
|
p1_points = ui.slider(min=0, max=100, value=10).classes("w-70")
|
||||||
|
ui.label().bind_text_from(p1_points, 'value').classes("text-lg text-normaltext")
|
||||||
|
|
||||||
ui.separator().classes('w-full mt-4') # Ein schöner Trennstrich für die Optik
|
ui.separator().classes('w-full mt-4') # Ein schöner Trennstrich für die Optik
|
||||||
|
|
||||||
# 5. Dropdown und Gegner Punkte
|
|
||||||
ui.label("Gegner:").classes('text-xl font-bold w-full text-left')
|
ui.label("Gegner:").classes('text-xl font-bold w-full text-left')
|
||||||
|
|
||||||
# ÄNDERUNG: w-64 durch w-full ersetzt
|
|
||||||
opponent_select = ui.select(options=dropdown_options, label='Gegner auswählen').classes('w-full')
|
opponent_select = ui.select(options=dropdown_options, label='Gegner auswählen').classes('w-full')
|
||||||
|
with ui.row().classes("w-full items-center justify-between"):
|
||||||
# ÄNDERUNG: .classes('w-full') hinzugefügt
|
p2_points = ui.slider(min=0, max=100, value=10).classes("w-70")
|
||||||
p2_points = ui.slider(min=0, max=100, value=10).props("label-always").classes('w-full')
|
ui.label().bind_text_from(p2_points, 'value').classes("text-lg text-normaltext")
|
||||||
|
|
||||||
ui.space()
|
ui.space()
|
||||||
|
|
||||||
|
|
@ -71,15 +66,8 @@ def setup_routes():
|
||||||
ui.notify("Match erfolgreich eingetragen!", color="green")
|
ui.notify("Match erfolgreich eingetragen!", color="green")
|
||||||
ui.navigate.to(f'/statistic/{systemname}')
|
ui.navigate.to(f'/statistic/{systemname}')
|
||||||
|
|
||||||
|
|
||||||
with ui.dialog().classes("w-full items-center") as form_info, ui.card():
|
|
||||||
ui.label('Um ein Spiel einzutragen einfach deine erspielten Punkte, deinen Gegner und die Punkte von deinem Gegner eintragen').classes("font-bold text-white text-l")
|
|
||||||
ui.label('ACHTUNG: Damit ein Spieler als Gegner ausgewählt werden kann, muss er der Liga beigetreten sein!').classes("font-bold text-white text-l")
|
|
||||||
ui.label('Nach dem Absenden muss dein Gegner in seiner Liga App das Spiel noch kurz bestätigen. Solltest du einen Fehler gemacht haben, kannst du das Spiel (bevor es bestätigt wurde) auf der Hauptseite selber löschen.').classes("font-bold text-white text-l")
|
|
||||||
ui.button(icon="close", on_click=form_info.close).classes("w-10 h-8 rounded-full")
|
|
||||||
|
|
||||||
# Buttons ganz unten in einer Reihe
|
# Buttons ganz unten in einer Reihe
|
||||||
with ui.row().classes("w-full items-center justify-between mt-8"):
|
with ui.row().classes("w-full items-center justify-between mt-8"):
|
||||||
ui.button(icon="close", on_click=lambda: ui.navigate.to(f'/statistic/{systemname}')).classes("w-10 h-8 rounded-full")
|
ui.button(icon="close", on_click=lambda: ui.navigate.to(f'/statistic/{systemname}')).classes("w-10 h-8 rounded-full")
|
||||||
ui.button(icon="help", color="information" ,on_click=form_info.open).classes("w-10 h-8 rounded-full")
|
info_system.create_info_button("match_form_info")
|
||||||
ui.button(text="Absenden", color="positive", on_click=lambda: input_match_to_database())
|
ui.button(text="Absenden", color="positive", on_click=lambda: input_match_to_database())
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from nicegui import ui, app
|
from nicegui import ui, app
|
||||||
from data import data_api
|
from data import data_api
|
||||||
from gui import gui_style
|
from gui import gui_style
|
||||||
|
|
||||||
|
|
||||||
def setup_routes():
|
def setup_routes():
|
||||||
@ui.page('/matchhistory', dark=True)
|
@ui.page('/matchhistory', dark=True)
|
||||||
|
|
@ -8,17 +9,14 @@ def setup_routes():
|
||||||
|
|
||||||
gui_style.apply_design()
|
gui_style.apply_design()
|
||||||
|
|
||||||
# Sicherheits-Check: Ist der Nutzer eingeloggt?
|
|
||||||
if not app.storage.user.get('authenticated', False):
|
if not app.storage.user.get('authenticated', False):
|
||||||
ui.label('Bitte logge dich ein.').classes('text-red-500 text-2xl m-4')
|
ui.label('Bitte logge dich ein.').classes('text-red-500 text-2xl m-4')
|
||||||
return
|
return
|
||||||
|
|
||||||
player_id = app.storage.user.get('db_id')
|
player_id = app.storage.user.get('db_id')
|
||||||
|
|
||||||
# Das Haupt-Layout der Seite
|
with ui.column().classes('w-full max-w-7xl mx-auto p-4'):
|
||||||
with ui.column().classes('w-full max-w-5xl mx-auto p-4'):
|
|
||||||
|
|
||||||
# Kopfbereich mit Zurück-Button
|
|
||||||
with ui.row().classes('w-full items-center justify-between mb-6'):
|
with ui.row().classes('w-full items-center justify-between mb-6'):
|
||||||
ui.label("Komplette Match Historie").classes("text-3xl font-bold text-white")
|
ui.label("Komplette Match Historie").classes("text-3xl font-bold text-white")
|
||||||
ui.button("Zurück", icon="arrow_back", on_click=lambda: ui.navigate.to('/')).classes('bg-zinc-700 text-white')
|
ui.button("Zurück", icon="arrow_back", on_click=lambda: ui.navigate.to('/')).classes('bg-zinc-700 text-white')
|
||||||
|
|
@ -26,21 +24,37 @@ def setup_routes():
|
||||||
raw_matches = data_api.get_match_history_log(player_id)
|
raw_matches = data_api.get_match_history_log(player_id)
|
||||||
table_rows = []
|
table_rows = []
|
||||||
|
|
||||||
# Daten für die Tabelle aufbereiten
|
def fmt_signed(val, pending=False):
|
||||||
|
"""Formatiert einen Integer-Wert mit Vorzeichen oder gibt Sondertexte zurück."""
|
||||||
|
if pending:
|
||||||
|
return "Ausstehend"
|
||||||
|
if val is None:
|
||||||
|
return "0"
|
||||||
|
if val > 0:
|
||||||
|
return f"+{val}"
|
||||||
|
return str(val)
|
||||||
|
|
||||||
for i, match in enumerate(raw_matches):
|
for i, match in enumerate(raw_matches):
|
||||||
# Bin ich P1 oder P2?
|
is_player1 = match['player1_id'] == player_id
|
||||||
if match['player1_id'] == player_id:
|
pending = match['match_is_counted'] == 0
|
||||||
|
|
||||||
|
if is_player1:
|
||||||
opponent = f"{match['p2_display']} aka {match['p2_discord']}"
|
opponent = f"{match['p2_display']} aka {match['p2_discord']}"
|
||||||
my_score = match['score_player1']
|
my_score = match['score_player1']
|
||||||
opp_score = match['score_player2']
|
opp_score = match['score_player2']
|
||||||
my_mmr_change = match['player1_mmr_change']
|
my_mmr_change = match['player1_mmr_change']
|
||||||
|
my_khorne = match['player1_khorne']
|
||||||
|
my_tzeentch = match['player1_tzeentch']
|
||||||
|
my_slaanesh = match['player1_slaanesh']
|
||||||
else:
|
else:
|
||||||
opponent = f"{match['p1_display']} aka {match['p1_discord']}"
|
opponent = f"{match['p1_display']} aka {match['p1_discord']}"
|
||||||
my_score = match['score_player2']
|
my_score = match['score_player2']
|
||||||
opp_score = match['score_player1']
|
opp_score = match['score_player1']
|
||||||
my_mmr_change = match['player2_mmr_change']
|
my_mmr_change = match['player2_mmr_change']
|
||||||
|
my_khorne = match['player2_khorne']
|
||||||
|
my_tzeentch = match['player2_tzeentch']
|
||||||
|
my_slaanesh = match['player2_slaanesh']
|
||||||
|
|
||||||
# Ergebnis Text
|
|
||||||
if my_score > opp_score:
|
if my_score > opp_score:
|
||||||
result = "Gewonnen"
|
result = "Gewonnen"
|
||||||
elif my_score < opp_score:
|
elif my_score < opp_score:
|
||||||
|
|
@ -48,51 +62,61 @@ def setup_routes():
|
||||||
else:
|
else:
|
||||||
result = "Unentschieden"
|
result = "Unentschieden"
|
||||||
|
|
||||||
# MMR Text schön formatieren
|
elo_factor = match['elo_factor']
|
||||||
if match['match_is_counted'] == 0:
|
rust_factor = match['rust_factor']
|
||||||
mmr_text = "Ausstehend"
|
|
||||||
elif my_mmr_change is None:
|
|
||||||
mmr_text = "0"
|
|
||||||
elif my_mmr_change > 0:
|
|
||||||
mmr_text = f"+{my_mmr_change}"
|
|
||||||
elif my_mmr_change < 0:
|
|
||||||
mmr_text = f"{my_mmr_change}"
|
|
||||||
else:
|
|
||||||
mmr_text = str(my_mmr_change)
|
|
||||||
|
|
||||||
table_rows.append({
|
table_rows.append({
|
||||||
'id': i,
|
'id': i,
|
||||||
'date': str(match['played_at'])[:10],
|
'date': str(match['played_at'])[:10],
|
||||||
'system': match['gamesystem_name'],
|
'system': match['gamesystem_name'],
|
||||||
|
'score': str(my_score),
|
||||||
'opponent': opponent,
|
'opponent': opponent,
|
||||||
'score': f"{my_score}",
|
'opp_score': str(opp_score),
|
||||||
'opp_score': f"{opp_score}",
|
|
||||||
'result': result,
|
'result': result,
|
||||||
'mmr': mmr_text
|
'elo': fmt_signed(round(elo_factor, 2) if elo_factor is not None else None, pending),
|
||||||
|
'rust': fmt_signed(round(rust_factor, 2) if rust_factor is not None else None, pending),
|
||||||
|
'khorne': fmt_signed(my_khorne, pending),
|
||||||
|
'tzeentch': fmt_signed(my_tzeentch, pending),
|
||||||
|
'slaanesh': fmt_signed(my_slaanesh, pending),
|
||||||
|
'mmr': fmt_signed(my_mmr_change, pending),
|
||||||
})
|
})
|
||||||
|
|
||||||
# Spalten definieren
|
|
||||||
columns = [
|
columns = [
|
||||||
{'name': 'date', 'label': 'Datum', 'field': 'date', 'align': 'left'},
|
{'name': 'date', 'label': 'Datum', 'field': 'date', 'align': 'left'},
|
||||||
{'name': 'system', 'label': 'System', 'field': 'system', 'align': 'left'},
|
{'name': 'system', 'label': 'System', 'field': 'system', 'align': 'left'},
|
||||||
{'name': 'score', 'label': 'Punkte', 'field': 'score', 'align': 'left'},
|
{'name': 'score', 'label': 'Eigene Punkte', 'field': 'score', 'align': 'center'},
|
||||||
{'name': 'opponent', 'label': 'Gegner', 'field': 'opponent', 'align': 'left'},
|
{'name': 'opponent', 'label': 'Gegner', 'field': 'opponent', 'align': 'left'},
|
||||||
{'name': 'opp_score', 'label': 'Gegner Punkte', 'field': 'score', 'align': 'center'},
|
{'name': 'opp_score','label': 'Gegner Punkte', 'field': 'opp_score','align': 'center'},
|
||||||
{'name': 'result', 'label': 'Ergebnis', 'field': 'result', 'align': 'left'},
|
{'name': 'result', 'label': 'Ergebnis', 'field': 'result', 'align': 'left'},
|
||||||
{'name': 'mmr', 'label': 'MMR Änderung', 'field': 'mmr', 'align': 'right'}
|
{'name': 'elo', 'label': 'Elo Faktor', 'field': 'elo', 'align': 'right'},
|
||||||
|
{'name': 'rust', 'label': 'Rost Faktor', 'field': 'rust', 'align': 'right'},
|
||||||
|
{'name': 'khorne', 'label': 'Khorne', 'field': 'khorne', 'align': 'right'},
|
||||||
|
{'name': 'tzeentch', 'label': 'Tzeentch', 'field': 'tzeentch', 'align': 'right'},
|
||||||
|
{'name': 'slaanesh', 'label': 'Slaanesh', 'field': 'slaanesh', 'align': 'right'},
|
||||||
|
{'name': 'mmr', 'label': 'MMR Änderung', 'field': 'mmr', 'align': 'right'},
|
||||||
]
|
]
|
||||||
|
|
||||||
# Tabelle zeichnen
|
# Shared slot template for colored signed values
|
||||||
if len(table_rows) > 0:
|
colored_slot = '''
|
||||||
history_table = ui.table(columns=columns, rows=table_rows, row_key='id').classes('w-full bg-zinc-900 text-white')
|
<q-td :props="props">
|
||||||
|
<span :class="{
|
||||||
|
'text-green-500 font-bold': props.row[props.col.field].startsWith('+'),
|
||||||
|
'text-red-500 font-bold': props.row[props.col.field].startsWith('-'),
|
||||||
|
'text-gray-400 italic': props.row[props.col.field] === 'Ausstehend'
|
||||||
|
}">
|
||||||
|
{{ props.row[props.col.field] }}
|
||||||
|
</span>
|
||||||
|
</q-td>
|
||||||
|
'''
|
||||||
|
|
||||||
# KLEINER TRICK: Wir färben die MMR-Spalte grün oder rot, je nachdem ob da ein "+" oder "-" steht!
|
if table_rows:
|
||||||
history_table.add_slot('body-cell-mmr', '''
|
history_table = ui.table(
|
||||||
<q-td :props="props">
|
columns=columns,
|
||||||
<span :class="{'text-green-500 font-bold': props.row.mmr.startsWith('+'), 'text-red-500 font-bold': props.row.mmr.startsWith('-'), 'text-gray-400 italic': props.row.mmr === 'Ausstehend'}">
|
rows=table_rows,
|
||||||
{{ props.row.mmr }}
|
row_key='id'
|
||||||
</span>
|
).classes('w-full bg-zinc-900 text-white')
|
||||||
</q-td>
|
|
||||||
''')
|
for col in ['elo', 'rust', 'khorne', 'tzeentch', 'slaanesh', 'mmr']:
|
||||||
|
history_table.add_slot(f'body-cell-{col}', colored_slot)
|
||||||
else:
|
else:
|
||||||
ui.label("Keine Spiele gefunden.").classes("text-gray-400 italic")
|
ui.label("Keine Spiele gefunden.").classes("text-gray-400 italic")
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import os
|
||||||
from wood import logger
|
from wood import logger
|
||||||
|
|
||||||
|
|
||||||
point_inflation = 0.7 # => entspricht %
|
point_inflation = 0.8 # => entspricht %
|
||||||
K_FACTOR = 30 # Die "Border" (Maximalpunkte) die ein Sieg gibt.
|
K_FACTOR = 40 # Die "Border" (Maximalpunkte) die ein Sieg gibt.
|
||||||
|
|
||||||
# Mach die DB abfrage für die Relevanten Daten. Von hier aus werden die "Aufgaben" und Daten dann an die kleineren Berechnungs Funktionen verteilt.
|
# Mach die DB abfrage für die Relevanten Daten. Von hier aus werden die "Aufgaben" und Daten dann an die kleineren Berechnungs Funktionen verteilt.
|
||||||
def calculate_match (match_id):
|
def calculate_match (match_id):
|
||||||
|
|
@ -62,8 +62,8 @@ def calculate_match (match_id):
|
||||||
l_base = int(base_change*point_inflation)
|
l_base = int(base_change*point_inflation)
|
||||||
l_khorne = int(calculation.wrath_of_khorne(looser_id, system_id))
|
l_khorne = int(calculation.wrath_of_khorne(looser_id, system_id))
|
||||||
|
|
||||||
slaanesh = int(calculation.slaanesh_delight())
|
slaanesh = calculation.slaanesh_delight()
|
||||||
tzeentch = int(calculation.tzeentch_scemes(system_id, winner_score, looser_score))
|
tzeentch = calculation.tzeentch_schemes(system_id, winner_score, looser_score)
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# 3. Daten Verpacken
|
# 3. Daten Verpacken
|
||||||
|
|
@ -93,9 +93,8 @@ def calculate_match (match_id):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log("MATCH CALC", f"Match{match_id} berechnet.")
|
logger.log(f"calc_match ID:{match_id}", f"Winner {data_api.get_player_name(winner_id)}: Base {w_base} + Khorne({w_khorne}) + Slaanesh({slaanesh}) + Tzeentch({tzeentch}) = {calc_results[winner_id]["total"]}")
|
||||||
logger.log("MATCH CALC", f"Winner {data_api.get_player_name(winner_id)}: Base {w_base} + Khorne {w_khorne} + Slaanesh {slaanesh} + Tzeentch {tzeentch}")
|
logger.log(f"calc_match ID:{match_id}", f"Looser {data_api.get_player_name(looser_id)}: -Base({l_base}) + Khorne({l_khorne}) - Slaanesh({slaanesh}) - Tzeentch({tzeentch}) = {calc_results[looser_id]["total"]}")
|
||||||
logger.log("MATCH CALC", f"Looser {data_api.get_player_name(looser_id)}: Base {l_base} + Khorne {l_khorne} - Slaanesh {slaanesh} - Tzeentch {tzeentch}")
|
|
||||||
data_api.save_calculated_match(calc_results)
|
data_api.save_calculated_match(calc_results)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,15 @@ def wrath_of_khorne(player_id, system_id):
|
||||||
def slaanesh_delight():
|
def slaanesh_delight():
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def tzeentch_scemes(system_id, winner_score, looser_score):
|
|
||||||
|
def tzeentch_schemes(system_id, winner_score, looser_score):
|
||||||
sys_data = data_api.get_gamesystem_data(system_id)
|
sys_data = data_api.get_gamesystem_data(system_id)
|
||||||
min_score = sys_data["min_score"]
|
|
||||||
max_score = sys_data["max_score"]
|
max_score = sys_data["max_score"]
|
||||||
|
|
||||||
bonus = int(((max_score*(winner_score-looser_score)))/(max_score*1.1)) #Multiplikatiionsfaktor für die Berechnung.
|
diff_normalized = (winner_score - looser_score) / max_score # 0.0 – 1.0
|
||||||
|
threshold = 0.1 # Bonus startet erst ab 10% Vorsprung
|
||||||
|
|
||||||
return 0
|
bonus = int(max(0, diff_normalized - threshold) * 10) # Ergibt 0–9
|
||||||
|
bonus = min(bonus, 9) # Sicherheits-Cap
|
||||||
|
|
||||||
|
return bonus
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user