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); } }); }
private string SerializeGame([NotNull] MGM.Game.Game game) { var memoryStream = new MemoryStream(); Serializer.WriteObject(memoryStream, game); return(Encoding.UTF8.GetString(memoryStream.ToArray())); }
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); }); }
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); }); }
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); } }); }
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); } })); }
/// <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(); }); }