From aaaf6d44e979f7f697090033f1f34ffde3c18d59 Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Wed, 18 Mar 2026 15:14:29 +0000 Subject: [PATCH 1/5] Kleine UI Verbesserung auf der main seite. --- gui/main_gui.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gui/main_gui.py b/gui/main_gui.py index d70b36b..adc4251 100644 --- a/gui/main_gui.py +++ b/gui/main_gui.py @@ -132,9 +132,10 @@ def setup_routes(admin_discord_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'): - # Info-Text: Was wurde eingetragen? - info_text = f"[{match['system_name']}] {match['p1_name']} behauptet: Er hat {match['score_player1']} : {match['score_player2']} gegen dich gespielt." - ui.label(info_text).classes('text-lg text-gray-200') + info_text = f"{match['system_name']} - {match["played_at"]} " + detail_text = f"{match['p1_name']} behauptet: {match['p1_name']} ({match['score_player1']}) vs. Du ({match['score_player2']})" + 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!) with ui.row().classes('gap-2'): @@ -143,7 +144,7 @@ def setup_routes(admin_discord_id): ui.space() # 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.label("Bestätigen wenn die Angaben stimmen, ablehnen wenn sich ein Fehler eingeschlichen hat.") # --------------------------- # --- Selbst eingetragene, offene Spiele --- @@ -152,7 +153,7 @@ def setup_routes(admin_discord_id): if len(submitted_matches) > 0: # Eine etwas dezentere Karte (grau) 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: # 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 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 = f"[{match['system_name']}] Warten auf Bestätigung von {match['p2_name']} ({match['score_player1']} : {match['score_player2']})" - ui.label(info_text).classes('text-lg text-gray-400') - - # Der Zurückziehen-Button (wieder mit unserem lambda m_id=... Trick!) - ui.button("Zurückziehen", color="warning", icon="delete", on_click=lambda e, m_id=match['match_id']: retract_match(m_id)) - + info_text = f"{match['system_name']} - {match["played_at"]} " + 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') + ui.label(detail_text).classes('text-bold text-normaltext') + 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 --- -- 2.43.0 From 7c5f1d1e3300c45610aee4f7fbd21b5f0fb58dd0 Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Wed, 18 Mar 2026 21:24:05 +0100 Subject: [PATCH 2/5] Log Messages in der data_api angepasst. --- ...-c446a3b8-a6ed-40c3-a878-3069e9d230cb.json | 2 +- data/data_api.py | 26 +++-- gui/match_history_gui.py | 108 +++++++++++------- 3 files changed, 81 insertions(+), 55 deletions(-) diff --git a/.nicegui/storage-user-c446a3b8-a6ed-40c3-a878-3069e9d230cb.json b/.nicegui/storage-user-c446a3b8-a6ed-40c3-a878-3069e9d230cb.json index 9e26dfe..cf2e059 100644 --- a/.nicegui/storage-user-c446a3b8-a6ed-40c3-a878-3069e9d230cb.json +++ b/.nicegui/storage-user-c446a3b8-a6ed-40c3-a878-3069e9d230cb.json @@ -1 +1 @@ -{} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/data/data_api.py b/data/data_api.py index 97dc0d6..ab2a1fc 100644 --- a/data/data_api.py +++ b/data/data_api.py @@ -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. 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)) - 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() cursor.execute("SELECT id, discord_name, display_name, discord_avatar_url FROM players WHERE discord_id = ?", (discord_id,)) player = cursor.fetchone() @@ -178,7 +178,7 @@ def join_league(player_id, gamesystem_id): INSERT INTO player_game_statistic (player_id, gamesystem_id) 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)) 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)) 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.close() @@ -335,12 +335,12 @@ def save_calculated_match(calc_results: dict): )) 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 except Exception as e: 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 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 - - - def get_gamesystems_data(): 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) 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.close() @@ -602,15 +598,20 @@ def get_submitted_matches(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.row_factory = sqlite3.Row cursor = connection.cursor() query = """ 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.player2_id, p2.display_name AS p2_display, p2.discord_name AS p2_discord, m.score_player2, m.player2_mmr_change, + m.player1_id, p1.display_name AS p1_display, p1.discord_name AS p1_discord, + 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 FROM matches m JOIN gamesystems sys ON m.gamesystem_id = sys.id @@ -629,6 +630,7 @@ def get_match_history_log(player_id): + # ----------------------------------------------------- # Testing and Prototyping # ----------------------------------------------------- diff --git a/gui/match_history_gui.py b/gui/match_history_gui.py index 1ccd79a..8244ec2 100644 --- a/gui/match_history_gui.py +++ b/gui/match_history_gui.py @@ -1,6 +1,7 @@ from nicegui import ui, app from data import data_api -from gui import gui_style +from gui import gui_style + def setup_routes(): @ui.page('/matchhistory', dark=True) @@ -8,17 +9,14 @@ def setup_routes(): gui_style.apply_design() - # Sicherheits-Check: Ist der Nutzer eingeloggt? if not app.storage.user.get('authenticated', False): ui.label('Bitte logge dich ein.').classes('text-red-500 text-2xl m-4') return player_id = app.storage.user.get('db_id') - # Das Haupt-Layout der Seite - with ui.column().classes('w-full max-w-5xl mx-auto p-4'): + with ui.column().classes('w-full max-w-7xl mx-auto p-4'): - # Kopfbereich mit Zurück-Button 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.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) 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): - # Bin ich P1 oder P2? - if match['player1_id'] == player_id: + is_player1 = match['player1_id'] == player_id + pending = match['match_is_counted'] == 0 + + if is_player1: opponent = f"{match['p2_display']} aka {match['p2_discord']}" my_score = match['score_player1'] opp_score = match['score_player2'] my_mmr_change = match['player1_mmr_change'] + my_khorne = match['player1_khorne'] + my_tzeentch = match['player1_tzeentch'] + my_slaanesh = match['player1_slaanesh'] else: opponent = f"{match['p1_display']} aka {match['p1_discord']}" my_score = match['score_player2'] opp_score = match['score_player1'] 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: result = "Gewonnen" elif my_score < opp_score: @@ -48,51 +62,61 @@ def setup_routes(): else: result = "Unentschieden" - # MMR Text schön formatieren - if match['match_is_counted'] == 0: - 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) + elo_factor = match['elo_factor'] + rust_factor = match['rust_factor'] table_rows.append({ 'id': i, 'date': str(match['played_at'])[:10], 'system': match['gamesystem_name'], + 'score': str(my_score), 'opponent': opponent, - 'score': f"{my_score}", - 'opp_score': f"{opp_score}", + 'opp_score': str(opp_score), '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 = [ - {'name': 'date', 'label': 'Datum', 'field': 'date', 'align': 'left'}, - {'name': 'system', 'label': 'System', 'field': 'system', 'align': 'left'}, - {'name': 'score', 'label': 'Punkte', 'field': 'score', 'align': 'left'}, - {'name': 'opponent', 'label': 'Gegner', 'field': 'opponent', 'align': 'left'}, - {'name': 'opp_score', 'label': 'Gegner Punkte', 'field': 'score', 'align': 'center'}, - {'name': 'result', 'label': 'Ergebnis', 'field': 'result', 'align': 'left'}, - {'name': 'mmr', 'label': 'MMR Änderung', 'field': 'mmr', 'align': 'right'} + {'name': 'date', 'label': 'Datum', 'field': 'date', 'align': 'left'}, + {'name': 'system', 'label': 'System', 'field': 'system', 'align': 'left'}, + {'name': 'score', 'label': 'Eigene Punkte', 'field': 'score', 'align': 'center'}, + {'name': 'opponent', 'label': 'Gegner', 'field': 'opponent', 'align': 'left'}, + {'name': 'opp_score','label': 'Gegner Punkte', 'field': 'opp_score','align': 'center'}, + {'name': 'result', 'label': 'Ergebnis', 'field': 'result', 'align': 'left'}, + {'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 - if len(table_rows) > 0: - history_table = ui.table(columns=columns, rows=table_rows, row_key='id').classes('w-full bg-zinc-900 text-white') + # Shared slot template for colored signed values + colored_slot = ''' + + + {{ props.row[props.col.field] }} + + + ''' - # KLEINER TRICK: Wir färben die MMR-Spalte grün oder rot, je nachdem ob da ein "+" oder "-" steht! - history_table.add_slot('body-cell-mmr', ''' - - - {{ props.row.mmr }} - - - ''') + if table_rows: + history_table = ui.table( + columns=columns, + rows=table_rows, + row_key='id' + ).classes('w-full bg-zinc-900 text-white') + + for col in ['elo', 'rust', 'khorne', 'tzeentch', 'slaanesh', 'mmr']: + history_table.add_slot(f'body-cell-{col}', colored_slot) else: ui.label("Keine Spiele gefunden.").classes("text-gray-400 italic") -- 2.43.0 From a262088e00b9c882f9e6e0d829f7c0e6145724d2 Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Wed, 18 Mar 2026 21:48:06 +0100 Subject: [PATCH 3/5] Match Formular angepasst. --- gui/info_text/info_texts.json | 17 +++++------------ gui/match_gui.py | 30 +++++++++--------------------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/gui/info_text/info_texts.json b/gui/info_text/info_texts.json index 83c107b..034cce9 100644 --- a/gui/info_text/info_texts.json +++ b/gui/info_text/info_texts.json @@ -3,22 +3,15 @@ "Um einer Liga beizutreten einfach auf **BEITRETEN** drücken und bestätigen.", "Um deine Statistik in einer Liga zu sehen, klick auf eine Liga." ], - "mmr_info": [ "**MMR Punkte** sind die Liga Punkte um die gespielt wird.", "Verliert man ein Spiel, verliert man Punkte. Und umgekehrt." ], - "match_form_info": [ "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":[ - - ], - - "prügelknabe_info":[ - - ] -} + "tyrann_info": [], + "prügelknabe_info": [] +} \ No newline at end of file diff --git a/gui/match_gui.py b/gui/match_gui.py index 072a361..d4a91eb 100644 --- a/gui/match_gui.py +++ b/gui/match_gui.py @@ -2,6 +2,7 @@ from nicegui import ui, app from gui import gui_style from data import data_api from match_calculations import calc_match +from gui.info_text import info_system 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 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') - # ÄNDERUNG: h-60 entfernt, stattdessen gap-6 (Abstand zwischen den Elementen) with ui.column().classes("w-full items-center gap-6"): - # 1. Daten aus der DB holen raw_players = data_api.get_all_players_from_system(systemname) my_id = app.storage.user.get('db_id') - # 3. Eine saubere Optionen-Liste für NiceGUI bauen dropdown_options = {} - for p in raw_players: if p['player_id'] == my_id: continue dropdown_options[p['player_id']] = f"{p['display_name']} 'aka' {p['discord_name']}" - # ÄNDERUNG: .classes('w-full') hinzugefügt, damit der Slider sich anpasst - p1_points = ui.slider(min=0, max=100, value=10).props("label-always").classes('w-full') + with ui.row().classes("w-full items-center justify-between"): + 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 - # 5. Dropdown und Gegner Punkte + 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') - - # ÄNDERUNG: .classes('w-full') hinzugefügt - p2_points = ui.slider(min=0, max=100, value=10).props("label-always").classes('w-full') + with ui.row().classes("w-full items-center justify-between"): + p2_points = ui.slider(min=0, max=100, value=10).classes("w-70") + ui.label().bind_text_from(p2_points, 'value').classes("text-lg text-normaltext") ui.space() @@ -71,15 +66,8 @@ def setup_routes(): ui.notify("Match erfolgreich eingetragen!", color="green") 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 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="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()) -- 2.43.0 From 6855f87d02c0b8f98a9fb781ea851446a78dcfdb Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Fri, 20 Mar 2026 10:17:29 +0000 Subject: [PATCH 4/5] =?UTF-8?q?Tzeench=20Regel=20eingebunden.=20Point=20In?= =?UTF-8?q?flation=20auf=200.8=20ge=C3=A4ndert.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...e-user-21d6fdd4-43d2-4625-8dc2-9282b6aa433f.json | 2 +- match_calculations/calc_match.py | 13 ++++++------- match_calculations/calculation.py | 12 ++++++++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.nicegui/storage-user-21d6fdd4-43d2-4625-8dc2-9282b6aa433f.json b/.nicegui/storage-user-21d6fdd4-43d2-4625-8dc2-9282b6aa433f.json index cf2e059..768c8da 100644 --- a/.nicegui/storage-user-21d6fdd4-43d2-4625-8dc2-9282b6aa433f.json +++ b/.nicegui/storage-user-21d6fdd4-43d2-4625-8dc2-9282b6aa433f.json @@ -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"} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/match_calculations/calc_match.py b/match_calculations/calc_match.py index a6c7511..58db5dc 100644 --- a/match_calculations/calc_match.py +++ b/match_calculations/calc_match.py @@ -5,8 +5,8 @@ import os from wood import logger -point_inflation = 0.7 # => entspricht % -K_FACTOR = 30 # Die "Border" (Maximalpunkte) die ein Sieg gibt. +point_inflation = 0,8 # => entspricht % +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. def calculate_match (match_id): @@ -62,8 +62,8 @@ def calculate_match (match_id): l_base = int(base_change*point_inflation) l_khorne = int(calculation.wrath_of_khorne(looser_id, system_id)) - slaanesh = int(calculation.slaanesh_delight()) - tzeentch = int(calculation.tzeentch_scemes(system_id, winner_score, looser_score)) + slaanesh = calculation.slaanesh_delight() + tzeentch = calculation.tzeentch_schemes(system_id, winner_score, looser_score) # ========================================== # 3. Daten Verpacken @@ -93,9 +93,8 @@ def calculate_match (match_id): } } - logger.log("MATCH CALC", f"Match{match_id} berechnet.") - 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("MATCH CALC", f"Looser {data_api.get_player_name(looser_id)}: Base {l_base} + Khorne {l_khorne} - Slaanesh {slaanesh} - Tzeentch {tzeentch}") + 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(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"]}") data_api.save_calculated_match(calc_results) diff --git a/match_calculations/calculation.py b/match_calculations/calculation.py index 4444bb3..f2c85b4 100644 --- a/match_calculations/calculation.py +++ b/match_calculations/calculation.py @@ -67,11 +67,15 @@ def wrath_of_khorne(player_id, system_id): def slaanesh_delight(): 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) - min_score = sys_data["min_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 -- 2.43.0 From 46eee731dce4bd6289e81e7ecb0cbfed0e94f275 Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Fri, 20 Mar 2026 10:18:34 +0000 Subject: [PATCH 5/5] Tzeench Regel und Point Inflation angepasst. --- match_calculations/calc_match.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/match_calculations/calc_match.py b/match_calculations/calc_match.py index 58db5dc..1c92452 100644 --- a/match_calculations/calc_match.py +++ b/match_calculations/calc_match.py @@ -5,7 +5,7 @@ import os from wood import logger -point_inflation = 0,8 # => entspricht % +point_inflation = 0.8 # => entspricht % 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. -- 2.43.0