Quellcode durchsuchen

Add draw result and change channels structure

Tigran vor 4 Jahren
Ursprung
Commit
3ad099c79e

+ 4 - 4
MafiaTelegramBot/Controllers/RoomController.cs

@@ -41,10 +41,10 @@ namespace MafiaTelegramBot.Controllers
                 if (!player.SetRoomName(roomName)) return ResultCode.UserAlreadyInGame;
                 OpenedGames[roomKey].Players.Add(player.Id, player);
 
-                if (OpenedGames[roomKey].Players.Count > Constants.MEMORY_CLEANER_INTERVAL)
-                    OpenedGames[roomKey].StopTimer();
+                if (OpenedGames[roomKey].Players.Count > Constants.MEMORY_CLEANER_PLAYERS_COUNT) OpenedGames[roomKey].StopTimer();
                 
                 await OpenedGames[roomKey].PlayersMessageChannel.SendExcept(player.Id, $"{player.NickName} {strings.connected_to_game}");
+                OpenedGames[roomKey].PlayersMessageChannel.AddPerson(player.ChatId);
                 return ResultCode.CodeOk;
             });
         }
@@ -60,7 +60,7 @@ namespace MafiaTelegramBot.Controllers
             {
                 var roomName = player.GetRoomName();
                 var roomKey = RoomEncrypter.GetCode(roomName);
-                if (!await player.RemoveGame()) return ResultCode.UserNotInGame;
+                if (!player.RemoveGame()) return ResultCode.UserNotInGame;
                 await OpenedGames[roomKey].Leave(player);
                 if (!OpenedGames[roomKey].IsRunning &&
                     OpenedGames[roomKey].Players.Count <= Constants.MEMORY_CLEANER_INTERVAL)
@@ -82,7 +82,7 @@ namespace MafiaTelegramBot.Controllers
                     {
                         await OpenedGames[roomKey].PlayersMessageChannel.SendTo(player.Id, strings.room_dissolved,
                             player.IsAdmin ? Keyboard.AdminMainMenu : Keyboard.MainMenu);
-                        await player.RemoveGame();
+                        player.RemoveGame();
                         player.ResetState();
                     }
                     RoomEncrypter.RemoveCode(OpenedGames[roomKey].RoomName);

+ 4 - 30
MafiaTelegramBot/DataBase/Entity/UserEntity.cs

@@ -10,40 +10,14 @@ namespace MafiaTelegramBot.DataBase.Entity
     {
         [Key]
         [DatabaseGenerated(DatabaseGeneratedOption.None)]
-        [Column("id"), MaxLength(127)] public long Id { get; init; }
-        [Column("chat_id") , MaxLength(127)] public long ChatId { get; init; }
-        
-        [NotMapped] private string _username = "\\[NoUsername\\]";
-        [Column("username") , MaxLength(127)] public string Username
-        {
-            get => _username;
-            set
-            {
-                var buff = _username;
-                _username = value;
-                if (buff != value && buff != "\\[NoUsername\\]") Task.Run(async () => await UserDao.Update(this));
-            }
-        }
+        [Column("id"), MaxLength(127)] public long Id { get; set; }
+        [Column("chat_id") , MaxLength(127)] public long ChatId { get; set; }
+        [Column("username"), MaxLength(127)] public string Username { get; set; } = "\\[NoUsername\\]";
 
         [Column("nickname") , MaxLength(127)] public string NickName { get; set; } = "\\[NoNickname\\]";
         
         [Column("rank_number") , MaxLength(127)] public int RankNumber { get; set; } = 0;
         
-        [Column("is_admin"), MaxLength(127)] public int isAdmin { get; set; } = 0;
-
-        [NotMapped]
-        public bool IsAdmin
-        {
-            get => isAdmin > 0;
-            set => isAdmin = value ? 1 : 0;
-        }
-
-        public async Task UpdateNickName(string newName)
-        {
-            var buff = NickName;
-            NickName = newName;
-            if (buff != newName && buff != "\\[NoNickname\\]")
-                await UserDao.Update(this);
-        }
+        [Column("is_admin"), MaxLength(127)] public int IsAdmin { get; set; } = 0;
     }
 }

+ 9 - 14
MafiaTelegramBot/DataBase/EntityDao/UserDao.cs

@@ -1,4 +1,3 @@
-using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
@@ -33,24 +32,20 @@ namespace MafiaTelegramBot.DataBase.EntityDao
         {
             if (ActiveUsers.ContainsKey(id)) return ActiveUsers[id];
             var user = await Task.Run(()=> DataBase.Users.First(user1 => user1.Id == id));
-            var player = Player.FromUserEntity(user);
-            player.OpenedRoles = await OpenedRolesDao.GetOpenedRolesById(id);
-            player.Achievements = await AchievementsDao.GetAchievementsProgressById(id);
-            player.Statistics = await StatisticsDao.GetStatisticsListById(id);
+            var player = new Player
+            {
+                User = user,
+                OpenedRoles = await OpenedRolesDao.GetOpenedRolesById(id),
+                Achievements = await AchievementsDao.GetAchievementsProgressById(id),
+                Statistics = await StatisticsDao.GetStatisticsListById(id)
+            };
             ActiveUsers.Add(user.Id, player);
             return player;
         }
         
-        public static async Task Update(UserEntity user)
+        public static async Task AddNew(UserEntity user)
         {
-            var result = await DataBase.Users.SingleOrDefaultAsync(b => b.Id == user.Id);
-            if (result == null) DataBase.Users.Add(user);
-            else
-            {
-                result.NickName = user.NickName;
-                result.Username = user.Username;
-                DataBase.Users.Update(result);
-            }
+            DataBase.Users.Add(user);
             await DataBase.SaveChangesAsync();
         }
 

+ 1 - 1
MafiaTelegramBot/Game/GameRoles/WerewolfRole.cs

@@ -63,7 +63,7 @@ namespace MafiaTelegramBot.Game.GameRoles
             if (don != null) message += $"\n({don.TurnOrder}) {don.NickName} - {roles.Don}";
             if (dame != null) message += $"\n({dame.TurnOrder}) {dame.NickName} - {roles.Dame}";
             message = mafia.Aggregate(message, (current, player) => current + $"\n({player.TurnOrder}) {player.NickName}");
