public override async Task Leave(IPlayerBase player)
        {
            if (GameState.Active)
            {
                return;
            }

            var info = await player.Info();

            if (GameState.Players.Contains(info.UserKey))
            {
                GameState.Players.Remove(info.UserKey);
                await SaveState();

                await base.Leave(player);
            }
        }
        private static async Task DoClientWork(IGrainFactory client)
        {
            var provider = client.GetGrain <IGameProvider>("GameProvider");

            var gameGuid = await provider.AddGame(new GameInfo("TumblerGame", Guid.NewGuid()));

            Console.WriteLine($"Added game `TumblerGame: {gameGuid}`");

            Console.WriteLine("Provider Games: ");
            foreach (var game in await provider.Games())
            {
                Console.WriteLine($"Game 1: {game.Name}, {game.Guid}");
            }

            const int nplayers = 20;

            Console.WriteLine($"Adding {nplayers} Players....");

            var gameGrain = client.GetGrain <IGameBase>(gameGuid, "Grains.Game.Tumbler.TumblerGame");
            var player    = new IPlayerBase[nplayers];

            for (var i = 0; i < nplayers; i++)
            {
                player[i] = client.GetGrain <IPlayerBase>(PlayerHelper.MakeKey(Guid.NewGuid(), i + 1),
                                                          "Grains.Player.Tumbler.TumblerPlayer");
                await gameGrain.Join(player[i]);
            }

            Console.WriteLine("Starting the tumbler game...");
            await gameGrain.Start();

/*            // create two players
*           var blackjackGame = client.GetGrain<IGame>(blackjack);
*           var player1 = client.GetGrain<IPlayer>(Guid.NewGuid());
*           await blackjackGame.Join(player1);
*
*           var baccaratGame = client.GetGrain<IGame>(baccarat);
*           var player2 = client.GetGrain<IPlayer>(Guid.NewGuid());
*           await baccaratGame.Join(player2);
*
*           var player3 = client.GetGrain<IPlayer>(Guid.NewGuid());
*           await baccaratGame.Join(player3);*/
        }
        public override async Task Join(IPlayerBase player)
        {
            if (GameState.Active)
            {
                return;
            }

            var info = await player.Info();

            if (GameState.Players.Contains(info.UserKey))
            {
                return;
            }

            GameState.Players.Add(info.UserKey);
            await SaveState();

            await base.Join(player);
        }
        public override async Task <TumblerGameResponse> Play(IPlayerBase player, TumblerGameRequest request)
        {
            var result = new TumblerGameResponse();

            if (!GameState.Active)
            {
                return(result);
            }

            if (GameState.PlayerTurnIndex >= GameState.Players.Count)
            {
                return(result);
            }

            var info = await player.Info();

            var playing = GameState.Players[GameState.PlayerTurnIndex];

            if (playing != info.UserKey) // it is not this player's turn
            {
                return(result);
            }

            if (!GameState.RolledDices.ContainsKey(playing))
            {
                GameState.RolledDices[playing] = new List <Dice>();
            }

            GameState.RolledDices[playing].Add(request.Dice1);
            GameState.RolledDices[playing].Add(request.Dice2);

            GameState.PlayerTurnIndex++;

            if (GameState.PlayerTurnIndex < GameState.Players.Count)
            {
                await SaveState();

                //notify next player of his/her turn
                await RequestPlay(GameState.Players[GameState.PlayerTurnIndex]);

                return(result);
            }

            var winner       = Guid.Empty;
            var winnerPoints = 0;

            foreach (var(guid, rolled) in GameState.RolledDices)
            {
                var sum = rolled.Sum(play => play.Sum);
                if (sum <= winnerPoints)
                {
                    continue;
                }

                winnerPoints = sum;
                winner       = guid;
            }

            GameState.Active        = false; // game has ended
            GameState.WinningPlayer = winner;
            await SaveState();

            await NotifyPlayers($"Player {winner} is the winner by scoring {winnerPoints} points!");

            return(result);
        }