async Task IGamePlayService.MakeMoveAsync(MoveModel move, CancellationToken cancellationToken) { var game = await ValidateMoveInternalAsync(move, cancellationToken : cancellationToken); var turns = await _turnRepository.GetTurnsByGameIdAsync(game.Id, cancellationToken : cancellationToken); var currentTurn = turns .Where(x => !x.EndTime.HasValue) .OrderByDescending(x => x.StartTime) .FirstOrDefault(); var turnUpdate = new TurnUpdateData { EndTime = DateTime.UtcNow, }; await _turnRepository.UpdateTurnAsync(currentTurn.Id, turnUpdate, cancellationToken : cancellationToken); var currentMove = new MoveData { GameDeckCardCollectionId = move.GameDeckCardCollectionId, Column = move.Column, Row = move.Row, TurnId = currentTurn.Id, }; await _moveRepository.AddMoveAsync(currentMove, cancellationToken : cancellationToken); var nextUserId = game.UserIds .SkipWhile(x => x != move.UserId) .Skip(1) .FirstOrDefault(); if (nextUserId == default) { nextUserId = game.UserIds.First(); } var newTurn = new TurnData { CurrentUserId = nextUserId, GameId = game.Id, StartTime = DateTime.UtcNow, }; await _turnRepository.AddTurnAsync(newTurn, cancellationToken : cancellationToken); var gameUpdate = new GameUpdateData { CurrentUserId = nextUserId, }; await _gameRepository.UpdateGameAsync(game.Id, gameUpdate, cancellationToken : cancellationToken); }
private async Task PrepareGameForPlayAsync(int id, int[] userIds, CancellationToken cancellationToken) { var randomUserIds = userIds.OrderBy(x => RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue)).ToArray(); var currentUserId = randomUserIds[0]; var updateGame = new GameUpdateData { CurrentUserId = currentUserId, }; await _gameRepository.UpdateGameAsync(id, updateGame, cancellationToken : cancellationToken); await _gameRepository.UpdateGameUsersOrderAsync(id, randomUserIds, cancellationToken : cancellationToken); var newTurn = new TurnData { CurrentUserId = currentUserId, GameId = id, }; await _turnRepository.AddTurnAsync(newTurn, cancellationToken : cancellationToken); }
private async Task AddUserToGameInternalAsync(int id, int userId, int deckId, CancellationToken cancellationToken = default) { var game = await _gameRepository.GetGameByIdAsync(id); if (game == null) { throw new InvalidGameException($"Game { id } does not exist."); } var gameUsers = await _gameRepository.GetGameUsersAsync(id, cancellationToken : cancellationToken); if (gameUsers.Any(x => x.Id == userId)) { throw new InvalidPlayerException($"User { userId } is already in game { id }."); } var gul = gameUsers.Length; if (gul >= game.MaxPlayers) { throw new InvalidPlayerException($"Game { id } is already filled."); } var deck = await _deckRepository.GetDeckByIdAsync(deckId, userId, cancellationToken : cancellationToken); if (deck == null) { throw new InvalidDeckException($"Deck { deckId } does not exist."); } if (deck.UserId != userId) { throw new InvalidDeckException($"Deck { deckId } does not belong to user { userId }."); } var dc = deck.Cards.Select(x => x.CardId).ToArray(); var dcc = dc.Length; if (dcc < deck.MaxCards) { throw new InvalidDeckException($"Deck { deckId } needs { deck.MaxCards } cards. Currently only has { dcc }."); } await _gameDeckRepository.AddGameDeckAsync(id, userId, deck.Name, deck.Description, dc, cancellationToken : cancellationToken); if (gul + 1 == game.MaxPlayers) { var allUsers = gameUsers.Select(x => x.Id).Concat(new int[] { userId }).ToArray(); var currentUserIdx = new Random().Next(0, allUsers.Length); var currentUserId = allUsers[currentUserIdx]; var updateGame = new GameUpdateData { CurrentUserId = currentUserId, }; await _gameRepository.UpdateGameAsync(id, updateGame, cancellationToken : cancellationToken); var newTurn = new TurnData { CurrentUserId = currentUserId, GameId = game.Id, }; await _turnRepository.AddTurnAsync(newTurn, cancellationToken : cancellationToken); } }