MMR Berechnung. Aber irgendwas stimmt nicht.

This commit is contained in:
Daniel Nagel 2026-03-12 15:11:54 +00:00
parent a715cd7bff
commit b10a1508f2
4 changed files with 15 additions and 45 deletions

View File

@ -1 +1 @@
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"Schwitzender Klebschnüffler","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"Stolpernder Guardmen","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}

View File

@ -459,7 +459,6 @@ def apply_match_to_player_statistic (player_id, gamesystem_id, mmr_change, score
last_played = CURRENT_TIMESTAMP
WHERE player_id = ? AND gamesystem_id = ?
"""
# ACHTUNG: Wir müssen scored_points ZWEIMAL übergeben!
# Einmal für die 'points' und einmal für die Berechnung der 'avv_points'.
cursor.execute(query, (mmr_change, scored_points, scored_points, player_id, gamesystem_id))
@ -512,7 +511,6 @@ def update_match_mmr_change(match_id, p1_change, p2_change):
connection.close()
def get_player_name(player_id):
"""Gibt den Namen eines Spielers im Format 'Anzeigename (Discordname)' zurück."""
@ -552,7 +550,6 @@ def get_system_name(sys_id):
return "Gelöschtes System"
def get_days_since_last_system_game(player_id, gamesystem_id):
"""Gibt zurück, wie viele Tage das letzte Spiel in einem bestimmten System her ist."""
connection = sqlite3.connect(DB_PATH)
@ -576,7 +573,6 @@ def get_days_since_last_system_game(player_id, gamesystem_id):
# -----------------------------------------------------
# Matches Bestätigen, Löschen, Berechnen, ...
# -----------------------------------------------------
@ -613,7 +609,6 @@ def delete_match(match_id, player_id):
# DELETE FROM löscht die gesamte Zeile, bei der die ID übereinstimmt.
cursor.execute("DELETE FROM matches WHERE id = ?", (match_id,))
logger.log ("MATCH", f"Match mit ID:{match_id} wurde gelöscht von {get_player_name(player_id)}")
connection.commit()
connection.close()
@ -624,7 +619,6 @@ def confirm_match(match_id):
# Ändert nur die Spalte player2_check auf 1 (True)
cursor.execute("UPDATE matches SET player2_check = 1 WHERE id = ?", (match_id,))
logger.log ("MATCH CALC", f"Match mit ID{match_id} wurde als 'Confirmed' gekennzeichnet")
connection.commit()
connection.close()
@ -636,7 +630,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 ("MATCH CALC", f"Match mit ID{match_id} wurde als 'Counted' gekennzeichnet")
connection.commit()
connection.close()
@ -665,8 +658,6 @@ def get_submitted_matches(player_id):
return [dict(row) for row in rows]
def get_match_history_log(player_id):
"""Holt ALLE Matches eines Spielers inklusive der MMR-Änderungen für das Log."""
connection = sqlite3.connect(DB_PATH)

View File

@ -2,6 +2,7 @@ from data import data_api
from match_calculations import calc_mmr_change
import json
import os
from wood import logger
# 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):
@ -30,7 +31,6 @@ def calculate_match (match_id):
draw_diff = determine_draw_diff(sys_id)
# Abgrenzen ob das Match schon berechnet wurde. Weil ein Draw kann 4 Punkte unterschied haben
# 43-41 ist ein Draw aber rein Mathematisch würde es auch ein anderes if triggern
# Abgrenzen, wer gewonnen hat (if, elif, else Kette)
@ -60,7 +60,6 @@ def calculate_match (match_id):
looser_score = p1_score
mmr_change_winner, mmr_change_looser = calc_mmr_change.calc_mmr_change(sys_name, winner_id, looser_id, winner_score, looser_score, match_is_draw)
data_api.apply_match_to_player_statistic (winner_id, sys_id, mmr_change_winner, winner_score)
data_api.apply_match_to_player_statistic (looser_id, sys_id, mmr_change_looser, looser_score)

View File

@ -1,4 +1,5 @@
from data import data_api
from wood import logger
# Faktor für die Punkte Inflation. Um diesen Wert verliert der Verlierer weniger Punkte als der Sieger bekommt. Über Kurz oder Lang werden
# die meisten Spieler über 1000MMR sein. Sprich: Neueinsteiger, oder leute die weniger spielen sind eher im unteren Ende als in der Mitte.
@ -7,7 +8,7 @@ point_inflation = 0.7 # => entspricht % ! z.B. 0.7 = 70%
def calc_mmr_change(systemname, winner_id, looser_id, winner_points, looser_points, match_is_draw):
point_inflation = 0.7 # Verlierer verliert nur 70% der Punkte
K_FACTOR = 35 # Die "Border" (Maximalpunkte) die ein Sieg gibt.
K_FACTOR = 40 # Die "Border" (Maximalpunkte) die ein Sieg gibt.
def get_rust_dampener(days_ago):
"""Berechnet den Dämpfungsfaktor basierend auf den vergangen Tagen."""
@ -27,10 +28,10 @@ def calc_mmr_change(systemname, winner_id, looser_id, winner_points, looser_poin
w_stat = data_api.get_player_system_stats(winner_id, gamesystem_id)
l_stat = data_api.get_player_system_stats(looser_id, gamesystem_id)
# Wenn ein Spieler noch keine keine Stats hat wird None zurück gegeben. Fallback für diesen Fall
w_mmr = w_stat['mmr'] if w_stat and w_stat['mmr'] is not None else 1000
l_mmr = l_stat['mmr'] if l_stat and l_stat['mmr'] is not None else 1000
# 2. Die fließende Elo-Mathematik (Ersetzt die JSON Datei)
# Berechnet die Siegwahrscheinlichkeit des Gewinners (Wert zwischen 0.0 und 1.0)
expected_win = 1 / (1 + 10 ** ((l_mmr - w_mmr) / 400))
@ -46,42 +47,21 @@ def calc_mmr_change(systemname, winner_id, looser_id, winner_points, looser_poin
w_days = data_api.get_days_since_last_system_game(winner_id, gamesystem_id)
l_days = data_api.get_days_since_last_system_game(looser_id, gamesystem_id)
def get_rust_dampener(days_ago):
if days_ago <= 30:
return 1.0 # Volle Punkte
elif days_ago > 90:
return 0.1 # Maximal eingerostet (nur 10% der Punkteänderung)
else:
# Lineare Rampe von 0.8 (bei Tag 31) runter auf 0.1 (bei Tag 90)
# Formel: Startwert - (Differenz * Prozentualer Weg)
factor = 0.8 - 0.7 * ((days_ago - 30) / 60)
return round(factor, 2)
days = max(w_days, l_days)
rust_factor = get_rust_dampener(w_days)
w_mmr_change = base_change * rust_factor
l_mmr_change = base_change * rust_factor
# 4. Deine Sonderregeln (Slaanesh & Khorne) addieren
rust_factor = get_rust_dampener(days)
sla_points = 0 #slaanesh_delight(winner_points, looser_points)
w_mmr_change += sla_points
# Auch der Verlierer bekommt Slaanesh Punkte addiert, wenn es die Regel so sagt
l_mmr_change += sla_points
logger.log(f"MATCH CALC", f"Base Change {base_change}, Rost Faktor {rust_factor}, EloFaktor {expected_win}")
winner_final = int(w_mmr_change + wrath_of_khorne(winner_id))
# 5. Verlierer-Punkte abziehen und Inflation (0.7) anwenden
# Wenn Das Match ein Draw ist, können keine Slaanesh Punkte auftreten.
if match_is_draw:
looser_final = int(-w_mmr_change) # Bei Draw spiegeln wir es einfach (ohne Inflation)
winner_final_mmr_change = int(w_mmr_change + wrath_of_khorne(winner_id)* rust_factor)
looser_final_mmr_change = int(l_mmr_change + wrath_of_khorne(looser_id)* rust_factor)
else:
looser_base = int(l_mmr_change + wrath_of_khorne(looser_id))
looser_final = -int(looser_base * point_inflation)
return winner_final, looser_final
winner_final_mmr_change = int((base_change + wrath_of_khorne(winner_id) + sla_points) * rust_factor)
looser_final_mmr_change = int((base_change + wrath_of_khorne(winner_id) - sla_points) * rust_factor)
return winner_final_mmr_change, looser_final_mmr_change
# -----------------