Пример #1
0
        /// <summary>
        /// 计算指定地区的综合工作指数
        ///
        /// 综合工作指数 = SUM(缩放平移过的建筑工作效率 * 建筑优先级)
        /// 厢房效率不计入统计
        ///
        /// 由于必须在最开始执行,所以无法使用 prepared data
        /// </summary>
        /// <param name="partId"></param>
        /// <param name="placeId"></param>
        /// <returns></returns>
        private static float GetCompositeWorkIndex(int partId, int placeId)
        {
            float compositeWorkIndex = 0.0f;

            // 统计所有建筑的工作效率(厢房效率不计入统计)
            var buildings = DateFile.instance.homeBuildingsDate[partId][placeId];

            foreach (int buildingIndex in buildings.Keys)
            {
                if (!Original.BuildingNeedsWorker(partId, placeId, buildingIndex))
                {
                    continue;
                }

                if (Bedroom.IsBedroom(partId, placeId, buildingIndex))
                {
                    continue;
                }

                if (DateFile.instance.actorsWorkingDate.ContainsKey(partId) &&
                    DateFile.instance.actorsWorkingDate[partId].ContainsKey(placeId) &&
                    DateFile.instance.actorsWorkingDate[partId][placeId].ContainsKey(buildingIndex))
                {
                    int   workerId                = DateFile.instance.actorsWorkingDate[partId][placeId][buildingIndex];
                    int   workEffectiveness       = Original.GetWorkEffectiveness(partId, placeId, buildingIndex, workerId);
                    float scaledWorkEffectiveness = (workEffectiveness - 100f) / 100f;
                    int   priority                = HumanResource.GetBuildingWorkingPriority(partId, placeId, buildingIndex);

                    compositeWorkIndex += scaledWorkEffectiveness * priority;
                }
            }

            return(compositeWorkIndex);
        }
Пример #2
0
        // 对于每个需要厢房才能满效率的建筑,尝试找到邻接厢房,生成建筑列表和候选厢房列表
        private static void GetBedroomsForWork_PrepareData(int partId, int placeId,
                                                           Dictionary <int, BuildingWorkInfo> buildings,
                                                           Dictionary <int, List <int> > attrCandidates,
                                                           Dictionary <int, Dictionary <int, int> > workerAttrs,
                                                           Dictionary <int, BuildingInfo> buildingsNeedBedroom,
                                                           Dictionary <int, BedroomInfo> bedroomCandidates)
        {
            // 遍历所有建筑
            foreach (var info in buildings.Values)
            {
                // 排除厢房
                if (info.requiredAttrId == 0)
                {
                    continue;
                }

                // 如果没有候选人,则不寻找邻接厢房
                var sortedWorkerIds = attrCandidates[info.requiredAttrId];
                if (sortedWorkerIds.Any())
                {
                    int workerId     = sortedWorkerIds[0];
                    int attrMaxValue = workerAttrs[workerId][info.requiredAttrId];
                    // 凭单个候选人无法满效率
                    if (attrMaxValue < info.fullWorkingAttrValue)
                    {
                        // 找到邻接厢房,并创建供之后使用的数据结构
                        var adjacentBedrooms = Bedroom.GetAdjacentBedrooms(partId, placeId, info.buildingIndex);

                        // 记录需要厢房的建筑信息
                        buildingsNeedBedroom[info.buildingIndex] = new BuildingInfo
                        {
                            buildingWorkInfo = info,
                            adjacentBedrooms = adjacentBedrooms,
                        };

                        // 记录候选厢房的信息
                        foreach (int bedroomBuildingIndex in adjacentBedrooms)
                        {
                            if (!bedroomCandidates.ContainsKey(bedroomBuildingIndex))
                            {
                                bedroomCandidates[bedroomBuildingIndex] = new BedroomInfo
                                {
                                    buildingIndex        = bedroomBuildingIndex,
                                    buildingsNeedBedroom = new List <int>(),
                                };
                            }

                            bedroomCandidates[bedroomBuildingIndex].buildingsNeedBedroom.Add(info.buildingIndex);
                        }
                    }
                }
            }
        }
