예제 #1
0
        public async Task Run()
        {
            string mainMenuCommandOrNull = null;

            User = await _userService.GetOrAddUser(_userInfo);

            await SayHelloAsync();

            while (true)
            {
                try
                {
                    if (mainMenuCommandOrNull != null)
                    {
                        await HandleMainMenu(mainMenuCommandOrNull);

                        mainMenuCommandOrNull = null;
                    }
                    await ModeSelection();
                }
                catch (UserAFKException) {
                    return;
                }
                catch (ProcessInterruptedWithMenuCommand e) {
                    mainMenuCommandOrNull = e.Command;
                }
                catch (Exception e) {
                    Botlog.Error(ChatIo.ChatId.Identifier, $"{ChatIo.ChatId.Username} exception: {e}");
                    await ChatIo.SendMessageAsync("Oops. something goes wrong ;(");
                }
            }
        }
예제 #2
0
        public async Task UpdateCurrentScore(User user, int count)
        {
            var sw    = Stopwatch.StartNew();
            var words = await _userWordsRepository.GetOldestUpdatedWords(user, count);

            foreach (var word in words)
            {
                var model = new UserWordModel(word);
                model.UpdateCurrentScore();
                await _userWordsRepository.UpdateMetrics(model.Entity);
            }
            sw.Stop();
            Botlog.Metric(user.TelegramId, nameof(UpdateCurrentScore), $"{words.Count}", sw.Elapsed);
        }
예제 #3
0
        public async Task Run()
        {
            try
            {
                await Initialize();

                (string Command, IBotCommandHandler CommandHandler)? mainMenuCommandOrNull = null;

                while (true)
                {
                    try
                    {
                        //run main scenario or mainMenuCommand
                        await HandleMainScenario(mainMenuCommandOrNull);

                        mainMenuCommandOrNull = null;
                    }
                    catch (UserAFKException)
                    {
                        return;
                    }
                    catch (ProcessInterruptedWithMenuCommand e)
                    {
                        //main scenario may be interrupted with main menu command
                        mainMenuCommandOrNull = (e.Command, e.CommandHandler);
                    }
                    catch (Exception e)
                    {
                        Botlog.WriteError(ChatIo.ChatId.Identifier, $"{ChatIo.ChatId.Username} exception: {e}", true);
                        await ChatIo.SendMessageAsync(Chat.Texts.OopsSomethingGoesWrong);

                        throw;
                    }
                }
            }
            catch (Exception e)
            {
                Botlog.WriteError(ChatIo?.ChatId?.Identifier, $"Fatal on run: {e}", true);
                throw;
            }
        }
예제 #4
0
        private async Task Initialize()
        {
            //Initialize user
            var user = await _userService.GetUserOrNull(_userInfo);

            if (user == null)
            {
                var addUserTask = _userService.AddUserFromTelegram(_userInfo);
                await ChatIo.SendMessageAsync(_settings.WelcomeMessage);

                user = await addUserTask;
                Botlog.WriteInfo($"New user {user.TelegramNick}", user.TelegramId.ToString(), true);
            }

            Chat = new ChatRoom(ChatIo, user);
            // Initialize update hooks
            _translationSelectedUpdateHook = new TranslationSelectedUpdateHook(_addWordsService, Chat);
            _wellKnownWordsUpdateHook      = new LeafWellKnownWordsUpdateHook(Chat);

            ChatIo.AddUpdateHook(_translationSelectedUpdateHook);
            ChatIo.AddUpdateHook(_wellKnownWordsUpdateHook);

            // Initialize  command handlers
            _addWordCommandHandler = new AddBotCommandHandler(_addWordsService, _translationSelectedUpdateHook);

            ChatIo.CommandHandlers = new[] {
                HelpBotCommandHandler.Instance,
                new StatsBotCommandHandler(_settings.ExamSettings),
                new LearnBotCommandHandler(_userService, _usersWordsService, _settings.ExamSettings),
                _addWordCommandHandler,
                new ShowLearningSetsBotCommandHandler(_learningSetService),
                new ShowWellLearnedWordsCommandHandler(_usersWordsService, _wellKnownWordsUpdateHook),
                new SelectLearningSet(
                    _learningSetService, _localDictionaryService, _userService, _usersWordsService, _addWordsService),
                new StartBotCommandHandler(ShowMainMenu),
                new ChlangBotCommandHandler(_userService)
            };
        }
