internal static List <Skill> ProfessionBalanced(List <Skill> pool, int regularPerProfession, int elitePerProfession, int commonSkills)
        {
            // Create empty bags:
            GrabBag[] regular = new GrabBag[10];
            GrabBag[] elite   = new GrabBag[10];
            GrabBag   common  = new GrabBag();

            for (int i = 0; i < 10; ++i)
            {
                regular[i] = new GrabBag();
                elite[i]   = new GrabBag();
            }

            // Fill the bags!
            foreach (Skill skill in pool)
            {
                if (skill.Profession == Skill.Professions.None)
                {
                    // Fill up a single common skills bag. These are mostly PvE only skills. I'm not differentiating elite as there are only the three norn forms.
                    common.Add(skill);
                }
                else
                {
                    if (skill.IsElite)
                    {
                        elite[(int)skill.Profession].Add(skill);
                    }
                    else
                    {
                        regular[(int)skill.Profession].Add(skill);
                    }
                }
            }

            // Draw from the bags!
            List <Skill> codex = new List <Skill>();

            for (int i = 0; i < 10; ++i)
            {
                regular[i].PutXIntoCodex(codex, regularPerProfession);
                elite[i].PutXIntoCodex(codex, elitePerProfession);
            }

            common.PutXIntoCodex(codex, commonSkills);

            // Sort the codex properly and return it:
            codex.SkillSort();
            return(codex);
        }
        internal static List <Skill> AttributeBalanced(List <Skill> pool, int regularPerAttribute, int elitePerAttribute, int pveOnlyPulls)
        {
            // Prepare bags:
            GrabBag[] attrRegularBags  = new GrabBag[42];
            GrabBag[] attrEliteBags    = new GrabBag[42];
            GrabBag   common           = new GrabBag();
            GrabBag   noAttrRegularBag = new GrabBag();
            GrabBag   noAttrEliteBag   = new GrabBag();

            for (int i = 0; i < 42; ++i)
            {
                attrEliteBags[i]   = new GrabBag();
                attrRegularBags[i] = new GrabBag();
            }

            // Fill bags:
            foreach (Skill skill in pool)
            {
                if (skill.Attribute == Skill.Attributes.None)
                {
                    if (skill.IsElite)
                    {
                        skill.AddToBag(noAttrEliteBag);
                    }
                    else
                    {
                        skill.AddToBag(noAttrRegularBag);
                    }
                }
                else if (skill.Attribute == Skill.Attributes.PvE_Only)
                {
                    skill.AddToBag(common);
                }
                else // Any other attribute...
                {
                    if (skill.IsElite)
                    {
                        attrEliteBags[(int)skill.Attribute].Add(skill);
                    }
                    else
                    {
                        attrRegularBags[(int)skill.Attribute].Add(skill);
                    }
                }
            }

            // Draw from bags:
            List <Skill> codex = new List <Skill>();

            common.PutXIntoCodex(codex, pveOnlyPulls);
            noAttrRegularBag.PutXIntoCodex(codex, regularPerAttribute);
            noAttrEliteBag.PutXIntoCodex(codex, elitePerAttribute);
            for (int i = 0; i < 42; ++i)
            {
                attrRegularBags[i].PutXIntoCodex(codex, regularPerAttribute);
                attrEliteBags[i].PutXIntoCodex(codex, elitePerAttribute);
            }

            codex.SkillSort();

            return(codex);
        }
        static internal List <Skill> AttributeRegularProfessionElite(List <Skill> pool, int skillPerAttribute, int elitePerProfession, int pveOnlyPulls)
        {
            // Prepare bags:
            GrabBag[] attrRegularBags  = new GrabBag[42];
            GrabBag[] EliteBags        = new GrabBag[10];
            GrabBag   common           = new GrabBag();
            GrabBag   noAttrRegularBag = new GrabBag();

            for (int i = 0; i < 42; ++i)
            {
                attrRegularBags[i] = new GrabBag();
            }

            for (int i = 0; i < EliteBags.Length; ++i)
            {
                EliteBags[i] = new GrabBag();
            }

            // Fill bags:
            foreach (Skill skill in pool)
            {
                if (skill.IsElite)
                {
                    if (skill.Profession == Skill.Professions.None)
                    {
                        // The only elites without a profession are the norn blessings:
                        common.Add(skill);
                    }
                    else
                    {
                        EliteBags[(int)skill.Profession].Add(skill);
                    }
                }
                else
                {
                    if (skill.Attribute == Skill.Attributes.None)
                    {
                        skill.AddToBag(noAttrRegularBag);
                    }
                    else if (skill.Attribute == Skill.Attributes.PvE_Only)
                    {
                        skill.AddToBag(common);
                    }
                    else // Any other attribute...
                    {
                        attrRegularBags[(int)skill.Attribute].Add(skill);
                    }
                }
            }

            // Draw from bags:
            List <Skill> codex = new List <Skill>();

            common.PutXIntoCodex(codex, pveOnlyPulls);
            noAttrRegularBag.PutXIntoCodex(codex, skillPerAttribute);
            for (int i = 0; i < 42; ++i)
            {
                attrRegularBags[i].PutXIntoCodex(codex, skillPerAttribute);
            }

            for (int i = 0; i < EliteBags.Length; ++i)
            {
                EliteBags[i].PutXIntoCodex(codex, elitePerProfession);
            }

            codex.SkillSort();

            return(codex);
        }