Exemple #1
0
        public async Task <ActionResult> SubmitQuiz(string courseId, Guid slideId, string answer, bool isLti)
        {
            metricSender.SendCount("quiz.submit");
            if (isLti)
            {
                metricSender.SendCount("quiz.submit.lti");
            }
            metricSender.SendCount($"quiz.submit.{courseId}");
            metricSender.SendCount($"quiz.submit.{courseId}.{slideId}");

            var course = courseManager.GetCourse(courseId);
            var slide  = course.FindSlideById(slideId) as QuizSlide;

            if (slide == null)
            {
                return(new HttpNotFoundResult());
            }

            var userId        = User.Identity.GetUserId();
            var maxTriesCount = GetMaxAttemptsCount(courseId, slide);

            /* Not it's not important what user's score is, so just pass 0 */
            var state = GetQuizState(courseId, userId, slideId, 0, slide.MaxScore);

            if (!CanUserFillQuiz(state.Status))
            {
                return(new HttpStatusCodeResult(HttpStatusCode.OK, "Already answered"));
            }

            var attemptNumber = state.UsedAttemptsCount;

            metricSender.SendCount($"quiz.submit.try.{attemptNumber}");
            metricSender.SendCount($"quiz.submit.{courseId}.try.{attemptNumber}");
            metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.try.{attemptNumber}");

            if (slide.ManualChecking && !groupsRepo.IsManualCheckingEnabledForUser(course, userId))
            {
                return(new HttpStatusCodeResult(HttpStatusCode.OK, "Manual checking is disabled for you"));
            }

            var answers = JsonConvert.DeserializeObject <List <QuizAnswer> >(answer).GroupBy(x => x.BlockId);
            var quizBlockWithTaskCount = slide.Blocks.Count(x => x is AbstractQuestionBlock);
            var allQuizInfos           = new List <QuizInfoForDb>();

            foreach (var ans in answers)
            {
                var quizInfos = CreateQuizInfo(slide, ans);
                if (quizInfos != null)
                {
                    allQuizInfos.AddRange(quizInfos);
                }
            }

            var blocksInAnswerCount = allQuizInfos.Select(x => x.BlockId).Distinct().Count();

            if (blocksInAnswerCount != quizBlockWithTaskCount)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.Forbidden, "Has empty blocks"));
            }

            UserQuizSubmission submission;

            using (var transaction = db.Database.BeginTransaction())
            {
                submission = await userQuizzesRepo.AddSubmission(courseId, slideId, userId, DateTime.Now).ConfigureAwait(false);

                foreach (var quizInfoForDb in allQuizInfos)
                {
                    await userQuizzesRepo.AddUserQuizAnswer(
                        submission.Id,
                        quizInfoForDb.IsRightAnswer,
                        quizInfoForDb.BlockId,
                        quizInfoForDb.ItemId,
                        quizInfoForDb.Text,
                        quizInfoForDb.QuizBlockScore,
                        quizInfoForDb.QuizBlockMaxScore
                        ).ConfigureAwait(false);
                }

                transaction.Commit();
            }

            if (slide.ManualChecking)
            {
                /* If this quiz is already queued for checking for this user, remove waiting checkings */
                if (state.Status == QuizStatus.WaitsForManualChecking)
                {
                    await slideCheckingsRepo.RemoveWaitingManualCheckings <ManualQuizChecking>(courseId, slideId, userId).ConfigureAwait(false);
                }

                await slideCheckingsRepo.AddManualQuizChecking(submission, courseId, slideId, userId).ConfigureAwait(false);

                await visitsRepo.MarkVisitsAsWithManualChecking(courseId, slideId, userId).ConfigureAwait(false);
            }
            /* Recalculate score for quiz if this attempt is allowed. Don't recalculate score if this attempt number is more then maxTriesCount */
            else if (attemptNumber < maxTriesCount)
            {
                var score = allQuizInfos
                            .DistinctBy(forDb => forDb.BlockId)
                            .Sum(forDb => forDb.QuizBlockScore);

                metricSender.SendCount($"quiz.submit.try.{attemptNumber}.score", score);
                metricSender.SendCount($"quiz.submit.{courseId}.try.{attemptNumber}.score", score);
                metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.try.{attemptNumber}.score", score);
                metricSender.SendCount($"quiz.submit.score", score);
                metricSender.SendCount($"quiz.submit.{courseId}.score", score);
                metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.score", score);

                if (score == slide.MaxScore)
                {
                    metricSender.SendCount($"quiz.submit.try.{attemptNumber}.full_passed");
                    metricSender.SendCount($"quiz.submit.{courseId}.try.{attemptNumber}.full_passed");
                    metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.try.{attemptNumber}.full_passed");
                    metricSender.SendCount($"quiz.submit.full_passed");
                    metricSender.SendCount($"quiz.submit.{courseId}.full_passed");
                    metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.full_passed");
                }

                await slideCheckingsRepo.AddAutomaticQuizChecking(submission, courseId, slideId, userId, score).ConfigureAwait(false);

                await visitsRepo.UpdateScoreForVisit(courseId, slideId, slide.MaxScore, userId).ConfigureAwait(false);

                if (isLti)
                {
                    LtiUtils.SubmitScore(courseId, slide, userId);
                }
            }

            return(Json(new
            {
                url = Url.RouteUrl("Course.SlideById", new { courseId = courseId, slideId = slide.Url, send = 1 })
            }));
        }