-            Room.MafiaMessageChannel.AddPerson(Player);
+            Room.MafiaMessageChannel.AddPerson(Player.ChatId);
             await Room.PlayersMessageChannel.SendTo(Player.Id, message);
         }
 

+ 186 - 208
MafiaTelegramBot/Game/GameRooms/GameRoom.GameProcess.cs

@@ -33,20 +33,21 @@ namespace MafiaTelegramBot.Game.GameRooms
             IsDay = true;
             await PlayersMessageChannel.SendSticker(Stickers.Sticker["Day"]);
             await PlayersMessageChannel.Send(strings.first_day_message);
-            await Task.Run(async() =>
+            await Task.Run(async () =>
             {
                 var turnsCount = _turnOrder.Count;
                 Player firstPlayer = null;
                 for (var i = 0; i < turnsCount; ++i)
                 {
                     var player = _turnOrder.Dequeue();
-                    if(!player.IsPlaying) continue;
+                    if (!player.IsPlaying) continue;
                     await PlayersMessageChannel.Send($"{strings.now_turn} ({player.TurnOrder}) {player.NickName}");
                     if (TimerEnabled) await Bot.SendWithMarkdown2(player.ChatId, strings.you_turn_say);
                     await player.CurrentRole.SpeakAction();
                     if (firstPlayer != null && player.IsPlaying) _turnOrder.Enqueue(player);
                     else firstPlayer = player;
                 }
+
                 _turnOrder.Enqueue(firstPlayer);
             });
         }
@@ -54,41 +55,21 @@ namespace MafiaTelegramBot.Game.GameRooms
         private async Task FirstNight()
         {
             IsDay = false;
-            await Task.Run(async() =>
+            await Task.Run(async () =>
             {
-                //Start updating games stats
-                // var statsQuery = "SELECT * FROM mafia.statistics WHERE";
-                // foreach (var player in Players.Values)
-                // {
-                //     statsQuery += $" id = {player.Id} AND role = '{player.GetRole().ToString()}' OR role = 'All' OR";
-                // }
-
-                // statsQuery = statsQuery.Substring(0, statsQuery.Length - 2);
-
                 try
                 {
-                    // var statsList = UserDao.DataBase.Statistics.FromSqlRaw(statsQuery).ToArrayAsync().Result;
-
                     foreach (var player in Players.Values)
                     {
-                        var userProfile = UserDao.GetPlayerById(player.Id).Result;
-                        // foreach (var row in statsList.Where(s => s.UserId == player.Id))
-                        //     row.Games++;
-                        
-                        if (userProfile.Statistics.Contains(Roles.All))
-                        {
-                            userProfile.Statistics[player.CurrentRole.RoleKey].Games++;
-                            userProfile.Statistics[Roles.All].Games++;
-                        }
+                        player.Statistics[player.CurrentRole.RoleKey].Games++;
+                        player.Statistics[Roles.All].Games++;
                     }
-                    // UserDao.DataBase.Statistics.UpdateRange(statsList);
                 }
                 catch (Exception e)
                 {
                     await Console.Out.WriteLineAsync(e.Message);
                 }
-                //Stop updating games stats
-                
+
                 await PlayersMessageChannel.SendSticker(Stickers.Sticker["Night"]);
                 await PlayersMessageChannel.Send(strings.city_falls_asleep);
                 var mafia = Players.Values.Where(player => player.GetRole() is Roles.Mafia).ToArray();
@@ -97,7 +78,8 @@ namespace MafiaTelegramBot.Game.GameRooms
                 var message = strings.your_teammates;
                 if (don != null) message += $"\n({don.TurnOrder}) {don.NickName} - {roles.Don}";
                 if (dame != null) message += $"\n({dame.TurnOrder}) {dame.NickName} - {roles.Dame}";
-                message = mafia.Aggregate(message, (current, player) => current + $"\n({player.TurnOrder}) {player.NickName}");
+                message = mafia.Aggregate(message,
+                    (current, player) => current + $"\n({player.TurnOrder}) {player.NickName}");
                 await MafiaMessageChannel.Send(message);
                 var resetEvent = new ManualResetEvent(false);
                 var timer = new Timer
@@ -107,7 +89,7 @@ namespace MafiaTelegramBot.Game.GameRooms
                 };
                 timer.Elapsed += (_, _) => resetEvent.Set();
                 timer.Start();
-                
+
                 try
                 {
                     await UserDao.DataBase.SaveChangesAsync();
@@ -119,13 +101,14 @@ namespace MafiaTelegramBot.Game.GameRooms
 
                 foreach (var player in Players.Values)
                 {
-                    if (player.GetRole() is not (Roles.Don or Roles.Mafia or Roles.Dame)) 
+                    if (player.GetRole() is not (Roles.Don or Roles.Mafia or Roles.Dame))
                         player.CurrentRole.KnownRoles.Add(player.Id, player.GetRoleName());
                     else
                         foreach (var p in Players.Values
                             .Where(p => p.GetRole() is Roles.Don or Roles.Mafia or Roles.Dame))
                             player.CurrentRole.KnownRoles.Add(p.Id, p.GetRoleName());
                 }
+
                 resetEvent.WaitOne();
             });
         }
@@ -149,10 +132,11 @@ namespace MafiaTelegramBot.Game.GameRooms
         private bool GameNotEnded()
         {
             var playersCount = Players.Values.Count(p => p.IsAlive);
-            var mafiaCount = Players.Values.Count(p => p.IsAlive && p.GetRole() is Roles.Don or Roles.Mafia or Roles.Dame);
+            var mafiaCount =
+                Players.Values.Count(p => p.IsAlive && p.GetRole() is Roles.Don or Roles.Mafia or Roles.Dame);
             if (PlayersRole.ContainsKey(Roles.Werewolf)
                 && PlayersRole[Roles.Werewolf].Count == 1 && PlayersRole[Roles.Werewolf][0].IsAlive
-                && ((WerewolfRole) PlayersRole[Roles.Werewolf][0].CurrentRole).IsMafia) mafiaCount++;
+                && ((WerewolfRole)PlayersRole[Roles.Werewolf][0].CurrentRole).IsMafia) mafiaCount++;
             var villagersCount = playersCount - mafiaCount;
             return villagersCount > mafiaCount && mafiaCount > 0;
         }
