/// <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); }
public static void LogBuildingAndWorker(BuildingWorkInfo info, int selectedWorkerId, int partId, int placeId, TaiwuDate currDate, Dictionary <int, Dictionary <int, int> > workerAttrs, bool suppressNoWorkerWarnning) { var building = DateFile.instance.homeBuildingsDate[partId][placeId][info.buildingIndex]; int baseBuildingId = building[0]; int buildingLevel = building[1]; var baseBuilding = DateFile.instance.basehomePlaceDate[baseBuildingId]; string buildingName = baseBuilding[0]; string attrName = Output.GetRequiredAttrName(info.requiredAttrId); string logText = string.Format("{0}:{1} ({2}) {3} [{4}, {5}] - ", TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, Common.ToFullWidth(info.priority.ToString("F0").PadLeft(4))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_YELLOW, Common.ToFullWidth(buildingName.PadRight(5))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, Common.ToFullWidth(buildingLevel.ToString().PadLeft(2))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_RICE_WHITE, Common.ToFullWidth(attrName.PadRight(2))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, Common.ToFullWidth(info.halfWorkingAttrValue.ToString().PadLeft(3))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, Common.ToFullWidth(info.fullWorkingAttrValue.ToString().PadLeft(3)))); if (selectedWorkerId >= 0) { string workerName = DateFile.instance.GetActorName(selectedWorkerId); int attrValue = info.requiredAttrId != 0 ? workerAttrs[selectedWorkerId][info.requiredAttrId] : -1; int mood = int.Parse(DateFile.instance.GetActorDate(selectedWorkerId, 4, false)); int favor = DateFile.instance.GetActorFavor(false, DateFile.instance.MianActorID(), selectedWorkerId, getLevel: true); // 这里的工作效率并不一定等于最终工作效率,因为可能还有厢房未分配 int workEffectiveness = info.requiredAttrId != 0 ? Original.GetWorkEffectiveness(partId, placeId, info.buildingIndex, selectedWorkerId) : -1; string workEffectivenessStr = workEffectiveness >= 0 ? workEffectiveness / 2 + "%" : "N/A"; MajordomoWindow.instance.AppendMessage(currDate, Message.IMPORTANCE_LOW, logText + string.Format( "{0} 资质: {1} 心情: {2} 好感: {3} 工作效率: {4}", TaiwuCommon.SetColor(TaiwuCommon.COLOR_YELLOW, Common.ToFullWidth(workerName.PadRight(5))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, Common.ToFullWidth(attrValue.ToString().PadLeft(3))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, Common.ToFullWidth(mood.ToString().PadLeft(4))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, Common.ToFullWidth(favor.ToString().PadLeft(2))), TaiwuCommon.SetColor(TaiwuCommon.COLOR_WHITE, Common.ToFullWidth(workEffectivenessStr.PadLeft(4))))); } else { if (suppressNoWorkerWarnning) { MajordomoWindow.instance.AppendMessage(currDate, Message.IMPORTANCE_LOW, logText + TaiwuCommon.SetColor(TaiwuCommon.COLOR_LIGHT_GRAY, "无合适人选")); } else { MajordomoWindow.instance.AppendMessage(currDate, Message.IMPORTANCE_HIGH, logText + TaiwuCommon.SetColor(TaiwuCommon.COLOR_RED, "无合适人选")); } } }
/// <summary> /// 为指定建筑选择合适的工作人员 /// 按资质顺序检查实际效率是否达到及格线(或心情好感未达到标准),若达到则选择 /// 若没有任何人达到及格线(或心情好感皆达到标准),或者没有任何工作人员,则返回 -1 /// </summary> /// <param name="buildingIndex"></param> /// <param name="requiredAttrId"></param> /// <returns></returns> private int SelectBuildingWorker(int buildingIndex, int requiredAttrId) { int selectedWorkerId = -1; List <int> candidates = this.attrCandidates[requiredAttrId]; candidates = candidates.Where(workerId => !this.excludedWorkers.Contains(workerId)).ToList(); if (!candidates.Any()) { return(-1); } if (requiredAttrId != 0) { foreach (int workerId in candidates) { int effect = Original.GetWorkEffectiveness(this.partId, this.placeId, buildingIndex, workerId); if (effect >= WORK_EFFECTIVENESS_HALF) { selectedWorkerId = workerId; break; } } } else { foreach (int workerId in candidates) { int lackedMoodAndFavor = this.workerAttrs[workerId][requiredAttrId]; if (lackedMoodAndFavor > 0) { selectedWorkerId = workerId; break; } } } if (selectedWorkerId >= 0) { this.excludedBuildings.Add(buildingIndex); this.excludedWorkers.Add(selectedWorkerId); } return(selectedWorkerId); }
/// <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); }
public static void LogBuildingAndWorker(BuildingWorkInfo info, int selectedWorkerId, int partId, int placeId, Dictionary <int, Dictionary <int, int> > workerAttrs) { var building = DateFile.instance.homeBuildingsDate[partId][placeId][info.buildingIndex]; int baseBuildingId = building[0]; int buildingLevel = building[1]; var baseBuilding = DateFile.instance.basehomePlaceDate[baseBuildingId]; string buildingName = baseBuilding[0]; string attrName = Output.GetRequiredAttrName(info.requiredAttrId); string logText = $"{info.priority}\t" + $"{buildingName} ({buildingLevel}): " + $"{attrName} [{info.halfWorkingAttrValue}, {info.fullWorkingAttrValue}] - "; if (selectedWorkerId >= 0) { string workerName = DateFile.instance.GetActorName(selectedWorkerId); int attrValue = info.requiredAttrId != 0 ? workerAttrs[selectedWorkerId][info.requiredAttrId] : -1; int mood = int.Parse(DateFile.instance.GetActorDate(selectedWorkerId, 4, addValue: false)); int favor = DateFile.instance.GetActorFavor(false, DateFile.instance.MianActorID(), selectedWorkerId, getLevel: true); // 这里的工作效率并不一定等于最终工作效率,因为可能还有厢房未分配 int workEffectiveness = info.requiredAttrId != 0 ? Original.GetWorkEffectiveness(partId, placeId, info.buildingIndex, selectedWorkerId) : -1; string workEffectivenessStr = workEffectiveness >= 0 ? workEffectiveness / 2 + "%" : "N/A"; Main.Logger.Log(logText + $"{workerName}, 资质: {attrValue}, 心情: {mood}, 好感: {favor}, 工作效率: {workEffectivenessStr}"); } else { Main.Logger.Log(logText + "<无合适人选>"); } }