Kaynağa Gözat

MTB-10 realisation of button 'Start game'

Tigran 4 yıl önce
ebeveyn
işleme
d00b336c19

+ 1 - 0
MafiaTelegramBot.sln.DotSettings.user

@@ -2,6 +2,7 @@
 	<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=MafiaTelegramBot_002Fappsettings/@EntryIndexedValue">True</s:Boolean>
 	
 	<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=MafiaTelegramBot_002FResources_002Fkeyboard/@EntryIndexedValue">False</s:Boolean>
+	<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=MafiaTelegramBot_002FResources_002Froles/@EntryIndexedValue">False</s:Boolean>
 	
 	
 	

+ 2 - 1
MafiaTelegramBot/Controllers/RoomController.cs

@@ -37,7 +37,7 @@ namespace MafiaTelegramBot.Controllers
                 if (OpenedGames[roomKey].IsFilled()) return ResultCode.RoomIsFilled;
                 if (!await player.SetRoomKey(roomKey)) return ResultCode.UserAlreadyInGame;
                 OpenedGames[roomKey].Players.Add(player.Id, player);
-                await OpenedGames[roomKey].NotifyUserConnect(player);
+                await OpenedGames[roomKey].NotifyPlayersAbout(player.Id, $"{player.NickName} {strings.connected_to_game}");
                 return ResultCode.CodeOk;
             });
         }
@@ -59,6 +59,7 @@ namespace MafiaTelegramBot.Controllers
                 var roomKey = player.GetRoomKey();
                 if (!await player.RemoveGame()) return ResultCode.UserNotInGame;
                 OpenedGames[roomKey].Players.Remove(player.Id);
+                await OpenedGames[roomKey].NotifyPlayersAbout(player.Id, $"{player.NickName} {strings.connected_to_game}");
                 if (OpenedGames[roomKey].Players.Count != 0) return ResultCode.CodeOk;
                 RoomEncrypter.RemoveShortName(OpenedGames[roomKey].RoomName);
                 if(OpenedGames[roomKey].IsPrivate) RoomEncrypter.Remove(OpenedGames[roomKey].RoomName);

+ 13 - 1
MafiaTelegramBot/DataBase/User.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using MafiaTelegramBot.Controllers;
+using MafiaTelegramBot.Models;
 using MafiaTelegramBot.Resources;
 
 namespace MafiaTelegramBot.DataBase
@@ -17,7 +18,8 @@ namespace MafiaTelegramBot.DataBase
         public Dictionary<Roles, int> RoleGames = new();
         public Dictionary<Roles, int> RoleWins = new();
 
-        public Roles CurrentRole = Roles.None;
+        private Roles _currentRole = Roles.None;
+        public int TurnOrder = -1;
 
         private string _roomKey = "";
         
@@ -68,5 +70,15 @@ namespace MafiaTelegramBot.DataBase
         {
             return Id.GetHashCode();
         }
+
+        public void SetRole(Roles role)
+        {
+            _currentRole = role;
+        }
+
+        public string GetRole()
+        {
+            return roles.ResourceManager.GetString(_currentRole.ToString())!;
+        }
     }
 }

+ 17 - 0
MafiaTelegramBot/Extensions/DictionaryExtension.cs

@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using System.Linq;
+using MafiaTelegramBot.Resources;
+
+namespace MafiaTelegramBot.Extensions
+{
+    public static class DictionaryExtension
+    {
+        public static Roles GetRole(this Dictionary<Roles, int> dictionary, int index)
+        {
+            var (key, _) = dictionary.ElementAt(index);
+            dictionary[key]--;
+            if (dictionary[key] == 0) dictionary.Remove(key);
+            return key;
+        }
+    }
+}

+ 14 - 0
MafiaTelegramBot/Extensions/ListExtension.cs

@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace MafiaTelegramBot.Extensions
+{
+    public static class ListExtension
+    {
+        public static T GetAndRemove<T>(this List<T> list, int index)
+        {
+            var value = list[index];
+            list.RemoveAt(index);
+            return value;
+        }
+    }
+}

+ 146 - 14
MafiaTelegramBot/Game/GameRoom.cs

@@ -1,37 +1,125 @@
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using MafiaTelegramBot.DataBase;
 using MafiaTelegramBot.Models;
 using MafiaTelegramBot.Resources;
