예제 #1
0
        public void Delayed(GameState ownerState, MGM.Game.Game game, Action doAction, TimeSpan?delay = null)
        {
            if (delay == null)
            {
                delay = TimeSpan.FromSeconds(3);
            }
            // ReSharper disable once LocalizableElement
            if (delay > TimeSpan.FromMinutes(1))
            {
                throw new ArgumentOutOfRangeException(nameof(delay), "Delayed action must occur within 1 minute");
            }
            var language  = LocalizedStrings.Language;
            var telemetry = TelemetryStatic.TelemetryClient;

            RunInThreadPoolAndReportErrors(() =>
            {
                Thread.Sleep((TimeSpan)delay);
                LocalizedStrings.Language       = language;
                TelemetryStatic.TelemetryClient = telemetry;
                lock (game)
                {
                    if (ownerState != game.State)
                    {
                        return;                           //silently give up, state was changed
                    }
                    doAction();
                    SaveGame(game);
                }
            });
        }
예제 #2
0
        private string SerializeGame([NotNull] MGM.Game.Game game)
        {
            var memoryStream = new MemoryStream();

            Serializer.WriteObject(memoryStream, game);
            return(Encoding.UTF8.GetString(memoryStream.ToArray()));
        }
예제 #3
0
 public void ShowRandomStory(MGM.Game.Game game)
 {
     UsingDb(db =>
     {
         var count = db.Stories.Count();
         if (count == 0)
         {
             return;            //doing nothing - it can be so, just no stories from admin
         }
         var storyToTellIndex = _storyRandom.Next(count);
         var story            = db.Stories.Skip(storyToTellIndex).Take(1).Single();
         game.GameStateBannerProvider.ShowPhoto(story.PhotoId, story.Body);
     });
 }
예제 #4
0
        public void ShowStat(MGM.Game.Game game)
        {//8/3/2016 2:46:18 AM
            UsingDb(db =>
            {
                string stat = $@"{LocalizedStrings.Stat_PlayerStatHeader}
{LocalizedStrings.Stat_PlayerWin}/{LocalizedStrings.Stat_PlayerGamesCount}
";
                var users   = db.Games.ById(game.Id).Players.Select(player => player.UserInTelegram).ToArray();
                foreach (var userInTelegram in users)
                {
                    stat += $@"*{game.Players.ById(userInTelegram.Id).Username}* -{userInTelegram.WinCount}/{userInTelegram.AllGameCount}
";
                }
                game.GameStateBannerProvider.CreateBanner(stat);
            });
        }
예제 #5
0
        public void Delayed(GameState ownerState, MGM.Game.Game game, Action doAction, TimeSpan?delay = null)
        {
            if (delay == null)
            {
                delay = TimeSpan.FromSeconds(3);
            }
            // ReSharper disable once LocalizableElement
            if (delay > TimeSpan.FromMinutes(1))
            {
                throw new ArgumentOutOfRangeException(nameof(delay), "Delayed action must occur within 1 minute");
            }
            var language  = LocalizedStrings.Language;
            var telemetry = TelemetryStatic.TelemetryClient;

            RunInThreadPoolAndReportErrors(() =>
            {
                Thread.Sleep((TimeSpan)delay);
                LocalizedStrings.Language       = language;
                TelemetryStatic.TelemetryClient = telemetry;
                lock (game)//todo: this action (receive game, lock it, process and save) is repeted in several places - must be extracted to somewhere
                {
                    if (ownerState != game.State)
                    {
                        return;                           //silently give up, state was changed
                    }
                    try
                    {
                        doAction();
                    }
                    catch (ApiChatBadRequestException)
                    {
                        try
                        {
                            game.Abort(true);
                        }
                        catch (ApiChatBadRequestException)
                        {
                        }
                    }
                    SaveGame(game);
                }
            });
        }