@@ -160,8 +144,8 @@ namespace MafiaTelegramBot.Game.GameRooms
         private async Task DayPhase()
         {
             IsDay = true;
-            
-            var discussionTimer = new Timer {AutoReset = false, Interval = Constants.DISCUSSION_INTERVAL};
+
+            var discussionTimer = new Timer { AutoReset = false, Interval = Constants.DISCUSSION_INTERVAL };
             var discussionEnded = new ManualResetEvent(false);
             foreach (var player in Players.Values.Where(player => !player.IsBlocked)) player.IsSpeaker = true;
             discussionTimer.Elapsed += async (_, _) =>
@@ -173,13 +157,13 @@ namespace MafiaTelegramBot.Game.GameRooms
             await PlayersMessageChannel.Send(strings.disscution_time);
             discussionTimer.Start();
             discussionEnded.WaitOne();
-            
+
             var turnsCount = _turnOrder.Count;
             Player toEndQueue = null;
             for (var i = 0; i < turnsCount; ++i)
             {
                 var player = _turnOrder.Dequeue();
-                if(!Players.ContainsKey(player.Id)) continue;
+                if (!Players.ContainsKey(player.Id)) continue;
                 if (!player.IsBlocked && player.IsAlive)
                 {
                     await PlayersMessageChannel.Send($"{strings.now_turn} ({player.TurnOrder}) {player.NickName}");
@@ -187,9 +171,11 @@ namespace MafiaTelegramBot.Game.GameRooms
                     await player.CurrentRole.SpeakAction();
                     if (Players.ContainsKey(player.Id)) await player.CurrentRole.VotingAction(_voteUpList.Count == 0);
                 }
+
                 if (toEndQueue != null) _turnOrder.Enqueue(player);
                 else toEndQueue = player;
             }
+
             _turnOrder.Enqueue(toEndQueue);
         }
 
@@ -201,18 +187,19 @@ namespace MafiaTelegramBot.Game.GameRooms
             await Task.Run(async () =>
             {
                 var resetEvent = new ManualResetEvent(false);
-                var timer = new Timer{ Interval = Constants.NIGHT_ACTION_INTERVAL, AutoReset = false };
+                var timer = new Timer { Interval = Constants.NIGHT_ACTION_INTERVAL, AutoReset = false };
                 foreach (var player in Players.Values)
                     await player.CurrentRole.NightAction();
                 timer.Elapsed += (_, _) => resetEvent.Set();
                 var doctorId = PlayersRole[Roles.Doctor].Count == 1 ? PlayersRole[Roles.Doctor][0].Id : -1;
                 foreach (var player in Players.Values)
                 {
-                    if(doctorId != player.Id) player.CanBeHealed = true;
+                    if (doctorId != player.Id) player.CanBeHealed = true;
                     player.CanBeBlockedNight = true;
                     player.CanBeBlockedDay = true;
                     player.IsBlocked = false;
                 }
+
                 timer.Start();
                 resetEvent.WaitOne();
             });
