/// <summary>
        /// Groups the calculated team combinations for matches.  in a way, that most matches
        /// can be played in parallel.
        /// </summary>
        /// <param name="legType">First leg or return leg.</param>
        /// <param name="optiType">Optimization type for groups. Differences can be seen be with an uneven number of teams.</param>
        /// <returns>Return a collection containing collections of team combinations.</returns>
        internal Collection <TeamCombinationGroup <T> > GetBundledGroups(LegType legType, CombinationGroupOptimization optiType)
        {
            var combinationsQueue = new Queue <TeamCombination <T> >(_group.Count);
            TeamCombinationGroup <T> group;
            var bundledGroups = new Collection <TeamCombinationGroup <T> >();

            // create the FIFO queue
            foreach (var combination in _group)
            {
                combinationsQueue.Enqueue(combination);
            }

            switch (optiType)
            {
            case CombinationGroupOptimization.NoGrouping:
                // every group contains a collection with only 1 match
                while (combinationsQueue.Count > 0)
                {
                    group = new TeamCombinationGroup <T>();
                    group.Add(combinationsQueue.Dequeue());
                    bundledGroups.Add(group);
                }
                break;

            case CombinationGroupOptimization.GroupWithAlternatingHomeGuest:
                group = new TeamCombinationGroup <T>();
                while (combinationsQueue.Count > 0)
                {
                    TeamCombination <T> combination = combinationsQueue.Dequeue();
                    if (AnyTeamExistsInGroup(combination, group))
                    {
                        bundledGroups.Add(group);
                        group = new TeamCombinationGroup <T>();
                    }
                    group.Add(combination);
                }
                if (group.Count > 0)
                {
                    bundledGroups.Add(group);
                }
                break;

            case CombinationGroupOptimization.LeastGroupsPossible:
                while (combinationsQueue.Count > 0)
                {
                    var tmpGroup = new List <TeamCombination <T> >();
                    tmpGroup.AddRange(combinationsQueue);

                    group = new TeamCombinationGroup <T>();
                    foreach (var combination in tmpGroup)
                    {
                        if (!AnyTeamExistsInGroup(combination, group))
                        {
                            group.Add(combinationsQueue.Dequeue());
                        }
                    }
                    bundledGroups.Add(group);
                }
                break;
            }
            return(bundledGroups);
        }
        /// <summary>
        /// Calculates all matches for the given teams, using the round robin system.
        /// </summary>
        /// <param name="refereeType">Determines how referees will be assigned for the matches.</param>
        /// <param name="legType">First leg or return leg.</param>
        /// <param name="optiType">Optimization type for groups. Differences can be seen be with an uneven number of teams.</param>
        /// <returns>Return a collection containing collections of optimized team combinations.</returns>
        public Collection <TeamCombinationGroup <T> > GetBundledGroups(RefereeType refereeType, LegType legType, CombinationGroupOptimization optiType)
        {
            _refereeType = refereeType;
            CalcCombinations();

            return(new CombinationGroupOptimizer <T>((legType == LegType.First) ? _combinationGroup : _combinationGroupReturnLeg).GetBundledGroups(legType, optiType));
        }