BolfTracker.Web.GamePanelViewModel.GetCurrentPlayer C# (CSharp) Method

GetCurrentPlayer() private method

private GetCurrentPlayer ( ) : BolfTracker.Models.Player
return BolfTracker.Models.Player
        private Player GetCurrentPlayer()
        {
            var playerResult = new Player();
            int currentHole = GetCurrentHole();

            if (Shots.Any())
            {
                var activePlayers = ActivePlayers;
                var playersDescending = GetCurrentActivePlayers(activePlayers, includeOvertime: false);

                var duplicatePlayers = Shots.GroupBy(s => s.Player.Id).Where(p => p.Count() > 1);

                // Check to see if we've had any duplicate players yet (if so, that means we can determine the order)
                if (duplicatePlayers.Any())
                {
                    // If we are on the last hole or in overtime, the order could change because not everyone can win
                    if (currentHole >= 10)
                    {
                        var playersWhoCanWin = GetPlayersWhoCanWin(currentHole);

                        if (!playersWhoCanWin.Any() || playersWhoCanWin.Count() >= playersDescending.Count())
                        {
                            // If all of the players can win, we will go in normal order
                            var lastPlayerToShoot = Shots.Where(s => s.Game.Id == Game.Id).OrderByDescending(s => s.Id).Select(s => s.Player).First();

                            var playerList = playersDescending.Reverse().ToList();

                            int index = playerList.IndexOf(lastPlayerToShoot);

                            return playerList[index == -1 ? 0 : (index + 1) % (playerList.Count)];
                        }
                        else
                        {
                            // If only some of the players can win, we will go in descending order by points
                            var playersWhoCanStillWin = new List<LeaderboardViewModel>();

                            foreach (var player in playersWhoCanWin)
                            {
                                var playerCurrentHoleShots = Shots.Where(s => s.Player.Id == player.Player.Id && s.Game.Id == Game.Id && s.Hole.Id == currentHole);

                                if (!playerCurrentHoleShots.Any())
                                {
                                    playersWhoCanStillWin.Add(player);
                                }
                            }

                            var playersWhoCannotWin = new List<Player>();

                            if (playersWhoCanStillWin.Count == 0)
                            {
                                if (HoleIsPushed(currentHole))
                                {
                                    return playersWhoCanStillWin.First().Player;
                                }

                                // This means that one of the players who could win made a shot, so all of the people
                                // that cannot win need to take a shot to push them
                                foreach (var player in playersDescending)
                                {
                                    if (!Shots.Any(s => s.Player.Id == player.Id && s.Hole.Id == currentHole))
                                    {
                                        if (!playersWhoCanWin.Any(l => l.Player.Id == player.Id))
                                        {
                                            playersWhoCannotWin.Add(player);
                                        }
                                    }
                                }

                                // TODO: Here we need to figure out the order that these players who can push
                                // the hole need to go in.  My thought is that the players with the least amount of
                                // pushes for the current period (in our case month) get to go first.
                                if (playersWhoCannotWin.Any())
                                {
                                    return playersWhoCannotWin.Last();
                                }
                                else
                                {
                                    return playersDescending.Last();
                                }
                            }
                            else
                            {
                                return playersWhoCanStillWin.OrderByDescending(l => l.Points).First().Player;
                            }
                        }
                    }

                    return playersDescending.Last();
                }
                else
                {
                    // TODO: My thought for initial player order is that the people with the lowest shooting percentage
                    // get to go first, and once one of them makes it, the players with the lowest pushes get to go second

                    // If we can't determine the order, just get the next player who has not gone already
                    foreach (var player in _allPlayers)
                    {
                        if (!activePlayers.Any(p => p.Id == player.Id))
                        {
                            return player;
                        }
                    }
                }
            }

            return playerResult;
        }