Exemple #1
0
        public async Task <ActionResult> AddExerciseCodeReview(string courseId, int checkingId, [FromBody] ReviewInfo reviewInfo)
        {
            var checking = slideCheckingsRepo.FindManualCheckingById <ManualExerciseChecking>(checkingId);

            if (!string.Equals(checking.CourseId, courseId, StringComparison.OrdinalIgnoreCase))
            {
                return(new HttpStatusCodeResult(HttpStatusCode.Forbidden));
            }

            /* Make start position less than finish position */
            if (reviewInfo.StartLine > reviewInfo.FinishLine || (reviewInfo.StartLine == reviewInfo.FinishLine && reviewInfo.StartPosition > reviewInfo.FinishPosition))
            {
                var tmp = reviewInfo.StartLine;
                reviewInfo.StartLine  = reviewInfo.FinishLine;
                reviewInfo.FinishLine = tmp;

                tmp = reviewInfo.StartPosition;
                reviewInfo.StartPosition  = reviewInfo.FinishPosition;
                reviewInfo.FinishPosition = tmp;
            }

            var review = await slideCheckingsRepo.AddExerciseCodeReview(checking, User.Identity.GetUserId(), reviewInfo.StartLine, reviewInfo.StartPosition, reviewInfo.FinishLine, reviewInfo.FinishPosition, reviewInfo.Comment);

            return(PartialView("_ExerciseReview", new ExerciseCodeReviewModel
            {
                Review = review,
                ManualChecking = checking,
            }));
        }
Exemple #2
0
        public async Task <ActionResult> ScoreQuiz(int id, string nextUrl, string errorUrl = "")
        {
            metricSender.SendCount("quiz.manual_score");

            if (string.IsNullOrEmpty(errorUrl))
            {
                errorUrl = nextUrl;
            }

            using (var transaction = db.Database.BeginTransaction())
            {
                var checking = slideCheckingsRepo.FindManualCheckingById <ManualQuizChecking>(id);

                if (checking.IsChecked)
                {
                    return(Redirect(errorUrl + "Эта работа уже была проверена"));
                }

                if (!checking.IsLockedBy(User.Identity))
                {
                    return(Redirect(errorUrl + "Эта работа проверяется другим инструктором"));
                }

                var course = courseManager.GetCourse(checking.CourseId);
                var unit   = course.FindUnitBySlideId(checking.SlideId);

                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}");
                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.{checking.SlideId}");

                var answers = userQuizzesRepo.GetAnswersForUser(checking.CourseId, checking.SlideId, checking.UserId);

                QuizVersion quizVersion;
                /* If there is no user's answers for quiz, get the latest quiz version */
                if (answers.Count == 0)
                {
                    quizVersion = quizzesRepo.GetLastQuizVersion(checking.CourseId, checking.SlideId);
                }
                else
                {
                    var firstAnswer = answers.FirstOrDefault().Value.FirstOrDefault();
                    quizVersion = firstAnswer != null
                                                ? firstAnswer.QuizVersion
                                                : quizzesRepo.GetFirstQuizVersion(checking.CourseId, checking.SlideId);
                }

                var totalScore = 0;

                var quiz = quizVersion.GetRestoredQuiz(course, unit);
                foreach (var question in quiz.Blocks.OfType <AbstractQuestionBlock>())
                {
                    var scoreFieldName = "quiz__score__" + question.Id;
                    var scoreStr       = Request.Form[scoreFieldName];
                    /* Invalid form: score isn't integer */
                    if (!int.TryParse(scoreStr, out var score))
                    {
                        return(Redirect(errorUrl + $"Неверное количество баллов в задании «{question.QuestionIndex}. {question.Text.TruncateWithEllipsis(50)}»"));
                    }
                    /* Invalid form: score isn't from range 0..MAX_SCORE */
                    if (score < 0 || score > question.MaxScore)
                    {
                        return(Redirect(errorUrl + $"Неверное количество баллов в задании «{question.QuestionIndex}. {question.Text.TruncateWithEllipsis(50)}»: {score}"));
                    }

                    await userQuizzesRepo.SetScoreForQuizBlock(checking.CourseId, checking.UserId, checking.SlideId, question.Id, score);

                    totalScore += score;
                }

                await slideCheckingsRepo.MarkManualCheckingAsChecked(checking, totalScore);

                await visitsRepo.UpdateScoreForVisit(checking.CourseId, checking.SlideId, checking.UserId);

                transaction.Commit();

                metricSender.SendCount($"quiz.manual_score.score", totalScore);
                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.score", totalScore);
                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.{checking.SlideId}.score", totalScore);
                if (totalScore == quiz.MaxScore)
                {
                    metricSender.SendCount($"quiz.manual_score.full_scored");
                    metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.full_scored");
                    metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.{checking.SlideId}.full_scored");
                }

                await NotifyAboutManualQuizChecking(checking);
            }

            return(Redirect(nextUrl));
        }
