Browse Source

Statistics system

Tigran 3 years ago
parent
commit
ced41e2119

+ 2 - 0
CardCollector.sln.DotSettings.user

@@ -14,6 +14,8 @@
 	
 	<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=CardCollector_002FResources_002FCommand/@EntryIndexedValue">False</s:Boolean>
 	
+	<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=CardCollector_002FResources_002FLogsTranslations/@EntryIndexedValue">False</s:Boolean>
+	
 	
 	
 	

+ 9 - 0
CardCollector/Bot.cs

@@ -3,12 +3,16 @@ using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Timers;
+using CardCollector.Commands.CallbackQuery;
+using CardCollector.Commands.ChosenInlineResult;
+using CardCollector.DailyTasks.CustomTasks;
 using CardCollector.DataBase;
 using CardCollector.DataBase.EntityDao;
 using CardCollector.Resources;
 using CardCollector.TimerTasks;
 using Telegram.Bot;
 using Telegram.Bot.Types;
+using BuyGems = CardCollector.Commands.PreCheckoutQuery.BuyGems;
 using Timer = System.Timers.Timer;
 
 namespace CardCollector
@@ -54,6 +58,11 @@ namespace CardCollector
 
         public static async Task StopProgram()
         {
+            SendStickers.WriteLogs();
+            CollectIncome.WriteLogs();
+            SendStickerCommand.WriteLogs();
+            BuyGems.WriteLogs();
+            ConfirmSelling.WriteLogs();
             await BotDatabase.SaveData();
             await UserDao.ClearMemory();
             _end.Set();

+ 9 - 0
CardCollector/CardCollector.csproj

@@ -47,6 +47,10 @@
         <Generator>ResXFileCodeGenerator</Generator>
         <LastGenOutput>EffectTranslations.Designer.cs</LastGenOutput>
       </EmbeddedResource>
+      <EmbeddedResource Update="Resources\LogsTranslations.resx">
+        <Generator>ResXFileCodeGenerator</Generator>
+        <LastGenOutput>LogsTranslations.Designer.cs</LastGenOutput>
+      </EmbeddedResource>
     </ItemGroup>
 
     <ItemGroup>
@@ -90,6 +94,11 @@
         <AutoGen>True</AutoGen>
         <DependentUpon>EffectTranslations.resx</DependentUpon>
       </Compile>
+      <Compile Update="Resources\LogsTranslations.Designer.cs">
+        <DesignTime>True</DesignTime>
+        <AutoGen>True</AutoGen>
+        <DependentUpon>LogsStranslations.resx</DependentUpon>
+      </Compile>
     </ItemGroup>
 
 </Project>

+ 54 - 1
CardCollector/Commands/CallbackQuery/CollectIncome.cs

@@ -1,4 +1,7 @@
-using System.Threading.Tasks;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;
 using CardCollector.DataBase.EntityDao;
@@ -10,6 +13,7 @@ namespace CardCollector.Commands.CallbackQuery
     public class CollectIncome : CallbackQueryCommand
     {
         protected override string CommandText => Command.collect_income;
+        private static PeopleCollectedIncomeInfo _info = PeopleCollectedIncomeInfo.Build().Result;
 
         public override async Task Execute()
         {
@@ -30,7 +34,56 @@ namespace CardCollector.Commands.CallbackQuery
                 Keyboard.GetProfileKeyboard(User.PrivilegeLevel, packsCount));
         }
 
+        public override async Task AfterExecute()
+        {
+            if (!_info.Actual())
+            {
+                _info.WriteResults();
+                _info = await PeopleCollectedIncomeInfo.Build();
+            }
+            _info.Add(User.Id);
+        }
+
         public CollectIncome() { }
         public CollectIncome(UserEntity user, Update update) : base(user, update) { }
+        
+        private class PeopleCollectedIncomeInfo
+        {
+            private DateTime infoDate;
+            private CountLogs logsEntity;
+            private Dictionary<long, int> UserCollectCount = new ();
+
+            public static async Task<PeopleCollectedIncomeInfo> Build()
+            {
+                var result = new PeopleCollectedIncomeInfo();
+                result.infoDate = DateTime.Today;
+                result.logsEntity = await CountLogsDao.Get(result.infoDate);
+                return result;
+            }
+
+            public bool Actual()
+            {
+                return infoDate.Equals(DateTime.Today);
+            }
+
+            public void Add(long userId)
+            {
+                if (!UserCollectCount.ContainsKey(userId))
+                    UserCollectCount.Add(userId, 1);
+                else UserCollectCount[userId]++;
+            }
+
+            public void WriteResults()
+            {
+                var oneToThreeTimes = UserCollectCount.Values.Count(item => item < 4);
+                logsEntity.PeopleCollectedIncomeOneToThreeTimes += oneToThreeTimes;
+                logsEntity.PeopleCollectedIncomeMoreTimes += UserCollectCount.Count - oneToThreeTimes;
+            }
+        }
+
+        public static void WriteLogs()
+        {
+            _info.WriteResults();
+        }
     }
 }

