Beispiel #1
0
        /// <summary>
        /// Returns a list of matches where each team from list1 plays against a team from teams2.
        /// All teams from both lists play one match. Whether a team plays home or away is determined randomly.
        /// The total number of teams for both lists must be an even number and both lists must contain an equal number of teams.
        /// </summary>
        public List <Match> GetMatches(IList <Team> teams1, IList <Team> teams2)
        {
            // Total number of teams must be even and both lists same number of teams.
            bool isValid = (teams1.Count + teams2.Count) % 2 == 0 &&
                           teams1.Count == teams2.Count;

            if (!isValid)
            {
                throw new Exception("Even number of teams expected and both lists same number of teams");
            }

            teams1.Shuffle();
            teams2.Shuffle();

            var matches = new List <Match>();

            for (int i = 0; i < teams1.Count; i++)
            {
                // Optionally swith home/away
                var  homeTeam          = teams1[i];
                var  awayTeam          = teams2[i];
                bool switchHomeAndAway = _randomizer.GetRandomBoolean();
                if (switchHomeAndAway)
                {
                    homeTeam = teams2[i];
                    awayTeam = teams1[i];
                }

                var match = MatchFactory.CreateMatch(homeTeam, awayTeam);

                matches.Add(match);
            }

            return(matches);
        }
        /// <summary>
        /// Creates a schedule for the first round.
        /// </summary>
        /// <param name="teams"></param>
        /// <returns></returns>
        public Dictionary <int, List <Match> > GetSchedule(List <Team> teams)
        {
            var  possible       = new[] { 2, 4, 8, 16, 32, 64, 128, 256 };
            bool argumentsValid = possible.Contains(teams.Count);

            if (!argumentsValid)
            {
                throw new Exception("Unexpected number of teams");
            }

            teams.Shuffle();

            // Draw the first round, the other rounds will be drawn later.
            var schedule = new Dictionary <int, List <Match> >();

            schedule[0] = new List <Match>();
            int numberOfMatches = teams.Count / 2;

            int teamIndex = 0;

            for (int i = 0; i < numberOfMatches; i++)
            {
                var homeTeam = teams[teamIndex];
                var awayTeam = teams[teamIndex + 1];
                var match    = MatchFactory.CreateMatch(homeTeam, awayTeam);
                schedule[0].Add(match);
                teamIndex += 2;
            }

            return(schedule);
        }
        public List <Match> DrawNextRound(List <Team> winnersPreviousRound)
        {
            var matchesNextRound = new List <Match>();

            winnersPreviousRound.Shuffle();

            int numberOfMatches = winnersPreviousRound.Count / 2;
            int teamIndex       = 0;

            for (int i = 0; i < numberOfMatches; i++)
            {
                var homeTeam = winnersPreviousRound[teamIndex];
                var awayTeam = winnersPreviousRound[teamIndex + 1];
                var match    = MatchFactory.CreateMatch(homeTeam, awayTeam);
                matchesNextRound.Add(match);
                teamIndex += 2;
            }

            return(matchesNextRound);
        }
Beispiel #4
0
        /// <summary>
        /// Returns a list of matches where all teams play one match.
        /// Whether a team plays home or away is determined randomly.
        /// The given team list must contain an even number of teams.
        /// </summary>
        public List <Match> GetMatches(IList <Team> teams)
        {
            // Even number of teams expected.
            bool isValid = teams.Count % 2 == 0;

            if (!isValid)
            {
                throw new Exception("Even number of teams expected");
            }

            teams.Shuffle();

            var matches = new List <Match>();

            for (int i = 0; i < teams.Count; i += 2)
            {
                var match = MatchFactory.CreateMatch(teams[i], teams[i + 1]);
                matches.Add(match);
            }

            return(matches);
        }
Beispiel #5
0
        public static Match GetValidMatch()
        {
            var match = MatchFactory.CreateMatch(HomeTeam, AwayTeam);

            return(match);
        }
