GameRoom.GameProcess.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using MafiaTelegramBot.Controllers;
  7. using MafiaTelegramBot.CustomCollections.Extensions;
  8. using MafiaTelegramBot.DataBase;
  9. using MafiaTelegramBot.DataBase.EntityDao;
  10. using MafiaTelegramBot.Game.GameRoles;
  11. using MafiaTelegramBot.Models;
  12. using MafiaTelegramBot.Resources;
  13. using Microsoft.EntityFrameworkCore;
  14. using Timer = System.Timers.Timer;
  15. namespace MafiaTelegramBot.Game.GameRooms
  16. {
  17. public partial class GameRoom
  18. {
  19. public void Start()
  20. {
  21. new Task(async () =>
  22. {
  23. IsRunning = true;
  24. await FirstNight();
  25. await FirstDay();
  26. await GameCycle();
  27. await EndOfGame();
  28. }).Start();
  29. }
  30. private async Task FirstDay()
  31. {
  32. IsDay = true;
  33. await PlayersCh.SendSticker(Stickers.Sticker["Day"]);
  34. await PlayersCh.Send(strings.first_day_message);
  35. await Task.Run(async() =>
  36. {
  37. var turnsCount = _turnOrder.Count;
  38. Player firstPlayer = null;
  39. for (var i = 0; i < turnsCount; ++i)
  40. {
  41. var player = _turnOrder.Dequeue();
  42. if(!player.IsPlaying) continue;
  43. await PlayersCh.Send($"{strings.now_turn} ({player.TurnOrder}) {player.NickName}");
  44. if (TimerEnabled) await Bot.SendWithMarkdown2(player.ChatId, strings.you_turn_say);
  45. await player.CurrentRole.SpeakAction();
  46. if (firstPlayer != null && player.IsPlaying) _turnOrder.Enqueue(player);
  47. else firstPlayer = player;
  48. }
  49. _turnOrder.Enqueue(firstPlayer);
  50. });
  51. }
  52. private async Task FirstNight()
  53. {
  54. IsDay = false;
  55. await Task.Run(async() =>
  56. {
  57. //Start updating games stats
  58. var statsQuery = "SELECT * FROM mafia.statistics WHERE";
  59. foreach (var player in Players.Values)
  60. {
  61. statsQuery += $" id = {player.Id} AND role = '{player.GetRole().ToString()}' OR role = 'All' OR";
  62. }
  63. statsQuery = statsQuery.Substring(0, statsQuery.Length - 2);
  64. try
  65. {
  66. var statsList = UserDao.DataBase.Statistics.FromSqlRaw(statsQuery).ToArrayAsync().Result;
  67. foreach (var player in Players.Values)
  68. {
  69. var userProfile = UserDao.GetPlayerById(player.Id).Result;
  70. foreach (var row in statsList.Where(s => s.UserId == player.Id))
  71. row.Games++;
  72. if (userProfile.Statistics.Contains(Roles.All))
  73. {
  74. userProfile.Statistics[player.CurrentRole.RoleKey].Games++;
  75. userProfile.Statistics[Roles.All].Games++;
  76. }
  77. }
  78. UserDao.DataBase.Statistics.UpdateRange(statsList);
  79. }
  80. catch (Exception e)
  81. {
  82. await Console.Out.WriteLineAsync(e.Message);
  83. }
  84. //Stop updating games stats
  85. await PlayersCh.SendSticker(Stickers.Sticker["Night"]);
  86. await PlayersCh.Send(strings.city_falls_asleep);
  87. var mafia = Players.Values.Where(player => player.GetRole() is Roles.Mafia).ToArray();
  88. var don = Players.Values.FirstOrDefault(player => player.GetRole() is Roles.Don);
  89. var dame = Players.Values.FirstOrDefault(player => player.GetRole() is Roles.Dame);
  90. var message = strings.your_teammates;
  91. if (don != null) message += $"\n({don.TurnOrder}) {don.NickName} - {roles.Don}";
  92. if (dame != null) message += $"\n({dame.TurnOrder}) {dame.NickName} - {roles.Dame}";
  93. message = mafia.Aggregate(message, (current, player) => current + $"\n({player.TurnOrder}) {player.NickName}");
  94. await _mafiaCh.Send(message);
  95. var resetEvent = new ManualResetEvent(false);
  96. var timer = new Timer
  97. {
  98. AutoReset = false,
  99. Interval = Constants.FIRST_NIGHT_INTERVAL
  100. };
  101. timer.Elapsed += (_, _) => resetEvent.Set();
  102. timer.Start();
  103. try
  104. {
  105. await UserDao.DataBase.SaveChangesAsync();
  106. }
  107. catch (Exception e)
  108. {
  109. await Console.Out.WriteLineAsync(e.Message);
  110. }
  111. foreach (var player in Players.Values)
  112. {
  113. if (player.GetRole() is not (Roles.Don or Roles.Mafia or Roles.Dame))
  114. player.CurrentRole.KnownRoles.Add(player.Id, player.GetRoleName());
  115. else
  116. foreach (var p in Players.Values
  117. .Where(p => p.GetRole() is Roles.Don or Roles.Mafia or Roles.Dame))
  118. player.CurrentRole.KnownRoles.Add(p.Id, p.GetRoleName());
  119. }
  120. resetEvent.WaitOne();
  121. });
  122. }
  123. private async Task GameCycle()
  124. {
  125. await Task.Run(async () =>
  126. {
  127. while (GameNotEnded())
  128. {
  129. await NightPhase();
  130. await SummingUpPhase();
  131. if (!GameNotEnded()) break;
  132. await DayPhase();
  133. await DispatchPhase();
  134. if (!GameNotEnded()) break;
  135. }
  136. });
  137. }
  138. private bool GameNotEnded()
  139. {
  140. var playersCount = Players.Values.Count(p => p.IsAlive);
  141. var mafiaCount = Players.Values.Count(p => p.IsAlive && p.GetRole() is Roles.Don or Roles.Mafia or Roles.Dame);
  142. if (PlayersRole.ContainsKey(Roles.Werewolf)
  143. && PlayersRole[Roles.Werewolf].Count == 1 && PlayersRole[Roles.Werewolf][0].IsAlive
  144. && ((WerewolfRole) PlayersRole[Roles.Werewolf][0].CurrentRole).IsMafia) mafiaCount++;
  145. var villagersCount = playersCount - mafiaCount;
  146. return villagersCount > mafiaCount && mafiaCount > 0;
  147. }
  148. private async Task DayPhase()
  149. {
  150. IsDay = true;
  151. var discussionTimer = new Timer {AutoReset = false, Interval = Constants.DISCUSSION_INTERVAL};
  152. var discussionEnded = new ManualResetEvent(false);
  153. foreach (var player in Players.Values.Where(player => !player.IsBlocked)) player.IsSpeaker = true;
  154. discussionTimer.Elapsed += async (_, _) =>
  155. {
  156. foreach (var player in Players.Values) player.IsSpeaker = false;
  157. await PlayersCh.Send(strings.day_discussion_ended);
  158. discussionEnded.Set();
  159. };
  160. await PlayersCh.Send(strings.disscution_time);
  161. discussionTimer.Start();
  162. discussionEnded.WaitOne();
  163. var turnsCount = _turnOrder.Count;
  164. Player toEndQueue = null;
  165. for (var i = 0; i < turnsCount; ++i)
  166. {
  167. var player = _turnOrder.Dequeue();
  168. if(!Players.ContainsKey(player.Id)) continue;
  169. if (!player.IsBlocked && player.IsAlive)
  170. {
  171. await PlayersCh.Send($"{strings.now_turn} ({player.TurnOrder}) {player.NickName}");
  172. if (TimerEnabled) await Bot.SendWithMarkdown2(player.ChatId, strings.you_turn_say);
  173. await player.CurrentRole.SpeakAction();
  174. if (Players.ContainsKey(player.Id)) await player.CurrentRole.VotingAction(VoteUpList.Count == 0);
  175. }
  176. if (toEndQueue != null) _turnOrder.Enqueue(player);
  177. else toEndQueue = player;
  178. }
  179. _turnOrder.Enqueue(toEndQueue);
  180. }
  181. private async Task NightPhase()
  182. {
  183. IsDay = false;
  184. await PlayersCh.SendSticker(Stickers.Sticker["Night"]);
  185. await PlayersCh.Send(strings.city_falls_asleep);
  186. await Task.Run(async () =>
  187. {
  188. var resetEvent = new ManualResetEvent(false);
  189. var timer = new Timer{ Interval = Constants.NIGHT_ACTION_INTERVAL, AutoReset = false };
  190. foreach (var player in Players.Values)
  191. await player.CurrentRole.NightAction();
  192. timer.Elapsed += (_, _) => resetEvent.Set();
  193. var doctorId = PlayersRole[Roles.Doctor].Count == 1 ? PlayersRole[Roles.Doctor][0].Id : -1;
  194. foreach (var player in Players.Values)
  195. {
  196. if(doctorId != player.Id) player.CanBeHealed = true;
  197. player.CanBeBlockedNight = true;
  198. player.CanBeBlockedDay = true;
  199. player.IsBlocked = false;
  200. }
  201. timer.Start();
  202. resetEvent.WaitOne();
  203. });
  204. }
  205. public async Task SummingUpPhase()
  206. {
  207. await Task.Run(async () =>
  208. {
  209. var beforeKill = Players.Values.ToDictionary(p=>p.Id,p=>p.IsAlive);
  210. var mafiaNotAgree = "";
  211. var votes = Players.Values.Where(p=> p.IsAlive && p.CurrentRole.MafiaTargetId != -1 && p.CurrentRole.MafiaTargetId != -2 && p.CurrentRole.MafiaTargetId != -4)
  212. .GroupBy(p => p.CurrentRole.MafiaTargetId)
  213. .Select(item => new {id = item.Key, count = item.Count()})
  214. .ToList();
  215. if (votes.Count == 0)
  216. {
  217. var allMafiaVotes = Players.Values.Where(p => p.CurrentRole.MafiaTargetId is -1 or -2 or -3).Distinct().ToList();
  218. if (allMafiaVotes.Count == 1)
  219. {
  220. mafiaNotAgree = allMafiaVotes[0].CurrentRole.MafiaTargetId switch
  221. {
  222. -1 => strings.mafia_not_kill_message,
  223. -3 => strings.mafia_decided_not_kill,
  224. _ => "",
  225. };
  226. }
  227. }
  228. else {
  229. var max = votes.Max(item => item.count);
  230. var maxObjects = votes.Where(item => item.count == max).ToList();
  231. if(maxObjects.Count == 1)
  232. {
  233. if (Players.ContainsKey(maxObjects[0].id))
  234. await Players[maxObjects[0].id].CurrentRole.Kill();
  235. }
  236. }
  237. foreach (var (role, players) in PlayersRole)
  238. {
  239. if (role is Roles.Mafia)
  240. foreach (var mafia in players) await mafia.CurrentRole.ApplyNightActionResult();
  241. else if (players.Count == 1) await players[0].CurrentRole.ApplyNightActionResult();
  242. }
  243. var afterKill = Players.Values.ToDictionary(p=>p.Id,p=>p.IsAlive);
  244. var message = strings.city_wakes_up;
  245. if(afterKill.IsEquals(beforeKill)) message += strings.everyone_survived;
  246. else foreach (var (id, alive) in afterKill)
  247. if(beforeKill[id] != alive && Players.ContainsKey(id))
  248. {
  249. message += alive
  250. ? $"\n{Players[id].NickName} {strings.will_be_ressurected}"
  251. : $"\n{Players[id].NickName} {strings.will_be_killed}";
  252. if(!alive && Players[id].GetRole() is Roles.Don or Roles.Dame or Roles.Mafia
  253. && PlayersRole.ContainsKey(Roles.Werewolf) && PlayersRole[Roles.Werewolf].Count == 1)
  254. await ((WerewolfRole) PlayersRole[Roles.Werewolf][0].CurrentRole).TransformToMafia();
  255. await PlayersCh.SendTo(id, alive ? strings.you_will_be_ressurected : strings.you_will_be_killed);
  256. }
  257. message += '\n' + mafiaNotAgree;
  258. await PlayersCh.SendSticker(Stickers.Sticker["Day"]);
  259. await PlayersCh.Send(message);
  260. });
  261. }
  262. private async Task DefencePhase(List<Player> contenders)
  263. {
  264. await Task.Run( async () =>
  265. {
  266. var contendersCopy = contenders.ToList();
  267. foreach (var contender in contendersCopy.Where(p => !p.IsBlocked))
  268. if (Players.ContainsKey(contender.Id)) await contender.CurrentRole.DefenceAction();
  269. var votersPlayers = Players.Values.Where(p => p.IsAlive && !p.IsBlocked).ToArray();
  270. foreach (var voter in votersPlayers)
  271. await voter.CurrentRole.VotingAction(contendersCopy.Where(p => Players.ContainsKey(p.Id)).ToList());
  272. var timer = new Timer {Interval = Constants.VOTE_KILL_INTERVAL, AutoReset = false};
  273. var resetEvent = new ManualResetEvent(false);
  274. timer.Elapsed += async(_, _) =>
  275. {
  276. foreach (var voter in votersPlayers.Where(p => !VoteKillList.ContainsKey(p.Id) && Players.ContainsKey(p.Id)))
  277. await voter.CurrentRole.RandomVoting();
  278. resetEvent.Set();
  279. };
  280. timer.Start();
  281. resetEvent.WaitOne();
  282. });
  283. }
  284. private async Task DispatchPhase()
  285. {
  286. await Task.Run(async () =>
  287. {
  288. switch (VoteUpList.Count)
  289. {
  290. case 0:
  291. await PlayersCh.Send(strings.nothing_up_to_vote);
  292. break;
  293. case 1:
  294. {
  295. await VoteUpList[0].CurrentRole.Dispatch();
  296. break;
  297. }
  298. default:
  299. {
  300. await DefencePhase(VoteUpList);
  301. VoteUpList = await CalculateCandidates();
  302. switch (VoteUpList.Count)
  303. {
  304. case 0:
  305. await PlayersCh.Send(strings.nothing_up_to_dispatch);
  306. break;
  307. case 1:
  308. await VoteUpList[0].CurrentRole.Dispatch();
  309. break;
  310. case > 1:
  311. var copyVoteUpList = VoteUpList.ToList();
  312. await DefencePhase(VoteUpList);
  313. VoteUpList = await CalculateCandidates();
  314. var alivers = copyVoteUpList.Except(VoteUpList).ToList();
  315. foreach (var alive in alivers)
  316. alive.ElderRoleAchievementEvent();
  317. switch (VoteUpList.Count)
  318. {
  319. case 0:
  320. await PlayersCh.Send(strings.nothing_up_to_dispatch);
  321. break;
  322. case 1:
  323. await VoteUpList[0].CurrentRole.Dispatch();
  324. break;
  325. default:
  326. await PlayersCh.Send(strings.villagers_could_not_decide);
  327. foreach (var alive in VoteUpList)
  328. alive.ElderRoleAchievementEvent();
  329. break;
  330. }
  331. break;
  332. }
  333. break;
  334. }
  335. }
  336. VoteUpList.Clear();
  337. VoteKillList.Clear();
  338. });
  339. }
  340. private async Task<List<Player>> CalculateCandidates()
  341. {
  342. var message = strings.results_of_voting;
  343. foreach (var (playerId, targetId) in VoteKillList)
  344. {
  345. message += Players.ContainsKey(playerId) && Players.ContainsKey(targetId)
  346. ? $"\n({Players[playerId].TurnOrder}) {Players[playerId].NickName} {strings.vote_to} " +
  347. $"({Players[targetId].TurnOrder}) {Players[targetId].NickName}" : "";
  348. }
  349. if (message == strings.results_of_voting) message = strings.no_one_voted;
  350. await PlayersCh.Send(message);
  351. var votes = VoteUpList.Where(p=>Players.ContainsKey(p.Id))
  352. .GroupBy(p => p.Id)
  353. .Select(item => new {id = item.Key, count = item.Count()})
  354. .ToList();
  355. List<Player> result = new();
  356. if (votes.Count == 0) return result;
  357. var max = votes.Max(item => item.count);
  358. var maxObjects = votes.Where(item => item.count == max);
  359. result.AddRange(from obj in maxObjects select Players[obj.id]);
  360. VoteKillList.Clear();
  361. VoteUpList.Clear();
  362. return result;
  363. }
  364. private async Task PutUpVote(long playerId, long targetId, int messageId = -1, bool toKill = false)
  365. {
  366. if (Players.ContainsKey(playerId))
  367. {
  368. if (targetId == 0)
  369. {
  370. if (!toKill) await PlayersCh.SendExcept(playerId, $"{Players[playerId].NickName} {strings.skip_vote}");
  371. await PlayersCh.EditTo(playerId, messageId, strings.you_skip_vote);
  372. }
  373. else
  374. {
  375. if (Players.ContainsKey(targetId))
  376. {
  377. if (!toKill)
  378. {
  379. if (VoteUpList.AddUnique(Players[targetId]))
  380. {
  381. if (playerId != targetId)
  382. {
  383. await PlayersCh.SendExcept(playerId, $"{Players[playerId].NickName} {strings.put_up_vote_to} {Players[targetId].NickName}");
  384. await PlayersCh.EditTo(playerId, messageId, $"{strings.you_vote_player} {Players[targetId].NickName}");
  385. }
  386. else
  387. {
  388. await PlayersCh.SendExcept(playerId, $"{Players[playerId].NickName} {strings.vote_to_self}");
  389. await PlayersCh.EditTo(playerId, messageId, strings.you_vote_to_self);
  390. }
  391. }
  392. }
  393. else if (VoteKillList.AddUniqueByKey(playerId, targetId))
  394. {
  395. VoteUpList.Add(Players[targetId]);
  396. if (messageId != -1)
  397. {
  398. if (playerId != targetId)
  399. await PlayersCh.EditTo(playerId, messageId, $"{strings.you_vote_to_kill} {Players[targetId].NickName}");
  400. else
  401. await PlayersCh.EditTo(playerId, messageId, strings.you_vote_to_kill_self);
  402. }
  403. }
  404. }
  405. }
  406. }
  407. else await PlayersCh.SendTo(playerId, strings.this_player_left_from_game);
  408. }
  409. private async Task EndOfGame()
  410. {
  411. await Task.Run(async () =>
  412. {
  413. var aliveMafia = Players.Values.Count(p => p.GetRole() is Roles.Don or Roles.Dame or Roles.Mafia && p.IsAlive);
  414. if (PlayersRole.ContainsKey(Roles.Werewolf)
  415. && PlayersRole[Roles.Werewolf].Count == 1 && PlayersRole[Roles.Werewolf][0].IsAlive
  416. && ((WerewolfRole) PlayersRole[Roles.Werewolf][0].CurrentRole).IsMafia) aliveMafia++;
  417. var additionalResult = "";
  418. foreach (var (_, value) in PlayersRole)
  419. {
  420. if (value.Count != 1) continue;
  421. var yellowResult = await value[0].CurrentRole.IsWon();
  422. if (yellowResult != "") additionalResult += "\n" + yellowResult;
  423. }
  424. if (aliveMafia == 0)
  425. {
  426. await PlayersCh.Send(strings.villagers_won + additionalResult, exceptDied: false);
  427. await PlayersCh.SendSticker(Stickers.Sticker["VillagerWins"]);
  428. }
  429. else
  430. {
  431. if (aliveMafia == 1)
  432. {
  433. var player = Players.Values.FirstOrDefault(p => p.IsAlive && p.GetRole() is Roles.Don or Roles.Dame or Roles.Mafia) ??
  434. PlayersRole[Roles.Werewolf][0];
  435. player.LawyerRoleAchievementEvent();
  436. }
  437. await PlayersCh.Send(strings.mafia_won + additionalResult, exceptDied: false);
  438. await PlayersCh.SendSticker(Stickers.Sticker["MafiaWins"]);
  439. }
  440. if (PlayersRole.ContainsKey(Roles.Fool) && PlayersRole[Roles.Fool].Count == 1)
  441. await PlayersRole[Roles.Fool][0].CurrentRole.IsWon();
  442. var rolesMessage = strings.in_this_game_roles;
  443. var players = Players.Values.ToList();
  444. var statsQueryStats = "SELECT * FROM mafia.statistics WHERE";
  445. var statsQueryOpenRoles = "SELECT * FROM mafia.opened_roles WHERE";
  446. foreach (var player in players)
  447. {
  448. rolesMessage += $"\n({player.TurnOrder}) {player.NickName} - {player.GetRoleName()}";
  449. statsQueryStats += $" id = {player.Id} AND role = '{player.GetRole().ToString()}' OR role = 'All' OR";
  450. statsQueryOpenRoles += $" id = {player.Id} OR";
  451. }
  452. await PlayersCh.Send(rolesMessage);
  453. //var updatingNotifications = await PlayersCh.SendWithReturn("Update data! Wait until it disappears");
  454. statsQueryStats = statsQueryStats.Substring(0, statsQueryStats.Length - 2);
  455. statsQueryOpenRoles = statsQueryOpenRoles.Substring(0, statsQueryOpenRoles.Length - 2);
  456. try
  457. {
  458. var statsList = UserDao.DataBase.Statistics.FromSqlRaw(statsQueryStats).ToArrayAsync().Result;
  459. var openRolesList = UserDao.DataBase.OpenedRoles.FromSqlRaw(statsQueryOpenRoles).ToArrayAsync().Result;
  460. void UpdateWins(Player player)
  461. {
  462. var userProfile = UserDao.GetPlayerById(player.Id).Result;
  463. foreach (var row in statsList.Where(s => s.UserId == player.Id))
  464. {
  465. row.Wins++;
  466. }
  467. var roles = openRolesList.Where(o => o.Id == player.Id).First();
  468. if (roles.Hooker == false)
  469. roles.Hooker = true;
  470. if (userProfile.Statistics.Contains(Roles.All))
  471. {
  472. userProfile.Statistics[player.CurrentRole.RoleKey].Wins++;
  473. userProfile.Statistics[Roles.All].Wins++;
  474. }
  475. }
  476. var villagerTeam = players.Where(p => p.CurrentRole.ColorRole == 1 && p.GetRole() != Roles.Lawyer).Select(p => p.Id);
  477. var mafiaTeam = players.Where(p => p.CurrentRole.ColorRole == 2 || p.GetRole() == Roles.Lawyer).Select(p => p.Id);
  478. foreach (var player in players)
  479. {
  480. if (aliveMafia == 0)
  481. {
  482. if(player.CurrentRole.ColorRole == 1 && player.CurrentRole.RoleKey != Roles.Lawyer)
  483. {
  484. UpdateWins(player);
  485. if (player.CurrentRole.RoleKey == Roles.Werewolf)
  486. {
  487. if (player.CurrentRole.ColorRole == 1)
  488. player.WerewolfRoleAchievementEvent(1);
  489. else player.WerewolfRoleAchievementEvent(2, true);
  490. }
  491. player.ParasiteRoleAchievementEvent(villagerTeam.ToList());
  492. }
  493. else player.ResetParasiteProgress();
  494. }
  495. else
  496. {
  497. if(player.CurrentRole.ColorRole == 2 || player.CurrentRole.RoleKey == Roles.Lawyer)
  498. {
  499. UpdateWins(player);
  500. player.ParasiteRoleAchievementEvent(mafiaTeam.ToList());
  501. }
  502. else player.ResetParasiteProgress();
  503. }
  504. if (player.CurrentRole.ColorRole == 3)
  505. {
  506. if (player.CurrentRole.IsWon().Result != "") UpdateWins(player);
  507. else player.ResetParasiteProgress();
  508. }
  509. if (player.CurrentRole.RoleKey == Roles.Cop)
  510. {
  511. if (((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountRed ==
  512. ((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountBlack) player.JournalistAchievementEvent();
  513. if (((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountRed == 0 &&
  514. ((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountBlack != 0) player.DetectiveAchievementEvent();
  515. }
  516. player.ResetState();
  517. }
  518. UserDao.DataBase.Statistics.UpdateRange(statsList);
  519. UserDao.DataBase.OpenedRoles.UpdateRange(openRolesList);
  520. await UserDao.DataBase.SaveChangesAsync();
  521. }
  522. catch (Exception e)
  523. {
  524. await Console.Out.WriteLineAsync(e.Message);
  525. }
  526. IsRunning = false;
  527. IsDay = false;
  528. _turnOrder.Clear();
  529. Settings.Clear();
  530. foreach (var (_, list) in PlayersRole) list.Clear();
  531. if (!Players.ContainsKey(Owner.Id) || Players.Count == 0) new Task(async() =>
  532. await RoomController.DissolveRoom(RoomEncrypter.GetCode(RoomName))).Start();
  533. else
  534. {
  535. await Bot.SendWithMarkdown2(Owner.ChatId, strings.thanks_for_game, Keyboard.OwnerGameMenu);
  536. await PlayersCh.SendExcept(Owner.Id, strings.thanks_for_game, Keyboard.PlayerGameMenu);
  537. }
  538. if (Players.Count <= Constants.PLAYER_DISABLE_TIMER) StartTimer();
  539. await MafiaDataBase.GetInstance().SaveChangesAsync();
  540. });
  541. }
  542. }
  543. }