+using Telegram.Bot.Types.ReplyMarkups;
+using MafiaTelegramBot.Extensions;
 
 namespace MafiaTelegramBot.Game
 {
     public class GameRoom
     {
         private bool _isRunning;
-        
+
         public int MaxPlayers = 10;
         private int _minPlayers = Constants.PLAYER_LIMITS_MIN;
         public virtual bool IsPrivate { get; protected set; } = false;
-        public bool IsExtended { get; init; } = false;
+        public bool IsExtended { get; init; }
         public bool TimerEnabled { get; set; } = true;
         public string RoomName { get; init; } = "NoNameRoom";
         public User Creator { get; init; } = new();
-        
+
+        private readonly Queue<User> _turnOrder = new();
+
         public readonly Dictionary<long, User> Players = new();
-        public readonly Dictionary<string, string> Settings = new();
 
-        public async Task<ResultCode> Start()
+        public readonly Dictionary<Roles, int> Settings = new()
         {
-            return await Task.Run(() =>
+            {Roles.Mafia, 0},
+            {Roles.Cop, 0},
+            {Roles.Villager, 0},
+            {Roles.Doctor, 0},
+            {Roles.Don, 0},
+            {Roles.Hooker, 0},
+        };
+
+        public void Start()
+        {
+            new Task(async () =>
             {
-                if (Players.Count < _minPlayers) return ResultCode.TooFewPlayers;
-                if (Players.Count > MaxPlayers) return ResultCode.TooManyPlayers;
-                if (_isRunning) return ResultCode.GameAlreadyRunning;
                 _isRunning = true;
-                //TODO game start logic
-                return ResultCode.CodeOk;
+                await FirstDay();
+                await GameCycle();
+                await EndOfGame();
+            }).Start();
+        }
+
+        public async Task<ResultCode> Prepare()
+        {
+            var resultCode = CanStartGame();
+            if (resultCode != ResultCode.CodeOk) return resultCode;
+            await ReadSettings();
+            await GenerateTurnOrder();
+            await AssignRoles();
+            return resultCode;
+        }
+
+        private async Task FirstDay()
+        {
+            await Task.Run(() => { });
+        }
+
+
+        private async Task GameCycle()
+        {
+            await Task.Run(() => { });
+        }
+
+
+        private async Task EndOfGame()
+        {
+            await Task.Run(async () =>
+            {
+                foreach (var (_, player) in Players)
+                {
+                    player.SetRole(Roles.None);
+                    _isRunning = false;
+                    _turnOrder.Clear();
+                    await NotifyPlayersAbout(-1, strings.thanks_for_game);
+                }
+            });
+        }
+
+        private async Task ReadSettings()
+        {
+            if (!IsExtended) await SetNormalRoles();
+        }
+
+        private ResultCode CanStartGame()
+        {
+            if (Players.Count < _minPlayers) return ResultCode.TooFewPlayers;
+            if (Players.Count > MaxPlayers) return ResultCode.TooManyPlayers;
+            return _isRunning ? ResultCode.GameAlreadyRunning : ResultCode.CodeOk;
+        }
+
+        private async Task SetNormalRoles()
+        {
+            await Task.Run(() =>
+            {
+                Settings[Roles.Villager] = Players.Count;
+                Settings[Roles.Cop] = 1;
+                if (Players.Count != 8) Settings[Roles.Doctor] = 1;
+                else Settings[Roles.Doctor] = 0;
+                if (Players.Count % 3 == 0)
+                {
+                    Settings[Roles.Mafia] = Players.Count / 3;
+                    Settings[Roles.Don] = 0;
+                }
+                else
+                {
+                    Settings[Roles.Mafia] = (Players.Count / 3) - 1;
+                    Settings[Roles.Don] = 1;
+                }
+
+                foreach (var (key, value) in Settings)
+                    if (key != Roles.Villager)
+                        Settings[Roles.Villager] -= value;
+                foreach (var (key, value) in Settings)
+                    if (value < 1)
+                        Settings.Remove(key);
             });
         }
 
@@ -45,16 +133,60 @@ namespace MafiaTelegramBot.Game
             });
         }
 
+        private async Task AssignRoles()
+        {
+            await Task.Run(() =>
+            {
+                var random = new Random();
+                var settingsCopy = Settings.ToDictionary(
+                    entry => entry.Key,
+                    entry => entry.Value);
+                for (int i = 0; i < _turnOrder.Count; ++i)
+                {
+                    var user = _turnOrder.Dequeue();
+                    user.SetRole(settingsCopy.GetRole(random.Next(settingsCopy.Count)));
+                    _turnOrder.Enqueue(user);
+                }
+            });
+        }
+
+        private async Task GenerateTurnOrder()
+        {
+            await Task.Run(() =>
+            {
+                var random = new Random();
+                var playersCopy = Players.Values.ToList();
+                while (playersCopy.Count != 0)
+                {
+                    var player = playersCopy.GetAndRemove(random.Next(playersCopy.Count));
+                    _turnOrder.Enqueue(player);
+                    player.TurnOrder = _turnOrder.Count;
+                }
+            });
+        }
+
         public bool IsFilled()
         {
             return Players.Count == MaxPlayers;
         }
 