Beispiel #6
0
        /// <summary>
        /// Round-Robin magic:
        /// The first team of teams1 stays where he is, but all
        /// other teams move one position clockwise across the two lists.
        /// All items of teams1 (except the first) move 1 position to the RIGHT, so
        /// the last item of teams1 becomes the last item of teams2.
        /// All items of teams2 move 1 position to the LEFT, so the first item of teams2
        /// becomes the second item of teams1.
        ///
        /// EXAMPLE :)
        ///
        /// Round 1. (1 plays 14, 2 plays 13, ... )
        /// 1  2  3  4  5  6  7
        /// 14 13 12 11 10 9  8
        /// The first item stays and rotate the others clockwise one position
        /// Round 2. (1 plays 13, 14 plays 12, ... )
        /// 1  14 2  3  4  5  6
        /// 13 12 11 10 9  8  7
        ///
        /// http://en.wikipedia.org/wiki/Round-robin_tournament#Scheduling_algorithm
        /// </summary>
        /// <param name="teams"></param>
        /// <returns></returns>
        private Dictionary <int, List <Match> > GetRoundRobinTournament(List <Team> teams, int numberOfRounds, bool alsoReturnMatches)
        {
            int numberOfTeams = teams.Count;

            // An even number of teams is expected.
            if (numberOfTeams % 2 != 0)
            {
                throw new ArgumentException("An even number of teams is expected");
            }

            var matchSchedule = new Dictionary <int, List <Match> >();

            var dummyTeam = teams.SingleOrDefault(team => team.Id == GetDummyTeam().Id);

            int numberOfTeamsHalf = numberOfTeams / 2;

            // Divide the list of teams in two lists and reverse the second list.
            var teams1 = teams.GetRange(0, numberOfTeams / 2);
            var teams2 = teams.GetRange(numberOfTeams / 2, numberOfTeams / 2);

            teams2.Reverse();

            // Keep track of the number of home matches of each team
            // so an as evenly as possible home-away schedule can be created.
            Dictionary <Team, int> homeMatchCounter = teams.ToDictionary(k => k, v => 0);

            // Create a match schedule for every round.
            for (int roundNr = 0; roundNr < numberOfRounds; roundNr++)
            {
                var   matches    = new List <Match>();
                Match dummyMatch = null;

                // Combine the teams in both lists into matches.
                for (int teamIndex = 0; teamIndex < numberOfTeamsHalf; teamIndex++)
                {
                    // Default the first team plays at home.
                    var homeTeam = teams1[teamIndex];
                    var awayTeam = teams2[teamIndex];

                    // The team that has had the least number of home matches will play at home, so swap if necessary.
                    if (roundNr != 0 && homeMatchCounter[homeTeam] > homeMatchCounter[awayTeam])
                    {
                        var tempTeam = homeTeam;
                        homeTeam = awayTeam;
                        awayTeam = tempTeam;
                    }

                    // Create match.
                    var match = MatchFactory.CreateMatch(homeTeam, awayTeam);
                    matches.Add(match);

                    // Remember the dummy match (if applicable) for future reference.
                    if (match.HomeTeam.Equals(dummyTeam) || match.AwayTeam.Equals(dummyTeam))
                    {
                        dummyMatch = match;
                    }

                    // Raise the home count for the home team.
                    homeMatchCounter[match.HomeTeam]++;
                }

                // Remove the dummy match if applicable.
                if (dummyMatch != null)
                {
                    matches.Remove(dummyMatch);
                }

                matchSchedule.Add(roundNr, matches);

                // Before continuing to the next round, do the Round-Robin magic as described above...

                // Insert the first item of teams2 on the second position of teams1
                teams1.Insert(1, teams2[0]);

                // Remove the first item of teams2
                teams2.RemoveAt(0);

                // Add the last item of teams1 at the end of teams2 and remove it from teams1
                var lastTeam1 = teams1[teams1.Count - 1];
                teams2.Add(lastTeam1);
                teams1.Remove(lastTeam1);
            }

            // Now the schedule is complete for the first half of the season, add the return matches, if necessary.
            if (alsoReturnMatches)
            {
                var returnMatchSchedule = new Dictionary <int, List <Match> >();

                foreach (var round in matchSchedule)
                {
                    // Create matches where the home team is the away team and vice versa.
                    var matches = round.Value.Select(match => MatchFactory.CreateMatch(homeTeam: match.AwayTeam, awayTeam: match.HomeTeam)).ToList();

                    int returnRoundNr = round.Key + numberOfRounds;
                    returnMatchSchedule.Add(returnRoundNr, matches);
                }

                // Merge the two dictionaries into one match schedule and return it.
                returnMatchSchedule.ToList().ForEach(x => matchSchedule.Add(x.Key, x.Value));
            }

            return(matchSchedule);
        }