@@ -222,11 +209,13 @@ namespace MafiaTelegramBot.Game.GameRooms
         {
             await Task.Run(async () =>
             {
-                var beforeKill = Players.Values.ToDictionary(p=>p.Id,p=>p.IsAlive);
+                var beforeKill = Players.Values.ToDictionary(p => p.Id, p => p.IsAlive);
                 var mafiaNotAgree = "";
-                var votes = Players.Values.Where(p=> p.IsAlive && p.CurrentRole.MafiaTargetId != -1 && p.CurrentRole.MafiaTargetId != -2 && p.CurrentRole.MafiaTargetId != -4)
+                var votes = Players.Values.Where(p =>
+                        p.IsAlive && p.CurrentRole.MafiaTargetId != -1 && p.CurrentRole.MafiaTargetId != -2 &&
+                        p.CurrentRole.MafiaTargetId != -4)
                     .GroupBy(p => p.CurrentRole.MafiaTargetId)
-                    .Select(item => new {id = item.Key, count = item.Count()})
+                    .Select(item => new { id = item.Key, count = item.Count() })
                     .ToList();
                 if (votes.Count == 0)
                 {
@@ -242,35 +231,43 @@ namespace MafiaTelegramBot.Game.GameRooms
                         };
                     }
                 }
-                else {
+                else
+                {
                     var max = votes.Max(item => item.count);
                     var maxObjects = votes.Where(item => item.count == max).ToList();
-                    if(maxObjects.Count == 1)
+                    if (maxObjects.Count == 1)
                     {
                         if (Players.ContainsKey(maxObjects[0].id))
                             await Players[maxObjects[0].id].CurrentRole.Kill();
                     }
-                }   
+                }
+
                 foreach (var (role, players) in PlayersRole)
                 {
                     if (role is Roles.Mafia)
-                        foreach (var mafia in players) await mafia.CurrentRole.ApplyNightActionResult();
+                        foreach (var mafia in players)
+                            await mafia.CurrentRole.ApplyNightActionResult();
                     else if (players.Count == 1) await players[0].CurrentRole.ApplyNightActionResult();
                 }
-                var afterKill = Players.Values.ToDictionary(p=>p.Id,p=>p.IsAlive);
+
+                var afterKill = Players.Values.ToDictionary(p => p.Id, p => p.IsAlive);
                 var message = strings.city_wakes_up;
-                if(afterKill.IsEquals(beforeKill)) message += strings.everyone_survived;
-                else foreach (var (id, alive) in afterKill)
-                        if(beforeKill[id] != alive && Players.ContainsKey(id))
+                if (afterKill.IsEquals(beforeKill)) message += strings.everyone_survived;
+                else
+                    foreach (var (id, alive) in afterKill)
+                        if (beforeKill[id] != alive && Players.ContainsKey(id))
                         {
                             message += alive
                                 ? $"\n{Players[id].NickName} {strings.will_be_ressurected}"
                                 : $"\n{Players[id].NickName} {strings.will_be_killed}";
-                            if(!alive && Players[id].GetRole() is Roles.Don or Roles.Dame or Roles.Mafia
-                                      && PlayersRole.ContainsKey(Roles.Werewolf) && PlayersRole[Roles.Werewolf].Count == 1)
-                                await ((WerewolfRole) PlayersRole[Roles.Werewolf][0].CurrentRole).TransformToMafia();
-                            await PlayersMessageChannel.SendTo(id, alive ? strings.you_will_be_ressurected : strings.you_will_be_killed);
+                            if (!alive && Players[id].GetRole() is Roles.Don or Roles.Dame or Roles.Mafia
+                                       && PlayersRole.ContainsKey(Roles.Werewolf) &&
+                                       PlayersRole[Roles.Werewolf].Count == 1)
+                                await ((WerewolfRole)PlayersRole[Roles.Werewolf][0].CurrentRole).TransformToMafia();
+                            await PlayersMessageChannel.SendTo(id,
+                                alive ? strings.you_will_be_ressurected : strings.you_will_be_killed);
                         }
+
                 message += '\n' + mafiaNotAgree;
                 await PlayersMessageChannel.SendSticker(Stickers.Sticker["Day"]);
                 await PlayersMessageChannel.Send(message);
@@ -279,20 +276,22 @@ namespace MafiaTelegramBot.Game.GameRooms
 
         private async Task DefencePhase(List<Player> contenders)
         {
-            await Task.Run( async () =>
+            await Task.Run(async () =>
             {
                 var contendersCopy = contenders.ToList();
-                foreach (var contender in contendersCopy.Where(p => !p.IsBlocked)) 
-                    if (Players.ContainsKey(contender.Id)) await contender.CurrentRole.DefenceAction();
+                foreach (var contender in contendersCopy.Where(p => !p.IsBlocked))
+                    if (Players.ContainsKey(contender.Id))
+                        await contender.CurrentRole.DefenceAction();
                 var votersPlayers = Players.Values.Where(p => p.IsAlive && !p.IsBlocked).ToArray();
                 foreach (var voter in votersPlayers)
                     await voter.CurrentRole.VotingAction(contendersCopy.Where(p => Players.ContainsKey(p.Id)).ToList());
-                var timer = new Timer {Interval = Constants.VOTE_KILL_INTERVAL, AutoReset = false};
+                var timer = new Timer { Interval = Constants.VOTE_KILL_INTERVAL, AutoReset = false };
                 var resetEvent = new ManualResetEvent(false);
                 timer.Elapsed += async (_, _) =>
                 {
                     if (Constants.ENABLE_AUTO_VOTING)
-                        foreach (var voter in votersPlayers.Where(p => !_voteKillList.ContainsKey(p.Id) && Players.ContainsKey(p.Id)))
+                        foreach (var voter in votersPlayers.Where(p =>
+                            !_voteKillList.ContainsKey(p.Id) && Players.ContainsKey(p.Id)))
                             await voter.CurrentRole.RandomVoting();
                     resetEvent.Set();
                 };
@@ -333,8 +332,8 @@ namespace MafiaTelegramBot.Game.GameRooms
                                 _voteUpList = await CalculateCandidates();
                                 var alivers = copyVoteUpList.Except(_voteUpList).ToList();
                                 foreach (var alive in alivers)
-                                    alive.ElderRoleAchievementEvent();   
-                                
+                                    alive.ElderRoleAchievementEvent();
+
                                 switch (_voteUpList.Count)
                                 {
                                     case 0:
@@ -345,15 +344,18 @@ namespace MafiaTelegramBot.Game.GameRooms
                                         break;
                                     default:
                                         await PlayersMessageChannel.Send(strings.villagers_could_not_decide);
-                                        foreach (var alive in _voteUpList) 
+                                        foreach (var alive in _voteUpList)
                                             alive.ElderRoleAchievementEvent();
                                         break;
                                 }
+
                                 break;
                         }
+
                         break;
                     }
                 }
+
                 _voteUpList.Clear();
                 _voteKillList.Clear();
             });
@@ -366,14 +368,16 @@ namespace MafiaTelegramBot.Game.GameRooms
             {
                 message += Players.ContainsKey(playerId) && Players.ContainsKey(targetId)
                     ? $"\n({Players[playerId].TurnOrder}) {Players[playerId].NickName} {strings.vote_to} " +
-                           $"({Players[targetId].TurnOrder}) {Players[targetId].NickName}" : "";
+                      $"({Players[targetId].TurnOrder}) {Players[targetId].NickName}"
+                    : "";
             }
+
             if (message == strings.results_of_voting) message = strings.no_one_voted;
             await PlayersMessageChannel.Send(message);
-            
-            var votes = _voteUpList.Where(p=>Players.ContainsKey(p.Id))
+
+            var votes = _voteUpList.Where(p => Players.ContainsKey(p.Id))
                 .GroupBy(p => p.Id)
-                .Select(item => new {id = item.Key, count = item.Count()})
+                .Select(item => new { id = item.Key, count = item.Count() })
                 .ToList();
             List<Player> result = new();
             if (votes.Count == 0) return result;
@@ -391,7 +395,9 @@ namespace MafiaTelegramBot.Game.GameRooms
             {
                 if (targetId == 0)
                 {
-                    if (!toKill) await PlayersMessageChannel.SendExcept(playerId, $"{Players[playerId].NickName} {strings.skip_vote}");
+                    if (!toKill)
+                        await PlayersMessageChannel.SendExcept(playerId,
+                            $"{Players[playerId].NickName} {strings.skip_vote}");
                     await PlayersMessageChannel.EditTo(playerId, messageId, strings.you_skip_vote);
                 }
                 else
@@ -404,29 +410,34 @@ namespace MafiaTelegramBot.Game.GameRooms
                             {
                                 if (playerId != targetId)
                                 {
-                                    await PlayersMessageChannel.SendExcept(playerId, $"{Players[playerId].NickName} {strings.put_up_vote_to} {Players[targetId].NickName}");
-                                    await PlayersMessageChannel.EditTo(playerId, messageId, $"{strings.you_vote_player} {Players[targetId].NickName}");
+                                    await PlayersMessageChannel.SendExcept(playerId,
+                                        $"{Players[playerId].NickName} {strings.put_up_vote_to} {Players[targetId].NickName}");
+                                    await PlayersMessageChannel.EditTo(playerId, messageId,
+                                        $"{strings.you_vote_player} {Players[targetId].NickName}");
                                 }
                                 else
                                 {
-                                    await PlayersMessageChannel.SendExcept(playerId, $"{Players[playerId].NickName} {strings.vote_to_self}");
+                                    await PlayersMessageChannel.SendExcept(playerId,
+                                        $"{Players[playerId].NickName} {strings.vote_to_self}");
                                     await PlayersMessageChannel.EditTo(playerId, messageId, strings.you_vote_to_self);
                                 }
                             }
-                        } 
+                        }
                         else if (_voteKillList.AddUniqueByKey(playerId, targetId))
                         {
                             _voteUpList.Add(Players[targetId]);
                             if (messageId != -1)
                             {
                                 if (playerId != targetId)
-                                    await PlayersMessageChannel.EditTo(playerId, messageId, $"{strings.you_vote_to_kill} {Players[targetId].NickName}");
+                                    await PlayersMessageChannel.EditTo(playerId, messageId,
+                                        $"{strings.you_vote_to_kill} {Players[targetId].NickName}");
                                 else
-                                    await PlayersMessageChannel.EditTo(playerId, messageId, strings.you_vote_to_kill_self);
+                                    await PlayersMessageChannel.EditTo(playerId, messageId,
+                                        strings.you_vote_to_kill_self);
                             }
                         }
                     }