-        public async Task NotifyUserConnect(User user)
+        public async Task NotifyPlayersAbout(long ignoredUserId, string message)
+        {
+            foreach (var player in Players.Values.Where(player => ignoredUserId != player.Id))
+            {
+                await Bot.SendWithMarkdown2(player.ChatId, message);
+            }
+        }
+
+        public async Task NotifyPlayersAboutGameStarted()
         {
-            foreach (var player in Players.Values.Where(player => user.Id != player.Id))
+            foreach (var player in Players.Values)
             {
-                await Bot.SendWithMarkdown2(player.ChatId, $"{strings.entry_another_user} _*{user.NickName}*_");
+                var message =
+                    $"{strings.your_role}: _*{player.GetRole()}*_\n" +
+                    $"{strings.your_turn_order}: _*{player.TurnOrder}*_\n"+
+                    $"{strings.bot_starting_game}";
+                await Bot.SendWithMarkdown2(player.ChatId, message, Keyboards.InGamePlayerMenu);
             }
         }
     }

+ 9 - 0
MafiaTelegramBot/MafiaTelegramBot.csproj

@@ -21,6 +21,10 @@
         <Generator>ResXFileCodeGenerator</Generator>
         <LastGenOutput>keyboard.Designer.cs</LastGenOutput>
       </EmbeddedResource>
+      <EmbeddedResource Update="Resources\roles.resx">
+        <Generator>ResXFileCodeGenerator</Generator>
+        <LastGenOutput>roles.Designer.cs</LastGenOutput>
+      </EmbeddedResource>
     </ItemGroup>
 
     <ItemGroup>
@@ -34,6 +38,11 @@
         <AutoGen>True</AutoGen>
         <DependentUpon>keyboard.resx</DependentUpon>
       </Compile>
+      <Compile Update="Resources\roles.Designer.cs">
+        <DesignTime>True</DesignTime>
+        <AutoGen>True</AutoGen>
+        <DependentUpon>roles.resx</DependentUpon>
+      </Compile>
     </ItemGroup>
 
 </Project>

+ 1 - 0
MafiaTelegramBot/Models/Bot.cs

@@ -55,6 +55,7 @@ namespace MafiaTelegramBot.Models
                 new LookPlayersListCommand(),
                 new KickPlayerCommand(),
                 new DissolveRoomCommand(),
+                new StartGameCommand(),
             };
         }
         

+ 3 - 2
MafiaTelegramBot/Models/Commands/CustomMessageHandlers/ChangeNicknameHandler.cs

@@ -11,9 +11,10 @@ namespace MafiaTelegramBot.Models.Commands.CustomMessageHandlers
         protected override async Task<Message> Execute(Update update)
         {
             var newNickname = update.Message.Text;
+            var escapedNickName = await Utilities.EscapeSpecific(newNickname);
             var user = await UserDao.GetUserById(UserId);
-            await user.UpdateName(newNickname);
-            return await Bot.SendWithMarkdown2(ChatId, $"{strings.name_updated} _*{newNickname}*_");
+            await user.UpdateName(escapedNickName);
+            return await Bot.SendWithMarkdown2(ChatId, $"{strings.name_updated} _*{escapedNickName}*_");
         }
     }
 }

+ 24 - 0
MafiaTelegramBot/Models/Commands/StartGameCommand.cs

@@ -0,0 +1,24 @@
+using System.Threading.Tasks;
+using MafiaTelegramBot.Controllers;
+using MafiaTelegramBot.DataBase;
+using MafiaTelegramBot.Resources;
+using Telegram.Bot.Types;
+
+namespace MafiaTelegramBot.Models.Commands
+{
+    public class StartGameCommand : Command
+    {
+        protected override string Name => keyboard.begin_game;
+        protected override async Task<Message> Execute(Update update)
+        {
+            var owner = await UserDao.GetUserById(UserId);
+            var room = await RoomController.GetRoom(owner.GetRoomKey());
+            var result = await Bot.SendWithMarkdown2(owner.ChatId, strings.game_process_started);
+            var resultCode = await room.Prepare();
+            if (resultCode != ResultCode.CodeOk) return await Utilities.GetResultCodeMessage(resultCode, ChatId);
+            await room.NotifyPlayersAboutGameStarted();
+            room.Start();
+            return result;
+        }
+    }
+}

+ 6 - 0
MafiaTelegramBot/Resources/Keyboards.cs

