/// <summary> /// /// </summary> /// <param name="players"></param> /// <param name="seed"></param> /// <param name="playersPerTeam"></param> /// <param name="r"></param> /// <returns></returns> private Tuple<Team, Team> chooseTeams( List<Player> players, Player seed, int playersPerTeam, Random r ) { if ( players.Count >= 2 * playersPerTeam ) { List<Player> t = players.RandomOrdering( r, 2 * playersPerTeam ).ToList(); Team a = new Team(); Team b = new Team(); for ( int count = 0; count < 2 * playersPerTeam; count++ ) { if ( count < playersPerTeam ) { a.Players.Add( t[count] ); } else { b.Players.Add( t[count] ); } } return new Tuple<Team, Team>( a, b ); } //Return a tuple of EmptyTeams because we never got enough players together return new Tuple<Team, Team>( new EmptyTeam(), new EmptyTeam() ); }
/// <summary> /// Divide players into two teams with even players on one team and odd players on the other /// </summary> /// <param name="players"></param> /// <param name="playersPerTeam"></param> /// <param name="seed"></param> /// <returns></returns> private Tuple<Team, Team> bucketPlayers( List<Player> players, int playersPerTeam, Player seed ) { //Create teams Team a = new Team(); Team b = new Team(); //Add seed to first Team a.Players.Add( seed ); //Divide players between Teams for ( int count = 1; count < 2 * playersPerTeam; count++ ) { if ( count % 2 == 0 ) a.Players.Add( players[count - 1] ); else b.Players.Add( players[count - 1] ); } //Return Teams return new Tuple<Team, Team>( a, b ); }
/// <summary> /// /// </summary> /// <param name="players"></param> /// <param name="playersPerTeam"></param> /// <param name="seed"></param> /// <returns></returns> public Tuple<Team, Team> DividePlayers( List<Player> players, int playersPerTeam, Player seed ) { //if ( players.Count > 2 * PLAYERS_PER_TEAM ) //players.Sort( ( p1, p2 ) => p2.GetElo().CompareTo( p1.GetElo() ) ); //players.Sort( ( p1, p2 ) => Math.Abs( seed.GetElo() - p2.GetElo() ) ); int seedElo = seed.GetElo(); players.Sort( ( p1, p2 ) => Math.Abs( seedElo - p1.GetElo() ).CompareTo( Math.Abs( seedElo - p2.GetElo() ) ) ); //players.OrderByDescending( p => Math.Abs( seedElo - p.GetElo() ) ); Team a = new Team(); Team b = new Team(); a.Players.Add( seed ); for ( int count = 1; count < 2 * playersPerTeam; count++ ) { if ( count % 2 == 0 ) a.Players.Add( players[count - 1] ); else b.Players.Add( players[count - 1] ); } return new Tuple<Team, Team>( a, b ); }
/// <summary> /// Divide players into two Teams /// </summary> /// <param name="players"></param> /// <param name="seed"></param> /// <param name="playersPerTeam"></param> /// <returns></returns> public Tuple<Team, Team> ChooseTeams( List<Player> players, Player seed, int playersPerTeam ) { return chooseTeams( players, Finder, seed, playersPerTeam, EloRange ); }
/// <summary> /// Choose teams based upon placement into Elo buckets /// </summary> /// <param name="players"></param> /// <param name="finder"></param> /// <param name="seed"></param> /// <param name="playersPerTeam"></param> /// <param name="eloRange"></param> /// <returns></returns> private Tuple<Team, Team> chooseTeams( List<Player> players, IPlayerFinder finder, Player seed, int playersPerTeam, int eloRange ) { //Find possible players List<Player> possible = finder.FindPlayers( players, seed.GetElo(), eloRange ); //Add seed to possible players if not already present if ( !possible.Contains( seed ) ) possible.Add( seed ); //Check if there are enough players if ( possible.Count >= 2 * playersPerTeam ) { //Remove seed from list of possible players possible.Remove( seed ); //Bucket players into teams return bucketPlayers( possible, playersPerTeam, seed ); } //Return a tuple of EmptyTeams since we don't have enough players for two Teams return new Tuple<Team, Team>( new EmptyTeam(), new EmptyTeam() ); }
/// <summary> /// /// </summary> /// <param name="players"></param> /// <param name="finder"></param> /// <param name="divider"></param> /// <param name="seed"></param> /// <param name="playersPerTeam"></param> /// <param name="eloRange"></param> /// <returns></returns> private Tuple<Team, Team> chooseTeams( List<Player> players, IPlayerFinder finder, ITeamDivider divider, Player seed, int playersPerTeam, int eloRange ) { List<Player> possible = finder.FindPlayers( players, seed.GetElo(), eloRange ); if ( !possible.Contains( seed ) ) { possible.Add( seed ); } if ( possible.Count >= 2 * playersPerTeam ) { possible.Remove( seed ); return divider.DividePlayers( possible, playersPerTeam, seed ); } //Return a tuple of EmptyTeams because we never got enough players together return new Tuple<Team, Team>( new EmptyTeam(), new EmptyTeam() ); }
/// <summary> /// Divide players into two teams with some players on each team having guaranteed close Elo scores, the rest assigned based upon total team Elo /// </summary> /// <param name="players"></param> /// <param name="playersPerTeam"></param> /// <param name="seed"></param> /// <param name="numClose"></param> /// <param name="r"></param> /// <returns></returns> private Tuple<Team, Team> dividePlayers( List<Player> players, int playersPerTeam, Player seed, int numClose, Random r ) { if ( numClose < 2 * playersPerTeam ) { //Sort the players so that both teams get some of the top available players players.Sort( ( p1, p2 ) => p2.GetElo().CompareTo( p1.GetElo() ) ); //Create two Teams Team a = new Team(); Team b = new Team(); int startIndex = 0; int totalPlayersAssigned = 0; //Check if all of the players must be close in Elo if ( numClose == 2 * playersPerTeam ) { //Add the seed player to one team a.Players.Add( seed ); startIndex = 1; } //Add the number of players that need to be close to teams for ( int count = startIndex; count < numClose; count++ ) { if ( count % 2 == 0 ) a.Players.Add( players[count - 1] ); else b.Players.Add( players[count - 1] ); } totalPlayersAssigned = numClose; int numLeft = 2 * playersPerTeam - numClose; if ( numLeft > 0 ) { //Add the seed player to one team a.Players.Add( seed ); numLeft--; totalPlayersAssigned++; } //Get as many players as are needed and randomize them players = players.GetRange( numClose, players.Count - totalPlayersAssigned ).RandomOrdering( r ).ToList(); //Assign rest of players as needed for ( int count = 0; count < numLeft; count++ ) { //Don't reassign the seed if ( players[count] != seed ) { //Check if both teams need a player if ( a.Players.Count < playersPerTeam && b.Players.Count < playersPerTeam ) { //Calculate Elo differences double diffWithA = ((double)(a.GetTeamElo() + players[count].GetElo())) / (double)(a.Players.Count + 1) - b.GetAverageElo(); double diffWithB = ((double)(b.GetTeamElo() + players[count].GetElo())) / (double)(b.Players.Count + 1) - a.GetAverageElo(); //Decide which team gets the player if ( Math.Abs( diffWithA ) < Math.Abs( diffWithB ) ) { a.Players.Add( players[count] ); } else { b.Players.Add( players[count] ); } } //Assign to Team A else if ( a.Players.Count < playersPerTeam ) a.Players.Add( players[count] ); //Assign to Team B else if ( b.Players.Count < playersPerTeam ) b.Players.Add( players[count] ); } } return new Tuple<Team, Team>( a, b ); } //Return a game with EmptyTeams because there weren't enough players return new Tuple<Team, Team>( new EmptyTeam(), new EmptyTeam() ); }
/// <summary> /// Divide players into teams /// </summary> /// <param name="players"></param> /// <param name="playersPerTeam"></param> /// <param name="seed"></param> /// <returns></returns> public Tuple<Team, Team> DividePlayers( List<Player> players, int playersPerTeam, Player seed ) { return dividePlayers( players, playersPerTeam, seed, NumClose, Random ); }
/// <summary> /// Create some players /// </summary> /// <param name="numPlayers">The number of players to create</param> private void initializePlayers( int numPlayers ) { //Create some players for ( int count = 0; count < numPlayers; count++ ) { Player p = new Player( count ); //Assign a real Elo for the player to represent their actual skill p.RealElo = (int)Math.Round( sampleNormalDistribution() ); _players.Add( p ); } }
/// <summary> /// Ignore a player for all subsequent calls to chooseSeed until Initialize is called /// </summary> /// <param name="player"></param> public void IgnorePlayer( Player player ) { if ( player != null && !_ignoredPlayers.Contains( player ) ) _ignoredPlayers.Add( player ); }
/// <summary> /// Divide players into two Teams /// </summary> /// <param name="players"></param> /// <param name="seed"></param> /// <param name="playersPerTeam"></param> /// <returns></returns> public Tuple<Team, Team> ChooseTeams( List<Player> players, Player seed, int playersPerTeam ) { return chooseTeams( players, Divider, Finder, seed, playersPerTeam, EloRange, MaxElo, MinElo ); }
/// <summary> /// /// </summary> /// <param name="players"></param> /// <param name="divider"></param> /// <param name="finder"></param> /// <param name="seed"></param> /// <param name="playersPerTeam"></param> /// <param name="eloRange"></param> /// <param name="maxElo"></param> /// <param name="minElo"></param> /// <returns></returns> private Tuple<Team, Team> chooseTeams( List<Player> players, ITeamDivider divider, IPlayerFinder finder, Player seed, int playersPerTeam, int eloRange, int maxElo, int minElo ) { int max = 0; int min = 0; //Check if the range of Elos to check hits the max if ( seed.GetElo() + eloRange / 2 > maxElo ) { //Set max to maxElo max = maxElo; //Set min min = seed.GetElo() - (eloRange / 2) - (maxElo - seed.GetElo()); } else { //Check if the range of Elos to check hits the min if ( seed.GetElo() - eloRange / 2 < minElo ) { //Set min to minElo min = minElo; //Set max max = seed.GetElo() + (eloRange / 2) + (seed.GetElo() - minElo); } else { //Set max max = seed.GetElo() + eloRange / 2; //Set min min = seed.GetElo() - eloRange / 2; } } //Get possible players List<Player> possible = finder.FindPlayers( players, max, max - min ); //Add seed to list of possible players if ( !possible.Contains( seed ) ) { possible.Add( seed ); } //Check if there are enough players to make a match if ( possible.Count >= 2 * playersPerTeam ) { //Enough players possible.Remove( seed ); //Divide the players into two teams return divider.DividePlayers( possible, playersPerTeam, seed ); } else { //Not enough players, expand the Elo range if ( eloRange < maxElo - minElo ) return chooseTeams( players, divider, finder, seed, playersPerTeam, eloRange * 2, maxElo, minElo ); } //Return a tuple of EmptyTeams because we never got enough players together return new Tuple<Team, Team>( new EmptyTeam(), new EmptyTeam() ); }
/// <summary> /// Divide players randomly into two Teams /// </summary> /// <param name="players"></param> /// <param name="seed">Unused</param> /// <param name="playersPerTeam"></param> /// <returns></returns> public Tuple<Team, Team> ChooseTeams( List<Player> players, Player seed, int playersPerTeam ) { return chooseTeams( players, seed, playersPerTeam, Random ); }