-                }   
+                }
             }
             else await PlayersMessageChannel.SendTo(playerId, strings.this_player_left_from_game);
         }
@@ -435,159 +446,126 @@ namespace MafiaTelegramBot.Game.GameRooms
         {
             await Task.Run(async () =>
             {
-                var aliveMafia = Players.Values.Count(p => p.GetRole() is Roles.Don or Roles.Dame or Roles.Mafia && p.IsAlive);
-                if (PlayersRole.ContainsKey(Roles.Werewolf)
-                    && PlayersRole[Roles.Werewolf].Count == 1 && PlayersRole[Roles.Werewolf][0].IsAlive
-                    && ((WerewolfRole) PlayersRole[Roles.Werewolf][0].CurrentRole).IsMafia) aliveMafia++;
-                var additionalResult = "";
-                foreach (var (_, value) in PlayersRole)
+                if (Players.Values.Any(p => p.IsAlive)) await CalculateGameResults();
+                else await CalculateDrawResults();
+                IsRunning = false;
+                IsDay = false;
+                _turnOrder.Clear();
+                Settings.Clear();
+                foreach (var (_, list) in PlayersRole) list.Clear();
+                if (!Players.ContainsKey(Owner.Id)) await RoomController.DissolveRoom(RoomEncrypter.GetCode(RoomName));
+                else
                 {
-                    if (value.Count != 1) continue;
-                    var yellowResult = await value[0].CurrentRole.IsWon();
-                    if (yellowResult != "") additionalResult += "\n" + yellowResult;
+                    await PlayersMessageChannel.SendTo(Owner.ChatId, strings.thanks_for_game, Keyboard.OwnerGameMenu);
+                    await PlayersMessageChannel.SendExcept(Owner.Id, strings.thanks_for_game, Keyboard.PlayerGameMenu);
                 }
-                
-                if (aliveMafia == 0)
+
+                await UserDao.DataBase.SaveChangesAsync();
+                if (Players.Count <= Constants.MEMORY_CLEANER_PLAYERS_COUNT) StartTimer();
+            });
+        }
+
+        private async Task CalculateDrawResults()
+        {
+            foreach (var player in Players.Values)
+            {
+                await Bot.SendWithMarkdown2(player.ChatId, strings.game_ended_with_draw);
+                player.Statistics[Roles.All].Games--;
+                player.Statistics[player.GetRole()].Games--;
+                player.ResetState();
+            }
+        }
+
+        private async Task CalculateGameResults()
+        {
+            var aliveMafia = Players.Values.Count(p => p.CurrentRole.ColorRole is 2 && p.IsAlive);
+            var aliveVillagers = Players.Values.Count(p => p.CurrentRole.ColorRole is 1 or 3 && p.IsAlive);
+            var mafiaWins = aliveMafia >= aliveVillagers;
+            var additionalResult = "";
+            foreach (var player in Players.Values.Where(p=>p.CurrentRole.ColorRole is 3))
+            {
+                var yellowResult = await player.CurrentRole.IsWon();
+                if (yellowResult != "")
                 {
-                    await PlayersMessageChannel.Send(strings.villagers_won + additionalResult);
-                    await PlayersMessageChannel.SendSticker(Stickers.Sticker["VillagerWins"]);
+                    additionalResult += "\n" + yellowResult;
+                    player.HookerRoleAchievementEvent();
                 }
-                else
+                player.ResetParasiteProgress();
+            }
+            
+            if (mafiaWins && aliveMafia == 1)
+            {
+                var player = Players.Values.First(p => p.CurrentRole.ColorRole == 2 && p.IsAlive);
+                player.LawyerRoleAchievementEvent();
+            }
+            
+            var rolesMessage = strings.in_this_game_roles;
+            
+            var villagerTeam = Players.Values
+                .Where(p => p.CurrentRole.ColorRole == 1 && p.GetRole() != Roles.Lawyer)
+                .Select(p => p.Id).ToList();
+            var mafiaTeam = Players.Values
+                .Where(p => p.CurrentRole.ColorRole == 2 || p.GetRole() == Roles.Lawyer)
+                .Select(p => p.Id).ToList();
+            
+            foreach (var player in Players.Values)
+            {
+                rolesMessage += $"\n({player.TurnOrder}) {player.NickName} - {player.GetRoleName()}";
+                if (IsRanking) await SumRankingPoints(player, mafiaWins);
+                if (mafiaWins)
                 {
-                    if (aliveMafia == 1)
+                    await Bot.SendWithMarkdown2(player.ChatId, strings.mafia_won + additionalResult);
+                    await Bot.SendStickerAsync(player.ChatId, Stickers.Sticker["MafiaWins"]);
+                    if (player.CurrentRole.ColorRole == 2 || player.CurrentRole.RoleKey == Roles.Lawyer)
                     {
-                        var player = Players.Values.FirstOrDefault(p => p.IsAlive && p.GetRole() is Roles.Don or Roles.Dame or Roles.Mafia) ??
-                                     PlayersRole[Roles.Werewolf][0];
-                        player.LawyerRoleAchievementEvent();
+                        player.Statistics[Roles.All].Wins++;
+                        player.Statistics[player.GetRole()].Wins++;
+                        
+                        player.HookerRoleAchievementEvent();
+                        await player.ParasiteRoleAchievementEvent(mafiaTeam.ToList());
+                        player.WerewolfRoleAchievementEvent(2);
+                    }
+                    else
+                    {
+                        if (player.CurrentRole.ColorRole == 1)
+                            player.WerewolfRoleAchievementEvent(1, true);
+                        player.ResetParasiteProgress();
                     }
-                    await PlayersMessageChannel.Send(strings.mafia_won + additionalResult);
-                    await PlayersMessageChannel.SendSticker(Stickers.Sticker["MafiaWins"]);
-                }
-                if (PlayersRole.ContainsKey(Roles.Fool) && PlayersRole[Roles.Fool].Count == 1)
-                    await PlayersRole[Roles.Fool][0].CurrentRole.IsWon();
-                var rolesMessage = strings.in_this_game_roles;
-                var players = Players.Values.ToList();
-                
-                var statsQueryStats = "SELECT * FROM mafia.statistics WHERE";
-                var statsQueryOpenRoles = "SELECT * FROM mafia.opened_roles WHERE";
-                
-                foreach (var player in players)
-                {
-                    rolesMessage += $"\n({player.TurnOrder}) {player.NickName} - {player.GetRoleName()}";
-                    statsQueryStats += $" id = {player.Id} AND role = '{player.GetRole().ToString()}' OR role = 'All' OR";
-                    statsQueryOpenRoles += $" id = {player.Id} OR";
                 }
-                
-                await PlayersMessageChannel.Send(rolesMessage);
-                
-                //var updatingNotifications = await Ch.SendWithReturn("Update data! Wait until it disappears");
-                
-                statsQueryStats = statsQueryStats.Substring(0, statsQueryStats.Length - 2);
-                statsQueryOpenRoles = statsQueryOpenRoles.Substring(0, statsQueryOpenRoles.Length - 2);
-
-                try
+                else
                 {
-                    var statsList = UserDao.DataBase.Statistics.FromSqlRaw(statsQueryStats).ToArrayAsync().Result;
-                    var openRolesList = UserDao.DataBase.OpenedRoles.FromSqlRaw(statsQueryOpenRoles).ToArrayAsync().Result;
-                    
-                    void UpdateWins(Player player)
+                    await Bot.SendWithMarkdown2(player.ChatId, strings.villagers_won + additionalResult);
+                    await Bot.SendStickerAsync(player.ChatId, Stickers.Sticker["VillagerWins"]);
+                    if (player.CurrentRole.ColorRole == 1 && player.GetRole() != Roles.Lawyer)
                     {
-                        foreach (var row in statsList.Where(s => s.UserId == player.Id))
-                        {
-                            row.Wins++;
-                        }
-
-                        if (player.Statistics.Contains(Roles.All))
-                        {
-                            player.Statistics[player.CurrentRole.RoleKey].Wins++;
-                            player.Statistics[Roles.All].Wins++;
-                        }
+                        player.Statistics[Roles.All].Wins++;
+                        player.Statistics[player.GetRole()].Wins++;
+                        
+                        player.HookerRoleAchievementEvent();
+                        await player.ParasiteRoleAchievementEvent(villagerTeam.ToList());
+                        player.WerewolfRoleAchievementEvent(1);
                     }
-                    
-                    var villagerTeam = players.Where(p => p.CurrentRole.ColorRole == 1 && p.GetRole() != Roles.Lawyer).Select(p => p.Id).ToList();
-                    var mafiaTeam = players.Where(p => p.CurrentRole.ColorRole == 2 || p.GetRole() == Roles.Lawyer).Select(p => p.Id).ToList();
-                    
-                    foreach (var player in players)
+                    else
                     {
-                        if (aliveMafia == 0)
-                        {
-                            if(player.CurrentRole.ColorRole == 1 && player.GetRole() != Roles.Lawyer)
-                            {
-                                UpdateWins(player);
-                                player.HookerRoleAchievementEvent();
-                                await player.ParasiteRoleAchievementEvent(villagerTeam.ToList());
-                                player.WerewolfRoleAchievementEvent(1);
-                            }
-                            else
-                            {
-                                if (player.CurrentRole.ColorRole == 2)
-                                    player.WerewolfRoleAchievementEvent(2, true);
-                                player.ResetParasiteProgress();
-                            }
-                        }
-                        else
-                        {
-                            if(player.CurrentRole.ColorRole == 2 || player.CurrentRole.RoleKey == Roles.Lawyer)
-                            {
-                                UpdateWins(player);
-                                player.HookerRoleAchievementEvent();
-                                await player.ParasiteRoleAchievementEvent(mafiaTeam.ToList());
-                                player.WerewolfRoleAchievementEvent(2);
-                            }
-                            else
-                            {
-                                if (player.CurrentRole.ColorRole == 1)
-                                    player.WerewolfRoleAchievementEvent(1, true);
-                                player.ResetParasiteProgress();
-                            }
-                        }
-
-                        if (player.CurrentRole.ColorRole == 3)
-                        {
-                            if (player.CurrentRole.IsWon().Result != "")
-                            {
-                                player.HookerRoleAchievementEvent();
-                                UpdateWins(player);
-                            }
-                            player.ResetParasiteProgress();
-                        }
-
-                        if (IsRanking) await SumRankingPoints(player, aliveMafia != 0);
-                        
-                        if (player.CurrentRole.RoleKey == Roles.Cop)
-                        {
-                            if (((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountRed ==
-                                ((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountBlack) player.JournalistAchievementEvent();
-                            if (((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountRed == 0 &&
-                                ((CopRole) PlayersRole[Roles.Cop][0].CurrentRole).CountBlack != 0) player.DetectiveAchievementEvent();
-                        }
-                        
-                        
-                        player.ResetState();
+                        if (player.CurrentRole.ColorRole == 2)
+                            player.WerewolfRoleAchievementEvent(2, true);
+                        player.ResetParasiteProgress();
                     }
-                    UserDao.DataBase.Statistics.UpdateRange(statsList);
-                    UserDao.DataBase.OpenedRoles.UpdateRange(openRolesList);
-                    await UserDao.DataBase.SaveChangesAsync();
-                }
-                catch (Exception e)
-                {
-                    await Console.Out.WriteLineAsync(e.Message);
                 }
                 
-                IsRunning = false;
-                IsDay = false;
-                _turnOrder.Clear();
-                Settings.Clear();
-                foreach (var (_, list) in PlayersRole) list.Clear();
-                if (!Players.ContainsKey(Owner.Id) || Players.Count == 0) new Task(async() => 
-                    await RoomController.DissolveRoom(RoomEncrypter.GetCode(RoomName))).Start();
-                else
+                if (player.GetRole() == Roles.Cop)
                 {
-                    await PlayersMessageChannel.SendTo(Owner.ChatId, strings.thanks_for_game, Keyboard.OwnerGameMenu);
-                    await PlayersMessageChannel.SendExcept(Owner.Id, strings.thanks_for_game, Keyboard.PlayerGameMenu);
+                    if (((CopRole)PlayersRole[Roles.Cop][0].CurrentRole).CountRed ==
+                        ((CopRole)PlayersRole[Roles.Cop][0].CurrentRole).CountBlack)
+                        player.JournalistAchievementEvent();
+                    if (((CopRole)PlayersRole[Roles.Cop][0].CurrentRole).CountRed == 0 &&
+                        ((CopRole)PlayersRole[Roles.Cop][0].CurrentRole).CountBlack != 0)
+                        player.DetectiveAchievementEvent();
                 }
-                if (Players.Count <= Constants.MEMORY_CLEANER_INTERVAL) StartTimer();
-            });
+                
+                player.ResetState();
+            }
+            await PlayersMessageChannel.Send(rolesMessage);
         }
     }
 }

+ 25 - 15
MafiaTelegramBot/Game/GameRooms/GameRoom.MessageChannels.cs

@@ -1,8 +1,8 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using MafiaTelegramBot.CustomCollections.Extensions;
 using MafiaTelegramBot.Models;
-using MafiaTelegramBot.Resources;
 using Telegram.Bot.Types;
 using Telegram.Bot.Types.ReplyMarkups;
 
@@ -13,7 +13,7 @@ namespace MafiaTelegramBot.Game.GameRooms
         public class Channel
         {
             protected readonly GameRoom Room;
-            protected IEnumerable<Player> Players;
+            protected IEnumerable<long> Players;
             
             public async Task<Message> SendTo(long userId, string message, IReplyMarkup replyMarkup = null)
             {
@@ -28,31 +28,43 @@ namespace MafiaTelegramBot.Game.GameRooms
             
             public async Task Send(string message, IReplyMarkup replyMarkup = null)
             {
-                foreach (var player in Players)
-                    await Bot.SendWithMarkdown2(player.ChatId, message, replyMarkup);
+                foreach (var id in Players)
+                    await Bot.SendWithMarkdown2(id, message, replyMarkup);
             }
 
             public async Task SendExcept(long playerId, string message, IReplyMarkup replyMarkup = null)
             {
-                foreach (var player in Players)
-                    if (player.Id != playerId) await Bot.SendWithMarkdown2(player.ChatId, message, replyMarkup);
+                foreach (var id in Players)
+                    if (id != playerId) await Bot.SendWithMarkdown2(id, message, replyMarkup);
             }
 
             public async Task SendSticker(string fileId)
             {
-                foreach (var player in Players)
-                    await Bot.SendStickerAsync(player.ChatId, fileId);
+                foreach (var id in Players)
+                    await Bot.SendStickerAsync(id, fileId);
             }
 
             public void Remove(long playerId)
             {
-                Players = Players.Where(p => p.Id != playerId);
+                Players = Players.Where(id => id != playerId);
+            }
+
+            public void AddPerson(long id)
+            {
+                var list = Players.ToList();
+                list.AddUnique(id);
+                Players = list;
+            }
+
+            public virtual async Task UpdateList(IEnumerable<Player> players)
+            {
+                Players = await Task.FromResult(players.Select(p => p.ChatId));
             }
 
             public Channel(GameRoom room)
             {
                 Room = room;
-                Players = room.Players.Values;
+                Players = room.Players.Values.Select(p=>p.ChatId);
             }
         }
 
@@ -60,14 +72,12 @@ namespace MafiaTelegramBot.Game.GameRooms
         {
             public MafiaChannel(GameRoom room) : base(room)
             {
-                Players = room.Players.Values.Where(p => p.GetRole() is Roles.Don or Roles.Mafia or Roles.Dame);
+                Players = room.Players.Values.Where(p => p.CurrentRole.ColorRole is 2).Select(p=>p.ChatId);
             }
 
-            public void AddPerson(Player player)
+            public override async Task UpdateList(IEnumerable<Player> players)
             {
-                var list = Players.ToList();
-                list.Add(player);
-                Players = list;
+                Players = await Task.FromResult(players.Where(p=>p.CurrentRole.ColorRole == 2).Select(p => p.ChatId));
             }
         }
     }

+ 2 - 0
MafiaTelegramBot/Game/GameRooms/GameRoom.PrepareRoom.cs

@@ -53,6 +53,8 @@ namespace MafiaTelegramBot.Game.GameRooms
                     user.CurrentRole = Role.GetNewRoleInstance(next, this, user);
                     _turnOrder.Enqueue(user);
                 }
+                await PlayersMessageChannel.UpdateList(Players.Values);
+                await MafiaMessageChannel.UpdateList(Players.Values);
             });
         }
 