+ 84 - 0
CardCollector/Commands/CallbackQuery/ConfirmSelling.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using CardCollector.Commands.Message;
+using CardCollector.Controllers;
+using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
+using CardCollector.Resources;
+using CardCollector.Session.Modules;
+using Telegram.Bot.Types;
+
+namespace CardCollector.Commands.CallbackQuery
+{
+    public class ConfirmSelling : CallbackQueryCommand
+    {
+        protected override string CommandText => Command.confirm_selling;
+        protected override bool ClearStickers => true;
+
+        public override async Task Execute()
+        {
+            var collectionModule = User.Session.GetModule<CollectionModule>();
+            if (collectionModule.SellPrice <= 0)
+                await MessageController.AnswerCallbackQuery(User, CallbackQueryId, Messages.cant_sell_zero, true);
+            else
+            {
+                EnterGemsPrice.RemoveFromQueue(User.Id);
+                User.Stickers[collectionModule.SelectedSticker.Md5Hash].Count -= collectionModule.Count;
+                AuctionController.SellCard(User.Id, collectionModule.SelectedSticker.Id, collectionModule.SellPrice,
+                    collectionModule.Count);
+                await MessageController.EditMessage(User, Messages.successfully_selling);
+            }
+        }
+        
+        public ConfirmSelling(){}
+        public ConfirmSelling(UserEntity user, Update update) : base(user, update){}
+        
+        private static PeoplePutsStickerOnAuction info = PeoplePutsStickerOnAuction.Build().Result;
+        
+        public override async Task AfterExecute()
+        {
+            if (!info.Actual())
+            {
+                info.WriteResults();
+                info = await PeoplePutsStickerOnAuction.Build();
+            }
+            info.Add(User.Id);
+        }
+        
+        private class PeoplePutsStickerOnAuction
+        {
+            private DateTime infoDate;
+            private CountLogs logsEntity;
+            private HashSet<long> People = new();
+
+            public static async Task<PeoplePutsStickerOnAuction> Build()
+            {
+                var result = new PeoplePutsStickerOnAuction();
+                result.infoDate = DateTime.Today;
+                result.logsEntity = await CountLogsDao.Get(result.infoDate);
+                return result;
+            }
+
+            public bool Actual()
+            {
+                return infoDate.Equals(DateTime.Today);
+            }
+
+            public void Add(long userId)
+            {
+                People.Add(userId);
+            }
+
+            public void WriteResults()
+            {
+                logsEntity.PeoplePutsStickerToAuction += People.Count;
+            }
+        }
+
+        public static void WriteLogs()
+        {
+            info.WriteResults();
+        }
+    }
+}

+ 0 - 36
CardCollector/Commands/CallbackQuery/ConfirmationSelling.cs