예제 #5
0
        public async Task EnterAsync()
        {
            if (!await _usersWordsService.HasWordsFor(Chat.User))
            {
                await Chat.SendMessageAsync(Chat.Texts.NeedToAddMoreWordsBeforeLearning);

                return;
            }

            var startupScoreUpdate = _usersWordsService.UpdateCurrentScoreForRandomWords(Chat.User, _examSettings.MaxLearningWordsCountInOneExam * 2);
            var typing             = Chat.SendTyping();

            var c = Rand.RandomIn(_examSettings.MinLearningWordsCountInOneExam,
                                  _examSettings.MaxLearningWordsCountInOneExam);
            await startupScoreUpdate;
            await typing;
            var   learningWords
                = await _usersWordsService.GetWordsForLearningWithPhrasesAsync(Chat.User, c, 3);

            var learningWordsCount = learningWords.Length;

            if (learningWords.Average(w => w.AbsoluteScore) <= WordLeaningGlobalSettings.FamiliarWordMinScore)
            {
                var sb = new StringBuilder($"{Emojis.Learning} " + Chat.Texts.LearningCarefullyStudyTheListMarkdown + "\r\n\r\n```\r\n");

                foreach (var pairModel in learningWords.Shuffle())
                {
                    sb.AppendLine($"{pairModel.Word.EscapeForMarkdown()}\t\t:{pairModel.AllTranslationsAsSingleString.EscapeForMarkdown()}");
                }
                sb.AppendLine($"\r\n```\r\n\\.\\.\\. {Chat.Texts.thenClickStartMarkdown}");
                await Chat.SendMarkdownMessageAsync(sb.ToString(), new[] { new[] { new InlineKeyboardButton
                                                                                   {
                                                                                       CallbackData = "/startExamination",
                                                                                       Text         = Chat.Texts.StartButton
                                                                                   }, new InlineKeyboardButton
                                                                                   {
                                                                                       CallbackData = BotCommands.Start,
                                                                                       Text         = Chat.Texts.CancelButton,
                                                                                   } } });

                var userInput = await Chat.WaitInlineKeyboardInput();

                if (userInput != "/startExamination")
                {
                    return;
                }
            }
            var started = DateTime.Now;

            var learningAndAdvancedWords
                = (await _usersWordsService.AppendAdvancedWordsToExamList(
                       Chat.User, learningWords, _examSettings));

            var distinctLearningWords = learningAndAdvancedWords.Distinct().ToArray();

            var originWordsScore = new Dictionary <string, double>();

            foreach (var word in distinctLearningWords)
            {
                if (!originWordsScore.ContainsKey(word.Word))
                {
                    originWordsScore.Add(word.Word, word.AbsoluteScore);
                }
            }

            var gamingScoreBefore = Chat.User.GamingScore;

            var            questionsCount     = 0;
            var            questionsPassed    = 0;
            var            wordQuestionNumber = 0;
            QuestionResult lastExamResult     = null;

            foreach (var word in learningAndAdvancedWords)
            {
                var allLearningWordsWereShowedAtLeastOneTime = wordQuestionNumber < learningWordsCount;
                var question =
                    QuestionSelector.Singletone.GetNextQuestionFor(allLearningWordsWereShowedAtLeastOneTime, word);
                wordQuestionNumber++;

                var learnList = learningWords;

                if (!learningWords.Contains(word))
                {
                    learnList = learningWords.Append(word).ToArray();
                }

                if (wordQuestionNumber > 1 && question.NeedClearScreen)
                {
                    await WriteDontPeakMessage(lastExamResult?.ResultsBeforeHideousText);
                }

                Chat.User.OnAnyActivity();
                var originRate = word.Score;

                var questionMetric = new QuestionMetric(word, question.Name);
                var result         = await PassWithRetries(question, word, learnList, wordQuestionNumber);

                switch (result.Results)
                {
                case ExamResult.Passed:
                    var succTask = _usersWordsService.RegisterSuccess(word);
                    questionsCount++;
                    questionsPassed++;
                    questionMetric.OnExamFinished(word.Score, true);
                    Botlog.SaveQuestionMetricInfo(questionMetric, Chat.ChatId);
                    await succTask;
                    Chat.User.OnQuestionPassed(word.Score - originRate);
                    break;

                case ExamResult.Failed:
                    var failureTask = _usersWordsService.RegisterFailure(word);
                    questionMetric.OnExamFinished(word.Score, false);
                    Botlog.SaveQuestionMetricInfo(questionMetric, Chat.ChatId);
                    questionsCount++;
                    await failureTask;
                    Chat.User.OnQuestionFailed(word.Score - originRate);
                    break;

                case ExamResult.Retry:
                case ExamResult.Impossible:
                    throw new NotSupportedException(result.Results.ToString());
                }

                if (!string.IsNullOrWhiteSpace(result.OpenResultsText))
                {
                    await Chat.SendMarkdownMessageAsync(result.OpenResultsText);
                }

                lastExamResult = result;

                Botlog.RegisterExamInfo(Chat.User.TelegramId, started, questionsCount, questionsPassed);
            }

            Chat.User.OnLearningDone();
            var updateUserTask           = _userService.Update(Chat.User);
            var finializeScoreUpdateTask = _usersWordsService.UpdateCurrentScoreForRandomWords(Chat.User, 10);

            //info after examination
            await SendExamResultToUser(
                distinctLearningWords : distinctLearningWords,
                originWordsScore : originWordsScore,
                questionsPassed : questionsPassed,
                questionsCount : questionsCount,
                learningWords : learningWords,
                gamingScoreBefore : gamingScoreBefore);

            await updateUserTask;
            await finializeScoreUpdateTask;
        }
