Exemplo n.º 1
0
        public async Task <PlayResult> Play(string gameId, string username, PlayLetter[] letters)
        {
            var game = gameCache.ActiveGames.SingleOrDefault(g => g.Id == gameId) as Game;

            if (game == null)
            {
                string message = $"Invalid game: {gameId}";
                await logger.WarningAsync(message, context : $"{gameId}:{username}");

                return(new PlayResult {
                    MoveResult = message
                });
            }

            //  Play must be done by current player
            var player = game.GetPlayer(username);

            if (player.UserName != game.CurrentPlayer)
            {
                string message = $"Game Play received not from current player. (Game:{gameId} Current Player:{game.CurrentPlayer}) ";
                await logger.WarningAsync(message, context : $"{gameId}:{username}");

                return(new PlayResult {
                    MoveResult = message
                });
            }

            // Played letters must be int player rack
            var rack = player.Rack.Select(r => r.Char).ToList();

            foreach (var letter in letters)
            {
                if (letter.Letter.Letter.IsBlank)
                {
                    var blankInRack = rack.Contains(' ');
                    if (!blankInRack)
                    {
                        string message = "Player rack doesn't contain blank tiles";
                        await logger.InfoAsync(message, context : $"{gameId}:{username}");

                        return(new PlayResult {
                            MoveResult = message
                        });
                    }
                }
                else
                {
                    var letterInRack = rack.Contains(letter.Letter.Letter.Char);
                    if (!letterInRack)
                    {
                        string message = $"Player rack doesn't contain {letter.Letter.Letter.Char}";
                        await logger.InfoAsync(message, context : $"{gameId}:{username}");

                        return(new PlayResult {
                            MoveResult = message
                        });
                    }
                }
            }

            // Validate Move
            var validationResult = await game.ValidateMove(letters, lexiconService);

            if (validationResult.Result != "OK")
            {
                string message = $"Invalid move: {validationResult.Result} ";
                //await logger.InfoAsync(message, context: username);
                return(new PlayResult {
                    MoveResult = message
                });
            }

            // Score the words
            var scoreWords = game.ScoreMove(validationResult.Words, letters);


            // Create move entity
            var playFinish = new DateTime(DateTime.UtcNow.Ticks, DateTimeKind.Utc);
            var move       = new PlayMove
            {
                Letters    = letters,
                Player     = player.UserName,
                PlayStart  = new DateTime(game.CurrentStart.Ticks, DateTimeKind.Utc),
                PlayFinish = playFinish,
                Words      = scoreWords.ToArray(),
                Score      = scoreWords.Sum(w => w.Score)
            };

            // Update game time, and current player and reset ConsecutivePasses
            var opponent = game.Player01.UserName == player.UserName ? game.Player02 : game.Player01;

            game.CurrentStart      = playFinish;
            game.CurrentPlayer     = opponent.UserName;
            game.ConsecutivePasses = 0;

            // Update game moves
            var moves = game.PlayMoves.ToList();

            moves.Add(move);
            game.PlayMoves = moves;

            // TODO: update player rack
            var ePlayer         = player as GamePlayer;
            var eRack           = player.Rack.ToList();
            var lettersToRemove = letters.Select(l => l.Letter).ToList();

            foreach (var letter in lettersToRemove)
            {
                var rLetter = letter.Letter.IsBlank
                    ? eRack.First(l => l.IsBlank)
                    : eRack.First(l => l.Char == letter.Letter.Char);
                eRack.Remove(rLetter);
            }
            var lettersNeeded = 7 - eRack.Count();
            var newLetters    = game.LetterBag.TakeLetters(lettersNeeded);

            ePlayer.Rack  = eRack.Concat(newLetters);
            ePlayer.Score = moves.Where(m => m.Player == ePlayer.UserName).Sum(m => m.Score);



            // Save game state to DB
            await gameRepository.Update(game.ToDataModel());

            await gameRepository.AddMoves(game.Id, new GameMoveDataModel[] { move.ToDataModel() });

            //logger.Info($"Game move letter:[{letters.GetString()}] Words:[{string.Join(",", move.Words.Select(w => w.GetString() + "=" + w.Score))}]",context: player.UserName);
            await logger.InfoAsync($"PLAY! = Duration:[{Math.Round((move.PlayFinish.Value - move.PlayStart).TotalMinutes,2)}] Letters:[{letters.GetString()}] Words:[{string.Join(",", move.Words.Select(w => w.GetString() + "=" + w.Score))}]", context : $"{gameId}:{username}");

            return(new PlayResult
            {
                MoveResult = "OK",
                PlayMove = move
            });
        }