Exemple #3
0
        public async Task <ActionResult> SlideById(string courseId, string slideId = "", int?checkQueueItemId = null, int?version = null, int autoplay = 0)
        {
            if (slideId.Contains("_"))
            {
                slideId = slideId.Substring(slideId.LastIndexOf('_') + 1);
            }

            var groupsIds = Request.GetMultipleValuesFromQueryString("group");

            if (!Guid.TryParse(slideId, out var slideGuid))
            {
                return(HttpNotFound());
            }

            if (string.IsNullOrWhiteSpace(courseId))
            {
                if (string.IsNullOrWhiteSpace(slideId))
                {
                    return(RedirectToAction("Index", "Home"));
                }

                return(RedirectToSlideById(slideGuid));
            }

            var course = courseManager.FindCourse(courseId);

            if (course == null)
            {
                return(HttpNotFound());
            }

            var visibleUnits = unitsRepo.GetVisibleUnits(course, User);
            var isGuest      = !User.Identity.IsAuthenticated;

            var slide = slideGuid == Guid.Empty ? GetInitialSlideForStartup(courseId, visibleUnits) : course.FindSlideById(slideGuid);

            if (slide == null)
            {
                return(HttpNotFound());
            }

            AbstractManualSlideChecking queueItem = null;
            var isManualCheckingReadonly          = false;

            if (User.HasAccessFor(courseId, CourseRole.Instructor) && checkQueueItemId != null)
            {
                if (slide is QuizSlide)
                {
                    queueItem = slideCheckingsRepo.FindManualCheckingById <ManualQuizChecking>(checkQueueItemId.Value);
                }
                if (slide is ExerciseSlide)
                {
                    queueItem = slideCheckingsRepo.FindManualCheckingById <ManualExerciseChecking>(checkQueueItemId.Value);
                }

                if (queueItem == null)
                {
                    /* It's possible when checking has not been fully checked, lock has been released, but after it user re-send his solution and we removed old waiting checking */
                    var fakeQueueItem = slide is QuizSlide ? (AbstractManualSlideChecking) new ManualQuizChecking() : new ManualExerciseChecking();
                    return(RedirectToAction("CheckingQueue", "Admin", new
                    {
                        courseId = courseId,
                        message = "checking_removed"
                    }));
                }
            }

            var model = isGuest ?
                        CreateGuestCoursePageModel(course, slide, autoplay > 0) :
                        await CreateCoursePageModel(course, slide, queueItem, version, groupsIds, autoplay > 0, isManualCheckingReadonly);

            if (!string.IsNullOrEmpty(Request.QueryString["error"]))
            {
                model.Error = Request.QueryString["error"];
            }

            if (!visibleUnits.Contains(model.Slide.Info.Unit))
            {
                return(HttpNotFound("Slide is hidden " + slideGuid));
            }
            return(View("Slide", model));
        }
Exemple #4
0
        public async Task <ActionResult> ScoreQuiz(int id, string nextUrl, string errorUrl = "")
        {
            metricSender.SendCount("quiz.manual_score");

            if (string.IsNullOrEmpty(errorUrl))
            {
                errorUrl = nextUrl;
            }

            using (var transaction = db.Database.BeginTransaction())
            {
                var checking = slideCheckingsRepo.FindManualCheckingById <ManualQuizChecking>(id);

                var course = courseManager.GetCourse(checking.CourseId);
                var unit   = course.FindUnitBySlideId(checking.SlideId);
                var slide  = course.GetSlideById(checking.SlideId);

                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}");
                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.{checking.SlideId}");

                var totalScore = 0;

                var quiz = course.FindSlideById(checking.SlideId);
                if (quiz == null)
                {
                    return(Redirect(errorUrl + "Этого теста больше нет в курсе"));
                }

                foreach (var question in quiz.Blocks.OfType <AbstractQuestionBlock>())
                {
                    var scoreFieldName = "quiz__score__" + question.Id;
                    var scoreStr       = Request.Form[scoreFieldName];
                    /* Invalid form: score isn't integer */
                    if (!int.TryParse(scoreStr, out var score))
                    {
                        return(Redirect(errorUrl + $"Неверное количество баллов в задании «{question.QuestionIndex}. {question.Text.TruncateWithEllipsis(50)}»"));
                    }
                    /* Invalid form: score isn't from range 0..MAX_SCORE */
                    if (score < 0 || score > question.MaxScore)
                    {
                        return(Redirect(errorUrl + $"Неверное количество баллов в задании «{question.QuestionIndex}. {question.Text.TruncateWithEllipsis(50)}»: {score}"));
                    }

                    await userQuizzesRepo.SetScoreForQuizBlock(checking.Submission.Id, question.Id, score).ConfigureAwait(false);

                    totalScore += score;
                }

                await slideCheckingsRepo.MarkManualCheckingAsChecked(checking, totalScore).ConfigureAwait(false);

                await visitsRepo.UpdateScoreForVisit(checking.CourseId, checking.SlideId, slide.MaxScore, checking.UserId).ConfigureAwait(false);

                transaction.Commit();

                metricSender.SendCount($"quiz.manual_score.score", totalScore);
                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.score", totalScore);
                metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.{checking.SlideId}.score", totalScore);
                if (totalScore == quiz.MaxScore)
                {
                    metricSender.SendCount($"quiz.manual_score.full_scored");
                    metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.full_scored");
                    metricSender.SendCount($"quiz.manual_score.{checking.CourseId}.{checking.SlideId}.full_scored");
                }

                if (unit != null && unitsRepo.IsUnitVisibleForStudents(course, unit.Id))
                {
                    await NotifyAboutManualQuizChecking(checking).ConfigureAwait(false);
                }
            }

            return(Redirect(nextUrl));
        }
