Ejemplo n.º 1
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;
        }