@@ -1,36 +0,0 @@
-using System.Threading.Tasks;
-using CardCollector.Commands.Message;
-using CardCollector.Controllers;
-using CardCollector.DataBase.Entity;
-using CardCollector.Resources;
-using CardCollector.Session.Modules;
-using Telegram.Bot.Types;
-
-namespace CardCollector.Commands.CallbackQuery
-{
-    public class ConfirmationSelling : CallbackQueryCommand
-    {
-        protected override string CommandText => Command.confirm_selling;
-        protected override bool ClearStickers => true;
-
-        public override async Task Execute()
-        {
-            var collectionModule = User.Session.GetModule<CollectionModule>();
-            if (collectionModule.SellPrice <= 0)
-                await MessageController.AnswerCallbackQuery(User, CallbackQueryId, Messages.cant_sell_zero, true);
-            else
-            {
-                EnterGemsPrice.RemoveFromQueue(User.Id);
-                User.Stickers[collectionModule.SelectedSticker.Md5Hash].Count -= collectionModule.Count;
-                AuctionController.SellCard(User.Id, collectionModule.SelectedSticker.Id, collectionModule.SellPrice,
-                    collectionModule.Count);
-                await MessageController.EditMessage(User, Messages.successfully_selling);
-            }
-        }
-        
-        public ConfirmationSelling(){}
-        public ConfirmationSelling(UserEntity user, Update update) : base(user, update){}
-    }
-    
-    
-}

+ 8 - 1
CardCollector/Commands/CallbackQuery/LogsMenu.cs

@@ -2,6 +2,7 @@
 using System.Threading.Tasks;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
 using CardCollector.Resources;
 using Telegram.Bot.Types;
 using Telegram.Bot.Types.Enums;
@@ -16,7 +17,13 @@ namespace CardCollector.Commands.CallbackQuery
         {
             var date = Convert.ToDateTime(CallbackData.Split('=')[1]);
             var message = string.Format(Messages.logs_on_date, date.ToString("dd.MM.yyyy"));
-            //TODO add logs rows
+            var logsPage = await CountLogsDao.Get(date);
+            message += $"\n{LogsTranslations.PCIOTTT}: {logsPage.PeopleCollectedIncomeOneToThreeTimes}" +
+                       $"\n{LogsTranslations.PCIMT}: {logsPage.PeopleCollectedIncomeMoreTimes}" +
+                       $"\n{LogsTranslations.PCDT}: {logsPage.PeopleCompletedDailyTask}" +
+                       $"\n{LogsTranslations.PSSOOMT}: {logsPage.PeopleSendsStickerOneOrMoreTimes}" +
+                       $"\n{LogsTranslations.PD}: {logsPage.PeopleDonated}" +
+                       $"\n{LogsTranslations.PPSTA}: {logsPage.PeoplePutsStickerToAuction}";
             await MessageController.EditMessage(User, message, Keyboard.LogsMenu(date), ParseMode.Html);
         }
 

+ 1 - 1
CardCollector/Commands/CallbackQueryCommand.cs

@@ -39,7 +39,7 @@ namespace CardCollector.Commands
             new CollectIncome(),
             new Combine(),
             new CombineStickers(),
-            new ConfirmationSelling(),
+            new ConfirmSelling(),
             new ConfirmBuying(),
             new ConfirmExchange(),
             new Count(),

+ 1 - 1
CardCollector/Commands/ChosenInlineResult/GiveExp.cs

