public LevelData GenerateLevelData(AutoGenConfig config)
        {
            LevelData lvlData = new LevelData();

            lvlData.type              = config.type;
            lvlData.total             = config.total;
            lvlData.max_order         = config.maxOrder;
            lvlData.first_arrivals    = config.firstArrivals;
            lvlData.full_patience_num = config.fullPatienceNum;
            lvlData.order_interval    = config.orderInterval;
            lvlData.litter_interval   = config.litterInterval;
            lvlData.broken_interval   = config.brokenInterval;
            lvlData.waiting_decay     = config.waitDecay;
            lvlData.cooking_decay     = config.cookingDecay;
            lvlData.burn_decay        = config.burnDecay;
            lvlData.order_decay       = config.orderDecay;

            List <CustomerOrder> orders = GenerateOrders(config.foodWeightList, config.customerList);
            List <string>        scoreList;
            Requirements         requirements;

            if (GenerateRequirements(orders, config, out scoreList, out requirements))
            {
                lvlData.scoreList    = scoreList;
                lvlData.requirements = requirements;
            }
            lvlData.orders = orders;
            return(lvlData);
        }
        public bool GenerateRequirements(List <CustomerOrder> orders, AutoGenConfig config, out List <string> scoreList, out Requirements requirements)
        {
            int estimateCustomerCount;

            scoreList    = EstimateTargetScore(orders, config, out estimateCustomerCount);
            requirements = CalcRequirements(orders, config, estimateCustomerCount);
            return(true);
        }
        protected Requirements CalcRequirements(List <CustomerOrder> orders, AutoGenConfig config, int customerCount)
        {
            Requirements requirements = new Requirements();
            int          diffculty    = config.difficulty;

            if (diffculty > 3)
            {
                diffculty = 3;
            }

            int additionFoodNum = diffculty;

            if (config.difficulty >= 3 && config.waitDecay.interval > 0)
            {
                float ratio = 1.0f + (config.difficulty - 1) * 0.15f;
                additionFoodNum = (int)Math.Ceiling(additionFoodNum * ratio);
            }

            foreach (CustomerOrder ord in orders)
            {
                ord.latestFirstCome = 0;
            }

            int additionCustNum = config.difficulty == 1 ? 1 : (int)Math.Ceiling((config.difficulty - 1) * 1.5f);

            // 生成指定食物
            if (config.random_food_requirement)
            {
                List <KeyValuePair <string, float> > sortedFoodWeights = new List <KeyValuePair <string, float> >();
                foreach (var item in config.foodWeightList)
                {
                    sortedFoodWeights.Add(item);
                }
                sortedFoodWeights.Sort((x, y) =>
                {
                    return(y.Value.CompareTo(x.Value));
                });

                // 随机取概率排前两位的食物
                int index = 0;
                int max   = sortedFoodWeights.Count;

                if (max > 2)
                {
                    max = 2;
                }
                index = _random.Next(0, max - 1);
                string requiredFood = sortedFoodWeights[index].Key;

                // 动态计算食物个数
                int specialCount = 0;
                foreach (CustomerOrder ord in orders)
                {
                    if (ord.foods.Contains(requiredFood) && ord.interval.min > 0)
                    {
                        specialCount += customerCount / ((ord.interval.max + ord.interval.min) / 2);
                    }
                }
                float weight;
                config.foodWeightList.TryGetValue(requiredFood, out weight);
                int requireNum = (int)Math.Ceiling(weight * (customerCount - specialCount)) + specialCount + additionFoodNum;

                if (requireNum < MIN_REQUIRE_FOOD_NUM)
                {
                    requireNum = MIN_REQUIRE_FOOD_NUM;
                }

                if (config.type == LevelType.FIXED_TIME)
                {
                    float cookTime = CalcFoodCookTime(requiredFood);
                    if (cookTime > 1e-6)
                    {
                        max = (int)Math.Ceiling(config.total / cookTime);
                        if (requireNum > max)
                        {
                            requireNum = max;
                        }
                    }
                }

                Requirements.NameAndNumber req = new Requirements.NameAndNumber();
                req.name   = requiredFood;
                req.number = requireNum;
                requirements.requiredFoods.Add(req);

                int maxWeightIndex = -1;
                for (int i = 0; i < orders.Count; ++i)
                {
                    if (orders[i].foods.Contains(requiredFood))
                    {
                        if (maxWeightIndex < 0)
                        {
                            maxWeightIndex = i;
                        }
                        else if (orders[i].weight > orders[maxWeightIndex].weight)
                        {
                            maxWeightIndex = i;
                        }
                    }
                }
                if (maxWeightIndex >= 0)
                {
                    orders[maxWeightIndex].latestFirstCome = (int)Math.Ceiling((float)customerCount / requireNum);
                }
            }

            // 计算服务任意顾客总数
            if (config.any_customer_requirement)
            {
                Requirements.NameAndNumber req = new Requirements.NameAndNumber();
                req.name   = "anyone";
                req.number = customerCount + additionCustNum;
                requirements.requiredCustomers.Add(req);
            }

            // 生成指定顾客
            if (config.random_customer_requirement)
            {
                float weight = 0;
                // 随机选取概率排前二位的顾客
                Dictionary <string, float> customerWeights = new Dictionary <string, float>();
                foreach (CustomerOrder ord in orders)
                {
                    weight = 0;
                    customerWeights.TryGetValue(ord.customer, out weight);
                    customerWeights[ord.customer] = weight + ord.weight;
                }
                List <KeyValuePair <string, float> > sortedCustomerWeights = new List <KeyValuePair <string, float> >();
                foreach (var item in customerWeights)
                {
                    sortedCustomerWeights.Add(item);
                }
                sortedCustomerWeights.Sort((x, y) =>
                {
                    return(y.Value.CompareTo(x.Value));
                });
                int    index            = _random.Next(0, 1);
                string requiredCustomer = sortedCustomerWeights[index].Key;

                // 动态计算个数
                int specialCount = 0;
                foreach (CustomerOrder ord in orders)
                {
                    if (ord.customer.Equals(requiredCustomer) && ord.interval.min > 0)
                    {
                        specialCount += customerCount / ((ord.interval.max + ord.interval.min) / 2);
                    }
                }

                weight = 0;
                float total_weight = 0;
                foreach (CustomerOrder ord in orders)
                {
                    if (ord.customer.Equals(requiredCustomer))
                    {
                        weight += ord.weight;
                    }
                    total_weight += ord.weight;
                }

                int min = 0;
                if (diffculty >= 3 && config.type == LevelType.LOST_CUSTOMER)
                {
                    min = (int)Math.Ceiling((float)customerCount / (float)config.maxOrder);
                }
                int requireNum = (int)Math.Ceiling(weight / total_weight * (customerCount - specialCount)) + specialCount + additionCustNum;
                if (requireNum < min)
                {
                    requireNum = min;
                }

                Requirements.NameAndNumber req = new Requirements.NameAndNumber();
                req.name   = requiredCustomer;
                req.number = requireNum;
                requirements.requiredCustomers.Add(req);

                int maxWeightIndex = -1;
                for (int i = 0; i < orders.Count; ++i)
                {
                    if (orders[i].customer.Equals(requiredCustomer))
                    {
                        if (maxWeightIndex < 0)
                        {
                            maxWeightIndex = i;
                        }
                        else if (orders[i].weight > orders[maxWeightIndex].weight)
                        {
                            maxWeightIndex = i;
                        }
                    }
                }
                if (maxWeightIndex >= 0)
                {
                    orders[maxWeightIndex].latestFirstCome = (int)Math.Ceiling((float)customerCount / requireNum);
                }
            }

            // 生成指定收集笑脸个数
            if (config.random_smile_requirement && config.fullPatienceNum > 0)
            {
                float patiencePerCustomer = 4.5f;
                if (config.waitDecay.interval > 0)
                {
                    patiencePerCustomer -= 0.2f;
                }

                requirements.smileCount = (int)Math.Ceiling((float)customerCount * patiencePerCustomer / config.fullPatienceNum);
            }

            return(requirements);
        }
        protected List <string> EstimateTargetScore(List <CustomerOrder> orders, AutoGenConfig config, out int estimateCustomerCount)
        {
            int score = 0;

            estimateCustomerCount = 0;

            float totalprice = 0;
            float multiple   = 1;

            switch (config.difficulty)
            {
            case 1:
                multiple = 1.3f;
                break;

            case 2:
                multiple = 1.5f;
                break;

            case 3:
                multiple = 1.8f;
                break;

            case 4:
                multiple = 2.5f;
                break;

            case 5:
                multiple = 3.5f;
                break;

            default:
                break;
            }

            if (config.type == LevelType.FIXED_TIME)
            {
                // 简单利用加权平均制作时间乘以加权平均价格来计算
                float totaltime = 0;
                foreach (CustomerOrder ord in orders)
                {
                    float waittime;
                    totaltime  += CalcOrderTime(ord) * ord.weight;
                    totalprice += CalcIncome(ord, out waittime) * ord.weight;
                }
                float lastFirstArriveTime = 0;
                if (config.firstArrivals.Count > 0)
                {
                    lastFirstArriveTime = config.firstArrivals[config.firstArrivals.Count - 1];
                }

                estimateCustomerCount = (int)(Math.Ceiling(((float)config.total - lastFirstArriveTime) / totaltime) + config.maxOrder * multiple);
            }
            else if (config.type == LevelType.FIXED_CUSTOMER)
            {
                foreach (CustomerOrder ord in orders)
                {
                    float waittime;
                    totalprice += CalcIncome(ord, out waittime) * ord.weight;
                }
                estimateCustomerCount = config.total;
            }
            else if (config.type == LevelType.LOST_CUSTOMER)
            {
                // 估算极限时间
                float totaltime      = 0;
                float total_waittime = 0;
                foreach (CustomerOrder ord in orders)
                {
                    float waittime;
                    totaltime      += CalcOrderTime(ord) * ord.weight;
                    totalprice     += CalcIncome(ord, out waittime) * ord.weight;
                    total_waittime += waittime * ord.weight;
                }

                totaltime *= 1.3f + (5 - config.difficulty) * 0.1f;

                int   num   = 0;
                float decay = 1.0f;
                while (decay * total_waittime > totaltime)
                {
                    num   += (int)config.waitDecay.interval;
                    decay *= config.waitDecay.rate;
                }
                estimateCustomerCount = num;
                // 多一个流失机会则多加一轮
                estimateCustomerCount += (int)((config.total - 1) * config.maxOrder * (multiple * 0.5f));
            }
            else
            {
                System.Diagnostics.Debug.Assert(false, "无效的关卡类型!");
            }

            float score_ratio = 1.0f + (config.difficulty - 1) * 0.05f;

            score = (int)(totalprice * estimateCustomerCount * score_ratio / 10) * 10;

            float scoreAmp = 1.0f + (0.05f * config.difficulty) + ((float)_random.NextDouble() * 0.05f + 0.1f) * config.difficulty;
            int   score2   = (int)(score * scoreAmp / 10) * 10;
            int   score3   = (int)(score2 * scoreAmp / 10) * 10;

            return(new List <string>()
            {
                score.ToString(), score2.ToString(), score3.ToString()
            });
        }