using DbController; using System.Text; using Tabletop.Core.Filters; using Tabletop.Core.Models; namespace Tabletop.Core.Services { public class GameService(PlayerService playerService, UserService userService) : IModelService { private readonly PlayerService _playerService = playerService; private readonly UserService _userService = userService; public async Task CreateAsync(Game input, IDbController dbController, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); string sql = $@"INSERT INTO Games ( UserId, GamemodeId, SurfaceId, LayoutId, Name, NumberOfRounds, Force, NumberOfTeams, NumberOfPlayers, Date ) VALUES ( @USER_ID, @GAMEMODE_ID, @SURFACE_ID, @LAYOUT_ID, @NAME, @NUMBER_OF_ROUNDS, @FORCE, @NUMBER_OF_TEAMS, @NUMBER_OF_PLAYERS, @DATE ); {dbController.GetLastIdSql()}"; input.GameId = await dbController.GetFirstAsync(sql, input.GetParameters(), cancellationToken); foreach (var item in input.Players) { item.GameId = input.GameId; await _playerService.CreateAsync(item, dbController, cancellationToken); } } public async Task DeleteAsync(Game input, IDbController dbController, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); string sql = "DELETE FROM Games WHERE GameId = @GAME_ID"; await dbController.QueryAsync(sql, new { GAME_ID = input.GameId, }, cancellationToken); } public async Task GetAsync(int gameId, IDbController dbController, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); string sql = @"SELECT * FROM Games WHERE GameId = @GAME_ID"; var game = await dbController.GetFirstAsync(sql, new { GAME_ID = gameId }, cancellationToken); if (game != null) { game.Players = await _playerService.GetGamePlayersAsync(game.GameId, dbController, cancellationToken); } return game; } public static async Task> GetAllAsync(IDbController dbController, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); string sql = "SELECT * FROM Games"; var list = await dbController.SelectDataAsync(sql, cancellationToken: cancellationToken); return list; } public async Task> GetAsync(GameFilter filter, IDbController dbController, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); StringBuilder sb = new(); sb.AppendLine("SELECT DISTINCT g.* FROM Games g LEFT JOIN Players p ON g.GameId = p.GameId WHERE p.UserId = @USER_ID OR g.UserId = @USER_ID "); sb.AppendLine(GetFilterWhere(filter)); sb.AppendLine(@$" ORDER BY Date DESC "); sb.AppendLine(dbController.GetPaginationSyntax(filter.PageNumber, filter.Limit)); string sql = sb.ToString(); List list = await dbController.SelectDataAsync(sql, GetFilterParameter(filter), cancellationToken); if (list.Count != 0) { foreach (var item in list) { item.Players = await _playerService.GetGamePlayersAsync(item.GameId, dbController, cancellationToken); item.Host = await _userService.GetUsernameAsync(item.UserId, dbController, cancellationToken); } } return list; } public async Task> GetLastGamesOfPlayerAsync(int userId, IDbController dbController, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); string sql = "SELECT TOP 5 g.GameId, g.GamemodeId, g.Date, g.Force FROM Games g INNER JOIN Players p ON g.GameId = p.GameId WHERE p.UserId = @USER_ID ORDER BY g.Date DESC"; var list = await dbController.SelectDataAsync(sql, new { USER_ID = userId, }, cancellationToken: cancellationToken); return list; } public Dictionary GetFilterParameter(GameFilter filter) { return new Dictionary { { "SEARCHPHRASE", $"%{filter.SearchPhrase}%" }, { "USER_ID", filter.UserId } }; } public string GetFilterWhere(GameFilter filter) { StringBuilder sb = new(); if (!string.IsNullOrWhiteSpace(filter.SearchPhrase)) { sb.AppendLine(@" AND (UPPER(Name) LIKE @SEARCHPHRASE)"); } string sql = sb.ToString(); return sql; } public async Task GetTotalAsync(GameFilter filter, IDbController dbController, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); StringBuilder sb = new(); sb.AppendLine("SELECT COUNT(*) FROM Games WHERE UserId = @USER_ID"); sb.AppendLine(GetFilterWhere(filter)); string sql = sb.ToString(); int result = await dbController.GetFirstAsync(sql, GetFilterParameter(filter), cancellationToken); return result; } public async Task UpdateAsync(Game input, IDbController dbController, CancellationToken cancellationToken = default) { string sql = @"UPDATE Games SET GamemodeId = @GAMEMODE_ID, SurfaceId = @SURFACE_ID, LayoutId = @LAYOUT_ID, Name = @NAME, NumberOfRounds = @NUMBER_OF_ROUNDS, Force = @FORCE, NumberOfTeams = @NUMBER_OF_TEAMS, NumberOfPlayers = @NUMBER_OF_PLAYERS, Date = @DATE WHERE GameId = @GAME_ID"; await dbController.QueryAsync(sql, input.GetParameters(), cancellationToken); } } }