@@ -7,7 +7,7 @@ using Telegram.Bot.Types;
 namespace CardCollector.Commands.ChosenInlineResult
 {
     /* Данная команда выполняется при отправке пользователем стикера */
-    public class GiveExp : ChosenInlineResultCommand
+    public class GiveExp : SendStickerCommand
     {
         /* Ключевое слово для данной команды send_sticker */
         protected override string CommandText => Command.give_exp;

+ 1 - 1
CardCollector/Commands/ChosenInlineResult/SendPrivateSticker.cs

@@ -7,7 +7,7 @@ using Telegram.Bot.Types;
 
 namespace CardCollector.Commands.ChosenInlineResult
 {
-    public class SendPrivateSticker : ChosenInlineResultCommand
+    public class SendPrivateSticker : SendStickerCommand
     {
         protected override string CommandText => Command.send_private_sticker;
 

+ 62 - 0
CardCollector/Commands/ChosenInlineResult/SendStickerCommand.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
+using Telegram.Bot.Types;
+
+namespace CardCollector.Commands.ChosenInlineResult
+{
+    public abstract class SendStickerCommand : ChosenInlineResultCommand
+    {
+        private static PeopleSendsSticker info = PeopleSendsSticker.Build().Result;
+        
+        public override async Task AfterExecute()
+        {
+            if (!info.Actual())
+            {
+                info.WriteResults();
+                info = await PeopleSendsSticker.Build();
+            }
+            info.Add(User.Id);
+        }
+        
+        private class PeopleSendsSticker
+        {
+            private DateTime infoDate;
+            private CountLogs logsEntity;
+            private HashSet<long> People = new();
+
+            public static async Task<PeopleSendsSticker> Build()
+            {
+                var result = new PeopleSendsSticker();
+                result.infoDate = DateTime.Today;
+                result.logsEntity = await CountLogsDao.Get(result.infoDate);
+                return result;
+            }
+
+            public bool Actual()
+            {
+                return infoDate.Equals(DateTime.Today);
+            }
+
+            public void Add(long userId)
+            {
+                People.Add(userId);
+            }
+
+            public void WriteResults()
+            {
+                logsEntity.PeopleSendsStickerOneOrMoreTimes += People.Count;
+            }
+        }
+
+        public static void WriteLogs()
+        {
+            info.WriteResults();
+        }
+
+        protected SendStickerCommand() { }
+        protected SendStickerCommand(UserEntity user, Update update) : base(user, update) { }
+    }
+}

+ 15 - 1
CardCollector/Commands/Message/StopBot.cs

@@ -1,4 +1,5 @@
 using System.Threading.Tasks;
+using System.Timers;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;
 using CardCollector.Resources;
@@ -9,10 +10,23 @@ namespace CardCollector.Commands.Message
     public class StopBot : MessageCommand
     {
         protected override string CommandText => Text.stop_bot;
+        public static bool ConfirmStop = false;
 
         public override async Task Execute()
         {
-            await Bot.StopProgram();
+            if (ConfirmStop) await Bot.StopProgram();
+            else
+            {
+                await MessageController.EditMessage(User, Messages.confirm_stopping);
+                ConfirmStop = true;
+                var timer = new Timer
+                {
+                    AutoReset = false,
+                    Enabled = true,
+                    Interval = 60 * 1000
+                };
+                timer.Elapsed += (_, _) => ConfirmStop = false;
+            }
         }
 
         protected internal override bool IsMatches(UserEntity user, Update update)

+ 51 - 1
CardCollector/Commands/PreCheckoutQuery/BuyGems.cs

@@ -1,6 +1,9 @@
-using System.Threading.Tasks;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
 using CardCollector.Resources;
 using Telegram.Bot;
 using Telegram.Bot.Types;
@@ -25,5 +28,52 @@ namespace CardCollector.Commands.PreCheckoutQuery
 
         public BuyGems() { }
         public BuyGems(UserEntity user, Update update) : base(user, update) { }
+        
+        private static PeopleDonated info = PeopleDonated.Build().Result;
+        
+        public override async Task AfterExecute()
+        {
+            if (!info.Actual())
+            {
+                info.WriteResults();
+                info = await PeopleDonated.Build();
+            }
+            info.Add(User.Id);
+        }
+        
+        private class PeopleDonated
+        {
+            private DateTime infoDate;
+            private CountLogs logsEntity;
+            private HashSet<long> People = new();
+
+            public static async Task<PeopleDonated> Build()
+            {
+                var result = new PeopleDonated();
+                result.infoDate = DateTime.Today;
+                result.logsEntity = await CountLogsDao.Get(result.infoDate);
+                return result;
+            }
+
+            public bool Actual()
+            {
+                return infoDate.Equals(DateTime.Today);
+            }
+
+            public void Add(long userId)
+            {
+                People.Add(userId);
+            }
+
+            public void WriteResults()
+            {
+                logsEntity.PeopleDonated += People.Count;
+            }
+        }
+
+        public static void WriteLogs()
+        {
+            info.WriteResults();
+        }
     }
 }

+ 3 - 0
CardCollector/Commands/UpdateModel.cs

@@ -29,8 +29,11 @@ namespace CardCollector.Commands
             if (AddToStack) User.Session.AddMenuToStack(this);
             if (ClearStickers) await User.Session.ClearStickers();
             await Execute();
+            await AfterExecute();
         }
 
+        public virtual Task AfterExecute() => Task.CompletedTask;
+
         protected internal abstract bool IsMatches(UserEntity user, Update update);
 
         protected UpdateModel()

+ 49 - 2
CardCollector/DailyTasks/CustomTasks/SendStickers.cs

@@ -1,4 +1,5 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading.Tasks;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;
 using CardCollector.DataBase.EntityDao;
@@ -12,6 +13,7 @@ namespace CardCollector.DailyTasks.CustomTasks
         public override int Goal => 5;
         public override string Title => Titles.send_stickers;
         public override string Description => Descriptions.send_stickers;
+        private static PeopleCompletedTask info = PeopleCompletedTask.Build().Result;
 
         public override async Task<bool> Execute(UserEntity user, object[] args = null)
         {
@@ -21,7 +23,17 @@ namespace CardCollector.DailyTasks.CustomTasks
             if (user.Settings[UserSettingsEnum.DailyTaskProgress])
                 await MessageController.EditMessage(user,
                     $"{Messages.send_sticker_progress}: {Goal - task.Progress} / {Goal}");
-            return task.Progress == 0;
+            if (task.Progress == 0)
+            {
+                if (!info.Actual())
+                {
+                    info.WriteResults();
+                    info = await PeopleCompletedTask.Build();
+                }
+                info.Increase();
+                return true;
+            }
+            return false;
         }
 
         public override async Task GiveReward(UserEntity user, object[] args = null)
@@ -29,5 +41,40 @@ namespace CardCollector.DailyTasks.CustomTasks
             var userPacks = await UserPacksDao.GetOne(user.Id, 1);
             userPacks.Count++;
         }
+
+        private class PeopleCompletedTask
+        {
+            private DateTime infoDate;
+            private CountLogs logsEntity;
+            private int count = 0;
+
+            public static async Task<PeopleCompletedTask> Build()
+            {
+                var result = new PeopleCompletedTask();
+                result.infoDate = DateTime.Today;
+                result.logsEntity = await CountLogsDao.Get(result.infoDate);
+                return result;
+            }
+
+            public bool Actual()
+            {
+                return infoDate.Equals(DateTime.Today);
+            }
+
+            public void Increase()
+            {
+                count++;
+            }
+
+            public void WriteResults()
+            {
+                logsEntity.PeopleCompletedDailyTask += count;
+            }
+        }
+
+        public static void WriteLogs()
+        {
+            info.WriteResults();
+        }
     }
 }

