public async Task <IActionResult> InstructorsStatistics(Course course, int count = 10000, DateTime?from = null, DateTime?to = null) { if (course == null) { return(NotFound()); } if (!from.HasValue) { from = DateTime.MinValue; } if (!to.HasValue) { to = DateTime.MaxValue; } count = Math.Min(count, 10000); var instructorIds = userRolesRepo.GetListOfUsersWithCourseRole(CourseRole.Instructor, course.Id); var instructors = usersRepo.GetUsersByIds(instructorIds); var exerciseSlides = course.Slides.OfType <ExerciseSlide>().ToList(); var allSlideCheckings = await slideCheckingsRepo.GetManualCheckingQueueAsync <ManualExerciseChecking>(new ManualCheckingQueueFilterOptions { CourseId = course.Id, Count = count, OnlyChecked = null, From = @from.Value, To = to.Value, }).Include(c => c.Reviews).ToListAsync().ConfigureAwait(false); var result = new CodeReviewInstructorsStatisticsResponse { AnalyzedCodeReviewsCount = allSlideCheckings.Count, Instructors = new List <CodeReviewInstructorStatistics>() }; foreach (var instructor in instructors) { var checkingsCheckedByInstructor = allSlideCheckings.Where(c => c.IsChecked && (c.LockedById == instructor.Id || c.Reviews.Any(r => r.AuthorId == instructor.Id))).ToList(); var instructorGroups = await groupsRepo.GetMyGroupsFilterAccessibleToUserAsync(course.Id, instructor.Id).ConfigureAwait(false); var instructorGroupMemberIds = (await groupsRepo.GetGroupsMembersAsync(instructorGroups.Select(g => g.Id)).ConfigureAwait(false)).Select(m => m.UserId); var checkingQueue = allSlideCheckings.Where(c => !c.IsChecked && instructorGroupMemberIds.Contains(c.UserId)).ToList(); var comments = checkingsCheckedByInstructor.SelectMany(c => c.NotDeletedReviews).ToList(); var instructorStatistics = new CodeReviewInstructorStatistics { Instructor = BuildShortUserInfo(instructor, discloseLogin: true), Exercises = exerciseSlides.Select( slide => new CodeReviewExerciseStatistics { SlideId = slide.Id, ReviewedSubmissionsCount = checkingsCheckedByInstructor.Where(c => c.SlideId == slide.Id).DistinctBy(c => c.SubmissionId).Count(), QueueSize = checkingQueue.Count(c => c.SlideId == slide.Id), CommentsCount = comments.Count(c => c.ExerciseChecking.SlideId == slide.Id), } ) .Where(s => s.ReviewedSubmissionsCount + s.QueueSize + s.CommentsCount > 0) // Ignore empty (zeros) records .ToList() }; result.Instructors.Add(instructorStatistics); } return(Json(result)); }