public ActionResult Form(int? season)
        {
            if (season.HasValue == false)
                season = DocumentSession.LatestSeasonOrDefault(SystemTime.UtcNow.Year);

            var players = DocumentSession.Query<Player, PlayerSearch>()
                .ToArray();

            var results = DocumentSession.Query<ResultForPlayerIndex.Result, ResultForPlayerIndex>()
                .Where(x => x.Season == season.Value)
                .ToArray();
            var seasonAverages = results.ToDictionary(x => x.PlayerId);

            var response = new List<PlayerFormViewModel>();
            foreach (var player in players)
            {
                var name = player.Name;
                ResultForPlayerIndex.Result result;
                if (seasonAverages.TryGetValue(player.Id, out result)
                    && result.TotalSeries > 0)
                {
                    var playerForm = new PlayerFormViewModel(name)
                    {
                        TotalSeries = result.TotalSeries,
                        SeasonAverage = (double)result.TotalPins / Math.Max(1, result.TotalSeries),
                        Last5Average = (double)result.Last5TotalPins / Math.Max(1, result.Last5TotalSeries),
                        HasResult = true
                    };
                    response.Add(playerForm);
                }
                else if (player.PlayerStatus == Player.Status.Active)
                {
                    response.Add(new PlayerFormViewModel(name));
                }
            }

            return View(response.OrderByDescending(x => x.SeasonAverage).ThenBy(x => x.Name));
        }
        public ActionResult PlayerStatus(int turn, int season)
        {
            var rosters = DocumentSession.Query<Roster, RosterSearchTerms>()
                .Where(x => x.Turn == turn && x.Season == season)
                .ToArray();
            var from = rosters.Select(x => x.Date.Date)
                .Min();
            var to = rosters.Select(x => x.Date.Date)
                .Max();

            /*
             *    x   y
             * 1         1
             * 2    2
             *      3   3
             *     4 4
             */
            var absences = DocumentSession.Query<AbsenceIndex.Result, AbsenceIndex>()
                .Where(x => x.From <= from && to <= x.To
                    || x.From <= from && from <= x.To
                    || x.From <= to && to <= x.To
                    || from <= x.From && x.To <= to)
                .OrderBy(p => p.To)
                .ThenBy(p => p.PlayerName)
                .AsProjection<AbsenceIndex.Result>()
                .ToArray()
                .ToLookup(x => x.Player)
                .ToDictionary(x => x.Key, x => x.ToList());

            var players = DocumentSession.Query<Player, PlayerSearch>()
                .ToArray();
            var rostersForPlayers = new Dictionary<string, List<RosterViewModel>>();
            foreach (var roster in rosters)
            {
                var rosterViewModel = roster.MapTo<RosterViewModel>();
                foreach (var player in roster.Players)
                {
                    List<RosterViewModel> rosterViewModels;
                    if (rostersForPlayers.TryGetValue(player, out rosterViewModels) == false)
                    {
                        rosterViewModels = new List<RosterViewModel>();
                        rostersForPlayers.Add(player, rosterViewModels);
                    }

                    rosterViewModels.Add(rosterViewModel);
                }
            }

            var resultsForPlayer = DocumentSession.Query<ResultForPlayerIndex.Result, ResultForPlayerIndex>()
                                                  .Where(x => x.Season == season)
                                                  .ToArray()
                                                  .ToDictionary(x => x.PlayerId);

            var activities = new List<PlayerStatusViewModel>();
            foreach (var player in players)
            {
                PlayerFormViewModel playerForm;
                ResultForPlayerIndex.Result resultForPlayer;
                if (resultsForPlayer.TryGetValue(player.Id, out resultForPlayer)
                    && resultForPlayer.TotalSeries > 0)
                {
                    playerForm = new PlayerFormViewModel(player.Name)
                    {
                        TotalSeries = resultForPlayer.TotalSeries,
                        SeasonAverage = (double)resultForPlayer.TotalPins / Math.Max(1, resultForPlayer.TotalSeries),
                        Last5Average = (double)resultForPlayer.Last5TotalPins / Math.Max(1, resultForPlayer.Last5TotalSeries),
                        HasResult = true
                    };
                }
                else if (player.PlayerStatus == Player.Status.Active)
                {
                    playerForm = new PlayerFormViewModel(player.Name);
                }
                else
                {
                    continue;
                }

                var activity = new PlayerStatusViewModel(player.Name, playerForm);

                if (rostersForPlayers.ContainsKey(player.Id))
                {
                    var rostersForPlayer = rostersForPlayers[player.Id];
                    activity.Teams.AddRange(rostersForPlayer);
                }

                List<AbsenceIndex.Result> playerAbsences;
                if (absences.TryGetValue(player.Id, out playerAbsences))
                {
                    activity.Absences.AddRange(playerAbsences.OrderBy(x => x.From));
                }

                activities.Add(activity);
            }

            var activitiesWithNoAbsence = activities.Where(x => x.Absences.Count == 0);
            var activitiesWithAbsence = activities.Where(x => x.Absences.Count > 0);
            var vm = activitiesWithNoAbsence.OrderByDescending(x => x, new PlayerStatusViewModel.Comparer(CompareMode.PlayerForm))
                .Concat(activitiesWithAbsence.OrderBy(x => x.Absences.Min(y => y.To)).ThenBy(x => x.Name));
            return PartialView(vm);
        }