Пример #3
0
        // 获取增加工作效率的厢房列表
        // 如果某个建筑找不到标准状态下满效率的工作人选,那么就看其邻接区域有没有厢房,有则选择一个当作增加工作效率的厢房。
        public static Dictionary <int, List <BuildingWorkInfo> > GetBedroomsForWork(int partId, int placeId,
                                                                                    Dictionary <int, BuildingWorkInfo> buildings,
                                                                                    Dictionary <int, List <int> > attrCandidates,
                                                                                    Dictionary <int, Dictionary <int, int> > workerAttrs)
        {
            // 对于每个需要厢房才能满效率的建筑,尝试找到邻接厢房,生成需要厢房辅助的建筑列表和候选厢房列表
            // buildingIndex -> BuildingInfo
            var buildingsNeedBedroom = new Dictionary <int, BuildingInfo>();
            // bedroomIndex -> BedroomInfo
            var bedroomCandidates = new Dictionary <int, BedroomInfo>();

            Bedroom.GetBedroomsForWork_PrepareData(partId, placeId,
                                                   buildings, attrCandidates, workerAttrs, buildingsNeedBedroom, bedroomCandidates);

            // 按建筑优先级对需要厢房辅助的建筑排序,然后对于每个建筑,在其候选厢房中选择优先级最高的厢房
            List <int> sortedBuildingsNeedBedroom = buildingsNeedBedroom
                                                    .OrderByDescending(entry => entry.Value.buildingWorkInfo.priority)
                                                    .Select(entry => entry.Key).ToList();

            // 厢房 ID -> 该厢房辅助的建筑信息列表
            // bedroomIndex -> [BuildingWorkInfo, ]
            var bedroomsForWork = new Dictionary <int, List <BuildingWorkInfo> >();

            foreach (int buildingIndex in sortedBuildingsNeedBedroom)
            {
                int bedroomIndex = SelectBedroomForWork(partId, placeId, buildingIndex,
                                                        buildings, buildingsNeedBedroom, bedroomCandidates);

                if (bedroomIndex < 0)
                {
                    continue;
                }

                if (!bedroomsForWork.ContainsKey(bedroomIndex))
                {
                    bedroomsForWork[bedroomIndex] = new List <BuildingWorkInfo>();
                }
                bedroomsForWork[bedroomIndex].Add(buildings[buildingIndex]);
            }

            return(bedroomsForWork);
        }
Пример #4
0
        public static List <int> GetAdjacentBedrooms(int partId, int placeId, int buildingIndex)
        {
            var adjacentBedrooms = new List <int>();

            int[] adjacentBuildingIndexes = HomeSystem.instance.GetBuildingNeighbor(partId, placeId, buildingIndex);
            foreach (int adjacentBuildingIndex in adjacentBuildingIndexes)
            {
                if (!DateFile.instance.homeBuildingsDate[partId][placeId].ContainsKey(adjacentBuildingIndex))
                {
                    continue;
                }
                if (!Bedroom.IsBedroom(partId, placeId, adjacentBuildingIndex))
                {
                    continue;
                }
                adjacentBedrooms.Add(adjacentBuildingIndex);
            }

            return(adjacentBedrooms);
        }
Пример #5
0
        /// <summary>
        /// 计算指定地区的工作统计信息
        ///
        /// 综合工作指数 = SUM(缩放平移过的建筑工作效率 * 建筑优先级)
        /// 厢房效率不计入统计
        ///
        /// 由于必须在最开始执行,所以无法使用 prepared data
        /// </summary>
        /// <param name="partId"></param>
        /// <param name="placeId"></param>
        /// <returns></returns>
        private static WorkingStats GetWorkingStats(int partId, int placeId)
        {
            var stats = new WorkingStats();

            // 统计所有建筑的工作效率(厢房效率不计入统计)
            var buildings = DateFile.instance.homeBuildingsDate[partId][placeId];

            foreach (int buildingIndex in buildings.Keys)
            {
                if (!Original.BuildingNeedsWorker(partId, placeId, buildingIndex))
                {
                    continue;
                }

                if (Bedroom.IsBedroom(partId, placeId, buildingIndex))
                {
                    continue;
                }

                if (DateFile.instance.actorsWorkingDate.ContainsKey(partId) &&
                    DateFile.instance.actorsWorkingDate[partId].ContainsKey(placeId) &&
                    DateFile.instance.actorsWorkingDate[partId][placeId].ContainsKey(buildingIndex))
                {
                    int   workerId                = DateFile.instance.actorsWorkingDate[partId][placeId][buildingIndex];
                    int   workEffectiveness       = Original.GetWorkEffectiveness(partId, placeId, buildingIndex, workerId);
                    float scaledWorkEffectiveness = (workEffectiveness - 100f) / 100f;
                    float priority                = HumanResource.GetBuildingWorkingPriority(partId, placeId, buildingIndex, withAdjacentBedrooms: false);

                    ++stats.nProductiveBuildings;
                    stats.avgWorkEffectiveness += workEffectiveness / 200f;
                    stats.compositeWorkIndex   += scaledWorkEffectiveness * priority;
                }
            }

            if (stats.nProductiveBuildings > 0)
            {
                stats.avgWorkEffectiveness /= stats.nProductiveBuildings;
            }
            return(stats);
        }