예제 #6
0
        public async Task EnterAsync(User user)
        {
            if (!await _usersWordsService.HasWords(user))
            {
                await _chatIo.SendMessageAsync("You need to add some more words before examination");

                return;
            }

            //Randomization and jobs
            //if (RandomTools.Rnd.Next() % 30 == 0)
            //    await _usersWordsService.AddMutualPhrasesToVocabAsync(user, 10);
            // else

            var startupScoreUpdate = _usersWordsService.UpdateCurrentScore(user, _examSettings.MaxLearningWordsCountInOneExam * 2);
            var typing             = _chatIo.SendTyping();

            var c = Random.RandomIn(_examSettings.MinLearningWordsCountInOneExam,
                                    _examSettings.MaxLearningWordsCountInOneExam);
            await startupScoreUpdate;
            await typing;
            var   learningWords
                = await _usersWordsService.GetWordsForLearningWithPhrasesAsync(user, c, 3);

            var learningWordsCount = learningWords.Length;

            if (learningWords.Average(w => w.AbsoluteScore) <= 4)
            {
                var sb = new StringBuilder("Examination\r\n");

                foreach (var pairModel in learningWords.Randomize())
                {
                    sb.AppendLine($"{pairModel.Word}\t\t:{pairModel.TranslationAsList}");
                }
                await _chatIo.SendMessageAsync(sb.ToString(), new InlineKeyboardButton
                {
                    CallbackData = "/startExamination",
                    Text         = "Start"
                }, new InlineKeyboardButton
                {
                    CallbackData = "/start",
                    Text         = "Cancel",
                });

                var userInput = await _chatIo.WaitInlineKeyboardInput();

                if (userInput != "/startExamination")
                {
                    return;
                }
            }
            var started = DateTime.Now;

            var learningAndAdvancedWords
                = await _usersWordsService.AppendAdvancedWordsToExamList(user, learningWords, _examSettings);

            var        questionsCount  = 0;
            var        questionsPassed = 0;
            var        i = 0;
            ExamResult?lastExamResult = null;

            foreach (var word in learningAndAdvancedWords)
            {
                var allLearningWordsWereShowedAtLeastOneTime = i < learningWordsCount;
                var exam = QuestionSelector.Singletone.GetNextQuestionFor(allLearningWordsWereShowedAtLeastOneTime, word);
                i++;
                var retryFlag = false;
                do
                {
                    retryFlag = false;
                    var sw             = Stopwatch.StartNew();
                    var questionMetric = new QuestionMetric(word, exam.Name);

                    var learnList = learningWords;

                    if (!learningWords.Contains(word))
                    {
                        learnList = learningWords.Append(word).ToArray();
                    }

                    if (i > 1 && exam.NeedClearScreen && lastExamResult != ExamResult.Impossible)
                    {
                        await WriteDontPeakMessage();

                        if (lastExamResult == ExamResult.Passed)
                        {
                            await WritePassed();
                        }
                    }

                    var result = await exam.Pass(_chatIo, _usersWordsService, word, learnList);

                    sw.Stop();
                    questionMetric.ElaspedMs = (int)sw.ElapsedMilliseconds;
                    switch (result)
                    {
                    case ExamResult.Impossible:
                        exam      = QuestionSelector.Singletone.GetNextQuestionFor(i == 0, word);
                        retryFlag = true;
                        break;

                    case ExamResult.Passed:
                        await WritePassed();

                        Botlog.SaveQuestionMetric(questionMetric);
                        questionsCount++;
                        questionsPassed++;
                        break;

                    case ExamResult.Failed:
                        await WriteFailed();

                        questionMetric.Result = 0;
                        Botlog.SaveQuestionMetric(questionMetric);
                        questionsCount++;
                        break;

                    case ExamResult.Retry:
                        retryFlag = true;
                        break;

                    case ExamResult.Exit: return;
                    }

                    lastExamResult = result;
                } while (retryFlag);
                Botlog.RegisterExamAsync(user.TelegramId, started, questionsCount, questionsPassed);
            }
            var finializeScoreUpdateTask = _usersWordsService.UpdateCurrentScore(user, 10);

            var doneMessage = new StringBuilder($"Learning done:  {questionsPassed}/{questionsCount}\r\n");

            foreach (var pairModel in learningAndAdvancedWords.Distinct())
            {
                doneMessage.Append(pairModel.Word + " - " + pairModel.TranslationAsList + "  (" +
                                   pairModel.AbsoluteScore + ")\r\n");
            }

            await _chatIo.SendMessageAsync(doneMessage.ToString());
        }