Exemple #5
0
        public async Task <ActionResult> SlideById(string courseId, string slideId = "", int?checkQueueItemId = null, int?version = null, int autoplay = 0)
        {
            if (slideId.Contains("_"))
            {
                slideId = slideId.Substring(slideId.LastIndexOf('_') + 1);
            }

            var groupsIds = Request.GetMultipleValues("group");

            Guid slideGuid;

            if (!Guid.TryParse(slideId, out slideGuid))
            {
                return(HttpNotFound());
            }

            if (string.IsNullOrWhiteSpace(courseId))
            {
                if (string.IsNullOrWhiteSpace(slideId))
                {
                    return(RedirectToAction("Index", "Home"));
                }

                return(RedirectToSlideById(slideGuid));
            }

            var course = courseManager.FindCourse(courseId);

            if (course == null)
            {
                return(HttpNotFound());
            }

            var visibleUnits = unitsRepo.GetVisibleUnits(course, User);
            var isGuest      = !User.Identity.IsAuthenticated;

            var slide = slideGuid == Guid.Empty ? GetInitialSlideForStartup(courseId, course, visibleUnits) : course.FindSlideById(slideGuid);

            if (slide == null)
            {
                return(HttpNotFound());
            }

            AbstractManualSlideChecking queueItem = null;
            var isManualCheckingReadonly          = false;

            if (User.HasAccessFor(courseId, CourseRole.Instructor) && checkQueueItemId != null)
            {
                if (slide is QuizSlide)
                {
                    queueItem = slideCheckingsRepo.FindManualCheckingById <ManualQuizChecking>(checkQueueItemId.Value);
                }
                if (slide is ExerciseSlide)
                {
                    queueItem = slideCheckingsRepo.FindManualCheckingById <ManualExerciseChecking>(checkQueueItemId.Value);
                }

                if (queueItem == null)
                {
                    return(HttpNotFound());
                }

                /* If lock time is finished */
                if (!queueItem.IsLockedBy(User.Identity) && queueItem.HasLastLockedBy(User.Identity))
                {
                    return(RedirectToAction(GetAdminQueueActionName(queueItem), "Admin", new
                    {
                        CourseId = courseId,
                        group = string.Join(",", groupsIds),
                        done = queueItem.IsChecked,
                        message = "time_is_over",
                    }));
                }

                /* If it's not locked then lock them! */
                if (!queueItem.IsLocked)
                {
                    return(RedirectToAction(GetAdminCheckActionName(queueItem), "Admin", new
                    {
                        CourseId = courseId,
                        group = string.Join(",", groupsIds),
                        id = queueItem.Id,
                        recheck = true
                    }));
                }

                if (queueItem.IsLocked && !queueItem.IsLockedBy(User.Identity))
                {
                    isManualCheckingReadonly = true;
                }
            }

            var model = isGuest ?
                        CreateGuestCoursePageModel(course, slide, autoplay > 0) :
                        await CreateCoursePageModel(course, slide, queueItem, version, groupsIds, autoplay > 0, isManualCheckingReadonly);

            if (!string.IsNullOrEmpty(Request.QueryString["error"]))
            {
                model.Error = Request.QueryString["error"];
            }

            if (!visibleUnits.Contains(model.Slide.Info.Unit))
            {
                return(HttpNotFound("Slide is hidden " + slideGuid));
            }
            return(View("Slide", model));
        }