import sqlite3 import os import json from dotenv import load_dotenv load_dotenv() DB_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "league_database.db") dummy_is_in = True def init_db(): connection = sqlite3.connect(DB_PATH) cursor = connection.cursor() # Fremdschlüssel (Foreign Keys) in SQLite aktivieren cursor.execute('PRAGMA foreign_keys = ON;') # 1. Tabelle: players (Stammdaten) cursor.execute(''' CREATE TABLE IF NOT EXISTS players ( id INTEGER PRIMARY KEY AUTOINCREMENT, discord_id TEXT UNIQUE, discord_name TEXT NOT NULL, discord_avatar_url TEXT, display_name TEXT ) ''') # 2. Tabelle: gamesystems (Globale Spielsysteme) cursor.execute(''' CREATE TABLE IF NOT EXISTS gamesystems ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, picture TEXT, description TEXT, active_players INTEGER DEFAULT 0, min_score INTEGER DEFAULT 0, max_score INTEGER DEFAULT 100 ) ''') # 3. Tabelle: player_game_statistic (Welcher Spieler hat in welchem System welche Stats?) cursor.execute(''' CREATE TABLE IF NOT EXISTS player_game_statistic ( id INTEGER PRIMARY KEY AUTOINCREMENT, player_id INTEGER, gamesystem_id INTEGER, mmr INTEGER DEFAULT 1000, games_in_system INTEGER DEFAULT 0, points INTEGER DEFAULT 0, avv_points INTEGER DEFAULT 0, last_played TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (player_id) REFERENCES players (id), FOREIGN KEY (gamesystem_id) REFERENCES gamesystems (id) ) ''') # 4. Tabelle: matches (Wer hat wann gegen wen in welchem System gespielt?) cursor.execute(''' CREATE TABLE IF NOT EXISTS matches ( id INTEGER PRIMARY KEY AUTOINCREMENT, gamesystem_id INTEGER, player1_id INTEGER, score_player1 INTEGER, player2_id INTEGER, score_player2 INTEGER, played_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, player1_mmr_change INTEGER, player2_mmr_change INTEGER, player2_check INTEGER DEFAULT 0, match_is_counted INTEGER DEFAULT 0, FOREIGN KEY (gamesystem_id) REFERENCES gamesystems (id), FOREIGN KEY (player1_id) REFERENCES players (id), FOREIGN KEY (player2_id) REFERENCES players (id) ) ''') # 5. Tabelle: achievements (Der globale Katalog aller möglichen Erfolge - Stammdaten) cursor.execute(''' CREATE TABLE IF NOT EXISTS achievements ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, description TEXT NOT NULL, icon TEXT ) ''') # 6. Tabelle: player_achievements (Wer hat welchen Erfolg wann bekommen? - Bewegungsdaten) cursor.execute(''' CREATE TABLE IF NOT EXISTS player_achievements ( id INTEGER PRIMARY KEY AUTOINCREMENT, player_id INTEGER, achievement_id INTEGER, earned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, earned_in INTEGER, FOREIGN KEY (earned_in) REFERENCES gamesystems (id), FOREIGN KEY (player_id) REFERENCES players (id), FOREIGN KEY (achievement_id) REFERENCES achievements (id) ) ''') connection.commit() connection.close() print("Datenbank Struktur aufgebaut") #nächster Schritt: Standard Spielsysteme eintragen seed_gamesystems() # -------------------- # --- Start Setup der DB Daten. Damit sie nicht GANZ leer sind. # -------------------- def seed_gamesystems(): connection = sqlite3.connect(DB_PATH) cursor = connection.cursor() systems = [ ("Warhammer 40k", "40k_logo.png", "Die Schlacht um die Galaxie in einer entfernten Zukunft.", 0, 100), ("Warhammer Age of Sigmar", "aos_logo.png", "Der ewige Krieg um die Reiche der Sterblichen in einer epischen Fantasy-Welt.", 0, 50), ("Spearhead", "aos_logo.png", "Schnelle und taktische Scharmützel für actiongeladene Kämpfe.", 0, 50) ] # executemany ist eine extrem schnelle SQL For-Schleife für Inserts cursor.executemany("INSERT INTO gamesystems (name, picture, description, min_score, max_score) VALUES (?, ?, ?, ?, ?)", systems) connection.commit() connection.close() print("Spielsysteme angelegt!") #Nächster Schritt: Standard Achievments eintragen. generate_default_mmr_rules() seed_achievements() def seed_achievements(): connection = sqlite3.connect(DB_PATH) cursor = connection.cursor() # Unsere Start-Stückliste an Erfolgen (Name, Beschreibung, Icon) achievements = [ ("Kingslayer", "Hat den Spieler auf Platz 1 besiegt!", "👑"), ("Unstoppable", "3 Spiele in Folge gewonnen.", "🔥"), ("First Blood", "Das allererste Ligaspiel absolviert.", "🩸") ] cursor.executemany("INSERT INTO achievements (name, description, icon) VALUES (?, ?, ?)", achievements) connection.commit() connection.close() print("Achievements angelegt.") if dummy_is_in: seed_dummy_player() def seed_dummy_player(): connection = sqlite3.connect(DB_PATH) cursor = connection.cursor() # 1. Dummy-Spieler anlegen (falls noch nicht vorhanden) query_player = """ INSERT OR IGNORE INTO players (discord_id, discord_name, display_name, discord_avatar_url) VALUES (?, ?, ?, ?) """ cursor.execute(query_player, ("dummy_001", "dummy_user", "Dummy Mc DummDumm", "")) # 2. Wir holen uns die ID des Dummys (egal ob neu oder alt) cursor.execute("SELECT id FROM players WHERE discord_id = 'dummy_001'") dummy_row = cursor.fetchone() if dummy_row: dummy_id = dummy_row[0] # 3. Wir holen alle IDs der aktuellen Spielsysteme cursor.execute("SELECT id FROM gamesystems") systems = cursor.fetchall() # 4. Wir gehen jedes System durch und prüfen, ob er schon drin ist for sys in systems: sys_id = sys[0] cursor.execute("SELECT id FROM player_game_statistic WHERE player_id = ? AND gamesystem_id = ?", (dummy_id, sys_id)) is_in_league = cursor.fetchone() if not is_in_league: # Er ist noch nicht drin -> Eintragen! (MMR startet durch DEFAULT automatisch bei 1000) cursor.execute(""" INSERT INTO player_game_statistic (player_id, gamesystem_id) VALUES (?, ?) """, (dummy_id, sys_id)) connection.commit() connection.close() 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.")