/// <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 );
 }
예제 #9
0
        /// <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 );
 }