diff --git a/data/data_api.py b/data/data_api.py index 10aca36..9e68fe0 100644 --- a/data/data_api.py +++ b/data/data_api.py @@ -535,6 +535,7 @@ def get_player_name(player_id): else: return "Gelöschter Spieler" + def get_system_name(sys_id): if sys_id is None: return "Unbekanntes System" @@ -552,6 +553,27 @@ def get_system_name(sys_id): +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) + cursor = connection.cursor() + + # Julianday() berechnet in SQLite die Differenz in Tagen zwischen zwei Daten + query = """ + SELECT CAST(julianday('now') - julianday(last_played) AS INTEGER) + FROM player_game_statistic + WHERE player_id = ? AND gamesystem_id = ? + """ + cursor.execute(query, (player_id, gamesystem_id)) + result = cursor.fetchone() + connection.close() + + # Wenn er gefunden wurde und ein Datum hat, gib die Tage zurück. Sonst (Erstes Spiel) 0. + if result and result[0] is not None: + return result[0] + return 0 + + @@ -668,3 +690,45 @@ def get_match_history_log(player_id): connection.close() return [dict(row) for row in rows] + + + + + +# ----------------------------------------------------- +# Testing and Prototyping +# ----------------------------------------------------- +def create_random_dummy_match(player_id): + connection = sqlite3.connect(DB_PATH) + cursor = connection.cursor() + + # 1. Die ID des Dummys suchen (Wir suchen einfach nach dem Namen 'Dummy') + cursor.execute("SELECT id FROM players WHERE display_name LIKE '%Dummy%' OR discord_name LIKE '%Dummy%' LIMIT 1") + dummy_row = cursor.fetchone() + + if not dummy_row: + connection.close() + print("Fehler: Kein Dummy in der Datenbank gefunden!") + return False + dummy_id = dummy_row[0] + # 2. Zufällige Punkte generieren (z.B. zwischen 0 und 100) + score_p1 = random.randint(0, 100) + score_p2 = random.randint(0, 100) + # 3. Das Match hart in System 1 (gamesystem_id = 1) eintragen + query = """ + INSERT INTO matches (gamesystem_id, player2_id, player1_id, score_player1, score_player2, player2_check) + VALUES (?, ?, ?, ?, ?, 0) + """ + cursor.execute(query, (1, player_id, dummy_id, score_p1, score_p2)) + + connection.commit() + connection.close() + + p1_name = get_player_name(player_id) + dummy_name = get_player_name(dummy_id) + sys_name = get_system_name(1) + + logger.log("TEST_MATCH", f"Zufallsspiel generiert. [{sys_name}]: {p1_name} ({score_p1}) vs. {dummy_name} ({score_p2})", player_id) + + return True + diff --git a/data/setup_database.py b/data/setup_database.py index 7dc1fab..3ca6ceb 100644 --- a/data/setup_database.py +++ b/data/setup_database.py @@ -197,74 +197,3 @@ def seed_dummy_player(): print("Test-Gegner 'Dummy Mc DummDumm' ist bereit und in allen Ligen angemeldet!") - -def generate_default_mmr_rules(): - """Erstellt für jedes Spielsystem eine Standard-JSON-Datei, falls sie noch nicht existiert.""" - connection = sqlite3.connect(DB_PATH) - cursor = connection.cursor() - - cursor.execute("SELECT name FROM gamesystems") - systems = cursor.fetchall() - connection.close() - - # 1. Sicherstellen, dass der Ordner existiert (Best Practice!) - folder_path = "mmr_calculations" - os.makedirs(folder_path, exist_ok=True) - - # 2. Wir gehen jedes gefundene Spielsystem durch - for sys in systems: - sys_name = sys[0] - - # Wir machen den Namen "dateisicher" (z.B. "Warhammer 40k" -> "warhammer_40k") - safe_name = sys_name.replace(" ", "_").lower() - file_path = os.path.join(folder_path, f"mmr_rules_{safe_name}.json") - - # 3. SICHERHEITS-CHECK: Existiert die Datei schon? - # Wenn ja, ignorieren wir sie, damit wir dein händisches Balancing nicht überschreiben! - if not os.path.exists(file_path): - - # Das ist unsere Standard-Vorlage (Faktor 10) - default_rules = { - "system_info": f"Balancing für {sys_name}", - "draw_point_difference": 3, - "rank_matrix": { - "10": {"win": 10, "draw": 30}, - "9": {"win": 10, "draw": 30}, - "8": {"win": 10, "draw": 20}, - "7": {"win": 10, "draw": 20}, - "6": {"win": 20, "draw": 10}, - "5": {"win": 20, "draw": 10}, - "4": {"win": 20, "draw": 0}, - "3": {"win": 20, "draw": 0}, - "2": {"win": 30, "draw": 0}, - "1": {"win": 30, "draw": 0}, - "0": {"win": 30, "draw": 0}, - "-1": {"win": 30, "draw": 0}, - "-2": {"win": 40, "draw": 0}, - "-3": {"win": 40, "draw": -10}, - "-4": {"win": 50, "draw": -20}, - "-5": {"win": 60, "draw": -20}, - "-6": {"win": 70, "draw": -20}, - "-7": {"win": 80, "draw": -50}, - "-8": {"win": 100, "draw": -50}, - "-9": {"win": 120, "draw": -60}, - "-10": {"win": 150, "draw": -60} - }, - "score_bonus": [ - {"min_diff": 95, "bonus": 40}, - {"min_diff": 85, "bonus": 30}, - {"min_diff": 65, "bonus": 20}, - {"min_diff": 35, "bonus": 10}, - {"min_diff": 0, "bonus": 0} - ] - } - - # 4. JSON-Datei schreiben - # 'w' steht für write (schreiben). indent=4 macht es für Menschen schön lesbar formatiert. - with open(file_path, 'w', encoding='utf-8') as f: - json.dump(default_rules, f, indent=4, ensure_ascii=False) - - print(f"Neu: Balancing-Datei für '{sys_name}' wurde erstellt -> {file_path}") - else: - print(f"OK: Balancing-Datei für '{sys_name}' existiert bereits.") - diff --git a/gui/admin_gui.py b/gui/admin_gui.py index d299557..a9cdd25 100644 --- a/gui/admin_gui.py +++ b/gui/admin_gui.py @@ -2,6 +2,7 @@ from nicegui import ui, app from data import database, data_api from gui import gui_style from wood import logger +from gui import main_gui def setup_routes(): @ui.page('/admin', dark=True) @@ -14,7 +15,7 @@ def setup_routes(): if app.storage.user.get('authenticated', False): with ui.card().classes("w-full"): with ui.row().classes("w-full"): - ui.button("test") + ui.button(text= "test", on_click=lambda: data_api.create_random_dummy_match(2)) ui.button(icon="refresh", on_click=lambda: ui.navigate.reload) ui.label("System Audit Log").classes('text-2xl font-bold text-white mb-4') diff --git a/gui/main_gui.py b/gui/main_gui.py index 43f0d57..84dd00e 100644 --- a/gui/main_gui.py +++ b/gui/main_gui.py @@ -285,7 +285,7 @@ def setup_routes(admin_discord_id): ui.table(columns=table_columns, rows=table_rows, row_key='date').classes('w-full bg-zinc-900 text-white') # NEU: Der Button, der zur großen Log-Seite führt - ui.button("Komplette Historie & Log anzeigen", icon="history", on_click=lambda: ui.navigate.to('/matchhistory')).classes('w-full mt-4 bg-zinc-700 text-white hover:bg-zinc-600') + ui.button("Komplette Historie & Log anzeigen", icon="history", on_click=lambda: ui.navigate.to('/matchhistory')).classes('mt-4 bg-zinc-700 text-white hover:bg-zinc-600') else: ui.label("Noch keine Spiele absolviert.").classes("text-gray-500 italic") diff --git a/match_calculations/calc_match.py b/match_calculations/calc_match.py index cd48ecd..ceeccf1 100644 --- a/match_calculations/calc_match.py +++ b/match_calculations/calc_match.py @@ -80,13 +80,3 @@ def calculate_match (match_id): # Das Match als Berechnet markieren data_api.set_match_counted(match_id) - - -def load_mmr_rule_matrix(systemname): - safe_name = systemname.replace(" ", "_").lower() - - file_path = f"match_calculations/mmr_rules_{safe_name}.json" - with open(file_path, "r", encoding="utf-8") as file: - rules = json.load(file) - - return rules diff --git a/match_calculations/calc_mmr_change.py b/match_calculations/calc_mmr_change.py index 99bbf50..1995bb0 100644 --- a/match_calculations/calc_mmr_change.py +++ b/match_calculations/calc_mmr_change.py @@ -4,29 +4,69 @@ from data import data_api # die meisten Spieler über 1000MMR sein. Sprich: Neueinsteiger, oder leute die weniger spielen sind eher im unteren Ende als in der Mitte. 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, rules): - #Rang der Spieler holen. - gamesystem_id = data_api.get_gamesystem_id_by_name(systemname) - winner_rank = data_api.get_player_rank(winner_id,gamesystem_id) - looser_rank = data_api.get_player_rank(looser_id, gamesystem_id) - - if match_is_draw: - mmr_change = rules["rank_matrix"][str(max(-10, min(10, winner_rank-looser_rank)))]["draw"] - else: - mmr_change = rules["rank_matrix"][str(max(-10, min(10, winner_rank-looser_rank)))]["win"] +def calc_mmr_change(systemname, winner_id, looser_id, winner_points, looser_points, match_is_draw): - # Slaanesh Points berechnen und dem Change hinzufügen. - mmr_change += (sla_points := slaanesh_delight(winner_points, looser_points, rules)) + point_inflation = 0.7 # Verlierer verliert nur 70% der Punkte + K_FACTOR = 35 # Die "Border" (Maximalpunkte) die ein Sieg gibt. - # Variablen für den mmr_change anlegen. Sieger-Verlierer sind unterschiedlich! - winner_mmr_change = 0 + (mmr_change + wrath_of_khorne(winner_id)) - looser_mmr_change = 0 + (mmr_change + wrath_of_khorne(looser_id)) + def get_rust_dampener(days_ago): + """Berechnet den Dämpfungsfaktor basierend auf den vergangen Tagen.""" + 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) - if not match_is_draw: - # Verlierer verliert nur einen Teil der Punkte - looser_mmr_change = -int(winner_mmr_change * point_inflation) - return winner_mmr_change, looser_mmr_change + def calc_mmr_change(systemname, winner_id, looser_id, winner_points, looser_points, match_is_draw, rules): + gamesystem_id = data_api.get_gamesystem_id_by_name(systemname) + + # 1. Die aktuellen MMR-Punkte holen + w_stat = data_api.get_player_statistics_for_system(winner_id, gamesystem_id) + l_stat = data_api.get_player_statistics_for_system(looser_id, gamesystem_id) + + w_mmr = w_stat['mmr'] + l_mmr = l_stat['mmr'] + + + # 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)) + + if match_is_draw: + # Bei einem Draw (0.5) gewinnt der Schwächere leicht Punkte, der Stärkere verliert leicht. + base_change = K_FACTOR * (0.5 - expected_win) + else: + # Sieg (1.0). Gewinnt der Favorit, gibt es wenig Punkte. Gewinnt der Underdog, gibt es viele! + base_change = K_FACTOR * (1.0 - expected_win) + + # 3. Den "Rostigkeits-Dämpfer" anwenden + 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) + + + + # 4. Deine Sonderregeln (Slaanesh & Khorne) addieren + sla_points = slaanesh_delight(winner_points, looser_points, rules) + w_mmr_change += sla_points + + # Auch der Verlierer bekommt Slaanesh Punkte addiert, wenn es die Regel so sagt + l_mmr_change += sla_points + + winner_final = int(w_mmr_change + wrath_of_khorne(winner_id)) + + # 5. Verlierer-Punkte abziehen und Inflation (0.7) anwenden + if match_is_draw: + looser_final = int(-w_mmr_change) # Bei Draw spiegeln wir es einfach (ohne Inflation) + else: + looser_base = int(l_mmr_change + wrath_of_khorne(looser_id)) + looser_final = -int(looser_base * point_inflation) + + return winner_final, looser_final @@ -34,8 +74,6 @@ def calc_mmr_change(systemname, winner_id, looser_id, winner_points, looser_poin # ----------------- khorne_days = 16 khorne_bonus = 8 - - # ----------------- def wrath_of_khorne(player_id): last_played = data_api.get_days_since_last_game(player_id)["days_ago"] @@ -46,16 +84,7 @@ def wrath_of_khorne(player_id): def slaanesh_delight(winner_points, looser_points, rules): - - point_diff = winner_points - looser_points - # Standardwert, falls gar nichts zutrifft - bonus = 0 - - for threshold in rules["score_bonus"]: - if point_diff >= threshold["min_diff"]: - bonus = threshold["bonus"] - break - return bonus + print() def tzeentch_scemes(): diff --git a/match_calculations/mmr_rules_spearhead.json b/match_calculations/mmr_rules_spearhead.json deleted file mode 100644 index bd619ba..0000000 --- a/match_calculations/mmr_rules_spearhead.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "system_info": "Balancing für Spearhead", - "draw_point_difference": 3, - "rank_matrix": { - "10": { - "win": 10, - "draw": 30 - }, - "9": { - "win": 10, - "draw": 30 - }, - "8": { - "win": 10, - "draw": 20 - }, - "7": { - "win": 10, - "draw": 20 - }, - "6": { - "win": 20, - "draw": 10 - }, - "5": { - "win": 20, - "draw": 10 - }, - "4": { - "win": 20, - "draw": 0 - }, - "3": { - "win": 20, - "draw": 0 - }, - "2": { - "win": 30, - "draw": 0 - }, - "1": { - "win": 30, - "draw": 0 - }, - "0": { - "win": 30, - "draw": 0 - }, - "-1": { - "win": 30, - "draw": 0 - }, - "-2": { - "win": 40, - "draw": 0 - }, - "-3": { - "win": 40, - "draw": -10 - }, - "-4": { - "win": 50, - "draw": -20 - }, - "-5": { - "win": 60, - "draw": -20 - }, - "-6": { - "win": 70, - "draw": -20 - }, - "-7": { - "win": 80, - "draw": -50 - }, - "-8": { - "win": 100, - "draw": -50 - }, - "-9": { - "win": 120, - "draw": -60 - }, - "-10": { - "win": 150, - "draw": -60 - } - }, - "score_bonus": [ - { - "min_diff": 15, - "bonus": 40 - }, - { - "min_diff": 10, - "bonus": 30 - }, - { - "min_diff": 6, - "bonus": 20 - }, - { - "min_diff": 3, - "bonus": 10 - }, - { - "min_diff": 0, - "bonus": 0 - } - ] -} \ No newline at end of file diff --git a/match_calculations/mmr_rules_warhammer_40k.json b/match_calculations/mmr_rules_warhammer_40k.json deleted file mode 100644 index a7163db..0000000 --- a/match_calculations/mmr_rules_warhammer_40k.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "system_info": "Balancing für Warhammer 40k", - "draw_point_difference": 3, - "rank_matrix": { - "10": { - "win": 10, - "draw": 30 - }, - "9": { - "win": 10, - "draw": 30 - }, - "8": { - "win": 10, - "draw": 20 - }, - "7": { - "win": 10, - "draw": 20 - }, - "6": { - "win": 20, - "draw": 10 - }, - "5": { - "win": 20, - "draw": 10 - }, - "4": { - "win": 20, - "draw": 0 - }, - "3": { - "win": 20, - "draw": 0 - }, - "2": { - "win": 30, - "draw": 0 - }, - "1": { - "win": 30, - "draw": 0 - }, - "0": { - "win": 30, - "draw": 0 - }, - "-1": { - "win": 30, - "draw": 0 - }, - "-2": { - "win": 40, - "draw": 0 - }, - "-3": { - "win": 40, - "draw": -10 - }, - "-4": { - "win": 50, - "draw": -20 - }, - "-5": { - "win": 60, - "draw": -20 - }, - "-6": { - "win": 70, - "draw": -20 - }, - "-7": { - "win": 80, - "draw": -50 - }, - "-8": { - "win": 100, - "draw": -50 - }, - "-9": { - "win": 120, - "draw": -60 - }, - "-10": { - "win": 150, - "draw": -60 - } - }, - "score_bonus": [ - { - "min_diff": 95, - "bonus": 40 - }, - { - "min_diff": 85, - "bonus": 30 - }, - { - "min_diff": 65, - "bonus": 20 - }, - { - "min_diff": 35, - "bonus": 10 - }, - { - "min_diff": 0, - "bonus": 0 - } - ] -} \ No newline at end of file diff --git a/match_calculations/mmr_rules_warhammer_age_of_sigmar.json b/match_calculations/mmr_rules_warhammer_age_of_sigmar.json deleted file mode 100644 index a4bfbbf..0000000 --- a/match_calculations/mmr_rules_warhammer_age_of_sigmar.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "system_info": "Balancing für Warhammer Age of Sigmar", - "draw_point_difference": 3, - "rank_matrix": { - "10": { - "win": 10, - "draw": 30 - }, - "9": { - "win": 10, - "draw": 30 - }, - "8": { - "win": 10, - "draw": 20 - }, - "7": { - "win": 10, - "draw": 20 - }, - "6": { - "win": 20, - "draw": 10 - }, - "5": { - "win": 20, - "draw": 10 - }, - "4": { - "win": 20, - "draw": 0 - }, - "3": { - "win": 20, - "draw": 0 - }, - "2": { - "win": 30, - "draw": 0 - }, - "1": { - "win": 30, - "draw": 0 - }, - "0": { - "win": 30, - "draw": 0 - }, - "-1": { - "win": 30, - "draw": 0 - }, - "-2": { - "win": 40, - "draw": 0 - }, - "-3": { - "win": 40, - "draw": -10 - }, - "-4": { - "win": 50, - "draw": -20 - }, - "-5": { - "win": 60, - "draw": -20 - }, - "-6": { - "win": 70, - "draw": -20 - }, - "-7": { - "win": 80, - "draw": -50 - }, - "-8": { - "win": 100, - "draw": -50 - }, - "-9": { - "win": 120, - "draw": -60 - }, - "-10": { - "win": 150, - "draw": -60 - } - }, - "score_bonus": [ - { - "min_diff": 40, - "bonus": 40 - }, - { - "min_diff": 30, - "bonus": 30 - }, - { - "min_diff": 20, - "bonus": 20 - }, - { - "min_diff": 10, - "bonus": 10 - }, - { - "min_diff": 0, - "bonus": 0 - } - ] -} \ No newline at end of file diff --git a/mmr_calculations/mmr_rules_spearhead.json b/mmr_calculations/mmr_rules_spearhead.json deleted file mode 100644 index 346554f..0000000 --- a/mmr_calculations/mmr_rules_spearhead.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "system_info": "Balancing für Spearhead", - "draw_point_difference": 3, - "rank_matrix": { - "10": { - "win": 10, - "draw": 30 - }, - "9": { - "win": 10, - "draw": 30 - }, - "8": { - "win": 10, - "draw": 20 - }, - "7": { - "win": 10, - "draw": 20 - }, - "6": { - "win": 20, - "draw": 10 - }, - "5": { - "win": 20, - "draw": 10 - }, - "4": { - "win": 20, - "draw": 0 - }, - "3": { - "win": 20, - "draw": 0 - }, - "2": { - "win": 30, - "draw": 0 - }, - "1": { - "win": 30, - "draw": 0 - }, - "0": { - "win": 30, - "draw": 0 - }, - "-1": { - "win": 30, - "draw": 0 - }, - "-2": { - "win": 40, - "draw": 0 - }, - "-3": { - "win": 40, - "draw": -10 - }, - "-4": { - "win": 50, - "draw": -20 - }, - "-5": { - "win": 60, - "draw": -20 - }, - "-6": { - "win": 70, - "draw": -20 - }, - "-7": { - "win": 80, - "draw": -50 - }, - "-8": { - "win": 100, - "draw": -50 - }, - "-9": { - "win": 120, - "draw": -60 - }, - "-10": { - "win": 150, - "draw": -60 - } - }, - "score_bonus": [ - { - "min_diff": 95, - "bonus": 40 - }, - { - "min_diff": 85, - "bonus": 30 - }, - { - "min_diff": 65, - "bonus": 20 - }, - { - "min_diff": 35, - "bonus": 10 - }, - { - "min_diff": 0, - "bonus": 0 - } - ] -} \ No newline at end of file diff --git a/mmr_calculations/mmr_rules_warhammer_40k.json b/mmr_calculations/mmr_rules_warhammer_40k.json deleted file mode 100644 index a7163db..0000000 --- a/mmr_calculations/mmr_rules_warhammer_40k.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "system_info": "Balancing für Warhammer 40k", - "draw_point_difference": 3, - "rank_matrix": { - "10": { - "win": 10, - "draw": 30 - }, - "9": { - "win": 10, - "draw": 30 - }, - "8": { - "win": 10, - "draw": 20 - }, - "7": { - "win": 10, - "draw": 20 - }, - "6": { - "win": 20, - "draw": 10 - }, - "5": { - "win": 20, - "draw": 10 - }, - "4": { - "win": 20, - "draw": 0 - }, - "3": { - "win": 20, - "draw": 0 - }, - "2": { - "win": 30, - "draw": 0 - }, - "1": { - "win": 30, - "draw": 0 - }, - "0": { - "win": 30, - "draw": 0 - }, - "-1": { - "win": 30, - "draw": 0 - }, - "-2": { - "win": 40, - "draw": 0 - }, - "-3": { - "win": 40, - "draw": -10 - }, - "-4": { - "win": 50, - "draw": -20 - }, - "-5": { - "win": 60, - "draw": -20 - }, - "-6": { - "win": 70, - "draw": -20 - }, - "-7": { - "win": 80, - "draw": -50 - }, - "-8": { - "win": 100, - "draw": -50 - }, - "-9": { - "win": 120, - "draw": -60 - }, - "-10": { - "win": 150, - "draw": -60 - } - }, - "score_bonus": [ - { - "min_diff": 95, - "bonus": 40 - }, - { - "min_diff": 85, - "bonus": 30 - }, - { - "min_diff": 65, - "bonus": 20 - }, - { - "min_diff": 35, - "bonus": 10 - }, - { - "min_diff": 0, - "bonus": 0 - } - ] -} \ No newline at end of file diff --git a/mmr_calculations/mmr_rules_warhammer_age_of_sigmar.json b/mmr_calculations/mmr_rules_warhammer_age_of_sigmar.json deleted file mode 100644 index ce24867..0000000 --- a/mmr_calculations/mmr_rules_warhammer_age_of_sigmar.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "system_info": "Balancing für Warhammer Age of Sigmar", - "draw_point_difference": 3, - "rank_matrix": { - "10": { - "win": 10, - "draw": 30 - }, - "9": { - "win": 10, - "draw": 30 - }, - "8": { - "win": 10, - "draw": 20 - }, - "7": { - "win": 10, - "draw": 20 - }, - "6": { - "win": 20, - "draw": 10 - }, - "5": { - "win": 20, - "draw": 10 - }, - "4": { - "win": 20, - "draw": 0 - }, - "3": { - "win": 20, - "draw": 0 - }, - "2": { - "win": 30, - "draw": 0 - }, - "1": { - "win": 30, - "draw": 0 - }, - "0": { - "win": 30, - "draw": 0 - }, - "-1": { - "win": 30, - "draw": 0 - }, - "-2": { - "win": 40, - "draw": 0 - }, - "-3": { - "win": 40, - "draw": -10 - }, - "-4": { - "win": 50, - "draw": -20 - }, - "-5": { - "win": 60, - "draw": -20 - }, - "-6": { - "win": 70, - "draw": -20 - }, - "-7": { - "win": 80, - "draw": -50 - }, - "-8": { - "win": 100, - "draw": -50 - }, - "-9": { - "win": 120, - "draw": -60 - }, - "-10": { - "win": 150, - "draw": -60 - } - }, - "score_bonus": [ - { - "min_diff": 95, - "bonus": 40 - }, - { - "min_diff": 85, - "bonus": 30 - }, - { - "min_diff": 65, - "bonus": 20 - }, - { - "min_diff": 35, - "bonus": 10 - }, - { - "min_diff": 0, - "bonus": 0 - } - ] -} \ No newline at end of file