public ObservableCollection<PlayerMatch> ApplyAlgorithm(ObservableCollection<PlayerMatch> playerMatches) { ObservableCollection<PlayerMatch> outputList = new ObservableCollection<PlayerMatch>(); //Join the win stats onto list of user selected players IEnumerable<PlayerData> result = from pm in playerMatches join ps in GetPlayerStatsForAllPlayers().DefaultIfEmpty() on pm.PlayerID equals ps.PlayerID into temp from subtemp in temp.DefaultIfEmpty() select new PlayerData { PlayerMatch = pm, MatchWins = (subtemp == null ? 0 : subtemp.MatchWins), MatchesPlayed = subtemp.MatchesPlayed, WinRatio = SelectorServiceHelper.GetWinRatio(subtemp) } into results select results; IList<PlayerData> playerData = result.ToList(); // Randomly shuffle list playerData.Shuffle(); // Divide list of player data into a list per team IEnumerable<PlayerData> firstTeam = playerData.TakeFirstHalf(); IEnumerable<PlayerData> lastTeam = playerData.TakeLastHalf(); // Get total win ratios per team decimal? firstTeamsTotalWinRatio = firstTeam.Sum(x => x.WinRatio); decimal? lastTeamsTotalWinRatio = lastTeam.Sum(x => x.WinRatio); // Get difference in win ratio between teams decimal winRatioOffset = SelectorServiceHelper.GetOffset(firstTeamsTotalWinRatio, lastTeamsTotalWinRatio); // Prepare swap candidates based on win ratio differential PlayerData firstSwapCandidate = firstTeam.GetClosestToWinRatio(winRatioOffset / 2); PlayerData lastSwapCandidate = lastTeam.GetClosestToWinRatio(winRatioOffset / 2); // Get difference in win ratio between swap candidates decimal? candidateOffset = SelectorServiceHelper.GetOffset(firstSwapCandidate.WinRatio, lastSwapCandidate.WinRatio); // Undertake the swap if there would be a reduction in the differential i.e. improvement in team matching if (candidateOffset < winRatioOffset) playerData.Swap(firstSwapCandidate, lastSwapCandidate); // List is correctly ordered by player outputList.DistributePlayersBasedOnListOrder(playerData); // Assign the teams, smallest player should wear a bib SelectorServiceHelper.AssignShortestTeamToBibs(outputList, _footballRepository); return outputList; }