private UserModel GetUserModel(UserRolesInfo userRoles, Dictionary <string, Dictionary <CourseRole, List <string> > > coursesForUsers, List <string> coursesIds, HashSet <string> tempCoursesIds) { var user = new UserModel(userRoles) { CourseRoles = new Dictionary <string, ICoursesRolesListModel> { { LmsRoles.SysAdmin.ToString(), new SingleCourseRolesModel { HasAccess = userRoles.Roles.Contains(LmsRoles.SysAdmin.ToString()), ToggleUrl = Url.Content($"~/Account/{nameof(ToggleSystemRole)}?userId={userRoles.UserId}&role={LmsRoles.SysAdmin}"), // Url.Action is slow: https://www.jitbit.com/alexblog/263-fastest-way-to-generate-urls-in-an-aspnet-mvc-app/ } } } }; if (!coursesForUsers.TryGetValue(userRoles.UserId, out var coursesForUser)) { coursesForUser = new Dictionary <CourseRole, List <string> >(); } foreach (var role in Enum.GetValues(typeof(CourseRole)).Cast <CourseRole>().Where(roles => roles != CourseRole.Student)) { user.CourseRoles[role.ToString()] = new ManyCourseRolesModel { CourseRoles = coursesIds .Select(s => new CourseRoleModel { Role = role, CourseId = s, CourseTitle = courseManager.GetCourse(s).Title, HasAccess = coursesForUser.ContainsKey(role) && coursesForUser[role].Contains(s.ToLower()), ToggleUrl = Url.Content($"~/Account/{nameof(ToggleRole)}?courseId={s}&userId={user.UserId}&role={role}"), UserName = user.UserVisibleName, IsTempCourse = tempCoursesIds.Contains(s) }) .OrderBy(s => s.CourseTitle, StringComparer.InvariantCultureIgnoreCase) .ToList() }; } var systemAccesses = systemAccessesRepo.GetSystemAccesses(user.UserId).Select(a => a.AccessType); user.SystemAccesses = Enum.GetValues(typeof(SystemAccessType)) .Cast <SystemAccessType>() .ToDictionary( a => a, a => new SystemAccessModel { HasAccess = systemAccesses.Contains(a), ToggleUrl = Url.Content($"~/Account/{nameof(ToggleSystemAccess)}?userId={user.UserId}&accessType={a}"), UserName = user.UserVisibleName, } ); return(user); }
private async Task <AutomaticExerciseChecking> UpdateAutomaticExerciseChecking(AutomaticExerciseChecking checking, RunningResults result) { var compilationErrorHash = (await textsRepo.AddText(result.CompilationOutput)).Hash; var output = result.GetOutput().NormalizeEoln(); var outputHash = (await textsRepo.AddText(output)).Hash; var isWebRunner = checking.CourseId == "web" && checking.SlideId == Guid.Empty; var exerciseSlide = isWebRunner ? null : (ExerciseSlide)courseManager.GetCourse(checking.CourseId).GetSlideById(checking.SlideId, true); var isRightAnswer = IsRightAnswer(result, output, exerciseSlide?.Exercise); var elapsed = DateTime.Now - checking.Timestamp; elapsed = elapsed < TimeSpan.FromDays(1) ? elapsed : new TimeSpan(0, 23, 59, 59); var newChecking = new AutomaticExerciseChecking { Id = checking.Id, CourseId = checking.CourseId, SlideId = checking.SlideId, UserId = checking.UserId, Timestamp = checking.Timestamp, CompilationErrorHash = compilationErrorHash, IsCompilationError = result.Verdict == Verdict.CompilationError, OutputHash = outputHash, ExecutionServiceName = checking.ExecutionServiceName, Status = AutomaticExerciseCheckingStatus.Done, DisplayName = checking.DisplayName, Elapsed = elapsed, IsRightAnswer = isRightAnswer, CheckingAgentName = checking.CheckingAgentName, Points = result.Points }; return(newChecking); }
private async Task AddManualCheckingsForOldSolutions(string courseId, string userId) { log.Info($"Создаю ручные проверки для всех решения пользователя {userId} в курсе {courseId}"); var course = courseManager.GetCourse(courseId); /* For exercises */ var acceptedSubmissionsBySlide = userSolutionsRepo.GetAllAcceptedSubmissionsByUser(courseId, userId) .ToList() .GroupBy(s => s.SlideId) .ToDictionary(g => g.Key, g => g.ToList()); foreach (var acceptedSubmissionsForSlide in acceptedSubmissionsBySlide.Values) { /* If exists at least one manual checking for at least one submissions on slide, then ignore this slide */ if (!acceptedSubmissionsForSlide.Any(s => s.ManualCheckings.Any())) { /* Otherwise found the latest accepted submission */ var lastSubmission = acceptedSubmissionsForSlide.OrderByDescending(s => s.Timestamp).First(); var slideId = lastSubmission.SlideId; var slide = course.FindSlideById(slideId, false) as ExerciseSlide; if (slide == null || !slide.Scoring.RequireReview) { continue; } log.Info($"Создаю ручную проверку для решения {lastSubmission.Id}, слайд {slideId}"); await slideCheckingsRepo.AddManualExerciseChecking(courseId, slideId, userId, lastSubmission).ConfigureAwait(false); await visitsRepo.MarkVisitsAsWithManualChecking(courseId, slideId, userId).ConfigureAwait(false); } } /* For quizzes */ var passedQuizzesIds = userQuizzesRepo.GetPassedSlideIds(courseId, userId); foreach (var quizSlideId in passedQuizzesIds) { var slide = course.FindSlideById(quizSlideId, false) as QuizSlide; if (slide == null || !slide.ManualChecking) { continue; } if (!userQuizzesRepo.IsWaitingForManualCheck(courseId, quizSlideId, userId)) { log.Info($"Создаю ручную проверку для теста {slide.Id}"); var submission = userQuizzesRepo.FindLastUserSubmission(courseId, quizSlideId, userId); if (submission == null || submission.ManualChecking != null) { continue; } await slideCheckingsRepo.AddManualQuizChecking(submission, courseId, quizSlideId, userId).ConfigureAwait(false); await visitsRepo.MarkVisitsAsWithManualChecking(courseId, quizSlideId, userId).ConfigureAwait(false); } } }
public ActionResult GetDetails(int id) { var submission = solutionsRepo.FindNoTrackingSubmission(id); if (submission == null) { return(HttpNotFound()); } submission.SolutionCode.Text = ((ExerciseSlide)courseManager .GetCourse(submission.CourseId) .GetSlideById(submission.SlideId, true)) .Exercise .GetSourceCode(submission.SolutionCode.Text); return(View(submission)); }
public HashSet <string> GetVisibleCourses() { var appearances = db.UnitAppearances .Where(u => u.PublishTime <= DateTime.Now) .Select(u => new { u.CourseId, u.UnitId }) .AsEnumerable() .GroupBy(p => p.CourseId) .Where(g => courseManager.FindCourse(g.Key) != null) .Where(g => { var units = courseManager.GetCourse(g.Key).GetUnitsNotSafe().Select(u => u.Id).ToHashSet(); units.IntersectWith(g.Select(p => p.UnitId)); return(units.Any()); }) .Select(g => g.Key); return(new HashSet <string>(appearances, StringComparer.OrdinalIgnoreCase)); }
private async Task <AutomaticExerciseChecking> UpdateAutomaticExerciseChecking(AutomaticExerciseChecking checking, RunningResults result) { var compilationErrorHash = (await textsRepo.AddText(result.CompilationOutput)).Hash; var output = result.GetOutput().NormalizeEoln(); var outputHash = (await textsRepo.AddText(output)).Hash; var isWebRunner = checking.CourseId == "web" && checking.SlideId == Guid.Empty; var exerciseSlide = isWebRunner ? null : (ExerciseSlide)courseManager.GetCourse(checking.CourseId).GetSlideById(checking.SlideId); var expectedOutput = exerciseSlide?.Exercise.ExpectedOutput.NormalizeEoln(); var isRightAnswer = result.Verdict == Verdict.Ok && output.Equals(expectedOutput); var score = isRightAnswer ? exerciseSlide.Exercise.CorrectnessScore : 0; /* For skipped slides score is always 0 */ if (visitsRepo.IsSkipped(checking.CourseId, checking.SlideId, checking.UserId)) { score = 0; } var newChecking = new AutomaticExerciseChecking { Id = checking.Id, CourseId = checking.CourseId, SlideId = checking.SlideId, UserId = checking.UserId, Timestamp = checking.Timestamp, CompilationErrorHash = compilationErrorHash, IsCompilationError = result.Verdict == Verdict.CompilationError, OutputHash = outputHash, ExecutionServiceName = checking.ExecutionServiceName, Status = AutomaticExerciseCheckingStatus.Done, DisplayName = checking.DisplayName, Elapsed = DateTime.Now - checking.Timestamp, IsRightAnswer = isRightAnswer, Score = score, }; return(newChecking); }
public async Task <ActionResult> LtiSlide(string courseId, Guid slideId) { if (string.IsNullOrWhiteSpace(courseId)) { return(RedirectToAction("Index", "Home")); } var course = courseManager.GetCourse(courseId); var slide = course.GetSlideById(slideId, false); string userId; var owinRequest = Request.GetOwinContext().Request; if (await owinRequest.IsAuthenticatedLtiRequestAsync()) { var ltiRequest = await owinRequest.ParseLtiRequestAsync(); log.Info($"Нашёл LTI request в запросе: {ltiRequest.JsonSerialize()}"); userId = Request.GetOwinContext().Authentication.AuthenticationResponseGrant.Identity.GetUserId(); await ltiRequestsRepo.Update(courseId, userId, slide.Id, ltiRequest.JsonSerialize()); /* Substitute http(s) scheme with real scheme from header */ var uriBuilder = new UriBuilder(ltiRequest.Url) { Scheme = owinRequest.GetRealRequestScheme(), Port = owinRequest.GetRealRequestPort() }; return(Redirect(uriBuilder.Uri.AbsoluteUri)); } /* For now user should be authenticated */ if (!User.Identity.IsAuthenticated) { return(new HttpStatusCodeResult(HttpStatusCode.Forbidden)); } userId = User.Identity.GetUserId(); var visit = await VisitSlide(courseId, slide.Id, userId); /* Try to send score via LTI immediately after slide visiting */ try { if (visit.IsPassed) { LtiUtils.SubmitScore(courseId, slide, userId, visit); } } catch (Exception e) { ErrorLog.GetDefault(System.Web.HttpContext.Current).Log(new Error(e)); } var exerciseSlide = slide as ExerciseSlide; if (exerciseSlide != null) { var model = new CodeModel { CourseId = courseId, SlideId = exerciseSlide.Id, ExerciseBlock = exerciseSlide.Exercise, Context = CreateRenderContext(course, exerciseSlide, isLti: true) }; return(View("LtiExerciseSlide", model)); } var quizSlide = slide as QuizSlide; if (quizSlide != null) { var model = new LtiQuizModel { CourseId = courseId, Slide = quizSlide, UserId = userId }; return(View("LtiQuizSlide", model)); } return(View()); }