+ 1 - 0
CardCollector/DataBase/BotDatabase.cs

@@ -46,6 +46,7 @@ namespace CardCollector.DataBase
         public DbSet<UserLevel> UserLevel { get; set; }
         public DbSet<Level> Levels { get; set; }
         public DbSet<UserSettings> Settings { get; set; }
+        public DbSet<CountLogs> CountLogs { get; set; }
 
         /* Конфигурация подключения к БД */
         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

+ 18 - 0
CardCollector/DataBase/Entity/CountLogs.cs

@@ -0,0 +1,18 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace CardCollector.DataBase.Entity
+{
+    [Table("count_logs")]
+    public class CountLogs
+    {
+        [Key, Column("date"), MaxLength(32)] public DateTime Date { get; set; } = DateTime.Today;
+        [Column("pciottt"), MaxLength(32)] public int PeopleCollectedIncomeOneToThreeTimes { get; set; } = 0;
+        [Column("pcimt"), MaxLength(32)] public int PeopleCollectedIncomeMoreTimes { get; set; } = 0;
+        [Column("pcdt"), MaxLength(32)] public int PeopleCompletedDailyTask { get; set; } = 0;
+        [Column("pssoomt"), MaxLength(32)] public int PeopleSendsStickerOneOrMoreTimes { get; set; } = 0;
+        [Column("pd"), MaxLength(32)] public int PeopleDonated { get; set; } = 0;
+        [Column("ppsta"), MaxLength(32)] public int PeoplePutsStickerToAuction { get; set; } = 0;
+    }
+}