Пример #6
0
        /// <summary>
        /// 获取邻接厢房对指定建筑的能力加成
        /// </summary>
        /// <param name="partId"></param>
        /// <param name="placeId"></param>
        /// <param name="buildingIndex"></param>
        /// <param name="requiredAttrId"></param>
        /// <returns></returns>
        private static int GetAdjacentAttrBonus(int partId, int placeId, int buildingIndex, int requiredAttrId)
        {
            int totalAdjacentAttrValue = 0;

            foreach (int adjacentBuildingIndex in Bedroom.GetAdjacentBedrooms(partId, placeId, buildingIndex))
            {
                if (!DateFile.instance.actorsWorkingDate.ContainsKey(partId) ||
                    !DateFile.instance.actorsWorkingDate[partId].ContainsKey(placeId) ||
                    !DateFile.instance.actorsWorkingDate[partId][placeId].ContainsKey(adjacentBuildingIndex))
                {
                    continue;
                }

                int adjacentActorId = DateFile.instance.actorsWorkingDate[partId][placeId][adjacentBuildingIndex];

                int adjacentAttrValue = (requiredAttrId > 0) ? int.Parse(DateFile.instance.GetActorDate(adjacentActorId, requiredAttrId)) : 0;
                adjacentAttrValue = Original.ToStandardAttrValue(requiredAttrId, adjacentAttrValue);

                totalAdjacentAttrValue += adjacentAttrValue;
            }

            return(totalAdjacentAttrValue);
        }
Пример #7
0
        /// <summary>
        /// 为所有厢房安排工作人员
        /// </summary>
        private void AssignBedroomWorkers()
        {
            // 厢房 ID -> 该厢房辅助的建筑信息列表
            // bedroomIndex -> [BuildingWorkInfo, ]
            var bedroomsForWork = Bedroom.GetBedroomsForWork(this.partId, this.placeId,
                                                             this.buildings, this.attrCandidates, this.workerAttrs);

            // 更新辅助类厢房的优先级
            // 辅助类厢房优先级 = 基础优先级 + SUM(辅助建筑优先级)
            // bedroomIndex -> priority
            var auxiliaryBedroomsPriorities = new Dictionary <int, int>();

            foreach (var entry in bedroomsForWork)
            {
                int bedroomIndex     = entry.Key;
                var relatedBuildings = entry.Value;

                int basePriority = 7;
                int priority     = basePriority * WORKING_PRIORITY_STEP_SIZE + relatedBuildings.Select(info => info.priority).Sum();

                auxiliaryBedroomsPriorities[bedroomIndex] = priority;
            }

            // 对于辅助类厢房,按优先级依次分配合适的人选
            MajordomoWindow.instance.AppendMessage(this.currDate, Message.IMPORTANCE_LOWEST,
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_DARK_GRAY, "开始指派辅助类厢房……"));

            var sortedAuxiliaryBedrooms = auxiliaryBedroomsPriorities.OrderByDescending(entry => entry.Value).Select(entry => entry.Key);

            foreach (int bedroomIndex in sortedAuxiliaryBedrooms)
            {
                int selectedWorkerId = this.SelectAuxiliaryBedroomWorker(bedroomIndex, bedroomsForWork[bedroomIndex]);
                if (selectedWorkerId >= 0)
                {
                    Original.SetBuildingWorker(this.partId, this.placeId, bedroomIndex, selectedWorkerId);
                }

                Output.LogAuxiliaryBedroomAndWorker(bedroomIndex, bedroomsForWork[bedroomIndex],
                                                    auxiliaryBedroomsPriorities[bedroomIndex], selectedWorkerId, this.partId, this.placeId, this.currDate, this.workerAttrs);
            }

            // 对于一般厢房,按优先级依次分配合适的人选
            MajordomoWindow.instance.AppendMessage(this.currDate, Message.IMPORTANCE_LOWEST,
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_DARK_GRAY, "开始指派一般厢房……"));

            var sortedBedrooms = this.buildings.Where(entry => entry.Value.IsBedroom())
                                 .OrderByDescending(entry => entry.Value.priority).Select(entry => entry.Value);

            foreach (var info in sortedBedrooms)
            {
                if (this.excludedBuildings.Contains(info.buildingIndex))
                {
                    continue;
                }

                int selectedWorkerId = this.SelectBuildingWorker(info.buildingIndex, info.requiredAttrId);
                if (selectedWorkerId >= 0)
                {
                    Original.SetBuildingWorker(this.partId, this.placeId, info.buildingIndex, selectedWorkerId);
                }

                Output.LogBuildingAndWorker(info, selectedWorkerId, this.partId, this.placeId, this.currDate, this.workerAttrs);
            }
        }