package de.fussball.plugin.stats; import de.fussball.plugin.Fussball; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; import java.io.IOException; import java.util.*; /** * Verwaltet persistente Spielerstatistiken in stats.yml. * Gespeichert werden: Tore, Schüsse, Siege, Niederlagen, Unentschieden, gespielte Spiele. */ public class StatsManager { private final Fussball plugin; private final File statsFile; private FileConfiguration statsConfig; // In-Memory-Cache für schnellen Zugriff private final Map cache = new HashMap<>(); public StatsManager(Fussball plugin) { this.plugin = plugin; this.statsFile = new File(plugin.getDataFolder(), "stats.yml"); load(); } // ── Persistenz ────────────────────────────────────────────────────────── private void load() { if (!statsFile.exists()) { try { statsFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } statsConfig = YamlConfiguration.loadConfiguration(statsFile); cache.clear(); if (statsConfig.contains("players")) { for (String uuidStr : statsConfig.getConfigurationSection("players").getKeys(false)) { try { UUID uuid = UUID.fromString(uuidStr); String path = "players." + uuidStr; PlayerStats stats = new PlayerStats( statsConfig.getString(path + ".name", "Unbekannt"), statsConfig.getInt(path + ".goals", 0), statsConfig.getInt(path + ".kicks", 0), statsConfig.getInt(path + ".wins", 0), statsConfig.getInt(path + ".losses", 0), statsConfig.getInt(path + ".draws", 0), statsConfig.getInt(path + ".games", 0), statsConfig.getInt(path + ".assists", 0), statsConfig.getInt(path + ".ownGoals", 0) ); cache.put(uuid, stats); } catch (IllegalArgumentException ignored) {} } } plugin.getLogger().info("[Fussball] Statistiken geladen: " + cache.size() + " Spieler."); } public void save() { statsConfig.set("players", null); for (Map.Entry entry : cache.entrySet()) { String path = "players." + entry.getKey(); PlayerStats s = entry.getValue(); statsConfig.set(path + ".name", s.name); statsConfig.set(path + ".goals", s.goals); statsConfig.set(path + ".kicks", s.kicks); statsConfig.set(path + ".wins", s.wins); statsConfig.set(path + ".losses", s.losses); statsConfig.set(path + ".draws", s.draws); statsConfig.set(path + ".games", s.games); statsConfig.set(path + ".assists", s.assists); statsConfig.set(path + ".ownGoals", s.ownGoals); } try { statsConfig.save(statsFile); } catch (IOException e) { e.printStackTrace(); } } // ── Datenzugriff ──────────────────────────────────────────────────────── public PlayerStats getStats(UUID uuid) { return cache.computeIfAbsent(uuid, k -> new PlayerStats("Unbekannt", 0, 0, 0, 0, 0, 0, 0, 0)); } public void addGoal(UUID uuid, String name) { PlayerStats s = getStats(uuid); s.name = name; s.goals++; save(); } public void addOwnGoal(UUID uuid, String name) { PlayerStats s = getStats(uuid); s.name = name; s.ownGoals++; save(); } public void addAssist(UUID uuid, String name) { PlayerStats s = getStats(uuid); s.name = name; s.assists++; save(); } public void addGameResult(UUID uuid, String name, GameResult result) { PlayerStats s = getStats(uuid); s.name = name; s.games++; switch (result) { case WIN -> s.wins++; case LOSS -> s.losses++; case DRAW -> s.draws++; } save(); } public void flushKicks(Map kicks, Map names) { for (Map.Entry entry : kicks.entrySet()) { PlayerStats s = getStats(entry.getKey()); if (names.containsKey(entry.getKey())) s.name = names.get(entry.getKey()); s.kicks += entry.getValue(); } save(); } public boolean resetStats(UUID uuid) { boolean removed = cache.remove(uuid) != null; if (!removed) { return false; } save(); return true; } public int resetAllStats() { int count = cache.size(); if (count == 0) { return 0; } cache.clear(); save(); return count; } public UUID findPlayerUuidByName(String playerName) { for (Map.Entry entry : cache.entrySet()) { if (entry.getValue().name != null && entry.getValue().name.equalsIgnoreCase(playerName)) { return entry.getKey(); } } return null; } /** Gibt die Top-N-Torschützen zurück, sortiert nach Toren */ public List> getTopScorers(int limit) { List> list = new ArrayList<>(cache.entrySet()); list.sort((a, b) -> b.getValue().goals - a.getValue().goals); return list.subList(0, Math.min(limit, list.size())); } /** Gibt die Top-N-Spieler nach Siegen zurück */ public List> getTopWins(int limit) { List> list = new ArrayList<>(cache.entrySet()); list.sort((a, b) -> b.getValue().wins - a.getValue().wins); return list.subList(0, Math.min(limit, list.size())); } // ── Innere Klassen ─────────────────────────────────────────────────────── public static class PlayerStats { public String name; public int goals, kicks, wins, losses, draws, games, assists, ownGoals; public PlayerStats(String name, int goals, int kicks, int wins, int losses, int draws, int games, int assists, int ownGoals) { this.name = name; this.goals = goals; this.kicks = kicks; this.wins = wins; this.losses = losses; this.draws = draws; this.games = games; this.assists = assists; this.ownGoals = ownGoals; } public double getWinRate() { if (games == 0) return 0.0; return (double) wins / games * 100.0; } } public enum GameResult { WIN, LOSS, DRAW } }