@@ -28,6 +28,12 @@ namespace MafiaTelegramBot.Resources
                 new KeyboardButton[] {keyboard.leave}
             }, true
         );
+        
+        public static readonly ReplyKeyboardMarkup InGamePlayerMenu = new(new[]
+            {
+                new KeyboardButton[] {keyboard.look_players_list, keyboard.leave}
+            }, true
+        );
 
         public static InlineKeyboardMarkup RoomTypeKeyboard(long userId, Callback callbackPrivate, Callback callbackPublic)
         {

+ 90 - 0
MafiaTelegramBot/Resources/roles.Designer.cs

@@ -0,0 +1,90 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace MafiaTelegramBot.Resources {
+    using System;
+    
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class roles {
+        
+        private static System.Resources.ResourceManager resourceMan;
+        
+        private static System.Globalization.CultureInfo resourceCulture;
+        
+        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal roles() {
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.Equals(null, resourceMan)) {
+                    System.Resources.ResourceManager temp = new System.Resources.ResourceManager("MafiaTelegramBot.Resources.roles", typeof(roles).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static string Mafia {
+            get {
+                return ResourceManager.GetString("Mafia", resourceCulture);
+            }
+        }
+        
+        internal static string Doctor {
+            get {
+                return ResourceManager.GetString("Doctor", resourceCulture);
+            }
+        }
+        
+        internal static string Don {
+            get {
+                return ResourceManager.GetString("Don", resourceCulture);
+            }
+        }
+        
+        internal static string Cop {
+            get {
+                return ResourceManager.GetString("Cop", resourceCulture);
+            }
+        }
+        
+        internal static string Villager {
+            get {
+                return ResourceManager.GetString("Villager", resourceCulture);
+            }
+        }
+        
+        internal static string Hooker {
+            get {
+                return ResourceManager.GetString("Hooker", resourceCulture);
+            }
+        }
+        
+        internal static string None {
+            get {
+                return ResourceManager.GetString("None", resourceCulture);
+            }
+        }
+    }
+}

+ 42 - 0
MafiaTelegramBot/Resources/roles.resx

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<root>
+    <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+        <xsd:element name="root" msdata:IsDataSet="true">
+            
+        </xsd:element>
+    </xsd:schema>
+    <resheader name="resmimetype">
+        <value>text/microsoft-resx</value>
+    </resheader>
+    <resheader name="version">
+        <value>1.3</value>
+    </resheader>
+    <resheader name="reader">
+        <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    </resheader>
+    <resheader name="writer">
+        <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    </resheader>
+    <data name="Mafia" xml:space="preserve">
+        <value>Мафия</value>
+    </data>
+    <data name="Doctor" xml:space="preserve">
+        <value>Доктор</value>
+    </data>
+    <data name="Don" xml:space="preserve">
+        <value>Дон</value>
+    </data>
+    <data name="Cop" xml:space="preserve">
+        <value>Комиссар</value>
+    </data>
+    <data name="Villager" xml:space="preserve">
+        <value>Мирный житель</value>
+    </data>
+    <data name="Hooker" xml:space="preserve">
+        <value>Проститутка</value>
+    </data>
+    <data name="None" xml:space="preserve">
+        <value>Нет роли</value>
+    </data>
+</root>

+ 150 - 309
MafiaTelegramBot/Resources/strings.Designer.cs

@@ -1,7 +1,6 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:4.0.30319.42000
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -12,46 +11,32 @@ namespace MafiaTelegramBot {
     using System;
     
     
-    /// <summary>
-    ///   A strongly-typed resource class, for looking up localized strings, etc.
-    /// </summary>
-    // This class was auto-generated by the StronglyTypedResourceBuilder
-    // class via a tool like ResGen or Visual Studio.
-    // To add or remove a member, edit your .ResX file then rerun ResGen
-    // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class strings {
         
-        private static global::System.Resources.ResourceManager resourceMan;
+        private static System.Resources.ResourceManager resourceMan;
         
-        private static global::System.Globalization.CultureInfo resourceCulture;
+        private static System.Globalization.CultureInfo resourceCulture;
         
-        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
         internal strings() {
         }
         
-        /// <summary>
-        ///   Returns the cached ResourceManager instance used by this class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Resources.ResourceManager ResourceManager {
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static System.Resources.ResourceManager ResourceManager {
             get {
-                if (object.ReferenceEquals(resourceMan, null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MafiaTelegramBot.Resources.strings", typeof(strings).Assembly);
+                if (object.Equals(null, resourceMan)) {
+                    System.Resources.ResourceManager temp = new System.Resources.ResourceManager("MafiaTelegramBot.Resources.strings", typeof(strings).Assembly);
                     resourceMan = temp;
                 }
                 return resourceMan;
             }
         }
         
-        /// <summary>
-        ///   Overrides the current thread's CurrentUICulture property for all
-        ///   resource lookups using this strongly typed resource class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Globalization.CultureInfo Culture {
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static System.Globalization.CultureInfo Culture {
             get {
                 return resourceCulture;
             }
@@ -60,525 +45,381 @@ namespace MafiaTelegramBot {
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Приватная.
-        /// </summary>
-        internal static string _private {
+        internal static string start_message {
             get {
-                return ResourceManager.GetString("private", resourceCulture);
+                return ResourceManager.GetString("start_message", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Публичная.
-        /// </summary>
-        internal static string _public {
+        internal static string statistics_for {
             get {
-                return ResourceManager.GetString("public", resourceCulture);
+                return ResourceManager.GetString("statistics_for", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Сменить имя.
-        /// </summary>
-        internal static string change_name {
+        internal static string games_count {
             get {
-                return ResourceManager.GetString("change_name", resourceCulture);
+                return ResourceManager.GetString("games_count", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Выберите режим игры.
-        /// </summary>
-        internal static string choose_game_type {
+        internal static string wins_count {
             get {
-                return ResourceManager.GetString("choose_game_type", resourceCulture);
+                return ResourceManager.GetString("wins_count", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Выберите тип комнаты.
-        /// </summary>
-        internal static string choose_type_room {
+        internal static string winrate {
             get {
-                return ResourceManager.GetString("choose_type_room", resourceCulture);
+                return ResourceManager.GetString("winrate", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Команда не найдена.
-        /// </summary>
-        internal static string command_not_found {
+        internal static string shop {
             get {
-                return ResourceManager.GetString("command_not_found", resourceCulture);
+                return ResourceManager.GetString("shop", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Отключить.
-        /// </summary>
-        internal static string disable {
+        internal static string my_roles {
             get {
-                return ResourceManager.GetString("disable", resourceCulture);
+                return ResourceManager.GetString("my_roles", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to отключен.
-        /// </summary>
-        internal static string disabled {
+        internal static string settings {
             get {
-                return ResourceManager.GetString("disabled", resourceCulture);
+                return ResourceManager.GetString("settings", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Включить.
-        /// </summary>
-        internal static string enable {
+        internal static string your_name {
             get {
-                return ResourceManager.GetString("enable", resourceCulture);
+                return ResourceManager.GetString("your_name", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to включен.
-        /// </summary>
-        internal static string enabled {
+        internal static string change_name {
             get {
-                return ResourceManager.GetString("enabled", resourceCulture);
+                return ResourceManager.GetString("change_name", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Введите код от комнаты.
-        /// </summary>
-        internal static string enter_private_code {
+        internal static string enter_your_name {
             get {
-                return ResourceManager.GetString("enter_private_code", resourceCulture);
+                return ResourceManager.GetString("enter_your_name", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Введите название комнаты.
-        /// </summary>
-        internal static string enter_room_name {
+        internal static string name_updated {
             get {
-                return ResourceManager.GetString("enter_room_name", resourceCulture);
+                return ResourceManager.GetString("name_updated", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Введите ваше имя.
-        /// </summary>
-        internal static string enter_your_name {
+        internal static string command_not_found {
             get {
-                return ResourceManager.GetString("enter_your_name", resourceCulture);
+                return ResourceManager.GetString("command_not_found", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to В комнату вошёл.
-        /// </summary>
-        internal static string entry_another_user {
+        internal static string settings_room {
             get {
-                return ResourceManager.GetString("entry_another_user", resourceCulture);
+                return ResourceManager.GetString("settings_room", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Расширенный.
-        /// </summary>
-        internal static string extended {
+        internal static string choose_game_type {
             get {
-                return ResourceManager.GetString("extended", resourceCulture);
+                return ResourceManager.GetString("choose_game_type", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Комната с таким именем уже существует.
-        /// </summary>
-        internal static string game_already_exists {
+        internal static string no_name {
             get {
-                return ResourceManager.GetString("game_already_exists", resourceCulture);
+                return ResourceManager.GetString("no_name", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Игра уже запущена.
-        /// </summary>
-        internal static string game_already_running {
+        internal static string enter_room_name {
             get {
-                return ResourceManager.GetString("game_already_running", resourceCulture);
+                return ResourceManager.GetString("enter_room_name", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Число игр:.
-        /// </summary>
-        internal static string games_count {
+        internal static string room_with_name {
             get {
-                return ResourceManager.GetString("games_count", resourceCulture);
+                return ResourceManager.GetString("room_with_name", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Исключить.
-        /// </summary>
-        internal static string kick {
+        internal static string was_created {
             get {
-                return ResourceManager.GetString("kick", resourceCulture);
+                return ResourceManager.GetString("was_created", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Исключить пользователя.
-        /// </summary>
-        internal static string kick_user {
+        internal static string unexpected_error {
             get {
-                return ResourceManager.GetString("kick_user", resourceCulture);
+                return ResourceManager.GetString("unexpected_error", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to игрок был исключён.
-        /// </summary>
-        internal static string kick_user_success {
+        internal static string game_already_exists {
             get {
-                return ResourceManager.GetString("kick_user_success", resourceCulture);
+                return ResourceManager.GetString("game_already_exists", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Вы покинули игру.
-        /// </summary>
         internal static string leave_from_game {
             get {
                 return ResourceManager.GetString("leave_from_game", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Максимальное кол-во игроков.
-        /// </summary>
-        internal static string max_capacity_message {
+        internal static string user_not_in_game {
             get {
-                return ResourceManager.GetString("max_capacity_message", resourceCulture);
+                return ResourceManager.GetString("user_not_in_game", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Максимум - 16 игроков.
-        /// </summary>
-        internal static string maximum_players_count {
+        internal static string standart {
             get {
-                return ResourceManager.GetString("maximum_players_count", resourceCulture);
+                return ResourceManager.GetString("standart", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Максимум был установлен на.
-        /// </summary>
-        internal static string maximum_was_set_to {
+        internal static string extended {
             get {
-                return ResourceManager.GetString("maximum_was_set_to", resourceCulture);
+                return ResourceManager.GetString("extended", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Минимум - 6 игроков.
-        /// </summary>
-        internal static string minimum_players_count {
+        internal static string secret_key_is {
             get {
-                return ResourceManager.GetString("minimum_players_count", resourceCulture);
+                return ResourceManager.GetString("secret_key_is", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Мои роли.
-        /// </summary>
-        internal static string my_roles {
+        internal static string choose_type_room {
             get {
-                return ResourceManager.GetString("my_roles", resourceCulture);
+                return ResourceManager.GetString("choose_type_room", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Имя было обновлено на.
-        /// </summary>
-        internal static string name_updated {
+        internal static string enter_private_code {
             get {
-                return ResourceManager.GetString("name_updated", resourceCulture);
+                return ResourceManager.GetString("enter_private_code", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to No name.
-        /// </summary>
-        internal static string no_name {
+        internal static string room_is_filled {
             get {
-                return ResourceManager.GetString("no_name", resourceCulture);
+                return ResourceManager.GetString("room_is_filled", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to игроков.
-        /// </summary>
-        internal static string players {
+        internal static string user_already_in_game {
             get {
-                return ResourceManager.GetString("players", resourceCulture);
+                return ResourceManager.GetString("user_already_in_game", resourceCulture);
+            }
+        }
+        
+        internal static string successful_entry_into_room {
+            get {
+                return ResourceManager.GetString("successful_entry_into_room", resourceCulture);
+            }
+        }
+        
+        internal static string users_list {
+            get {
+                return ResourceManager.GetString("users_list", resourceCulture);
+            }
+        }
+        
+        internal static string users_list_empty {
+            get {
+                return ResourceManager.GetString("users_list_empty", resourceCulture);
+            }
+        }
+        
+        internal static string max_capacity_message {
+            get {
+                return ResourceManager.GetString("max_capacity_message", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Сначала покиньте комнату.
-        /// </summary>
         internal static string prefer_leave_from_room {
             get {
                 return ResourceManager.GetString("prefer_leave_from_room", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Нет свободных публичных комнат.
-        /// </summary>
+        internal static string room_does_not_exists {
+            get {
+                return ResourceManager.GetString("room_does_not_exists", resourceCulture);
+            }
+        }
+        
         internal static string public_rooms_are_not_exist {
             get {
                 return ResourceManager.GetString("public_rooms_are_not_exist", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Комната распущена.
-        /// </summary>
-        internal static string room_dissolved {
+        internal static string rooms {
             get {
-                return ResourceManager.GetString("room_dissolved", resourceCulture);
+                return ResourceManager.GetString("rooms", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Комната не существует.
-        /// </summary>
-        internal static string room_does_not_exists {
+        internal static string too_many_players {
             get {
-                return ResourceManager.GetString("room_does_not_exists", resourceCulture);
+                return ResourceManager.GetString("too_many_players", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Комната заполнена.
-        /// </summary>
-        internal static string room_is_filled {
+        internal static string too_few_players {
             get {
-                return ResourceManager.GetString("room_is_filled", resourceCulture);
+                return ResourceManager.GetString("too_few_players", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Комната с именем.
-        /// </summary>
-        internal static string room_with_name {
+        internal static string game_already_running {
             get {
-                return ResourceManager.GetString("room_with_name", resourceCulture);
+                return ResourceManager.GetString("game_already_running", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Комнаты.
-        /// </summary>
-        internal static string rooms {
+        internal static string minimum_players_count {
             get {
-                return ResourceManager.GetString("rooms", resourceCulture);
+                return ResourceManager.GetString("minimum_players_count", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Секретный код для подключения к комнате.
-        /// </summary>
-        internal static string secret_key_is {
+        internal static string maximum_players_count {
             get {
-                return ResourceManager.GetString("secret_key_is", resourceCulture);
+                return ResourceManager.GetString("maximum_players_count", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Настройки.
-        /// </summary>
-        internal static string settings {
+        internal static string maximum_was_set_to {
             get {
-                return ResourceManager.GetString("settings", resourceCulture);
+                return ResourceManager.GetString("maximum_was_set_to", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Задайте настройки комнаты.
-        /// </summary>
-        internal static string settings_room {
+        internal static string players {
             get {
-                return ResourceManager.GetString("settings_room", resourceCulture);
+                return ResourceManager.GetString("players", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Магазин.
-        /// </summary>
-        internal static string shop {
+        internal static string kick {
             get {
-                return ResourceManager.GetString("shop", resourceCulture);
+                return ResourceManager.GetString("kick", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Стандартный.
-        /// </summary>
-        internal static string standart {
+        internal static string kick_user {
             get {
-                return ResourceManager.GetString("standart", resourceCulture);
+                return ResourceManager.GetString("kick_user", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Что вы хотите сделать?.
-        /// </summary>
-        internal static string start_message {
+        internal static string kick_user_success {
             get {
-                return ResourceManager.GetString("start_message", resourceCulture);
+                return ResourceManager.GetString("kick_user_success", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Статистика для.
-        /// </summary>
-        internal static string statistics_for {
+        internal static string you_were_kicked {
             get {
-                return ResourceManager.GetString("statistics_for", resourceCulture);
+                return ResourceManager.GetString("you_were_kicked", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Вы были добавлены в комнату.
-        /// </summary>
-        internal static string successful_entry_into_room {
+        internal static string room_dissolved {
             get {
-                return ResourceManager.GetString("successful_entry_into_room", resourceCulture);
+                return ResourceManager.GetString("room_dissolved", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Таймер.
-        /// </summary>
         internal static string timer {
             get {
                 return ResourceManager.GetString("timer", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Недостаточно игроков для старта игры.
-        /// </summary>
-        internal static string too_few_players {
+        internal static string enabled {
             get {
-                return ResourceManager.GetString("too_few_players", resourceCulture);
+                return ResourceManager.GetString("enabled", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Количество игроков превышает максимальное.
-        /// </summary>
-        internal static string too_many_players {
+        internal static string disabled {
             get {
-                return ResourceManager.GetString("too_many_players", resourceCulture);
+                return ResourceManager.GetString("disabled", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Произошла неожиданная ошибка... Попробуйте ещё раз..
-        /// </summary>
-        internal static string unexpected_error {
+        internal static string enable {
             get {
-                return ResourceManager.GetString("unexpected_error", resourceCulture);
+                return ResourceManager.GetString("enable", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Вы уже находитесь в игре.
-        /// </summary>
-        internal static string user_already_in_game {
+        internal static string disable {
             get {
-                return ResourceManager.GetString("user_already_in_game", resourceCulture);
+                return ResourceManager.GetString("disable", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Вы не находитесь сейчас в игре.
-        /// </summary>
-        internal static string user_not_in_game {
+        internal static string _public {
             get {
-                return ResourceManager.GetString("user_not_in_game", resourceCulture);
+                return ResourceManager.GetString("public", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Участники в комнате.
-        /// </summary>
-        internal static string users_list {
+        internal static string _private {
             get {
-                return ResourceManager.GetString("users_list", resourceCulture);
+                return ResourceManager.GetString("private", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to В комнате нет игроков, кроме Вас.
-        /// </summary>
-        internal static string users_list_empty {
+        internal static string bot_starting_game {
             get {
-                return ResourceManager.GetString("users_list_empty", resourceCulture);
+                return ResourceManager.GetString("bot_starting_game", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to была создана.
-        /// </summary>
-        internal static string was_created {
+        internal static string game_process_started {
             get {
-                return ResourceManager.GetString("was_created", resourceCulture);
+                return ResourceManager.GetString("game_process_started", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Винрейт:.
-        /// </summary>
-        internal static string winrate {
+        internal static string connected_to_game {
             get {
-                return ResourceManager.GetString("winrate", resourceCulture);
+                return ResourceManager.GetString("connected_to_game", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Число побед:.
-        /// </summary>
-        internal static string wins_count {
+        internal static string your_turn_order {
             get {
-                return ResourceManager.GetString("wins_count", resourceCulture);
+                return ResourceManager.GetString("your_turn_order", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Вы были исключены.
-        /// </summary>
-        internal static string you_were_kicked {
+        internal static string your_role {
             get {
-                return ResourceManager.GetString("you_were_kicked", resourceCulture);
+                return ResourceManager.GetString("your_role", resourceCulture);
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Ваше имя:.
-        /// </summary>
-        internal static string your_name {
+        internal static string thanks_for_game {
             get {
-                return ResourceManager.GetString("your_name", resourceCulture);
+                return ResourceManager.GetString("thanks_for_game", resourceCulture);
             }
         }
     }

+ 18 - 3
MafiaTelegramBot/Resources/strings.resx

@@ -111,9 +111,6 @@
     <data name="successful_entry_into_room" xml:space="preserve">
         <value>Вы были добавлены в комнату</value>
     </data>
-    <data name="entry_another_user" xml:space="preserve">
-        <value>В комнату вошёл</value>
-    </data>
     <data name="users_list" xml:space="preserve">
         <value>Участники в комнате</value>
     </data>
@@ -192,4 +189,22 @@
     <data name="private" xml:space="preserve">
         <value>Приватная</value>
     </data>
+    <data name="bot_starting_game" xml:space="preserve">
+        <value>Игра начинается...</value>
+    </data>
+    <data name="game_process_started" xml:space="preserve">
+        <value>Процесс подготовки комнаты начался</value>
+    </data>
+    <data name="connected_to_game" xml:space="preserve">
+        <value>подключился к игре</value>
+    </data>
+    <data name="your_turn_order" xml:space="preserve">
+        <value>Вы ходите под номером</value>
+    </data>
+    <data name="your_role" xml:space="preserve">
+        <value>Ваша роль</value>
+    </data>
+    <data name="thanks_for_game" xml:space="preserve">
+        <value>Игра окончена, спасибо за игру!</value>
+    </data>
 </root>

+ 35 - 23
MafiaTelegramBot/Utilities.cs

@@ -1,3 +1,5 @@
+using System;
+using System.Linq;
 using System.Threading.Tasks;
 using MafiaTelegramBot.Models;
 using MafiaTelegramBot.Resources;
@@ -23,34 +25,44 @@ namespace MafiaTelegramBot
                 _ => Bot.SendWithMarkdown2(chatId, strings.unexpected_error)
             };
         }
-        public static async Task<string> ToMarkdownString(string res)
+        public static async Task<string> ToMarkdownString(string src)
         {
-            return await Task.Run(()=> res
-                .Replace(".", "\\.")
-                .Replace("@", "\\@")
-                .Replace("#", "\\#")
-                .Replace("!", "\\!")
-                .Replace("-", "\\-")
-            );
+            return src != null
+                ? await Task.Run(()=>
+            {
+                var newStr = src
+                    .Replace(".", "\\.")
+                    .Replace("#", "\\#")
+                    .Replace("!", "\\!")
+                    .Replace("-", "\\-");
+                return newStr;
+            }) : "";
         }
         
         public static async Task<string> EscapeSpecific(string src)
         {
-            var result = src != null
-                ? await Task.Run(()=> src
-                    .Replace(".", "\\.")
-                    .Replace("`", "\\`")
-                    .Replace("@", "\\@")
-                    .Replace("#", "\\#")
-                    .Replace("!", "\\!")
-                    .Replace("*", "\\*")
-                    .Replace("_", "\\_")
-                    .Replace("'", "\\'")
-                    .Replace("~", "\\~")
-                    .Replace("[", "\\[")
-                )
-                :"";
-            return result;
+            return src != null
+                ? await Task.Run(()=>
+                {
+                    var newStr = src
+                        .Replace("_", "\\_")
+                        .Replace("*", "\\*")
+                        .Replace("[", "\\[")
+                        .Replace("]", "\\]")
+                        .Replace("(", "\\(")
+                        .Replace(")", "\\)")
+                        .Replace("~", "\\~")
+                        .Replace("`", "\\`")
+                        .Replace(">", "\\>")
+                        .Replace("+", "\\+")
+                        .Replace("=", "\\=")
+                        .Replace("|", "\\|")
+                        .Replace("{", "\\{")
+                        .Replace("}", "\\}")
+                        .Replace("@", "\\@")
+                        .Replace("'", "\\'");
+                    return newStr;
+                }) :"";
         }
     }
 }