Asoka.Wang 21f044712c 1
2025-08-27 18:39:19 +08:00

1027 lines
29 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Models;
namespace NPP.SmartSchedue.Api.Contracts.Services.Integration.Output
{
/// <summary>
/// 人员分配生成结果
/// 智能分配算法第四层:结果生成阶段的核心数据模型
/// 包含成功分配、失败分配、质量评估、性能指标等完整业务信息
/// </summary>
public class AllocationGenerationResult
{
#region
/// <summary>
/// 成功分配的任务与人员映射
/// Key: 工作任务ID, Value: 最佳匹配的人员候选人
/// </summary>
public Dictionary<long, PersonnelCandidate> SuccessfulAllocations { get; set; } = new();
/// <summary>
/// 分配失败的任务列表
/// 包含失败原因、类型和建议解决方案
/// </summary>
public List<FailedAllocation> FailedAllocations { get; set; } = new();
#endregion
#region
/// <summary>
/// 整体质量评分 (0-100)
/// 综合考虑成功率、平均匹配分数、约束符合度等因素
/// </summary>
public double OverallQualityScore { get; set; }
/// <summary>
/// 分配成功率 (0-100)
/// 计算公式:成功分配数量 / 总任务数量 * 100
/// </summary>
public double SuccessRate => CalculateSuccessRate();
/// <summary>
/// 平均匹配质量分数 (0-100)
/// 所有成功分配的人员候选人平均评分
/// </summary>
public double AverageMatchQuality => CalculateAverageMatchQuality();
#endregion
#region
/// <summary>
/// 详细分配报告
/// 包含统计信息、人员利用率、风险分析等详细数据
/// </summary>
public AllocationReport DetailedReport { get; set; } = new();
/// <summary>
/// 分配策略执行摘要
/// 人性化的分配结果描述,便于业务人员理解
/// </summary>
public string AllocationSummary { get; set; } = string.Empty;
#endregion
#region
/// <summary>
/// 性能监控指标
/// 记录各个处理阶段的执行时间、资源消耗等性能数据
/// </summary>
public Dictionary<string, object> PerformanceMetrics { get; set; } = new();
/// <summary>
/// 算法执行总耗时(毫秒)
/// </summary>
public long TotalExecutionTimeMs => GetExecutionTime();
/// <summary>
/// 内存使用峰值(字节)
/// </summary>
public long PeakMemoryUsageBytes { get; set; }
#endregion
#region
/// <summary>
/// 人员工作负载分布
/// 分析各人员的任务分配数量和工作强度
/// </summary>
public Dictionary<long, PersonnelWorkloadInfo> PersonnelWorkloadDistribution => CalculateWorkloadDistribution();
/// <summary>
/// 技能匹配度分析
/// 评估整体技能匹配情况和资质覆盖度
/// </summary>
public SkillMatchAnalysis SkillMatchingAnalysis => AnalyzeSkillMatching();
/// <summary>
/// 约束冲突统计
/// 统计各类约束冲突的分布情况
/// </summary>
public Dictionary<string, int> ConstraintConflictStatistics => AnalyzeConstraintConflicts();
#endregion
#region
/// <summary>
/// 计算分配成功率
/// </summary>
private double CalculateSuccessRate()
{
var totalTasks = SuccessfulAllocations.Count + FailedAllocations.Count;
return totalTasks > 0 ? (double)SuccessfulAllocations.Count / totalTasks * 100 : 0;
}
/// <summary>
/// 计算平均匹配质量
/// </summary>
private double CalculateAverageMatchQuality()
{
return SuccessfulAllocations.Any()
? SuccessfulAllocations.Values.Average(c => c.TotalScore)
: 0;
}
/// <summary>
/// 获取执行时间
/// </summary>
private long GetExecutionTime()
{
return PerformanceMetrics.TryGetValue("TotalExecutionTime", out var time)
? Convert.ToInt64(time)
: 0;
}
/// <summary>
/// 计算人员工作负载分布
/// </summary>
private Dictionary<long, PersonnelWorkloadInfo> CalculateWorkloadDistribution()
{
return SuccessfulAllocations.Values
.GroupBy(c => c.PersonnelId)
.ToDictionary(
g => g.Key,
g => new PersonnelWorkloadInfo
{
PersonnelId = g.Key,
PersonnelName = g.First().PersonnelName,
AssignedTaskCount = g.Count(),
AverageMatchScore = g.Average(c => c.TotalScore),
TotalWorkload = g.Sum(c => c.EstimatedWorkload ?? 1.0)
});
}
/// <summary>
/// 分析技能匹配情况
/// </summary>
private SkillMatchAnalysis AnalyzeSkillMatching()
{
var analysis = new SkillMatchAnalysis();
if (SuccessfulAllocations.Any())
{
analysis.AverageSkillMatchScore = SuccessfulAllocations.Values
.Average(c => c.QualificationScore?.MatchScore ?? 0);
analysis.FullyQualifiedCount = SuccessfulAllocations.Values
.Count(c => (c.QualificationScore?.MatchScore ?? 0) >= 90);
analysis.PartiallyQualifiedCount = SuccessfulAllocations.Values
.Count(c => (c.QualificationScore?.MatchScore ?? 0) >= 70 &&
(c.QualificationScore?.MatchScore ?? 0) < 90);
analysis.MinimallyQualifiedCount = SuccessfulAllocations.Values
.Count(c => (c.QualificationScore?.MatchScore ?? 0) < 70);
}
return analysis;
}
/// <summary>
/// 分析约束冲突分布
/// </summary>
private Dictionary<string, int> AnalyzeConstraintConflicts()
{
var conflicts = new Dictionary<string, int>();
foreach (var failure in FailedAllocations)
{
var conflictType = failure.FailureType.ToString();
conflicts[conflictType] = conflicts.GetValueOrDefault(conflictType, 0) + 1;
}
return conflicts;
}
#endregion
#region
/// <summary>
/// 验证结果数据完整性
/// </summary>
public ValidationResult ValidateResultIntegrity()
{
var result = new ValidationResult { IsValid = true, Issues = new List<string>() };
// 检查基础数据完整性
if (SuccessfulAllocations == null)
{
result.IsValid = false;
result.Issues.Add("成功分配数据为空");
}
if (FailedAllocations == null)
{
result.IsValid = false;
result.Issues.Add("失败分配数据为空");
}
// 检查质量评分合理性
if (OverallQualityScore < 0 || OverallQualityScore > 100)
{
result.IsValid = false;
result.Issues.Add($"整体质量评分超出范围: {OverallQualityScore}");
}
// 检查性能指标
if (PerformanceMetrics == null || !PerformanceMetrics.Any())
{
result.Issues.Add("缺少性能监控数据");
}
return result;
}
/// <summary>
/// 获取结果健康状态
/// </summary>
public HealthStatus GetHealthStatus()
{
var successRate = SuccessRate;
var avgQuality = AverageMatchQuality;
if (successRate >= 90 && avgQuality >= 80)
return HealthStatus.Excellent;
else if (successRate >= 70 && avgQuality >= 70)
return HealthStatus.Good;
else if (successRate >= 50 && avgQuality >= 60)
return HealthStatus.Fair;
else
return HealthStatus.Poor;
}
#endregion
}
#region
/// <summary>
/// 人员候选人信息
/// 包含完整的评分体系和匹配详情
/// </summary>
public class PersonnelCandidate
{
/// <summary>
/// 人员ID
/// </summary>
public long PersonnelId { get; set; }
/// <summary>
/// 人员姓名
/// </summary>
public string PersonnelName { get; set; } = string.Empty;
/// <summary>
/// 资质评分详情
/// </summary>
public QualificationScore QualificationScore { get; set; } = new();
/// <summary>
/// 约束条件评分
/// </summary>
public ConstraintScore ConstraintScore { get; set; } = new();
/// <summary>
/// 优化决策评分
/// </summary>
public OptimizationScore OptimizationScore { get; set; }
/// <summary>
/// 综合总分 (0-100)
/// </summary>
public double TotalScore { get; set; }
/// <summary>
/// 是否为最优选择
/// </summary>
public bool IsOptimalChoice { get; set; }
/// <summary>
/// 候选人排名
/// </summary>
public int Rank { get; set; }
/// <summary>
/// 分配理由说明
/// </summary>
public string AllocationReason { get; set; } = string.Empty;
/// <summary>
/// 预估工作负载
/// </summary>
public double? EstimatedWorkload { get; set; }
/// <summary>
/// 风险评估等级
/// </summary>
public RiskLevel RiskLevel { get; set; } = RiskLevel.Low;
/// <summary>
/// 决策评分
/// </summary>
public DecisionScore DecisionScore { get; set; } = new();
public RecommendationLevel RecommendationLevel { get; set; } = RecommendationLevel.NotRecommended;
}
/// <summary>
/// 资质评分详情
/// </summary>
public class QualificationScore
{
/// <summary>
/// 资质匹配分数 (0-100)
/// </summary>
public double MatchScore { get; set; }
/// <summary>
/// 是否资质有效
/// </summary>
public bool IsQualificationValid { get; set; }
/// <summary>
/// 匹配的资质列表
/// </summary>
public List<string> MatchedQualifications { get; set; } = new();
/// <summary>
/// 缺失的资质列表
/// </summary>
public List<string> MissingQualifications { get; set; } = new();
/// <summary>
/// 资质详细信息
/// </summary>
public string QualificationDetails { get; set; } = string.Empty;
}
/// <summary>
/// 约束条件评分
/// 用于记录人员候选人在约束评估阶段的各项评分和详细信息
/// 包含时间可用性、工作限制、班次规则等多维度约束检查结果
/// </summary>
public class ConstraintScore
{
#region
/// <summary>
/// 约束符合度分数 (0-100)
/// 综合各项约束检查的加权平均分数
/// </summary>
public double ComplianceScore { get; set; }
/// <summary>
/// 时间可用性分数 (0-100)
/// 基于人员在工作时间段的可用性评估
/// </summary>
public double TimeAvailabilityScore { get; set; }
/// <summary>
/// 工作限制符合度分数 (0-100)
/// 基于人员工作限制规则的符合程度评估
/// </summary>
public double WorkLimitComplianceScore { get; set; }
/// <summary>
/// 班次规则符合度分数 (0-100)
/// 基于班次规则和排班政策的符合程度评估
/// </summary>
public double ShiftRuleComplianceScore { get; set; }
#endregion
#region
/// <summary>
/// 约束违规列表
/// 记录所有违反的约束规则和具体违规内容
/// </summary>
public List<ConstraintViolation> Violations { get; set; }
/// <summary>
/// 通过约束检查列表
/// 记录所有通过检查的约束规则
/// </summary>
public List<string> PassedConstraints { get; set; } = new();
/// <summary>
/// 约束评估详情
/// 包含详细的约束检查过程和结果说明
/// </summary>
public string ConstraintDetails { get; set; } = string.Empty;
#endregion
#region
/// <summary>
/// 地理位置约束分数 (0-100)
/// 基于人员与工作地点的距离和可达性评估
/// </summary>
public double LocationConstraintScore { get; set; }
/// <summary>
/// 设备可用性分数 (0-100)
/// 基于人员所需设备的可用性评估
/// </summary>
public double EquipmentAvailabilityScore { get; set; }
/// <summary>
/// 项目授权分数 (0-100)
/// 基于人员对特定项目的授权和访问权限评估
/// </summary>
public double ProjectAuthorizationScore { get; set; }
/// <summary>
/// 技能匹配约束分数 (0-100)
/// 基于人员技能与任务要求的匹配程度评估
/// </summary>
public double SkillMatchConstraintScore { get; set; }
#endregion
#region
/// <summary>
/// 约束风险等级
/// 基于约束符合度评估的风险等级
/// </summary>
public RiskLevel RiskLevel => ComplianceScore switch
{
>= 90 => RiskLevel.Low,
>= 80 => RiskLevel.Low,
>= 70 => RiskLevel.Medium,
>= 60 => RiskLevel.Medium,
_ => RiskLevel.High
};
/// <summary>
/// 约束风险描述
/// 详细描述约束风险的具体内容和影响
/// </summary>
public string RiskDescription { get; set; } = string.Empty;
/// <summary>
/// 风险缓解建议
/// 针对识别出的约束风险提供的缓解措施建议
/// </summary>
public List<string> RiskMitigationSuggestions { get; set; } = new();
#endregion
#region
/// <summary>
/// 约束检查执行时间(毫秒)
/// 记录约束评估过程的执行耗时
/// </summary>
public long ExecutionTimeMs { get; set; }
/// <summary>
/// 约束检查项目数量
/// 记录本次约束评估检查的约束项目总数
/// </summary>
public int TotalConstraintItems { get; set; }
/// <summary>
/// 约束检查通过率
/// 计算公式:通过项目数 / 总项目数 * 100
/// </summary>
public double PassRate => TotalConstraintItems > 0 ? (double)PassedConstraints.Count / TotalConstraintItems * 100 : 0;
#endregion
#region
public ConstraintScore()
{
Violations = new List<ConstraintViolation>();
PassedConstraints = new List<string>();
RiskMitigationSuggestions = new List<string>();
}
#endregion
#region
/// <summary>
/// 检查是否通过所有关键约束
/// </summary>
/// <returns>是否通过所有关键约束检查</returns>
public bool IsFullyCompliant => ComplianceScore >= 80 && Violations.Count == 0;
/// <summary>
/// 检查是否满足最低约束要求
/// </summary>
/// <returns>是否满足最低约束要求</returns>
public bool MeetsMinimumRequirements => ComplianceScore >= 60;
/// <summary>
/// 获取约束评估摘要
/// </summary>
/// <returns>约束评估的简要总结</returns>
public string GetConstraintSummary()
{
var summary = $"约束符合度:{ComplianceScore:F1}分,";
summary += $"通过检查:{PassedConstraints.Count}项,";
summary += $"违规项目:{Violations.Count}项,";
summary += $"风险等级:{RiskLevel}";
return summary;
}
/// <summary>
/// 添加通过约束检查信息
/// </summary>
/// <param name="constraint">通过的约束描述</param>
public void AddPassedConstraint(string constraint)
{
if (!string.IsNullOrEmpty(constraint) && !PassedConstraints.Contains(constraint))
{
PassedConstraints.Add(constraint);
}
}
/// <summary>
/// 计算综合约束评分
/// </summary>
/// <param name="weights">各维度权重配置</param>
/// <returns>加权综合评分</returns>
public double CalculateWeightedScore(Dictionary<string, double> weights)
{
if (weights == null || !weights.Any())
{
// 使用默认权重
weights = new Dictionary<string, double>
{
{ "TimeAvailability", 0.3 },
{ "WorkLimit", 0.25 },
{ "ShiftRule", 0.25 },
{ "Location", 0.1 },
{ "Equipment", 0.1 }
};
}
var weightedScore = 0.0;
var totalWeight = 0.0;
foreach (var kvp in weights)
{
var score = kvp.Key switch
{
"TimeAvailability" => TimeAvailabilityScore,
"WorkLimit" => WorkLimitComplianceScore,
"ShiftRule" => ShiftRuleComplianceScore,
"Location" => LocationConstraintScore,
"Equipment" => EquipmentAvailabilityScore,
_ => 0.0
};
weightedScore += score * kvp.Value;
totalWeight += kvp.Value;
}
return totalWeight > 0 ? weightedScore / totalWeight : 0;
}
#endregion
}
/// <summary>
/// 优化决策评分
/// </summary>
public class OptimizationScore
{
/// <summary>
/// 指定人员匹配分数
/// </summary>
public double AssignedPersonnelScore { get; set; }
/// <summary>
/// 项目FL人员优先分数
/// </summary>
public double ProjectFLScore { get; set; }
/// <summary>
/// 工作负载平衡分数
/// </summary>
public double WorkloadBalanceScore { get; set; }
/// <summary>
/// 班次连续性分数
/// </summary>
public double ShiftContinuityScore { get; set; }
/// <summary>
/// 技能匹配优化分数
/// </summary>
public double SkillOptimizationScore { get; set; }
/// <summary>
/// 协作历史分数
/// </summary>
public double CollaborationHistoryScore { get; set; }
/// <summary>
/// 优化总分 (0-100)
/// </summary>
public double TotalOptimizationScore { get; set; }
public double SkillMatchScore { get; set; }
public double EfficiencyScore { get; set; }
public double optimizationScore { get; set; }
public string OptimizationDetails { get; set; } = string.Empty;
}
/// <summary>
/// 分配失败信息
/// </summary>
public class FailedAllocation
{
/// <summary>
/// 工作任务ID
/// </summary>
public long WorkOrderId { get; set; }
/// <summary>
/// 任务编码
/// </summary>
public string WorkOrderCode { get; set; } = string.Empty;
/// <summary>
/// 失败原因描述
/// </summary>
public string FailureReason { get; set; } = string.Empty;
/// <summary>
/// 失败类型
/// </summary>
public AllocationFailureType FailureType { get; set; }
/// <summary>
/// 建议解决方案
/// </summary>
public List<string> SuggestedSolutions { get; set; } = new();
/// <summary>
/// 详细错误信息
/// </summary>
public List<string> DetailedErrors { get; set; } = new();
/// <summary>
/// 冲突的人员列表
/// </summary>
public List<ConflictingPersonnel> ConflictingPersonnels { get; set; } = new();
}
/// <summary>
/// 分配失败类型枚举
/// </summary>
public enum AllocationFailureType
{
/// <summary>
/// 无可用人员
/// </summary>
NoAvailablePersonnel = 1,
/// <summary>
/// 资质不匹配
/// </summary>
QualificationMismatch = 2,
/// <summary>
/// 时间冲突
/// </summary>
TimeConflict = 3,
/// <summary>
/// 工作量超限
/// </summary>
WorkloadExceeded = 4,
/// <summary>
/// 班次规则冲突
/// </summary>
ShiftRuleConflict = 5,
/// <summary>
/// 系统错误
/// </summary>
SystemError = 6,
/// <summary>
/// 业务规则冲突
/// </summary>
BusinessRuleConflict = 7
}
/// <summary>
/// 冲突人员信息
/// </summary>
public class ConflictingPersonnel
{
/// <summary>
/// 人员ID
/// </summary>
public long PersonnelId { get; set; }
/// <summary>
/// 人员姓名
/// </summary>
public string PersonnelName { get; set; } = string.Empty;
/// <summary>
/// 冲突类型
/// </summary>
public string ConflictType { get; set; } = string.Empty;
/// <summary>
/// 冲突描述
/// </summary>
public string ConflictDescription { get; set; } = string.Empty;
}
/// <summary>
/// 详细分配报告
/// </summary>
public class AllocationReport
{
/// <summary>
/// 成功分配数量
/// </summary>
public int SuccessfulAllocationCount { get; set; }
/// <summary>
/// 失败分配数量
/// </summary>
public int FailedAllocationCount { get; set; }
/// <summary>
/// 成功率百分比
/// </summary>
public double SuccessRate { get; set; }
/// <summary>
/// 平均质量评分
/// </summary>
public double AverageQualityScore { get; set; }
/// <summary>
/// 人员利用率分析
/// Key: 人员ID, Value: 分配任务数量
/// </summary>
public Dictionary<long, double> PersonnelUtilizationRate { get; set; } = new();
/// <summary>
/// 风险分析报告
/// </summary>
public RiskAnalysis RiskAnalysis { get; set; } = new();
/// <summary>
/// 优化建议列表
/// </summary>
public List<string> OptimizationSuggestions { get; set; } = new();
/// <summary>
/// 报告生成时间
/// </summary>
public DateTime GeneratedAt { get; set; } = DateTime.Now;
}
/// <summary>
/// 风险分析
/// </summary>
public class RiskAnalysis
{
/// <summary>
/// 整体风险评分 (0-100)
/// </summary>
public double OverallRiskScore { get; set; }
/// <summary>
/// 高风险任务数量
/// </summary>
public int HighRiskTaskCount { get; set; }
/// <summary>
/// 中风险任务数量
/// </summary>
public int MediumRiskTaskCount { get; set; }
/// <summary>
/// 低风险任务数量
/// </summary>
public int LowRiskTaskCount { get; set; }
/// <summary>
///
/// </summary>
public Dictionary<RiskLevel, int> RiskDistribution { get; set; } = new();
/// <summary>
/// 主要风险因素
/// </summary>
public List<string> PrimaryRiskFactors { get; set; } = new();
}
/// <summary>
/// 人员工作负载信息
/// </summary>
public class PersonnelWorkloadInfo
{
/// <summary>
/// 人员ID
/// </summary>
public long PersonnelId { get; set; }
/// <summary>
/// 人员姓名
/// </summary>
public string PersonnelName { get; set; } = string.Empty;
/// <summary>
/// 分配任务数量
/// </summary>
public int AssignedTaskCount { get; set; }
/// <summary>
/// 平均匹配分数
/// </summary>
public double AverageMatchScore { get; set; }
/// <summary>
/// 总工作负载
/// </summary>
public double TotalWorkload { get; set; }
/// <summary>
/// 负载状态
/// </summary>
public WorkloadStatus LoadStatus => DetermineLoadStatus();
/// <summary>
/// 确定负载状态
/// </summary>
private WorkloadStatus DetermineLoadStatus()
{
if (TotalWorkload >= 8.0) return WorkloadStatus.Overloaded;
if (TotalWorkload >= 6.0) return WorkloadStatus.HighLoad;
if (TotalWorkload >= 4.0) return WorkloadStatus.NormalLoad;
if (TotalWorkload >= 2.0) return WorkloadStatus.LightLoad;
return WorkloadStatus.Idle;
}
}
/// <summary>
/// 技能匹配分析
/// </summary>
public class SkillMatchAnalysis
{
/// <summary>
/// 平均技能匹配分数
/// </summary>
public double AverageSkillMatchScore { get; set; }
/// <summary>
/// 完全胜任人员数量
/// </summary>
public int FullyQualifiedCount { get; set; }
/// <summary>
/// 部分胜任人员数量
/// </summary>
public int PartiallyQualifiedCount { get; set; }
/// <summary>
/// 勉强胜任人员数量
/// </summary>
public int MinimallyQualifiedCount { get; set; }
/// <summary>
/// 技能覆盖度 (0-100)
/// </summary>
public double SkillCoverageRate => CalculateCoverageRate();
/// <summary>
/// 计算技能覆盖度
/// </summary>
private double CalculateCoverageRate()
{
var total = FullyQualifiedCount + PartiallyQualifiedCount + MinimallyQualifiedCount;
return total > 0 ? (double)(FullyQualifiedCount + PartiallyQualifiedCount) / total * 100 : 0;
}
}
/// <summary>
/// 验证结果
/// </summary>
public class ValidationResult
{
/// <summary>
/// 验证是否通过
/// </summary>
public bool IsValid { get; set; }
/// <summary>
/// 问题列表
/// </summary>
public List<string> Issues { get; set; } = new();
public List<ValidationViolation> Violations { get; set; } = new List<ValidationViolation>();
}
/// <summary>
/// 风险等级枚举
/// </summary>
public enum RiskLevel
{
/// <summary>
/// 低风险
/// </summary>
Low = 1,
/// <summary>
/// 中风险
/// </summary>
Medium = 2,
/// <summary>
/// 高风险
/// </summary>
High = 3,
/// <summary>
/// 极高风险
/// </summary>
Critical = 4
}
/// <summary>
/// 工作负载状态枚举
/// </summary>
public enum WorkloadStatus
{
/// <summary>
/// 空闲
/// </summary>
Idle = 0,
/// <summary>
/// 轻负载
/// </summary>
LightLoad = 1,
/// <summary>
/// 正常负载
/// </summary>
NormalLoad = 2,
/// <summary>
/// 高负载
/// </summary>
HighLoad = 3,
/// <summary>
/// 超负载
/// </summary>
Overloaded = 4
}
/// <summary>
/// 健康状态枚举
/// </summary>
public enum HealthStatus
{
/// <summary>
/// 优秀
/// </summary>
Excellent = 4,
/// <summary>
/// 良好
/// </summary>
Good = 3,
/// <summary>
/// 一般
/// </summary>
Fair = 2,
/// <summary>
/// 差
/// </summary>
Poor = 1
}
#endregion
}