+ 42 - 0
CardCollector/DataBase/EntityDao/CountLogsDao.cs

@@ -0,0 +1,42 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using CardCollector.DataBase.Entity;
+using Microsoft.EntityFrameworkCore;
+
+namespace CardCollector.DataBase.EntityDao
+{
+    public static class CountLogsDao
+    {
+        public static BotDatabase Instance;
+        public static DbSet<CountLogs> Table;
+
+        static CountLogsDao()
+        {
+            Instance = BotDatabase.GetClassInstance(typeof(CountLogsDao));
+            Table = Instance.CountLogs;
+        }
+
+        public static async Task<CountLogs> Get(DateTime date)
+        {
+            try {
+                return await Table.FirstOrDefaultAsync(item => item.Date == date) ?? await Create(date);
+            }
+            catch (InvalidOperationException) {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await Get(date);
+            }
+        }
+
+        private static async Task<CountLogs> Create(DateTime date)
+        {
+            try {
+                return (await Table.AddAsync(new CountLogs{Date = date})).Entity;
+            }
+            catch (InvalidOperationException) {
+                Thread.Sleep(Utilities.rnd.Next(30));
+                return await Create(date);
+            }
+        }
+    }
+}

+ 4 - 4
CardCollector/Resources/Keyboard.cs

