using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Input { /// /// 智能人员分配优化权重配置 /// 五层决策模型第三层:优化决策阶段的核心权重配置 /// 支持多策略、多场景、动态调整的智能权重管理 /// 深度业务思考:平衡效率、公平性、连续性、专业性等多维度目标 /// public class OptimizationWeights { #region 核心权重配置 /// /// 指定人员优先权重 (0.0-1.0) /// 业务含义:当任务有明确指定人员时的优先级权重 /// 适用场景:特殊技能需求、客户指定、专项任务等 /// [Range(0.0, 1.0, ErrorMessage = "指定人员权重必须在0.0-1.0范围内")] public double AssignedPersonnelWeight { get; set; } = 0.8; /// /// 项目FL人员优先权重 (0.0-1.0) /// 业务含义:项目内部FL(First Line)人员的优先级权重 /// 适用场景:项目连续性、知识传承、团队稳定性 /// [Range(0.0, 1.0, ErrorMessage = "项目FL人员权重必须在0.0-1.0范围内")] public double ProjectFLWeight { get; set; } = 0.6; /// /// 工作负载均衡权重 (0.0-1.0) /// 业务含义:人员工作负载分布均衡的重要性权重 /// 适用场景:公平分配、避免过劳、提升团队稳定性 /// [Range(0.0, 1.0, ErrorMessage = "工作负载均衡权重必须在0.0-1.0范围内")] public double WorkloadBalanceWeight { get; set; } = 0.4; /// /// 班次连续性权重 (0.0-1.0) /// 业务含义:保持人员班次连续性和规律性的权重 /// 适用场景:生物钟保护、工作效率优化、人员健康管理 /// [Range(0.0, 1.0, ErrorMessage = "班次连续性权重必须在0.0-1.0范围内")] public double ShiftContinuityWeight { get; set; } = 0.3; /// /// 技能匹配优先权重 (0.0-1.0) /// 业务含义:人员技能与任务需求匹配度的权重 /// 适用场景:质量保证、效率提升、风险控制 /// [Range(0.0, 1.0, ErrorMessage = "技能匹配权重必须在0.0-1.0范围内")] public double SkillMatchWeight { get; set; } = 0.5; /// /// 协作历史权重 (0.0-1.0) /// 业务含义:人员在相关项目的历史协作经验权重 /// 适用场景:团队默契、沟通效率、项目风险降低 /// [Range(0.0, 1.0, ErrorMessage = "协作历史权重必须在0.0-1.0范围内")] public double CollaborationHistoryWeight { get; set; } = 0.2; #endregion #region 扩展权重配置 /// /// 成本效益权重 (0.0-1.0) /// 业务含义:考虑人员成本与任务价值匹配的权重 /// 适用场景:成本控制、资源优化配置、ROI最大化 /// [Range(0.0, 1.0, ErrorMessage = "成本效益权重必须在0.0-1.0范围内")] public double CostEfficiencyWeight { get; set; } = 0.3; /// /// 地理位置便利性权重 (0.0-1.0) /// 业务含义:人员地理位置与工作地点便利性的权重 /// 适用场景:交通成本、响应速度、突发事件处理 /// [Range(0.0, 1.0, ErrorMessage = "地理位置便利性权重必须在0.0-1.0范围内")] public double LocationConvenienceWeight { get; set; } = 0.2; /// /// 培训发展权重 (0.0-1.0) /// 业务含义:为人员提供学习和发展机会的权重 /// 适用场景:人才培养、技能提升、职业发展规划 /// [Range(0.0, 1.0, ErrorMessage = "培训发展权重必须在0.0-1.0范围内")] public double TrainingDevelopmentWeight { get; set; } = 0.1; /// /// 紧急响应能力权重 (0.0-1.0) /// 业务含义:人员处理紧急情况能力的权重 /// 适用场景:应急任务、关键节点、风险管控 /// [Range(0.0, 1.0, ErrorMessage = "紧急响应能力权重必须在0.0-1.0范围内")] public double EmergencyResponseWeight { get; set; } = 0.4; #endregion #region 权重配置元数据 /// /// 权重配置名称 /// 用于识别和管理不同的权重配置方案 /// [Required(ErrorMessage = "权重配置名称不能为空")] [StringLength(100, ErrorMessage = "权重配置名称长度不能超过100字符")] public string ConfigurationName { get; set; } = "默认配置"; /// /// 权重配置描述 /// 详细说明该配置的适用场景和特点 /// [StringLength(500, ErrorMessage = "权重配置描述长度不能超过500字符")] public string Description { get; set; } = string.Empty; /// /// 配置策略类型 /// 标识该权重配置所属的分配策略类型 /// public OptimizationStrategy StrategyType { get; set; } = OptimizationStrategy.Balanced; /// /// 是否为系统预设配置 /// 标识是否为系统内置的标准配置 /// public bool IsSystemPreset { get; set; } = false; /// /// 配置创建者ID /// 记录创建该配置的用户或系统标识 /// public long? CreatedBy { get; set; } /// /// 配置创建时间 /// public DateTime CreatedTime { get; set; } = DateTime.Now; /// /// 最后修改时间 /// public DateTime LastModifiedTime { get; set; } = DateTime.Now; /// /// 配置版本号 /// 用于跟踪配置的变更历史 /// public string Version { get; set; } = "1.0.0"; #endregion #region 高级配置选项 /// /// 自定义权重规则 /// 支持用户定义的特殊权重计算规则 /// public Dictionary CustomWeightRules { get; set; } = new(); /// /// 权重动态调整配置 /// 根据实时条件动态调整权重的规则配置 /// public DynamicWeightAdjustment DynamicAdjustment { get; set; } = new(); /// /// 权重约束条件 /// 定义权重配置必须满足的约束条件 /// public WeightConstraints Constraints { get; set; } = new(); /// /// 权重归一化方式 /// 定义如何对权重进行标准化处理 /// public WeightNormalizationMethod NormalizationMethod { get; set; } = WeightNormalizationMethod.ProportionalSum; #endregion #region 核心业务方法 /// /// 验证权重配置的有效性 /// 深度业务思考:确保权重配置符合业务逻辑和数学约束 /// public WeightValidationResult ValidateConfiguration() { var result = new WeightValidationResult { IsValid = true, Issues = new List() }; try { // 1. 基础范围验证(通过DataAnnotations已覆盖) var properties = GetType().GetProperties() .Where(p => p.PropertyType == typeof(double) && p.Name.EndsWith("Weight")); foreach (var prop in properties) { var value = (double)prop.GetValue(this); if (value < 0.0 || value > 1.0) { result.IsValid = false; result.Issues.Add($"{prop.Name} 值 {value} 超出有效范围 [0.0, 1.0]"); } } // 2. 权重总和合理性检查 var totalWeight = GetTotalWeight(); if (totalWeight < 0.1) { result.Issues.Add($"权重总和过低 ({totalWeight:F2}),可能导致分配结果不稳定"); } else if (totalWeight > 5.0) { result.Issues.Add($"权重总和过高 ({totalWeight:F2}),建议进行归一化处理"); } // 3. 业务逻辑一致性检查 if (AssignedPersonnelWeight < 0.5 && StrategyType == OptimizationStrategy.AssignedPersonnelFirst) { result.Issues.Add("指定人员优先策略下,指定人员权重应不低于0.5"); } if (WorkloadBalanceWeight < 0.6 && StrategyType == OptimizationStrategy.LoadBalanceFirst) { result.Issues.Add("负载均衡优先策略下,工作负载均衡权重应不低于0.6"); } // 4. 约束条件检查 if (Constraints != null) { var constraintResult = Constraints.ValidateConstraints(this); if (!constraintResult.IsValid) { result.IsValid = false; result.Issues.AddRange(constraintResult.Issues); } } return result; } catch (Exception ex) { result.IsValid = false; result.Issues.Add($"权重配置验证异常:{ex.Message}"); return result; } } /// /// 获取权重总和 /// public double GetTotalWeight() { return AssignedPersonnelWeight + ProjectFLWeight + WorkloadBalanceWeight + ShiftContinuityWeight + SkillMatchWeight + CollaborationHistoryWeight + CostEfficiencyWeight + LocationConvenienceWeight + TrainingDevelopmentWeight + EmergencyResponseWeight; } /// /// 归一化权重配置 /// 将所有权重按比例调整到指定的总和 /// public void NormalizeWeights(double targetSum = 1.0) { var currentSum = GetTotalWeight(); if (currentSum <= 0) return; var factor = targetSum / currentSum; AssignedPersonnelWeight *= factor; ProjectFLWeight *= factor; WorkloadBalanceWeight *= factor; ShiftContinuityWeight *= factor; SkillMatchWeight *= factor; CollaborationHistoryWeight *= factor; CostEfficiencyWeight *= factor; LocationConvenienceWeight *= factor; TrainingDevelopmentWeight *= factor; EmergencyResponseWeight *= factor; LastModifiedTime = DateTime.Now; } /// /// 转换为字典格式 /// 用于与现有系统的权重配置格式兼容 /// public Dictionary ToDictionary() { return new Dictionary { ["AssignedPersonnel"] = AssignedPersonnelWeight, ["ProjectFL"] = ProjectFLWeight, ["WorkloadBalance"] = WorkloadBalanceWeight, ["ShiftContinuity"] = ShiftContinuityWeight, ["SkillMatch"] = SkillMatchWeight, ["CollaborationHistory"] = CollaborationHistoryWeight, ["CostEfficiency"] = CostEfficiencyWeight, ["LocationConvenience"] = LocationConvenienceWeight, ["TrainingDevelopment"] = TrainingDevelopmentWeight, ["EmergencyResponse"] = EmergencyResponseWeight }; } /// /// 从字典加载权重配置 /// public void LoadFromDictionary(Dictionary weights) { if (weights == null) return; AssignedPersonnelWeight = weights.GetValueOrDefault("AssignedPersonnel", AssignedPersonnelWeight); ProjectFLWeight = weights.GetValueOrDefault("ProjectFL", ProjectFLWeight); WorkloadBalanceWeight = weights.GetValueOrDefault("WorkloadBalance", WorkloadBalanceWeight); ShiftContinuityWeight = weights.GetValueOrDefault("ShiftContinuity", ShiftContinuityWeight); SkillMatchWeight = weights.GetValueOrDefault("SkillMatch", SkillMatchWeight); CollaborationHistoryWeight = weights.GetValueOrDefault("CollaborationHistory", CollaborationHistoryWeight); CostEfficiencyWeight = weights.GetValueOrDefault("CostEfficiency", CostEfficiencyWeight); LocationConvenienceWeight = weights.GetValueOrDefault("LocationConvenience", LocationConvenienceWeight); TrainingDevelopmentWeight = weights.GetValueOrDefault("TrainingDevelopment", TrainingDevelopmentWeight); EmergencyResponseWeight = weights.GetValueOrDefault("EmergencyResponse", EmergencyResponseWeight); LastModifiedTime = DateTime.Now; } /// /// 深拷贝权重配置 /// public OptimizationWeights DeepClone() { return new OptimizationWeights { AssignedPersonnelWeight = AssignedPersonnelWeight, ProjectFLWeight = ProjectFLWeight, WorkloadBalanceWeight = WorkloadBalanceWeight, ShiftContinuityWeight = ShiftContinuityWeight, SkillMatchWeight = SkillMatchWeight, CollaborationHistoryWeight = CollaborationHistoryWeight, CostEfficiencyWeight = CostEfficiencyWeight, LocationConvenienceWeight = LocationConvenienceWeight, TrainingDevelopmentWeight = TrainingDevelopmentWeight, EmergencyResponseWeight = EmergencyResponseWeight, ConfigurationName = ConfigurationName + "_Copy", Description = Description, StrategyType = StrategyType, IsSystemPreset = false, CreatedBy = CreatedBy, CreatedTime = DateTime.Now, LastModifiedTime = DateTime.Now, Version = "1.0.0", CustomWeightRules = new Dictionary(CustomWeightRules), DynamicAdjustment = DynamicAdjustment?.DeepClone(), Constraints = Constraints?.DeepClone(), NormalizationMethod = NormalizationMethod }; } #endregion #region 预设配置工厂方法 /// /// 创建效率优先配置 /// 适用场景:紧急任务、关键交付、高价值项目 /// public static OptimizationWeights CreateEfficiencyFirstConfiguration() { return new OptimizationWeights { ConfigurationName = "效率优先配置", Description = "优先考虑技能匹配和协作历史,适用于紧急任务和关键交付", StrategyType = OptimizationStrategy.EfficiencyFirst, IsSystemPreset = true, AssignedPersonnelWeight = 0.9, SkillMatchWeight = 0.8, CollaborationHistoryWeight = 0.7, ProjectFLWeight = 0.6, EmergencyResponseWeight = 0.8, WorkloadBalanceWeight = 0.2, ShiftContinuityWeight = 0.2, CostEfficiencyWeight = 0.3, LocationConvenienceWeight = 0.1, TrainingDevelopmentWeight = 0.1 }; } /// /// 创建公平分配配置 /// 适用场景:日常任务、团队建设、长期项目 /// public static OptimizationWeights CreateFairDistributionConfiguration() { return new OptimizationWeights { ConfigurationName = "公平分配配置", Description = "注重工作负载均衡和培训发展,适用于日常任务和团队建设", StrategyType = OptimizationStrategy.FairDistribution, IsSystemPreset = true, WorkloadBalanceWeight = 0.8, TrainingDevelopmentWeight = 0.6, SkillMatchWeight = 0.5, ShiftContinuityWeight = 0.5, ProjectFLWeight = 0.4, CollaborationHistoryWeight = 0.3, AssignedPersonnelWeight = 0.3, CostEfficiencyWeight = 0.4, LocationConvenienceWeight = 0.3, EmergencyResponseWeight = 0.2 }; } /// /// 创建连续性优先配置 /// 适用场景:轮班制工作、健康管理、规律性要求高的任务 /// public static OptimizationWeights CreateContinuityFirstConfiguration() { return new OptimizationWeights { ConfigurationName = "连续性优先配置", Description = "强调班次连续性和人员稳定性,适用于轮班制和规律性要求高的工作", StrategyType = OptimizationStrategy.ContinuityFirst, IsSystemPreset = true, ShiftContinuityWeight = 0.9, ProjectFLWeight = 0.7, CollaborationHistoryWeight = 0.6, WorkloadBalanceWeight = 0.6, SkillMatchWeight = 0.5, LocationConvenienceWeight = 0.4, AssignedPersonnelWeight = 0.4, CostEfficiencyWeight = 0.3, TrainingDevelopmentWeight = 0.2, EmergencyResponseWeight = 0.3 }; } #endregion } #region 支持类定义 /// /// 优化策略类型枚举 /// public enum OptimizationStrategy { /// /// 平衡策略 /// Balanced = 0, /// /// 效率优先 /// EfficiencyFirst = 1, /// /// 公平分配 /// FairDistribution = 2, /// /// 连续性优先 /// ContinuityFirst = 3, /// /// 指定人员优先 /// AssignedPersonnelFirst = 4, /// /// 负载均衡优先 /// LoadBalanceFirst = 5, /// /// 技能匹配优先 /// SkillMatchFirst = 6, /// /// 成本优化 /// CostOptimized = 7, /// /// 自定义策略 /// Custom = 99 } /// /// 权重归一化方法 /// public enum WeightNormalizationMethod { /// /// 不进行归一化 /// None = 0, /// /// 按比例归一化到总和为1 /// ProportionalSum = 1, /// /// 按最大值归一化 /// MaxValue = 2, /// /// 按标准差归一化 /// StandardDeviation = 3 } /// /// 权重验证结果 /// public class WeightValidationResult { /// /// 验证是否通过 /// public bool IsValid { get; set; } /// /// 验证问题列表 /// public List Issues { get; set; } = new(); /// /// 验证建议 /// public List Suggestions { get; set; } = new(); } /// /// 自定义权重规则 /// public class CustomWeightRule { /// /// 规则名称 /// public string RuleName { get; set; } = string.Empty; /// /// 规则表达式 /// public string RuleExpression { get; set; } = string.Empty; /// /// 规则权重 /// public double Weight { get; set; } /// /// 是否启用 /// public bool IsEnabled { get; set; } = true; /// /// 规则描述 /// public string Description { get; set; } = string.Empty; } /// /// 动态权重调整配置 /// public class DynamicWeightAdjustment { /// /// 是否启用动态调整 /// public bool IsEnabled { get; set; } = false; /// /// 调整触发条件 /// public List Triggers { get; set; } = new(); /// /// 调整规则 /// public List Rules { get; set; } = new(); /// /// 最大调整幅度 /// public double MaxAdjustmentRange { get; set; } = 0.3; /// /// 深拷贝 /// public DynamicWeightAdjustment DeepClone() { return new DynamicWeightAdjustment { IsEnabled = IsEnabled, Triggers = new List(Triggers), Rules = new List(Rules), MaxAdjustmentRange = MaxAdjustmentRange }; } } /// /// 调整触发条件 /// public class AdjustmentTrigger { /// /// 触发条件名称 /// public string TriggerName { get; set; } = string.Empty; /// /// 触发条件表达式 /// public string ConditionExpression { get; set; } = string.Empty; /// /// 触发阈值 /// public double Threshold { get; set; } } /// /// 调整规则 /// public class AdjustmentRule { /// /// 目标权重字段 /// public string TargetWeightField { get; set; } = string.Empty; /// /// 调整方式 /// public AdjustmentType AdjustmentType { get; set; } = AdjustmentType.Multiply; /// /// 调整值 /// public double AdjustmentValue { get; set; } } /// /// 调整方式枚举 /// public enum AdjustmentType { /// /// 加法调整 /// Add = 1, /// /// 乘法调整 /// Multiply = 2, /// /// 设置固定值 /// SetValue = 3 } /// /// 权重约束条件 /// public class WeightConstraints { /// /// 总权重最小值 /// public double MinTotalWeight { get; set; } = 0.1; /// /// 总权重最大值 /// public double MaxTotalWeight { get; set; } = 10.0; /// /// 必须权重字段 /// 这些权重字段不能为0 /// public List RequiredWeightFields { get; set; } = new(); /// /// 互斥权重组 /// 同组内只能有一个权重大于指定阈值 /// public List MutuallyExclusiveGroups { get; set; } = new(); /// /// 验证约束条件 /// public WeightValidationResult ValidateConstraints(OptimizationWeights weights) { var result = new WeightValidationResult { IsValid = true, Issues = new List() }; // 验证总权重范围 var totalWeight = weights.GetTotalWeight(); if (totalWeight < MinTotalWeight) { result.IsValid = false; result.Issues.Add($"总权重 {totalWeight:F2} 低于最小值 {MinTotalWeight:F2}"); } if (totalWeight > MaxTotalWeight) { result.IsValid = false; result.Issues.Add($"总权重 {totalWeight:F2} 超过最大值 {MaxTotalWeight:F2}"); } // 验证必须权重字段 var weightDict = weights.ToDictionary(); foreach (var requiredField in RequiredWeightFields) { if (weightDict.TryGetValue(requiredField, out var value) && value <= 0) { result.IsValid = false; result.Issues.Add($"必须权重字段 {requiredField} 不能为0"); } } // 验证互斥权重组 foreach (var group in MutuallyExclusiveGroups) { var highWeightFields = group.WeightFields .Where(field => weightDict.TryGetValue(field, out var value) && value > group.Threshold) .ToList(); if (highWeightFields.Count > 1) { result.IsValid = false; result.Issues.Add($"互斥权重组 {group.GroupName} 中有多个字段超过阈值:{string.Join(", ", highWeightFields)}"); } } return result; } /// /// 深拷贝 /// public WeightConstraints DeepClone() { return new WeightConstraints { MinTotalWeight = MinTotalWeight, MaxTotalWeight = MaxTotalWeight, RequiredWeightFields = new List(RequiredWeightFields), MutuallyExclusiveGroups = MutuallyExclusiveGroups.Select(g => g.DeepClone()).ToList() }; } } /// /// 互斥权重组 /// public class MutuallyExclusiveWeightGroup { /// /// 组名称 /// public string GroupName { get; set; } = string.Empty; /// /// 权重字段列表 /// public List WeightFields { get; set; } = new(); /// /// 阈值 /// public double Threshold { get; set; } = 0.5; /// /// 深拷贝 /// public MutuallyExclusiveWeightGroup DeepClone() { return new MutuallyExclusiveWeightGroup { GroupName = GroupName, WeightFields = new List(WeightFields), Threshold = Threshold }; } } #endregion }