Пример #1
0
        Day RandomDay()
        {
            Day day = new Day();

            // Make a clone of data from parameters
            Counter <MatchSize> numMatchSizesClone = new Counter <MatchSize>(parameters.numMatchSizes);
            List <Player>       playersClone;

            // If we have an existing day, try to copy matches across
            if (parameters.existingDay != null)
            {
                HashSet <Player> playersAsSet = new HashSet <Player>(parameters.players);
                foreach (Match match in parameters.existingDay.matches)
                {
                    // Make sure we need a match with this size
                    MatchSize matchSize = match.GetMatchSize();
                    if (numMatchSizesClone[matchSize] > 0)
                    {
                        // Check that all players from that match are still needed in this match
                        bool allPlayersInExisting = true;
                        foreach (Team team in match.teams)
                        {
                            foreach (Player player in team.players)
                            {
                                if (player != null)
                                {
                                    if (!playersAsSet.Contains(player))
                                    {
                                        allPlayersInExisting = false;
                                    }
                                }
                            }
                        }
                        if (allPlayersInExisting)
                        {
                            // Create a new match
                            Match copiedMatch = new Match(matchSize, match.isFixed, true);
                            copiedMatch.rink = match.rink;
                            day.matches.Add(copiedMatch);
                            // Copy the players from the existing match
                            for (int teamIndex = 0; teamIndex < 2; teamIndex++)
                            {
                                for (int position = 0; position < Team.MaxSize; position++)
                                {
                                    Player player = match.teams[teamIndex].players[position];
                                    copiedMatch.teams[teamIndex].players[position] = player;
                                    playersAsSet.Remove(player);
                                }
                            }
                            // Record that we've used a match of this size already
                            numMatchSizesClone[matchSize]--;
                        }
                    }
                }

                playersClone = new List <Player>(playersAsSet);
            }
            else
            {
                playersClone = new List <Player>(parameters.players);
            }

            // Create blank matches
            List <Match> matchesToAdd = new List <Match>();

            foreach (var matchSizeAndCount in numMatchSizesClone)
            {
                for (int i = 0; i < matchSizeAndCount.Value; i++)
                {
                    matchesToAdd.Add(new Match(matchSizeAndCount.Key, false, false));
                }
            }

            // The players could be placed randomly, but the improver algorithm takes a lot less time if players are placed in the correct position

            // Randomly rearrange the list of players
            playersClone.Shuffle();

            // Assign each player to their primary position
            List <Player>[] playersPerPosition = new List <Player> [Team.MaxSize];
            for (int position = 0; position < Team.MaxSize; position++)
            {
                playersPerPosition[position] = new List <Player>();
            }
            foreach (Player player in playersClone)
            {
                playersPerPosition[(int)player.PositionPrimary].Add(player);
            }

            // Look at how many players are requested for each position
            int[] requestedPlayers = new int[Team.MaxSize];
            foreach (Match match in matchesToAdd)
            {
                foreach (Team team in match.teams)
                {
                    for (int position = 0; position < Team.MaxSize; position++)
                    {
                        if (team.PositionShouldBeFilled((Position)position))
                        {
                            requestedPlayers[position]++;
                        }
                    }
                }
            }

            for (int position = 0; position < Team.MaxSize; position++)
            {
                // If earlier positions require more players, give players from this group
                for (int earlierPosition = 0; earlierPosition < position; earlierPosition++)
                {
                    while (playersPerPosition[earlierPosition].Count < requestedPlayers[earlierPosition] && playersPerPosition[position].Count > 0)
                    {
                        MovePlayer(earlierPosition);
                    }
                }
                // If this group has too many players, give to the next group
                while (playersPerPosition[position].Count > requestedPlayers[position])
                {
                    MovePlayer(position + 1);
                }

                void MovePlayer(int targetPosition)
                {
                    var list = playersPerPosition[position];

                    // Pick a player to get moved
                    int chosen = -1;

                    for (int i = 0; i < list.Count; i++)
                    {
                        if (IsBetter())
                        {
                            chosen = i;
                        }

                        bool IsBetter()
                        {
                            // If we haven't chosen anything yet then this must be better
                            if (chosen == -1)
                            {
                                return(true);
                            }
                            // If one player's primary position is closer to the target then they are a good choice
                            // This can only happen if the target is later than the current position
                            if (list[i].PositionPrimary != list[chosen].PositionPrimary)
                            {
                                return(list[i].PositionPrimary > list[chosen].PositionPrimary);
                            }
                            // If the player's secondary position is the target then they are a good choice
                            bool chosenIsSecondary  = list[chosen].PositionSecondary == (Position)targetPosition;
                            bool currentIsSecondary = list[i].PositionSecondary == (Position)targetPosition;

                            if (chosenIsSecondary && !currentIsSecondary)
                            {
                                return(false);
                            }
                            if (!chosenIsSecondary && currentIsSecondary)
                            {
                                return(true);
                            }
                            // Pick the player with the worse grade (unless the target is Lead, in that case pick the better grade)
                            return((Position)targetPosition == Position.Lead
                                ? list[i].GradePrimary > list[chosen].GradePrimary
                                : list[i].GradePrimary > list[chosen].GradePrimary);
                        }
                    }

                    // Move the player
                    playersPerPosition[targetPosition].Add(list[chosen]);
                    list.RemoveAt(chosen);
                }
            }

            // Insert the players into the list of matches to add
            int[] index = new int[Team.MaxSize];
            foreach (Match match in matchesToAdd)
            {
                foreach (Team team in match.teams)
                {
                    for (int position = 0; position < Team.MaxSize; position++)
                    {
                        if (team.PositionShouldBeFilled((Position)position))
                        {
                            team.players[position] = playersPerPosition[position][index[position]++];
                        }
                    }
                }
            }

            // Add the matches to the day
            foreach (Match match in matchesToAdd)
            {
                day.matches.Add(match);
            }

            return(day);
        }
Пример #2
0
 void MaxNumMatches(MatchSize preferredSize)
 {
     Tools.PickNumGamesForPlayers(playersSelectedForDay.Count - fixedMatchesDay.Players().Count(), preferredSize, out Counter <MatchSize> numMatchSizes);
     SetMatchSizes(numMatchSizes);
 }