namespace Outnumbered.Data; // Hides the SQL dialect so SQLite (dev) -> PostgreSQL (prod) is a provider swap, // not a logic change (spec ยง10). All methods run OFF the game thread. public interface IPlayerRepository { Task EnsureSchemaAsync(); Task LoadAsync(ulong steamId); Task SaveAsync(PersistPlayer player); Task SaveManyAsync(IReadOnlyList players); Task> GetTopAsync(int count); // Records (site leaderboards): improve-only writes kept OUT of the SaveMany upsert's column list, so a normal // save can never clobber them and they need no LoadedPlayer/PlayerData round-trip (write-only from the plugin). Task TryImproveBestWavesAsync(IReadOnlyList steamIds, int wave); // higher wave wins Task TryImproveGgBestAsync(ulong steamId, long elapsedMs); // lower time wins Task> GetTopWavesAsync(int count); Task> GetTopGgAsync(int count); // Per-match stats (RAM-first; persisted only on disconnect/shutdown, wiped on round end). Task LoadMatchAsync(ulong steamId); Task SaveMatchAsync(MatchState state); Task SaveManyMatchAsync(IReadOnlyList states); Task WipeMatchAsync(); }