Ejemplo n.º 1
0
        private static bool Prefix(UIDate __instance)
        {
            if (!Main.enabled)
            {
                return(true);
            }

            AutoHarvest.GetAllBooties();

            ResourceMaintainer.TryBuyingResources();

            ResourceMaintainer.UpdateResourceWarning();

            TurnEvent.AddEvent(__instance);

            if (Main.settings.autoAssignBuildingWorkers)
            {
                HumanResource hr          = new HumanResource();
                int           mainPartId  = int.Parse(DateFile.instance.GetGangDate(16, 3));
                int           mainPlaceId = int.Parse(DateFile.instance.GetGangDate(16, 4));
                hr.AssignBuildingWorkers(mainPartId, mainPlaceId);
            }

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 只要在各个 panel 创建完之后再创建 menu item,事件中的 panel 引用就都是有效的。
        /// </summary>
        private void CreateMenuItems()
        {
            this.logsPanelButton = this.CreateMenuButton("LogsPanelButton",
                                                         () => this.SwitchPanel(this.panelLogs),
                                                         Path.Combine(Path.Combine(Main.resBasePath, "Texture"), $"ButtonIcon_Majordomo_LogsPanel.png"),
                                                         "翻阅记录");

            this.chartsPanelButton = this.CreateMenuButton("ChartsPanelButton",
                                                           () => this.SwitchPanel(this.panelCharts),
                                                           Path.Combine(Path.Combine(Main.resBasePath, "Texture"), $"ButtonIcon_Majordomo_ChartsPanel.png"),
                                                           "查看图表");

            this.assignBuildingWorkersButton = this.CreateMenuButton("AssignBuildingWorkersButton",
                                                                     () => {
                YesOrNoWindow.instance.SetYesOrNoWindow(-1, "太吾管家", "管家已重新指派了各个建筑的负责人。", canClose: false);
                HumanResource.AssignBuildingWorkersForTaiwuVillage();
                this.panelLogs.SetPageIndex(-1);
                if (this.panelLogs.gameObject.activeInHierarchy)
                {
                    this.panelLogs.Update();
                }
            },
                                                                     Path.Combine(Path.Combine(Main.resBasePath, "Texture"), $"ButtonIcon_Majordomo_AssignBuildingWorkers.png"),
                                                                     "重新指派工作");
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 对于指定辅助厢房,生成候选人列表
        /// </summary>
        /// <param name="bedroomIndex">厢房的建筑 ID</param>
        /// <param name="relatedBuildings">该厢房辅助的建筑信息列表</param>
        /// <returns></returns>
        private List <AuxiliaryBedroomWorker> GetAuxiliaryBedroomWorkers(int bedroomIndex, List <BuildingWorkInfo> relatedBuildings)
        {
            var workers = new List <AuxiliaryBedroomWorker>();

            foreach (var entry in this.workerAttrs)
            {
                int workerId = entry.Key;

                if (this.excludedWorkers.Contains(workerId))
                {
                    continue;
                }

                var attrs = entry.Value;

                workers.Add(new AuxiliaryBedroomWorker
                {
                    actorId             = workerId,
                    integratedAttrValue = HumanResource.GetIntegratedAttrValue(attrs, relatedBuildings),
                    lackedMoodAndFavor  = HumanResource.GetLackedMoodAndFavor(workerId),
                });
            }

            return(workers);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
 private void CreateMessagePageMenuControls()
 {
     this.assignBuildingWorkersButton = this.CreateMenuButton("AssignBuildingWorkersButton",
                                                              () => { HumanResource.AssignBuildingWorkersForTaiwuVillage(); this.ShowMessage(showLastPage: true); },
                                                              Path.Combine(Path.Combine(Main.resBasePath, "Texture"), $"ButtonIcon_Majordomo_AssignBuildingWorkers.png"),
                                                              TaiwuCommon.SetColor(TaiwuCommon.COLOR_WHITE, "重新指派工作"));
 }
Ejemplo n.º 6
0
        /// <summary>
        /// 指派工作人员
        /// </summary>
        public void AssignBuildingWorkers()
        {
            float compositeWorkIndex = HumanResource.GetCompositeWorkIndex(this.partId, this.placeId);

            MajordomoWindow.instance.AppendMessage(this.currDate, Message.IMPORTANCE_NORMAL,
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_BLUE, "开始指派工作人员") + " - " +
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_DARK_BROWN, "综合工作指数") + ": " +
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_WHITE, compositeWorkIndex.ToString()));

            Original.RemoveWorkersFromBuildings(this.partId, this.placeId, this.excludedBuildings, this.excludedWorkers);

            MajordomoWindow.instance.AppendMessage(this.currDate, Message.IMPORTANCE_LOWEST,
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_DARK_GRAY, "开始第一轮指派……"));

            this.AssignBuildingWorkers_PrepareData();

            this.AssignBedroomWorkers();

            MajordomoWindow.instance.AppendMessage(this.currDate, Message.IMPORTANCE_LOWEST,
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_DARK_GRAY, "开始第二轮指派……"));

            // 指派完厢房后,重新计算
            this.AssignBuildingWorkers_PrepareData();

            this.AssignLeftBuildings();

            Original.UpdateAllBuildings(this.partId, this.placeId);

            compositeWorkIndex = HumanResource.GetCompositeWorkIndex(this.partId, this.placeId);
            MajordomoWindow.instance.AppendMessage(this.currDate, Message.IMPORTANCE_NORMAL,
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_BLUE, "结束指派工作人员") + " - " +
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_DARK_BROWN, "综合工作指数") + ": " +
                                                   TaiwuCommon.SetColor(TaiwuCommon.COLOR_WHITE, compositeWorkIndex.ToString()));
            MajordomoWindow.instance.SetCompositeWorkIndex(this.currDate, compositeWorkIndex);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 为太吾村指派工作人员(静态方法)
        /// </summary>
        public static void AssignBuildingWorkersForTaiwuVillage()
        {
            int           mainPartId  = int.Parse(DateFile.instance.GetGangDate(16, 3));
            int           mainPlaceId = int.Parse(DateFile.instance.GetGangDate(16, 4));
            HumanResource hr          = new HumanResource(mainPartId, mainPlaceId);

            hr.AssignBuildingWorkers();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// 获取当前据点需要工作人员的建筑,以及该建筑的工作相关信息
        /// </summary>
        /// <returns></returns>
        private Dictionary <int, List <BuildingWorkInfo> > GetBuildingsNeedWorker()
        {
            // requiredAttrId -> [BuildingWorkInfo, ]
            var attrBuildings = new Dictionary <int, List <BuildingWorkInfo> >();

            var buildings      = DateFile.instance.homeBuildingsDate[this.partId][this.placeId];
            var validBuildings = buildings.Where(entry => !this.excludedBuildings.Contains(entry.Key));

            foreach (var entry in validBuildings)
            {
                int   buildingIndex  = entry.Key;
                int[] building       = entry.Value;
                int   baseBuildingId = building[0];

                var  baseBuilding = DateFile.instance.basehomePlaceDate[baseBuildingId];
                bool needWorker   = int.Parse(baseBuilding[3]) == 1;
                if (!needWorker)
                {
                    continue;
                }

                int requiredAttrId = int.Parse(baseBuilding[33]);

                BuildingWorkInfo info = new BuildingWorkInfo
                {
                    buildingIndex        = buildingIndex,
                    requiredAttrId       = requiredAttrId,
                    priority             = HumanResource.GetBuildingWorkingPriority(this.partId, this.placeId, buildingIndex),
                    halfWorkingAttrValue = 0,
                    fullWorkingAttrValue = 0,
                };

                if (requiredAttrId != 0)
                {
                    int[] requiredAttrValues = Original.GetRequiredAttributeValues(this.partId, this.placeId, buildingIndex);
                    info.halfWorkingAttrValue = requiredAttrValues[0];
                    info.fullWorkingAttrValue = requiredAttrValues[1];
                }

                if (!attrBuildings.ContainsKey(requiredAttrId))
                {
                    attrBuildings[requiredAttrId] = new List <BuildingWorkInfo>();
                }
                attrBuildings[requiredAttrId].Add(info);
            }

            return(attrBuildings);
        }
Ejemplo n.º 9
0
        private void AssignBuildingWorkers_PrepareData()
        {
            List <int> workerIds = Original.GetWorkerIds(this.partId, this.placeId);

            workerIds = workerIds.Where(workerId => !this.excludedWorkers.Contains(workerId)).ToList();

            Dictionary <int, List <BuildingWorkInfo> > attrBuildings = this.GetBuildingsNeedWorker();

            //
            this.buildings = new Dictionary <int, BuildingWorkInfo>();
            foreach (var currBuildingWorkInfos in attrBuildings.Values)
            {
                foreach (var info in currBuildingWorkInfos)
                {
                    this.buildings[info.buildingIndex] = info;
                }
            }

            //
            this.workerAttrs    = new Dictionary <int, Dictionary <int, int> >();
            this.attrCandidates = new Dictionary <int, List <int> >();

            foreach (int workerId in workerIds)
            {
                this.workerAttrs[workerId] = new Dictionary <int, int>();
            }

            foreach (int requiredAttrId in attrBuildings.Keys)
            {
                foreach (int workerId in workerIds)
                {
                    // 不需要资质时(厢房),放入好感和心情相对标准状态的差值
                    int attrValue = requiredAttrId != 0 ?
                                    int.Parse(DateFile.instance.GetActorDate(workerId, requiredAttrId)) :
                                    HumanResource.GetLackedMoodAndFavor(workerId);
                    this.workerAttrs[workerId][requiredAttrId] = attrValue;
                }

                List <int> sortedWorkerIds = this.workerAttrs
                                             .OrderByDescending(elem => elem.Value[requiredAttrId])
                                             .Select(elem => elem.Key)
                                             .ToList();
                this.attrCandidates[requiredAttrId] = sortedWorkerIds;
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// 返回建筑指派工作人员的优先级
        ///
        /// 优先级 = 建筑种类因子 * 标准状态下满效率需求的标准化能力值
        /// 对于厢房,“标准状态下满效率需求的标准化能力值” 即为其等级
        /// 虽然这会导致方向的优先级和其他建筑没有可比性,但是厢房优先级本来就不会与其他建筑比较,所以没有问题
        /// </summary>
        /// <param name="partId"></param>
        /// <param name="placeId"></param>
        /// <param name="buildingIndex"></param>
        /// <param name="withAdjacentBedrooms">是否考虑邻接厢房的影响</param>
        /// <returns></returns>
        private static float GetBuildingWorkingPriority(int partId, int placeId, int buildingIndex, bool withAdjacentBedrooms)
        {
            int[] requiredAttrValues = Original.GetRequiredAttributeValues(partId, placeId, buildingIndex,
                                                                           withAdjacentBedrooms, getStandardAttrValue: true);
            int fullWorkingAttrValue = requiredAttrValues[1];

            // 对于厢房,“标准状态下满效率需求的标准化能力值” 即为其等级
            int[] building       = DateFile.instance.homeBuildingsDate[partId][placeId][buildingIndex];
            int   baseBuildingId = building[0];
            int   buildingLevel  = building[1];
            int   requiredAttrId = int.Parse(DateFile.instance.basehomePlaceDate[baseBuildingId][33]);

            if (requiredAttrId <= 0)
            {
                fullWorkingAttrValue = buildingLevel;
            }

            float typeFactor = HumanResource.GetBuildingPriorityFactor(baseBuildingId);

            return(typeFactor * fullWorkingAttrValue);
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
0
        private static bool Prefix(UIDate __instance)
        {
            if (!Main.enabled)
            {
                return(true);
            }

            AutoHarvest.GetAllBooties();

            ResourceMaintainer.TryBuyingResources();

            ResourceMaintainer.UpdateResourceWarning();

            TurnEvent.AddEvent(__instance);

            if (Main.settings.autoAssignBuildingWorkers)
            {
                HumanResource.AssignBuildingWorkersForTaiwuVillage();
            }

            return(true);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// 自动指派工作人员
        /// </summary>
        public void AssignBuildingWorkers()
        {
            Main.Logger.Log($"自动指派前综合工作指数: {HumanResource.GetComprehensiveWorkIndex(this.partId, this.placeId)}");

            Original.RemoveWorkersFromBuildings(this.partId, this.placeId, this.excludedBuildings, this.excludedWorkers);

            Main.Logger.Log("开始第一轮指派……");

            this.AssignBuildingWorkers_PrepareData();

            this.AssignBedroomWorkers();

            Main.Logger.Log("开始第二轮指派……");

            // 指派完厢房后,重新计算
            this.AssignBuildingWorkers_PrepareData();

            this.AssignLeftBuildings();

            Original.UpdateAllBuildings(this.partId, this.placeId);

            Main.Logger.Log($"自动指派后综合工作指数: {HumanResource.GetComprehensiveWorkIndex(this.partId, this.placeId)}");
        }