public async Task <IEnumerable <SkaterStatisticsModel> > Handle(StatisticLeaderQuery request, CancellationToken cancellationToken)
        {
            var baseQuery = request.StatisticType.Equals(StatisticType.BestAverageSpeed) ?
                            context.SkateLogEntries.Where(x => x.ApplicationUser.HasPaid && x.AverageSpeedInMph > 0 && x.Duration >= 1800) :
                            context.SkateLogEntries.Where(x => x.ApplicationUser.HasPaid);

            var allSkaterSummaries = await baseQuery.GroupBy(x => x.ApplicationUserId)
                                     .Select(x => new
            {
                ApplicationUserId    = x.Key,
                BestAverageSpeed     = x.Max(x => x.AverageSpeedInMph),
                BestTopSpeed         = x.Max(x => x.TopSpeedInMph),
                GreatestClimb        = x.Max(x => x.ElevationGainInFeet),
                SkybornSkater        = x.Max(x => x.HighestElevationInFeet),
                LongestJourney       = x.Max(x => x.DistanceInMiles),
                ShortestJourney      = x.Min(x => x.DistanceInMiles),
                LongestTotalDistance = x.Sum(x => x.DistanceInMiles),
                MostJourneys         = x.Count()
            })
                                     .ToListAsync();

            var skaterIds = allSkaterSummaries.Select(x => x.ApplicationUserId).ToList();
            var skaters   = await context.Users.Where(x => skaterIds.Contains(x.Id)).ToListAsync();

            var skaterSummaries = new List <Tuple <string, string> >();

            switch (request.StatisticType)
            {
            case StatisticType.BestAverageSpeed:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.BestAverageSpeed > 0)
                                         .OrderByDescending(x => x.BestAverageSpeed)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, $"{x.BestAverageSpeed:F2} MPH")));
                break;

            case StatisticType.BestTopSpeed:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.BestTopSpeed > 0)
                                         .OrderByDescending(x => x.BestTopSpeed)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, $"{x.BestTopSpeed:F2} MPH")));
                break;

            case StatisticType.LongestDistance:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.LongestJourney > 0)
                                         .OrderByDescending(x => x.LongestJourney)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, GetDistanceString(x.LongestJourney))));
                break;

            case StatisticType.ShortestDistance:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.ShortestJourney > 0)
                                         .OrderBy(x => x.ShortestJourney)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, GetDistanceString(x.ShortestJourney))));
                break;

            case StatisticType.GreatestElevationGain:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.GreatestClimb > 0)
                                         .OrderByDescending(x => x.GreatestClimb)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, $"{x.GreatestClimb:F2} Feet")));
                break;

            case StatisticType.HighestElevation:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.SkybornSkater > 0)
                                         .OrderByDescending(x => x.SkybornSkater)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, $"{x.SkybornSkater:F2} Feet")));
                break;

            case StatisticType.LongestTotalJourney:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.LongestTotalDistance > 0)
                                         .OrderByDescending(x => x.LongestTotalDistance)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, GetDistanceString(x.LongestTotalDistance))));
                break;

            case StatisticType.MostJourneys:
                skaterSummaries.AddRange(allSkaterSummaries.Where(x => x.MostJourneys > 0)
                                         .OrderByDescending(x => x.MostJourneys)
                                         .Select(x => new Tuple <string, string>(x.ApplicationUserId, $"{x.MostJourneys:F0} Journeys")));
                break;
            }

            return((from skaterSummary in skaterSummaries
                    join skater in skaters on skaterSummary.Item1 equals skater.Id
                    where skater.HasPaid
                    select new SkaterStatisticsModel
            {
                SkaterName = skater.SkaterName,
                SkaterProfile = GetProfileImage(skater),
                Statistic = skaterSummary.Item2
            }).ToList());
        }
        public override async Task <PageViewModel <StatisticLeadersViewModel> > Build()
        {
            var model = await base.Build();

            model.PageTitle        = "Event Statistics";
            model.DisplayPageTitle = "Event Statistics";

            var query = new StatisticLeaderQuery {
                StatisticType = statisticType
            };

            model.Content.Skaters = (await mediator.Send(query)).ToList();

            switch (statisticType)
            {
            case StatisticType.BestAverageSpeed:
                model.PageTitle              = "Skaters with the Best Average Speed";
                model.DisplayPageTitle       = "Skaters with the Best Average Speed";
                model.IntroductoryText       = "Skaters must have submitted a skating work out with a duration of at least 30 minutes in order to qualify for this leaderboard.";
                model.Content.StatisticTitle = "Average Speed";
                break;

            case StatisticType.BestTopSpeed:
                model.PageTitle              = "Skaters with the Best Top Speed";
                model.DisplayPageTitle       = "Skaters with the Best Top Speed";
                model.Content.StatisticTitle = "Top Speed";
                break;

            case StatisticType.LongestDistance:
                model.PageTitle              = "Skaters with the Longest Journeys";
                model.DisplayPageTitle       = "Skaters with the Longest Journeys";
                model.IntroductoryText       = "Skaters are shown here with the longest distance achieved in a single skate journey.";
                model.Content.StatisticTitle = "Distance";
                break;

            case StatisticType.ShortestDistance:
                model.PageTitle              = "Skaters with the Shortest Journeys";
                model.DisplayPageTitle       = "Skaters with the Shortest Journeys";
                model.IntroductoryText       = "Skaters are shown here with the shortest distance achieved in a single skate journey.";
                model.Content.StatisticTitle = "Distance";
                break;

            case StatisticType.GreatestElevationGain:
                model.PageTitle              = "Skaters with the Greatest Elevation Gain";
                model.DisplayPageTitle       = "Skaters with the Greatest Elevation Gain";
                model.IntroductoryText       = "Skaters are shown here with the greatest elevation gain achieved in a single skate journey.";
                model.Content.StatisticTitle = "Elevation";
                break;

            case StatisticType.HighestElevation:
                model.PageTitle              = "Skaters with the Highest Elevation";
                model.DisplayPageTitle       = "Skaters with the Highest Elevation";
                model.IntroductoryText       = "Skaters are shown here with the highest elevation visited across all journeys.";
                model.Content.StatisticTitle = "Elevation";
                break;

            case StatisticType.LongestTotalJourney:
                model.PageTitle              = "Skaters with Longest Total Journey";
                model.DisplayPageTitle       = "Skaters with Longest Total Journey";
                model.IntroductoryText       = "Skaters are shown here with the greatest cumulative distance across all their journeys.";
                model.Content.StatisticTitle = "Distance";
                break;

            case StatisticType.MostJourneys:
                model.PageTitle              = "Skaters with Most Journeys";
                model.DisplayPageTitle       = "Skaters with Most Journeys";
                model.IntroductoryText       = "Skaters are shown here with the greatest number of journeys.";
                model.Content.StatisticTitle = "Journeys";
                break;

            default:
                throw new NotImplementedException($"{statisticType} is not currently supported");
            }

            return(model);
        }