void ValidationTests()
        {
            HSCardsParser      parser  = new HSCardsParser("jsonWithTypes.json");
            HoningStoneBuilder builder = new HoningStoneBuilder();

            Dictionary <String, CardObject> cardTable = new Dictionary <string, CardObject>();
            HSCardOperator op = new HSCardOperator();

            // Populate all card table
            foreach (string key in parser.objects.Keys)
            {
                List <CardObject> cards_objects = parser.objects[key];
                builder.GenCardTableObject(ref cards_objects, ref cardTable);
            }

            HSCombosParser combosParser = new HSCombosParser();

            //combosParser.PopulateFromHoningNetwork(ref decksParser, ref cardTable, 5);
            combosParser.PopulateFromJson("ALYCOMBOOK.json");

            int maxComboSize = 10;
            //int maxMana         = 50;
            int maxCombos = 100;

            Random rand = new Random();

            foreach (String hero in parser.objects.Keys)
            {
                if (hero == "Neutral")
                {
                    continue;
                }

                HoningNetwork <String> net       = new HoningNetwork <string>();
                List <CardObject>      heroCards = parser.objects[hero];
                List <CardObject>      neutral   = parser.objects["Neutral"];

                builder.PopulateFromCardData(ref net, ref heroCards);
                builder.BuildThirdLevel(ref net, ref heroCards);
                builder.PopulateFromCardData(ref net, ref neutral);
                builder.BuildThirdLevel(ref net, ref neutral);

                HSHoningBayes fixedBayes = new HSHoningBayes(hero.ToLower(), ref combosParser, ref net, ref cardTable);

                fixedBayes.SaveKNNDataset("ARSDataset.dataset");

                Dataset       fixedDataset = new Dataset("ARSDataset.dataset", ',');
                KNNEfficiency fixedKNN     = new KNNEfficiency(fixedDataset);

                HSHoningBayes dynamicBayes = new HSHoningBayes(hero.ToLower(), ref combosParser, ref net, ref cardTable);

                List <String> Terminals = net.getTerminalList();

                // Random Honing config
                HSCardExpasionConfiguration config = new HSCardExpasionConfiguration(fixedBayes, fixedKNN);
                config.cutByManaCost            = false;
                config.max_lowerlevel_to_expand = 1;
                config.giver_inflation          = false;

                // Guided Honing config
                HSCardExpasionConfiguration configGuided = new HSCardExpasionConfiguration(fixedBayes, fixedKNN);
                configGuided.cutByManaCost            = false;
                configGuided.max_lowerlevel_to_expand = 1;
                configGuided.giver_inflation          = false;

                // Tests i and ii control variables
                double ihs  = 0.0f;
                double iihs = 0.0f;

                double[] surprise_vec;
                Double[] comboArray;
                // Tests i and ii control variables

                // Tests i, ii, iii, iv, v control variables
                int           mana = 50;
                double        surprise;
                double        efficiency;
                double        creativity;
                List <String> combo;
                // Tests i, ii, iii, iv, v control variables

                int combosize = 5;

                for (int combos = 0; combos < maxCombos; combos++)
                {
                    //for (int mana = 2; mana <= maxMana; mana++)
                    //{
                    //for (int combosize = 2; combosize <= maxComboSize; combosize++)
                    // {
                    // Honing shared seed
                    int    RandomicSeed = rand.Next(Terminals.Count);
                    String seed         = Terminals[RandomicSeed];

                    //--------------------------------------------------------------------------------------------------------------------------
                    // Surpresa estática
                    // (i)totalmente aleatorio (sem honing)

                    /* List<String> randomComboList = new List<String>();
                     * while(randomComboList.Count < combosize)
                     * {
                     *   int randNode = rand.Next(Terminals.Count);
                     *   randomComboList.Add(Terminals[randNode]);
                     * }
                     *
                     * // Surprise
                     * ComboNode node = ToComboNode(randomComboList);
                     *
                     * fixedBayes.CalculateSurprise(ref node, 1, out surprise_vec, out surprise, false);
                     *
                     * // update surprise
                     * if (surprise > ihs)
                     *   ihs = surprise;
                     *
                     * // Calculate efficiency
                     * fixedBayes.GenerateComboVector(ref node, out comboArray);
                     * Instance target = new Instance(comboArray);
                     * efficiency = fixedKNN.getKNearestWinrates(target, 5);
                     * efficiency /= 100;
                     *
                     * // Calculate creativity
                     * creativity = ((surprise / ihs) + efficiency) / 2;
                     *
                     * //--------------------------------------------------------------------------------------------------------------------------
                     *
                     * // (ii)honing velho aleatorio
                     * Dictionary<String, String> shcombolist = new Dictionary<String, String>();
                     * Dictionary<String, HoningNode<String>> honingOut;
                     * List<String> bridges;
                     * net.getMfList(seed, out bridges);
                     * net.recruitNeurds(bridges, out honingOut, "terminal");
                     *
                     * List<String> comboH = new List<string>();
                     *
                     * int limit = combosize;
                     * if(honingOut.Count < combosize)
                     *   limit = honingOut.Count;
                     * for (int i = 0; i < limit; i++)
                     *   comboH.Add(honingOut.ElementAt(i).Key);
                     *
                     * // Surprise
                     * node = ToComboNode(comboH);
                     *
                     * fixedBayes.CalculateSurprise(ref node, 1, out surprise_vec, out surprise, false);
                     *
                     * // update surprise
                     * if (surprise > iihs)
                     *   iihs = surprise;
                     *
                     * // Calculate efficiency
                     * fixedBayes.GenerateComboVector(ref node, out comboArray);
                     * target = new Instance(comboArray);
                     * efficiency = fixedKNN.getKNearestWinrates(target, 5);
                     * efficiency /= 100;
                     *
                     * // Calculate creativity
                     * creativity = ((surprise / iihs) + efficiency) / 2;
                     *
                     * //--------------------------------------------------------------------------------------------------------------------------
                     *
                     * // (iii)honing novo aleatorio
                     * HoningTest(
                     *   config,
                     *   fixedBayes,
                     *   fixedKNN,
                     *   mana,
                     *   combosize,
                     *   net,
                     *   cardTable,
                     *   seed,
                     *   op,
                     *   ExpansionGeneralPolitics.Random,
                     *   out combo,
                     *   out creativity,
                     *   out efficiency,
                     *   out surprise);*/

                    //--------------------------------------------------------------------------------------------------------------------------

                    // (iv)busca pela aresta com maior valor eficiência + surpresa (GULOSO)
                    HoningTest(
                        configGuided,
                        fixedBayes,
                        fixedKNN,
                        mana,
                        combosize,
                        net,
                        cardTable,
                        seed,
                        op,
                        ExpansionGeneralPolitics.Weight,
                        out combo,
                        out creativity,
                        out efficiency,
                        out surprise);

                    Console.WriteLine("Cluster honing finished runing.");
                    //--------------------------------------------------------------------------------------------------------------------------


                    //--------------------------------------------------------------------------------------------------------------------------

                    // Surpresa dinâmica
                    // (i)totalmente aleatorio (sem honing)
                    // (ii)honing velho aleatorio
                    // (iii)honing novo aleatorio
                    // (iv)busca pela aresta com maior valor eficiência + surpresa
                    //}
                }
                //}
            }
        }
        void HoningTest(
            HSCardExpasionConfiguration config,
            HSHoningBayes fixedBayes,
            KNNEfficiency fixedKNN,
            int mana,
            int maxCards,
            HoningNetwork <String> net,
            Dictionary <String, CardObject> cardTable,
            String seed,
            HSCardOperator op,
            ExpansionGeneralPolitics pol,
            out List <String> combo,
            out double creativity,
            out double efficiency,
            out double surprise)
        {
            config.maxCards   = maxCards;
            config.total_mana = mana;
            List <List <String> > out_subcluster;
            List <String>         out_combo;

            op.GreedyExpansionDelegated(
                ref net,
                ref config,
                ref cardTable,
                pol,
                PriorityPolitics.Random,
                PriorityPolitics.Random,
                seed,
                out out_subcluster,
                out out_combo);

            // Context filter
            int voidCount = 0;

            for (int i = 0; i < out_combo.Count; i++)
            {
                if (out_combo[i] == "")
                {
                    voidCount++;
                }
            }

            while (voidCount > 0)
            {
                out_combo.Remove("");
                voidCount--;
            }

            // Surprise
            ComboNode comboNode = ToComboNode(out_combo);

            double[] surpriseVector;
            fixedBayes.CalculateSurprise(ref comboNode, 1, out surpriseVector, out surprise, true);

            // Calculate efficiency
            Double[] efficiencyVector;
            config.bayes.GenerateComboVector(ref comboNode, out efficiencyVector);
            Instance knnInstance = new Instance(efficiencyVector);

            efficiency = config.knn.getKNearestWinrates(knnInstance, 5);

            // Percent
            efficiency /= 100;

            // Calculate creativity
            creativity = ((surprise / config.highestSurprise) + efficiency) / 2;

            // Combo return
            combo = out_combo;
        }