+ 42 - 14
MafiaTelegramBot/Game/Player.cs

@@ -9,12 +9,11 @@ using MafiaTelegramBot.DataBase.EntityDao;
 using MafiaTelegramBot.Game.GameRoles;
 using MafiaTelegramBot.Models;
 using MafiaTelegramBot.Resources;
-using Microsoft.EntityFrameworkCore;
 using Newtonsoft.Json;
 
 namespace MafiaTelegramBot.Game
 {
-    public class Player : UserEntity
+    public class Player
     {
         public GameRooms.GameRoom.Role CurrentRole = new NoneRole();
         public int TurnOrder = -1;
@@ -28,9 +27,46 @@ namespace MafiaTelegramBot.Game
         public bool CanBeBlockedNight = true;
         public bool CanBeBlockedDay = true;
 
-        public StatisticsList Statistics = new();
-        public OpenedRolesEntity OpenedRoles = new();
-        public AchievementsEntity Achievements = new();
+        public long Id
+        {
+            get => User.Id;
+            set => User.Id = value;
+        }
+
+        public long ChatId
+        {
+            get => User.ChatId;
+            set => User.ChatId = value;
+        }
+        
+        public string Username
+        {
+            get => User.Username;
+            set => User.Username = value;
+        }
+        
+        public string NickName
+        {
+            get => User.NickName;
+            set => User.NickName = value;
+        }
+        
+        public int RankNumber
+        {
+            get => User.RankNumber;
+            set => User.RankNumber = value;
+        }
+        
+        public bool IsAdmin
+        {
+            get => User.IsAdmin > 0;
+            set => User.IsAdmin = value ? 1 : 0;
+        }
+
+        public UserEntity User = new ();
+        public StatisticsList Statistics = new ();
+        public OpenedRolesEntity OpenedRoles = new ();
+        public AchievementsEntity Achievements = new ();
 
         public void SetActive()
         {
@@ -42,13 +78,6 @@ namespace MafiaTelegramBot.Game
             return DateTime.Now.Subtract(_lastActivity);
         }
 
-        public static Player FromUserEntity(UserEntity b)
-        {
-            var serialized = JsonConvert.SerializeObject(b);
-            Player a = JsonConvert.DeserializeObject<Player>(serialized);
-            return a;
-        }
-
         public string GetRoomName()
         {
             return _roomName;
@@ -61,11 +90,10 @@ namespace MafiaTelegramBot.Game
             return true;
         }
 
-        public async Task<bool> RemoveGame()
+        public bool RemoveGame()
         {
             if (_roomName == "") return false;
             _roomName = "";
-            await UserDao.Update(this);
             return true;
         }
 

+ 1 - 1
MafiaTelegramBot/Models/Bot.cs

@@ -180,7 +180,7 @@ namespace MafiaTelegramBot.Models
                 Username = username,
                 NickName =  nickName
             };
-            await UserDao.Update(user);
+            await UserDao.AddNew(user.User);
             await StatisticsDao.CreatePlayerStats(user.Id);
             UserDao.ActiveUsers.Add(user.Id, user);
         }

