コード例 #1
0
ファイル: AnalyticsController.cs プロジェクト: epeshk/uLearn
        public ActionResult UnitStatistics(UnitStatisticsParams param)
        {
            const int usersLimit = 200;

            var courseId     = param.CourseId;
            var unitId       = param.UnitId;
            var periodStart  = param.PeriodStartDate;
            var periodFinish = param.PeriodFinishDate;
            var groupsIds    = Request.GetMultipleValues("group");

            var realPeriodFinish = periodFinish.Add(TimeSpan.FromDays(1));

            var course = courseManager.GetCourse(courseId);

            if (!unitId.HasValue)
            {
                return(View("UnitStatisticsList", new UnitStatisticPageModel
                {
                    Course = course,
                    Units = course.Units,
                }));
            }
            var selectedUnit = course.GetUnitById(unitId.Value);
            var slides       = selectedUnit.Slides;
            var slidesIds    = slides.Select(s => s.Id).ToList();
            var quizzes      = slides.OfType <QuizSlide>();
            var exersices    = slides.OfType <ExerciseSlide>();

            var groups        = groupsRepo.GetAvailableForUserGroups(courseId, User);
            var filterOptions = ControllerUtils.GetFilterOptionsByGroup <VisitsFilterOptions>(groupsRepo, User, courseId, groupsIds);

            filterOptions.SlidesIds    = slidesIds;
            filterOptions.PeriodStart  = periodStart;
            filterOptions.PeriodFinish = realPeriodFinish;

            /* Dictionary<SlideId, List<Visit>> */
            var slidesVisits = visitsRepo.GetVisitsInPeriodForEachSlide(filterOptions);

            var usersVisitedAllSlidesBeforePeriodCount         = visitsRepo.GetUsersVisitedAllSlides(filterOptions.WithPeriodStart(DateTime.MinValue).WithPeriodFinish(periodStart)).Count();
            var usersVisitedAllSlidesInPeriodCount             = visitsRepo.GetUsersVisitedAllSlides(filterOptions).Count();
            var usersVisitedAllSlidesBeforePeriodFinishedCount = visitsRepo.GetUsersVisitedAllSlides(filterOptions.WithPeriodStart(DateTime.MinValue)).Count();

            var quizzesAverageScore = quizzes.ToDictionary(q => q.Id,
                                                           q => (int)slidesVisits.GetOrDefault(q.Id, new List <Visit>())
                                                           .Where(v => v.IsPassed)
                                                           .Select(v => 100 * Math.Min(v.Score, q.MaxScore) / (q.MaxScore != 0 ? q.MaxScore : 1))
                                                           .DefaultIfEmpty(-1)
                                                           .Average()
                                                           );

            /* Dictionary<SlideId, count (distinct by user)> */
            var exercisesSolutionsCount = userSolutionsRepo.GetAllSubmissions(courseId, slidesIds, periodStart, realPeriodFinish)
                                          .GroupBy(s => s.SlideId)
                                          .ToDictionary(g => g.Key, g => g.DistinctBy(s => s.UserId).Count());

            var exercisesAcceptedSolutionsCount = userSolutionsRepo.GetAllAcceptedSubmissions(courseId, slidesIds, periodStart, realPeriodFinish)
                                                  .GroupBy(s => s.SlideId)
                                                  .ToDictionary(g => g.Key, g => g.DistinctBy(s => s.UserId).Count());

            var usersIds = visitsRepo.GetVisitsInPeriod(filterOptions).DistinctBy(v => v.UserId).Select(v => v.UserId);

            /* If we filtered out users from one or several groups show them all */
            if (filterOptions.UsersIds != null && !filterOptions.IsUserIdsSupplement)
            {
                usersIds = filterOptions.UsersIds;
            }
            var visitedUsers = usersIds
                               .Join(db.Users, v => v, u => u.Id, (v, u) => new UnitStatisticUserInfo {
                UserId = u.Id, UserName = u.UserName, UserVisibleName = (u.LastName + u.FirstName != "" ? u.LastName + " " + u.FirstName : u.UserName).Trim()
            })
                               .ToList();
            var isMore = visitedUsers.Count > usersLimit;

            var visitedSlidesCountByUser = visitsRepo.GetVisitsInPeriod(filterOptions)
                                           .GroupBy(v => v.UserId)
                                           .ToDictionary(g => g.Key, g => g.Count());
            var visitedSlidesCountByUserAllTime = visitsRepo.GetVisitsInPeriod(filterOptions.WithPeriodStart(DateTime.MinValue).WithPeriodFinish(DateTime.MaxValue))
                                                  .GroupBy(v => v.UserId)
                                                  .ToDictionary(g => g.Key, g => g.Count());

            /* Get `usersLimit` best by slides count and order them by name */
            visitedUsers = visitedUsers
                           .OrderByDescending(u => visitedSlidesCountByUserAllTime.GetOrDefault(u.UserId, 0))
                           .Take(usersLimit)
                           .OrderBy(u => u.UserVisibleName)
                           .ToList();

            var visitedUsersIds  = visitedUsers.Select(v => v.UserId).ToList();
            var additionalScores = additionalScoresRepo
                                   .GetAdditionalScoresForUsers(courseId, unitId.Value, visitedUsersIds)
                                   .ToDictionary(kv => kv.Key, kv => kv.Value.Score);
            var usersGroupsIds = groupsRepo.GetUsersGroupsIds(courseId, visitedUsersIds);
            var enabledAdditionalScoringGroupsForGroups = groupsRepo.GetEnabledAdditionalScoringGroups(courseId)
                                                          .GroupBy(e => e.GroupId)
                                                          .ToDictionary(g => g.Key, g => g.Select(e => e.ScoringGroupId).ToList());

            var model = new UnitStatisticPageModel
            {
                Course            = course,
                Units             = course.Units,
                Unit              = selectedUnit,
                SelectedGroupsIds = groupsIds,
                Groups            = groups,

                PeriodStart  = periodStart,
                PeriodFinish = periodFinish,

                Slides       = slides,
                SlidesVisits = slidesVisits,

                UsersVisitedAllSlidesBeforePeriodCount         = usersVisitedAllSlidesBeforePeriodCount,
                UsersVisitedAllSlidesInPeriodCount             = usersVisitedAllSlidesInPeriodCount,
                UsersVisitedAllSlidesBeforePeriodFinishedCount = usersVisitedAllSlidesBeforePeriodFinishedCount,

                QuizzesAverageScore             = quizzesAverageScore,
                ExercisesSolutionsCount         = exercisesSolutionsCount,
                ExercisesAcceptedSolutionsCount = exercisesAcceptedSolutionsCount,
                VisitedUsers                    = visitedUsers,
                VisitedUsersIsMore              = isMore,
                VisitedSlidesCountByUser        = visitedSlidesCountByUser,
                VisitedSlidesCountByUserAllTime = visitedSlidesCountByUserAllTime,

                AdditionalScores = additionalScores,
                UsersGroupsIds   = usersGroupsIds,
                EnabledAdditionalScoringGroupsForGroups = enabledAdditionalScoringGroupsForGroups,
            };

            return(View(model));
        }