예제 #6
0
        public MGM.Game.Game GetGameForUser(UserInChat userInChat, bool isPrivate)
        {
            return(UsingDb(db =>
            {
                {
                    int gameIdToLoad;
                    if (!isPrivate)
                    {
                        //Retrieve game for this chat
                        var chatId = userInChat.ChatId;
                        var chat = db.ChatInTelegrams.ById(chatId);
                        var thisChatGames = chat.Games;

                        var notFinishedGame =
                            thisChatGames.SingleOrDefault(
                                game =>
                                game.FinishTime == null ||
                                game.FinishTime > DateTime.Now - EndState.EndStateMinMinutesTime);
                        if (notFinishedGame == null)
                        {
                            var locker = _gameCreationLockers.GetOrCreateLocker(userInChat.Chat); //todo low clean
                            lock (locker)
                            {
                                notFinishedGame = new Database.DataModels.Game.Game
                                {
                                    ChatInTelegram = chat,
                                    CreationTime = DateTime.Now,
                                    LastAccessTime = DateTime.Now
                                };
                                db.Add(notFinishedGame);
                                db.SaveChanges();
                                db.Refresh(RefreshMode.OverwriteChangesFromStore, notFinishedGame);


                                var newGameP = new MGM.Game.Game(userInChat.Chat.Title,
                                                                 new GameStateBannerProvider(new ApiChat(Api, userInChat.Chat, _limiter)), notFinishedGame.Id,
                                                                 this, this, chatId, this);
                                newGameP.State = new GameState.NewGameState(newGameP);
                                notFinishedGame.SerializedGame = SerializeGame(newGameP);
                                db.SaveChanges();
                                db.Refresh(RefreshMode.OverwriteChangesFromStore, notFinishedGame);
                            }
                        }

                        gameIdToLoad = notFinishedGame.Id;
                    }
                    else
                    {
                        //looking for games with this player, if many - choose first one that is awaiting for vote
                        var userInTelegram = db.UserInTelegrams.ById(userInChat.UserId);

                        var gameOfThrones = db.Players
                                            .Where(player => player.UserInTelegram == userInTelegram)
                                            .Where(player => player.Game.IsNight)
                                            .Where(player => player.Game.FinishTime == null)
                                            .Where(player => player.PutToVoting != null)
                                            .OrderBy(player => player.PutToVoting) //first is earliest
                                            .FirstOrDefault()
                                            ?.Game;

                        if (gameOfThrones == null)
                        {
//если игра не найдена
                            throw new BrakeFlowCallException(LocalizedStrings.GameProvider_NoGamesYouCanVote);
                        }
                        gameIdToLoad = gameOfThrones.Id;
                    }

                    return InternalLoadFromCacheOrDb(gameIdToLoad);
                }
            }));
        }
예제 #7
0
        /// <summary>
        ///     It's not thread safe and must be called from game lock
        /// </summary>
        public void SaveGame(MGM.Game.Game game)
        {
            UsingDb(db =>
            {
                var gameP            = db.Games.ById(game.Id);
                gameP.LastAccessTime = DateTime.Now;
                gameP.SerializedGame = SerializeGame(game);

                var creationTimeStamp = game.State.CreationTimeStamp;
                if (gameP.FinishTime == null)
                {
                    if (game.State.Status == GameStatus.Over)
                    {
                        //if game is finished - save when and update gamers rating
                        gameP.FinishTime = creationTimeStamp;

                        if (!game.State.Cast <EndState>().Abort)//if game was not aborted
                        {
                            foreach (var player in gameP.Players)
                            {
                                player.UserInTelegram.AllGameCount++;
                            }

                            if (game.MafiaWins)
                            {
                                foreach (var mafia in game.Mafias)
                                {
                                    db.UserInTelegrams.ById(mafia.Id).WinCount++;
                                }
                            }
                            else
                            {
                                if (!game.CitizenWins)
                                {
                                    throw new InvalidOperationException("How it could be so?");
                                }
                                var mafiaIds = game.Mafias.Select(player1 => player1.Id).ToArray();
                                foreach (var civilian in gameP.Players.Where(player => !mafiaIds.Contains(player.Id)))
                                {
                                    civilian.UserInTelegram.WinCount++;
                                }
                            }
                        }
                    }
                }

                if (game.State is AutoGameState)
                {
                    var timeLeft = game.State.Cast <AutoGameState>().TimeLeft;

                    gameP.MaxWakeupTime = DateTime.Now + timeLeft -
                                          (timeLeft > TimeSpan.FromSeconds(AutoGameState.WarnBeforeEndInSecond)
                                              ? TimeSpan.FromSeconds(20)
                                              : TimeSpan.Zero);
                }
                else
                {
                    gameP.MaxWakeupTime = null;
                }

                if (game.State is GameState.NewGameState)
                {
                    //everytime resave players
                    //todo: low perfomance impact
                    db.Delete(gameP.Players);
                    foreach (var player in game.Players)
                    {
                        db.Add(new Player
                        {
                            Game   = gameP,
                            UserId = player.Id//todo: low
                        });
                    }
                }
                if (game.State is NightState)
                {
                    gameP.IsNight = true;
                    foreach (var mafia in game.Mafias)
                    {
                        gameP.Players.Single(player => player.UserId == mafia.Id).PutToVoting =
                            creationTimeStamp;
                    }

                    if (game.Police != null && game.IsAlive(game.Police))
                    {
                        gameP.Players.Single(player => player.UserId == game.Police.Id).PutToVoting =
                            creationTimeStamp;
                    }

                    if (game.Doctor != null && game.IsAlive(game.Doctor))
                    {
                        gameP.Players.Single(player => player.UserId == game.Doctor.Id).PutToVoting =
                            creationTimeStamp; //todo: low too much queryable clones
                    }
                }
                else
                {
                    gameP.IsNight = false;
                }

                db.SaveChanges();
            });
        }