+ 2 - 0
MafiaTelegramBot/Models/Commands/Command.cs

@@ -1,4 +1,5 @@
 #nullable enable
+using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using MafiaTelegramBot.Controllers;
@@ -28,6 +29,7 @@ namespace MafiaTelegramBot.Models.Commands
         {
             var chatId = update.Message.Chat.Id;
             var userId = update.Message.From.Id;
+            Console.WriteLine($"{userId} {update.Message.Text}");
             await Bot.Get().SendChatActionAsync(chatId, ChatAction.Typing);
             
             if (!await UserDao.UserExists(userId)) await Bot.RegisterNewUser(update);

+ 1 - 1
MafiaTelegramBot/Models/Commands/CustomMessageHandlers/ChangeNicknameHandler.cs

@@ -13,7 +13,7 @@ namespace MafiaTelegramBot.Models.Commands.CustomMessageHandlers
             var newNickname = update.Message.Text;
             var escapedNickName = await Utilities.EscapeSpecific(newNickname);
             var user = await UserDao.GetPlayerById(UserId);
-            await user.UpdateNickName(escapedNickName);
+            user.NickName = newNickname;
             return await Bot.SendWithMarkdown2(ChatId, $"{strings.name_updated} _*{escapedNickName}*_");
         }
     }

+ 2 - 0
MafiaTelegramBot/Models/Inlines/Query.cs