Ejemplo n.º 3
0
        public void PopulateFromHoningNetwork(ref HSDecksParser decks, ref Dictionary <String, CardObject> cardTable, int mana_mult)
        {
            combos_per_card    = 10;
            combos_by_quantity = new Dictionary <string, Dictionary <int, List <ComboNode> > >();

            // Hero loop
            foreach (String hero in decks.decks_by_hero.Keys)
            {
                // Decks loop
                foreach (HSDeckInfo deckinfo in decks.decks_by_hero[hero])
                {
                    // Generate honingNet for the deck
                    HoningNetwork <String> deck_net      = new HoningNetwork <string>();
                    List <CardObject>      cards_objects = new List <CardObject>();
                    HoningStoneBuilder     builder       = new HoningStoneBuilder();

                    // Generate card table info to populate the honingNetwork
                    foreach (String card in deckinfo.cards)
                    {
                        if (cardTable.ContainsKey(card))
                        {
                            cards_objects.Add(cardTable[card]);
                        }
                    }

                    builder.PopulateFromCardData(ref deck_net, ref cards_objects);
                    builder.BuildThirdLevel(ref deck_net, ref cards_objects);

                    // Generate all combos
                    HSCardOperator op = new HSCardOperator();
                    HSCardExpasionConfiguration conf = new HSCardExpasionConfiguration(null, null);

                    for (int j = 1; j < mana_mult; j++)
                    {
                        // Mana to spend on combo
                        conf.total_mana = 10 * j;

                        // Same deck insertion flag
                        bool same_deck = false;
                        foreach (String card in deckinfo.cards)
                        {
                            for (int i = 0; i < combos_per_card; i++)
                            {
                                List <List <String> > combo;
                                List <String>         sCombo;
                                op.GreedyExpansionDelegated(
                                    ref deck_net,
                                    ref conf,
                                    ref cardTable,
                                    ExpansionGeneralPolitics.Random,
                                    PriorityPolitics.Random,
                                    PriorityPolitics.Random,
                                    card,
                                    out combo,
                                    out sCombo);

                                // Create new combo object(Node) or get an existing one
                                Dictionary <String, String> comboToFind = new Dictionary <string, string>();
                                foreach (String c in sCombo)
                                {
                                    comboToFind.Add(c, c);
                                }

                                if (comboToFind.Count == 0)
                                {
                                    continue;
                                }

                                ComboNode new_combo = FindCombo(ref comboToFind, hero);

                                if (new_combo == null)
                                {
                                    new_combo = new ComboNode();
                                    if (!combos_by_quantity.ContainsKey(hero))
                                    {
                                        combos_by_quantity.Add(hero, new Dictionary <int, List <ComboNode> >());
                                    }
                                    if (!combos_by_quantity[hero].ContainsKey(comboToFind.Count))
                                    {
                                        combos_by_quantity[hero].Add(comboToFind.Count, new List <ComboNode>());
                                    }


                                    // Configura winrate for this combo
                                    float comboWinrate;
                                    float.TryParse(deckinfo.winrate, out comboWinrate);
                                    new_combo.winrates.Add(comboWinrate);
                                    new_combo.combo = comboToFind;

                                    // Add the combo to the master holder
                                    combos_by_quantity[hero][comboToFind.Count].Add(new_combo);
                                }
                                else
                                {
                                    if (!same_deck && new_combo.combo.Count != 0)
                                    {
                                        float comboWinrate;
                                        float.TryParse(deckinfo.winrate, out comboWinrate);
                                        new_combo.winrates.Add(comboWinrate);
                                    }
                                }

                                same_deck = true;
                            }
                        } // end foreach card
                    }     // end for manda
                }         // end foreach deck
            }             // end foreach hero
        }
        public List <String> GreedyExpansion(
            ref HoningNetwork <String> net,
            ref HSCardExpasionConfiguration config,
            ref Dictionary <String, CardObject> cardTable,
            ExpansionGeneralPolitics politic,
            PriorityPolitics giverPriorities,
            PriorityPolitics receiverPriorities,
            String seed)
        {
            HSCardCluster base_cluster = GenerateCardCluster(seed, ref cardTable, ref net);

            if (base_cluster == null)
            {
                return(null);
            }

            if (config.total_mana == 0)
            {
                return(null);
            }

            List <String> comboNodes = new List <String>();

            List <String> combo = new List <String>();

            combo.Add(base_cluster.card);

            Dictionary <String, bool> markers = new Dictionary <string, Boolean>();

            List <String> giver_recruiting;
            List <String> receiver_recruiting;

            if (config.giver_inflation)
            {
                giver_recruiting = RecruitNeighbours(ref net, ref base_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                comboNodes.AddRange(giver_recruiting);
            }

            if (config.receiver_inflation)
            {
                receiver_recruiting = RecruitNeighbours(ref net, ref base_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                comboNodes.AddRange(receiver_recruiting);
            }

            while (comboNodes.Count > 0)
            {
                String current = comboNodes.First();
                comboNodes.Remove(current);
                HSCardCluster new_cluster = GenerateCardCluster(current, ref cardTable, ref net);

                if (!markers.ContainsKey(current))
                {
                    markers.Add(current, true);
                }

                combo.Add(new_cluster.card);

                if (config.giver_inflation)
                {
                    giver_recruiting = RecruitNeighbours(ref net, ref new_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(giver_recruiting);
                }

                if (config.receiver_inflation)
                {
                    receiver_recruiting = RecruitNeighbours(ref net, ref new_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(receiver_recruiting);
                }
            }

            // Mana threshold 10 mana = 1 turn, 30 mana = 3 turns combo
            if (config.cutByManaCost)
            {
                List <String> new_output = new List <String>();
                int           total_mana = 0;
                foreach (String key in combo)
                {
                    String s = key.ToLower();
                    int    mana_cost;
                    Int32.TryParse(cardTable[s].cost, out mana_cost);
                    total_mana += mana_cost;

                    if (total_mana >= config.total_mana)
                    {
                        break;
                    }

                    new_output.Add(key);

                    if (new_output.Count == config.maxCards)
                    {
                        break;
                    }
                }

                return(new_output);
            }

            return(combo);
        }
        public void GreedyExpansionDelegated(
            ref HoningNetwork <String> net,
            ref HSCardExpasionConfiguration config,
            ref Dictionary <String, CardObject> cardTable,
            ExpansionGeneralPolitics politic,
            PriorityPolitics giverPriorities,
            PriorityPolitics receiverPriorities,
            String seed,
            out List <List <String> > out_subcomboClusters,
            out List <String> out_simpleComboList)
        {
            HSCardCluster base_cluster = GenerateCardCluster(seed, ref cardTable, ref net);

            out_subcomboClusters = new List <List <string> >();
            out_simpleComboList  = new List <string>();

            if (base_cluster == null)
            {
                return;
            }

            if (config.total_mana == 0)
            {
                return;
            }

            List <List <String> > final_form = new List <List <string> >();

            List <String> comboNodes = new List <String>();

            List <String> combo = new List <String>();

            combo.Add(base_cluster.card);

            Dictionary <String, bool> markers = new Dictionary <string, Boolean>();

            List <String> giver_recruiting;
            List <String> receiver_recruiting;

            if (config.giver_inflation)
            {
                giver_recruiting = RecruitNeighbours(ref net, ref base_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                comboNodes.AddRange(giver_recruiting);
                combo.AddRange(giver_recruiting);
            }

            if (config.receiver_inflation)
            {
                receiver_recruiting = RecruitNeighbours(ref net, ref base_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                comboNodes.AddRange(receiver_recruiting);
                combo.AddRange(receiver_recruiting);
            }

            final_form.Add(combo);

            // Context filter
            int voidCount = 0;

            for (int i = 0; i < comboNodes.Count; i++)
            {
                if (comboNodes[i] == "")
                {
                    voidCount++;
                }
            }

            while (voidCount > 0)
            {
                comboNodes.Remove("");
                voidCount--;
            }

            while (comboNodes.Count > 0)
            {
                String current = comboNodes.First();
                comboNodes.Remove(current);
                HSCardCluster new_cluster = GenerateCardCluster(current, ref cardTable, ref net);

                combo = new List <String>();
                combo.Add(new_cluster.card);

                if (!markers.ContainsKey(current))
                {
                    markers.Add(current, true);
                }

                if (config.giver_inflation)
                {
                    giver_recruiting = RecruitNeighbours(ref net, ref new_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(giver_recruiting);
                    combo.AddRange(giver_recruiting);
                }

                if (config.receiver_inflation)
                {
                    receiver_recruiting = RecruitNeighbours(ref net, ref new_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(receiver_recruiting);
                    combo.AddRange(receiver_recruiting);
                }

                final_form.Add(combo);

                if (final_form.Count == config.maxCards)
                {
                    break;
                }
            }

            // Mana threshold 10 mana = 1 turn, 30 mana = 3 turns combo
            if (config.cutByManaCost)
            {
                Dictionary <String, String> keys = new Dictionary <string, string>();
                int  total_mana = 0;
                bool breaked    = false;
                foreach (List <String> key in final_form)
                {
                    foreach (String k in key)
                    {
                        String s = k.ToLower();

                        if (keys.ContainsKey(k))
                        {
                            continue;
                        }

                        int mana_cost;
                        Int32.TryParse(cardTable[s].cost, out mana_cost);
                        total_mana += mana_cost;

                        if (total_mana >= config.total_mana)
                        {
                            breaked = true;
                            break;
                        }

                        keys.Add(k, k);

                        if (keys.Count == config.maxCards)
                        {
                            breaked = true;
                            break;
                        }
                    }

                    if (breaked)
                    {
                        break;
                    }
                }
                out_simpleComboList = keys.Keys.ToList();
            }
            else
            {
                bool breaked = false;
                foreach (List <String> key in final_form)
                {
                    foreach (String k in key)
                    {
                        out_simpleComboList.Add(k);
                        if (out_simpleComboList.Count == config.maxCards)
                        {
                            breaked = true;
                            break;
                        }
                    }
                    if (breaked)
                    {
                        break;
                    }
                }
            }

            out_subcomboClusters = final_form;
        }
        public List <String> RecruitNeighbours(
            ref HoningNetwork <String> net,
            ref Dictionary <String, Dictionary <String, HoningNode <String> > > subcluster,
            ref HSCardExpasionConfiguration config,
            ref Dictionary <String, CardObject> cardTable,
            ref ExpansionGeneralPolitics politic,
            ref PriorityPolitics selectionPriorities,
            ref Dictionary <String, Boolean> markers,
            ref List <String> combo)
        {
            List <String> res = new List <string>();

            if (subcluster.Count == 0)
            {
                return(res);
            }

            // Configurating expansion levels
            int upper_level_index = 0;

            if (config.max_upperLevel_to_expand < 0)
            {
                upper_level_index = -1;
            }
            else
            {
                Random rand = new Random();

                switch (selectionPriorities)
                {
                case PriorityPolitics.Random:
                    upper_level_index = rand.Next(subcluster.Count - 1);
                    break;

                case PriorityPolitics.First:
                    upper_level_index = 0;
                    break;

                case PriorityPolitics.Last:
                    upper_level_index = subcluster.Count - 1;
                    break;

                case PriorityPolitics.HigherWeight:
                    // NOT YET
                    break;

                case PriorityPolitics.LowestWeight:
                    // NOT YET
                    break;

                case PriorityPolitics.MidWeight:
                    // NOT YET
                    break;
                }
            }

            Dictionary <String, Dictionary <String, HoningNode <String> > > workingspace = new Dictionary <string, Dictionary <string, HoningNode <string> > >();

            if (upper_level_index < 0)
            {
                workingspace = subcluster;
            }
            else
            {
                workingspace.Add(subcluster.ElementAt(upper_level_index).Key, subcluster.ElementAt(upper_level_index).Value);
            }

            // Inflating solution
            foreach (String key in workingspace.Keys)
            {
                Dictionary <String, HoningNode <String> > dic = workingspace[key];
                List <String> space = InflateNeighbours(dic, cardTable, config, politic, markers, combo);
                res.AddRange(space);
            }

            return(res);
        }
        public List <String> InflateNeighbours(
            Dictionary <String, HoningNode <String> > workspace,
            Dictionary <String, CardObject> cardTable,
            HSCardExpasionConfiguration config,
            ExpansionGeneralPolitics politics,
            Dictionary <String, Boolean> markers,
            List <String> combo)
        {
            List <String> res = new List <string>();

            // Inflation window
            int    windowSize = 3;
            int    displace   = 0;
            Random dRange     = new Random();

            if (workspace.Count > windowSize)
            {
                displace = dRange.Next(workspace.Count - windowSize);

                for (int i = displace; i < displace + windowSize; i++)
                {
                    res.Add(workspace.ElementAt(i).Value.holder);
                }
            }
            else
            {
                foreach (String k in workspace.Keys)
                {
                    if (!markers.ContainsKey(k))
                    {
                        res.Add(workspace[k].holder);
                    }
                }
            }

            if (res.Count == 0)
            {
                return(res);
            }

            List <String> final_ret = new List <string>();

            Boolean[] check       = new Boolean[res.Count];
            Boolean   allCheckded = false;
            int       cur         = 0;

            switch (politics)
            {
            case ExpansionGeneralPolitics.Lowest_Mana:
                try
                {
                    res.Sort(
                        delegate(String a, String b)
                    {
                        if (a == null || b == null)
                        {
                            return(-1);
                        }
                        int Ia, Ib;
                        Int32.TryParse(cardTable[a].cost, out Ia);
                        Int32.TryParse(cardTable[b].cost, out Ib);
                        if (Ia > Ib)
                        {
                            return(0);
                        }
                        return(-1);
                    }
                        );
                }
                catch (ArgumentException)
                {
                }

                cur = 0;
                while (final_ret.Count < config.single_expasion_quant)
                {
                    if (allCheckded)
                    {
                        break;
                    }

                    check[cur] = true;
                    if (!markers.ContainsKey(res[cur]))
                    {
                        markers.Add(res[cur], true);
                        final_ret.Add(res[cur]);
                    }

                    cur++;

                    allCheckded = true;
                    for (int i = 0; i < res.Count; i++)
                    {
                        if (check[i] == false)
                        {
                            allCheckded = false;
                            break;
                        }
                    }
                }

                break;

            case ExpansionGeneralPolitics.Higher_Mana:
                try
                {
                    res.Sort(
                        delegate(String a, String b)
                    {
                        if (a == null || b == null)
                        {
                            return(-1);
                        }
                        int Ia, Ib;
                        Int32.TryParse(cardTable[a].cost, out Ia);
                        Int32.TryParse(cardTable[a].cost, out Ib);
                        if (Ia < Ib)
                        {
                            return(0);
                        }
                        return(-1);
                    }
                        );
                }
                catch (ArgumentException)
                {
                }

                cur = 0;
                while (final_ret.Count < config.single_expasion_quant)
                {
                    if (allCheckded)
                    {
                        break;
                    }

                    check[cur] = true;
                    if (!markers.ContainsKey(res[cur]))
                    {
                        markers.Add(res[cur], true);
                        final_ret.Add(res[cur]);
                    }

                    cur++;

                    allCheckded = true;
                    for (int i = 0; i < res.Count; i++)
                    {
                        if (check[i] == false)
                        {
                            allCheckded = false;
                            break;
                        }
                    }
                }
                break;

            case ExpansionGeneralPolitics.Random:
                // Roullet selection

                Random rand  = new Random();
                int    total = config.single_expasion_quant;
                cur = 0;

                for (int i = 0; i < res.Count; i++)
                {
                    check[i] = false;
                }

                while (total > 0)
                {
                    if (allCheckded)
                    {
                        break;
                    }

                    if (cur >= res.Count)
                    {
                        cur = 0;
                    }

                    float t = (float)rand.NextDouble();
                    if (t >= config.single_expasion_quant_threshold)
                    {
                        check[cur] = true;
                        if (!markers.ContainsKey(res[cur]))
                        {
                            markers.Add(res[cur], true);
                            final_ret.Add(res[cur]);
                            total--;
                        }
                    }
                    cur++;

                    allCheckded = true;
                    for (int i = 0; i < res.Count; i++)
                    {
                        if (check[i] == false)
                        {
                            allCheckded = false;
                            break;
                        }
                    }
                }
                break;

            case ExpansionGeneralPolitics.Weight:
                // Do nothing
                // Calculate edge weights from efficiency and surprise
                ComboNode node = new ComboNode();

                foreach (String card in combo)
                {
                    node.combo.Add(card, card);
                }

                total = config.single_expasion_quant;

                List <KeyValuePair <string, double> > card_creativity_list = new List <KeyValuePair <string, double> >();
                String hs = "";
                double localHighSurprise = 0.0;
                foreach (String s in res)
                {
                    if (node.combo.ContainsKey(s))
                    {
                        continue;
                    }

                    node.combo.Add(s, s);

                    // Calculate efficiency
                    Double[] comboArray;
                    config.bayes.GenerateComboVector(ref node, out comboArray);
                    Instance target     = new Instance(comboArray);
                    Double   newWinrate = config.knn.getKNearestWinrates(target, 5);
                    newWinrate /= 100;

                    // Calculate surprise
                    double[] surpriseVec;
                    double   surprise;
                    config.bayes.CalculateSurprise(ref node, 1, out surpriseVec, out surprise, false);

                    // Update globalSurprise
                    if (surprise >= config.highestSurprise)
                    {
                        config.highestSurprise = surprise;
                    }

                    if (surprise >= localHighSurprise)
                    {
                        localHighSurprise = surprise;
                        hs = s;
                    }

                    // Calculate criativity
                    double creativityFactor = ((surprise / config.highestSurprise) + newWinrate) / 2;

                    card_creativity_list.Add(new KeyValuePair <string, double>(s, creativityFactor));

                    node.combo.Remove(s);
                }

                // Sort creativity combo

                /*card_creativity_list.Sort(delegate(KeyValuePair<string, double> A, KeyValuePair<string, double> B)
                 * {
                 *  if (A.Value < B.Value)
                 *      return 0;
                 *  return -1;
                 * });*/

                if (config.single_expasion_quant == 1)
                {
                    if (!markers.ContainsKey(hs))
                    {
                        final_ret.Add(hs);
                    }
                }
                else
                {
                    cur = 0;
                    while (final_ret.Count < config.single_expasion_quant)
                    {
                        if (allCheckded)
                        {
                            break;
                        }

                        check[cur] = true;
                        if (!markers.ContainsKey(card_creativity_list[cur].Key))
                        {
                            markers.Add(card_creativity_list[cur].Key, true);
                            final_ret.Add(card_creativity_list[cur].Key);
                        }

                        cur++;

                        allCheckded = true;
                        for (int i = 0; i < res.Count; i++)
                        {
                            if (check[i] == false)
                            {
                                allCheckded = false;
                                break;
                            }
                        }
                    }
                }
                break;
            }

            return(final_ret);
        }