public async Task <string> SubmitQuiz(string courseId, string slideIndex, string answer, bool isLti) { var intSlideIndex = int.Parse(slideIndex); var course = courseManager.GetCourse(courseId); var userId = User.Identity.GetUserId(); var slide = course.Slides[intSlideIndex]; var slideId = slide.Id; if (visitsRepo.IsPassed(userId, slideId)) { return("already answered"); } var time = DateTime.Now; var answers = JsonConvert.DeserializeObject <List <QuizAnswer> >(answer).GroupBy(x => x.QuizId); var quizBlockWithTaskCount = course.Slides[intSlideIndex].Blocks.Count(x => x is AbstractQuestionBlock); var incorrectQuizzes = new List <string>(); var fillInBlockType = typeof(FillInBlock); var allQuizInfos = new List <QuizInfoForDb>(); foreach (var ans in answers) { var quizInfos = CreateQuizInfo(course, intSlideIndex, ans); foreach (var quizInfo in quizInfos) { allQuizInfos.Add(quizInfo); if (!quizInfo.IsRightAnswer && quizInfo.QuizType == fillInBlockType) { incorrectQuizzes.Add(ans.Key); } } } var blocksInAnswerCount = allQuizInfos.Select(x => x.QuizId).Distinct().Count(); if (blocksInAnswerCount != quizBlockWithTaskCount) { return("has empty blocks"); } var score = allQuizInfos .Where(forDb => forDb.IsRightQuizBlock) .Select(forDb => forDb.QuizId) .Distinct() .Count(); foreach (var quizInfoForDb in allQuizInfos) { await userQuizzesRepo.AddUserQuiz(courseId, quizInfoForDb.IsRightAnswer, quizInfoForDb.ItemId, quizInfoForDb.QuizId, slideId, quizInfoForDb.Text, userId, time, quizInfoForDb.IsRightQuizBlock); } await visitsRepo.AddAttempt(slideId, userId, score); if (isLti) { LtiUtils.SubmitScore(slide, userId); } return(string.Join("*", incorrectQuizzes.Distinct())); }
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 = GetMaxTriesCount(courseId, slide); var quizState = GetQuizState(courseId, userId, slideId); if (!CanUserFillQuiz(quizState.Item1)) { return(new HttpStatusCodeResult(HttpStatusCode.OK, "Already answered")); } var tryIndex = quizState.Item2; metricSender.SendCount($"quiz.submit.try.{tryIndex}"); metricSender.SendCount($"quiz.submit.{courseId}.try.{tryIndex}"); metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.try.{tryIndex}"); if (slide.ManualChecking && !groupsRepo.IsManualCheckingEnabledForUser(course, userId)) { return(new HttpStatusCodeResult(HttpStatusCode.OK, "Manual checking is disabled for you")); } var time = DateTime.Now; var answers = JsonConvert.DeserializeObject <List <QuizAnswer> >(answer).GroupBy(x => x.QuizId); 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.QuizId).Distinct().Count(); if (blocksInAnswerCount != quizBlockWithTaskCount) { return(new HttpStatusCodeResult(HttpStatusCode.Forbidden, "Has empty blocks")); } using (var transaction = db.Database.BeginTransaction()) { await userQuizzesRepo.RemoveUserQuizzes(courseId, slideId, userId); foreach (var quizInfoForDb in allQuizInfos) { await userQuizzesRepo.AddUserQuiz(courseId, quizInfoForDb.IsRightAnswer, quizInfoForDb.ItemId, quizInfoForDb.QuizId, slideId, quizInfoForDb.Text, userId, time, quizInfoForDb.QuizBlockScore, quizInfoForDb.QuizBlockMaxScore); } transaction.Commit(); } if (slide.ManualChecking) { /* If this quiz is already queued for checking for this user, don't add it to queue again */ if (quizState.Item1 != QuizState.WaitForCheck) { await slideCheckingsRepo.AddQuizAttemptForManualChecking(courseId, slideId, userId); await visitsRepo.MarkVisitsAsWithManualChecking(courseId, slideId, userId); } } /* Recalculate score for quiz if this attempt is allowed. Don't recalculate score if this attempt is more then maxTriesCount */ else if (tryIndex < maxTriesCount) { var score = allQuizInfos .DistinctBy(forDb => forDb.QuizId) .Sum(forDb => forDb.QuizBlockScore); metricSender.SendCount($"quiz.submit.try.{tryIndex}.score", score); metricSender.SendCount($"quiz.submit.{courseId}.try.{tryIndex}.score", score); metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.try.{tryIndex}.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.{tryIndex}.full_passed"); metricSender.SendCount($"quiz.submit.{courseId}.try.{tryIndex}.full_passed"); metricSender.SendCount($"quiz.submit.{courseId}.{slideId}.try.{tryIndex}.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.AddQuizAttemptWithAutomaticChecking(courseId, slideId, userId, score); await visitsRepo.UpdateScoreForVisit(courseId, slideId, userId); if (isLti) { LtiUtils.SubmitScore(courseId, slide, userId); } } return(Json(new { url = Url.RouteUrl("Course.SlideById", new { courseId = courseId, slideId = slide.Url, send = 1 }) })); }
public async Task <ActionResult> SubmitQuiz(string courseId, Guid slideId, string answer, bool isLti) { var course = courseManager.GetCourse(courseId); var slide = course.FindSlideById(slideId) as QuizSlide; if (slide == null) { return(new HttpNotFoundResult()); } var userId = User.Identity.GetUserId(); var maxDropCount = GetMaxDropCount(slide); var quizState = GetQuizState(courseId, userId, slideId, maxDropCount).Item1; if (!CanUserFillQuiz(quizState)) { return(new HttpStatusCodeResult(HttpStatusCode.OK, "Already answered")); } if (slide.ManualChecking && !groupsRepo.IsManualCheckingEnabledForUser(course, userId)) { return(new HttpStatusCodeResult(HttpStatusCode.OK, "Manual checking is disabled for you")); } var time = DateTime.Now; var answers = JsonConvert.DeserializeObject <List <QuizAnswer> >(answer).GroupBy(x => x.QuizId); 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.QuizId).Distinct().Count(); if (blocksInAnswerCount != quizBlockWithTaskCount) { return(new HttpStatusCodeResult(HttpStatusCode.Forbidden, "Has empty blocks")); } using (var transaction = db.Database.BeginTransaction()) { await userQuizzesRepo.RemoveUserQuizzes(courseId, slideId, userId); foreach (var quizInfoForDb in allQuizInfos) { await userQuizzesRepo.AddUserQuiz(courseId, quizInfoForDb.IsRightAnswer, quizInfoForDb.ItemId, quizInfoForDb.QuizId, slideId, quizInfoForDb.Text, userId, time, quizInfoForDb.QuizBlockScore, quizInfoForDb.QuizBlockMaxScore); } transaction.Commit(); } if (slide.ManualChecking) { /* If this quiz is already queued for checking for this user, don't add it to queue again */ if (quizState != QuizState.WaitForCheck) { await slideCheckingsRepo.AddQuizAttemptForManualChecking(courseId, slideId, userId); await visitsRepo.MarkVisitsAsWithManualChecking(slideId, userId); } } else { var score = allQuizInfos .DistinctBy(forDb => forDb.QuizId) .Sum(forDb => forDb.QuizBlockScore); await slideCheckingsRepo.AddQuizAttemptWithAutomaticChecking(courseId, slideId, userId, score); await visitsRepo.UpdateScoreForVisit(courseId, slideId, userId); if (isLti) { LtiUtils.SubmitScore(slide, userId); } } return(new HttpStatusCodeResult(HttpStatusCode.OK)); }