public ActionResult Stats(ContestFullResultsViewModel viewModel)
        {
            if (!this.UserHasAccessToContest(viewModel.Id))
            {
                throw new HttpException((int)HttpStatusCode.Forbidden, Resource.Contest_results_not_available);
            }

            var maxResult         = this.Data.Contests.All().FirstOrDefault(c => c.Id == viewModel.Id).Problems.Sum(p => p.MaximumPoints);
            var participantsCount = viewModel.Results.Count();
            var statsModel        = new ContestStatsViewModel();

            statsModel.MinResultsCount   = viewModel.Results.Count(r => r.Total == 0);
            statsModel.MinResultsPercent = (double)statsModel.MinResultsCount / participantsCount;
            statsModel.MaxResultsCount   = viewModel.Results.Count(r => r.Total == maxResult);
            statsModel.MaxResultsPercent = (double)statsModel.MaxResultsCount / participantsCount;
            statsModel.AverageResult     = (double)viewModel.Results.Sum(r => r.Total) / participantsCount;

            int fromPoints = 0;
            int toPoints   = 0;

            foreach (var problem in viewModel.Problems)
            {
                var maxResultsForProblem        = viewModel.Results.Count(r => r.ProblemResults.Any(pr => pr.ProblemName == problem.Name && pr.BestSubmission != null && pr.BestSubmission.Points == pr.MaximumPoints));
                var maxResultsForProblemPercent = (double)maxResultsForProblem / participantsCount;
                statsModel.StatsByProblem.Add(new ContestProblemStatsViewModel
                {
                    Name              = problem.Name,
                    MaxResultsCount   = maxResultsForProblem,
                    MaxResultsPercent = maxResultsForProblemPercent,
                    MaxPossiblePoints = problem.MaximumPoints
                });

                if (toPoints == 0)
                {
                    toPoints = problem.MaximumPoints;
                }
                else
                {
                    toPoints += problem.MaximumPoints;
                }

                var participantsInPointsRange        = viewModel.Results.Count(r => r.Total >= fromPoints && r.Total <= toPoints);
                var participantsInPointsRangePercent = (double)participantsInPointsRange / participantsCount;

                statsModel.StatsByPointsRange.Add(new ContestPointsRangeViewModel
                {
                    PointsFrom               = fromPoints,
                    PointsTo                 = toPoints,
                    Participants             = participantsInPointsRange,
                    PercentOfAllParticipants = participantsInPointsRangePercent
                });

                fromPoints = toPoints + 1;
            }

            return(this.PartialView("_StatsPartial", statsModel));
        }
예제 #2
0
        public ActionResult Stats(int contestId, bool official)
        {
            if (!this.CheckIfUserHasContestPermissions(contestId))
            {
                throw new HttpException((int)HttpStatusCode.Forbidden, Resource.Contest_results_not_available);
            }

            var contest = this.contestsData.GetByIdWithProblems(contestId);

            if (contest == null)
            {
                throw new HttpException((int)HttpStatusCode.NotFound, Resource.Contest_not_found);
            }

            var contestResults = this.GetContestResults(contest, official, true, true);

            var maxResult = this.contestsData.GetMaxPointsById(contest.Id);

            var participantsCount = contestResults.Results.Count();
            var statsModel        = new ContestStatsViewModel
            {
                MinResultsCount = contestResults.Results.Count(r => r.Total == 0),
                MaxResultsCount = contestResults.Results.Count(r => r.Total == maxResult),
                AverageResult   = (double)contestResults.Results.Sum(r => r.Total) / participantsCount
            };

            statsModel.MinResultsPercent = (double)statsModel.MinResultsCount / participantsCount;
            statsModel.MaxResultsPercent = (double)statsModel.MaxResultsCount / participantsCount;

            var fromPoints = 0;
            var toPoints   = 0;

            if (contest.IsOnline && official)
            {
                statsModel.IsGroupedByProblemGroup = true;

                foreach (var problems in contestResults.Problems.GroupBy(p => p.ProblemGroupId))
                {
                    var maxResultsForProblemGroupCount = contestResults.Results
                                                         .Count(r => r.ProblemResults?
                                                                .Any(pr => problems
                                                                     .Any(p =>
                                                                          p.Id == pr.ProblemId &&
                                                                          pr.BestSubmission.Points == pr.MaximumPoints)) ?? false);

                    var maxPointsForProblemGroup = problems.FirstOrDefault()?.MaximumPoints ?? default(int);
                    var problemGroupName         = string.Join("<br/>", problems.Select(p => p.Name));

                    AddStatsByProblem(problemGroupName, maxPointsForProblemGroup, maxResultsForProblemGroupCount);
                    AddStatsByPointsRange(maxPointsForProblemGroup, contestResults.Results);
                }
            }
            else
            {
                foreach (var problem in contestResults.Problems)
                {
                    var maxResultForProblemCount = contestResults.Results
                                                   .Count(r => r.ProblemResults?
                                                          .Any(pr =>
                                                               pr.ProblemId == problem.Id &&
                                                               pr.BestSubmission.Points == problem.MaximumPoints) ?? false);

                    AddStatsByProblem(problem.Name, problem.MaximumPoints, maxResultForProblemCount);
                    AddStatsByPointsRange(problem.MaximumPoints, contestResults.Results);
                }
            }

            void AddStatsByProblem(string name, int maxPoints, int maxResultsCount)
            {
                var maxResultsPercent = (double)maxResultsCount / participantsCount;

                statsModel.StatsByProblem.Add(new ContestProblemStatsViewModel
                {
                    Name              = name,
                    MaxResultsCount   = maxResultsCount,
                    MaxResultsPercent = maxResultsPercent,
                    MaxPossiblePoints = maxPoints
                });
            }

            void AddStatsByPointsRange(int maxPoints, IEnumerable <ParticipantResultViewModel> results)
            {
                if (toPoints == 0)
                {
                    toPoints = maxPoints;
                }
                else
                {
                    toPoints += maxPoints;
                }

                // ReSharper disable once AccessToModifiedClosure
                var participantsInPointsRange = results.Count(r => r.Total >= fromPoints && r.Total <= toPoints);

                var participantsInPointsRangePercent = (double)participantsInPointsRange / participantsCount;

                statsModel.StatsByPointsRange.Add(new ContestPointsRangeViewModel
                {
                    PointsFrom               = fromPoints,
                    PointsTo                 = toPoints,
                    Participants             = participantsInPointsRange,
                    PercentOfAllParticipants = participantsInPointsRangePercent
                });

                fromPoints = toPoints + 1;
            }

            return(this.PartialView("_StatsPartial", statsModel));
        }