@@ -32,10 +32,10 @@ namespace CardCollector.Resources
             var keyboard = new List<InlineKeyboardButton[]>
             {
                 new[]
-                {//TODO исправить суммы монет
-                    InlineKeyboardButton.WithCallbackData($"100{Text.coin}", $"{Command.set_exchange_sum}=100"),
-                    InlineKeyboardButton.WithCallbackData($"300{Text.coin}", $"{Command.set_exchange_sum}=300"),
-                    InlineKeyboardButton.WithCallbackData($"700{Text.coin}", $"{Command.set_exchange_sum}=700")
+                {
+                    InlineKeyboardButton.WithCallbackData($"300{Text.coin}", $"{Command.set_exchange_sum}=2"),
+                    InlineKeyboardButton.WithCallbackData($"600{Text.coin}", $"{Command.set_exchange_sum}=4"),
+                    InlineKeyboardButton.WithCallbackData($"900{Text.coin}", $"{Command.set_exchange_sum}=6")
                 }
             };
             if (confirmButton) keyboard.Add(new[] {InlineKeyboardButton.WithCallbackData(Text.confirm_exchange,

+ 117 - 0
CardCollector/Resources/LogsTranslations.Designer.cs

@@ -0,0 +1,117 @@
+//------------------------------------------------------------------------------
+// <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.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CardCollector.Resources {
+    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()]
+    internal class LogsTranslations {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal LogsTranslations() {
+        }
+        
+        /// <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 {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CardCollector.Resources.LogsTranslations", typeof(LogsTranslations).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 {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Людей выполнило ежедневное задание.
+        /// </summary>
+        internal static string PCDT {
+            get {
+                return ResourceManager.GetString("PCDT", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Людей собрало прибыль больше 3 раз.
+        /// </summary>
+        internal static string PCIMT {
+            get {
+                return ResourceManager.GetString("PCIMT", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Людей собрало прибыль 1-3 раза.
+        /// </summary>
+        internal static string PCIOTTT {
+            get {
+                return ResourceManager.GetString("PCIOTTT", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Людей задонатило.
+        /// </summary>
+        internal static string PD {
+            get {
+                return ResourceManager.GetString("PD", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Людей выставилос стикер на аукцион.
+        /// </summary>
+        internal static string PPSTA {
+            get {
+                return ResourceManager.GetString("PPSTA", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Людей отправило хотя бы 1 стикер.
+        /// </summary>
+        internal static string PSSOOMT {
+            get {
+                return ResourceManager.GetString("PSSOOMT", resourceCulture);
+            }
+        }
+    }
+}

+ 39 - 0
CardCollector/Resources/LogsTranslations.resx

@@ -0,0 +1,39 @@
+<?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="PCIOTTT" xml:space="preserve">
+        <value>Людей собрало прибыль 1-3 раза</value>
+    </data>
+    <data name="PCIMT" xml:space="preserve">
+        <value>Людей собрало прибыль больше 3 раз</value>
+    </data>
+    <data name="PCDT" xml:space="preserve">
+        <value>Людей выполнило ежедневное задание</value>
+    </data>
+    <data name="PSSOOMT" xml:space="preserve">
+        <value>Людей отправило хотя бы 1 стикер</value>
+    </data>
+    <data name="PD" xml:space="preserve">
+        <value>Людей задонатило</value>
+    </data>
+    <data name="PPSTA" xml:space="preserve">
+        <value>Людей выставилос стикер на аукцион</value>
+    </data>
+</root>

+ 10 - 10
CardCollector/Resources/Messages.Designer.cs

@@ -296,6 +296,15 @@ namespace CardCollector.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Подтвердите остановку (повторите команду).
+        /// </summary>
+        internal static string confirm_stopping {
+            get {
+                return ResourceManager.GetString("confirm_stopping", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Поздравляем! Вы получили стикер:.
         /// </summary>
@@ -532,7 +541,7 @@ namespace CardCollector.Resources {
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Логи на &lt;b&gt;{0}&lt;/b&gt;:.
+        ///   Looks up a localized string similar to Статистика за &lt;b&gt;{0}&lt;/b&gt;:.
         /// </summary>
         internal static string logs_on_date {
             get {
@@ -755,15 +764,6 @@ namespace CardCollector.Resources {
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized string similar to Авторских паков:.
-        /// </summary>
-        internal static string specific_packs {
-            get {
-                return ResourceManager.GetString("specific_packs", resourceCulture);
-            }
-        }
-        
         /// <summary>
         ///   Looks up a localized string similar to Добро пожаловать! Этот бот позволяет вам коллекционировать стикеры. Вы можете выбрать одну из опций ниже.
         ///

+ 4 - 4
CardCollector/Resources/Messages.resx

@@ -209,9 +209,6 @@
     <data name="offer_expired" xml:space="preserve">
         <value>Время акции истекло!</value>
     </data>
-    <data name="specific_packs" xml:space="preserve">
-        <value>Авторских паков:</value>
-    </data>
     <data name="effect_PiggyBank200" xml:space="preserve">
         <value>Поздравляем! Ваша копилка увеличена на 200!</value>
     </data>
@@ -346,6 +343,9 @@ https://telegra.ph/help-11-04-4</value>
         <value>👑&lt;b&gt;Панель управления&lt;/b&gt;👑</value>
     </data>
     <data name="logs_on_date" xml:space="preserve">
-        <value>Логи на &lt;b&gt;{0}&lt;/b&gt;:</value>
+        <value>Статистика за &lt;b&gt;{0}&lt;/b&gt;:</value>
+    </data>
+    <data name="confirm_stopping" xml:space="preserve">
+        <value>Подтвердите остановку (повторите команду)</value>
     </data>
 </root>