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)); }
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)); }