@@ -1,4 +1,5 @@
 #nullable enable
+using System;
 using System.Threading.Tasks;
 using MafiaTelegramBot.Controllers;
 using MafiaTelegramBot.DataBase.EntityDao;
@@ -23,6 +24,7 @@ namespace MafiaTelegramBot.Models.Inlines
             await Bot.Get().SendChatActionAsync(chatId, ChatAction.Typing);
             var data = update.CallbackQuery.Data;
             var userId = long.Parse(data.Split('|')[1]);
+            Console.WriteLine($"{userId} {data}");
             var user = await UserDao.GetPlayerById(userId);
             user.SetActive();
             if (user.IsPlaying)

+ 1 - 2
MafiaTelegramBot/Models/Payments/Payment.cs

@@ -2,7 +2,6 @@
 using System;
 using System.Threading.Tasks;
 using Telegram.Bot.Types;
-using Telegram.Bot.Types.Enums;
 
 namespace MafiaTelegramBot.Models.Payments
 {
@@ -13,7 +12,7 @@ namespace MafiaTelegramBot.Models.Payments
         {
             return command == Name;
         }
-        public static async Task<Message> Update(Update update)
+        public static Task<Message> Update(Update update)
         {
             throw new NotImplementedException();
             /*var payments = Bot.Payments;

+ 1 - 0
MafiaTelegramBot/Resources/Constants.cs

@@ -8,6 +8,7 @@ namespace MafiaTelegramBot.Resources
     {
         public const int PLAYER_LIMITS_MIN = 6;
         public const int MEMORY_CLEANER_INTERVAL = 60 * 60 * 1000;
+        public const int MEMORY_CLEANER_PLAYERS_COUNT = 3;
         // ReSharper disable once InconsistentNaming
         public static readonly TimeSpan PLAYER_INACTIVE_INTERVAL = new(0, 40, 0);
         public const int MINUTES_UNTIL_DISSOLVE = 10;

+ 6 - 0
MafiaTelegramBot/Resources/strings.Designer.cs

@@ -1376,5 +1376,11 @@ namespace MafiaTelegramBot {
                 return ResourceManager.GetString("points", resourceCulture);
             }
         }
+        
+        internal static string game_ended_with_draw {
+            get {
+                return ResourceManager.GetString("game_ended_with_draw", resourceCulture);
+            }
+        }
     }
 }

+ 3 - 0
MafiaTelegramBot/Resources/strings.resx

@@ -684,4 +684,7 @@
     <data name="points" xml:space="preserve">
         <value>очков</value>
     </data>
+    <data name="game_ended_with_draw" xml:space="preserve">
+        <value>Весь город погиб при загадочных обстоятельствах. Игра закончилась ничьей... Рейтинг изменен не будет</value>
+    </data>
 </root>