$path = "NPP.SmartSchedue.Api/Services/Integration/Algorithms/LinearProgrammingEngine.cs"
$lines = [System.Collections.Generic.List[string]]::new()
$lines.AddRange([System.IO.File]::ReadAllLines($path))

function FindContainsIndex([string[]]$array, [string]$value, [int]$start = 0) {
    for ($i = $start; $i -lt $array.Length; $i++) {
        if ($array[$i].Contains($value)) { return $i }
    }
    return -1
}

function FindBlockIndices([string[]]$array, [int]$start) {
    $brace = 0
    for ($i = $start; $i -lt $array.Length; $i++) {
        if ($array[$i].Contains('{')) { $brace++ }
        if ($array[$i].Contains('}')) { $brace-- }
        if ($brace -eq 0) { return $i }
    }
    return -1
}

# BuildAuxiliaryVariables adjustments
$index = FindContainsIndex $lines 'var auxiliaryVars = new Dictionary<string, Variable>();'
if ($index -ge 0) {
    $lines.InsertRange($index + 1, [string[]]@(
'            var historicalWorkloads = BuildHistoricalWorkloadMap(context, out var totalHistoricalTasks);',
'            var avgWorkload = context.AvailablePersonnel.Count > 0',
'                ? (double)(context.Tasks.Count + totalHistoricalTasks) / context.AvailablePersonnel.Count',
'                : 0.0;'
    ))
}
$index = FindContainsIndex $lines 'var avgWorkload = (double)context.Tasks.Count / context.AvailablePersonnel.Count;'
if ($index -ge 0) { $lines.RemoveAt($index) }
$index = FindContainsIndex $lines 'var negDeviationVar = solver.MakeNumVar(0, avgWorkload, $"neg_dev_'
if ($index -ge 0) { $lines[$index] = '                var negDeviationVar = solver.MakeNumVar(0, Math.Max(0.0, avgWorkload), $"neg_dev_{personnel.Id}");' }

# Replace fairness method
$regionIndex = FindContainsIndex $lines '#region 公平性约束 - 对应遗传算法负载均衡机制'
if ($regionIndex -ge 0) {
    $start = $regionIndex + 2
    $end = FindContainsIndex $lines '#endregion' ($start)
    if ($end -gt $start) {
        $lines.RemoveRange($start, $end - $start)
        $newFairness = [string[]]@(
'        private void AddFairnessConstraints(',
'            Solver solver,',
'            Dictionary<(long TaskId, long PersonnelId), Variable> decisionVars,',
'            Dictionary<string, Variable> auxiliaryVars,',
'            GlobalAllocationContext context)',
'        {',
'            var constraintCount = 0;',
'',
'            _logger.LogInformation("⚖️ 开始添加公平性约束...");',
'',
'            var totalTasks = context.Tasks.Count;',
'            var totalPersonnel = context.AvailablePersonnel.Count;',
'            var historicalWorkloads = BuildHistoricalWorkloadMap(context, out var totalHistoricalWorkload);',
'            var totalWorkload = totalTasks + totalHistoricalWorkload;',
'            var avgWorkload = totalPersonnel > 0 ? (double)totalWorkload / totalPersonnel : 0.0;',
'',
'            // 公平性约束1：负载均衡偏差计算',
'            foreach (var personnel in context.AvailablePersonnel)',
'            {',
'                var workloadVarKey = $"workload_{personnel.Id}";',
'                var posDevVarKey = $"pos_dev_{personnel.Id}";',
'                var negDevVarKey = $"neg_dev_{personnel.Id}";',
'                var historicalWorkload = historicalWorkloads.GetValueOrDefault(personnel.Id);',
'',
'                if (auxiliaryVars.ContainsKey(workloadVarKey) &&',
'                    auxiliaryVars.ContainsKey(posDevVarKey) &&',
'                    auxiliaryVars.ContainsKey(negDevVarKey))',
'                {',
'                    // 约束：currentWorkload + 历史工作量偏移 = avgWorkload + pos_deviation - neg_deviation',
'                    var targetWorkload = avgWorkload - historicalWorkload;',
'                    var balanceConstraint = solver.MakeConstraint(targetWorkload, targetWorkload,',
'                        $"load_balance_{personnel.Id}");',
'',
'                    balanceConstraint.SetCoefficient(auxiliaryVars[workloadVarKey], 1);',
'                    balanceConstraint.SetCoefficient(auxiliaryVars[posDevVarKey], -1);',
'                    balanceConstraint.SetCoefficient(auxiliaryVars[negDevVarKey], 1);',
'                    constraintCount++;',
'                }',
'            }',
'',
'            // 公平性约束2：最大负载限制 - 防止极端不均衡',
'            var maxTotalWorkload = Math.Ceiling(avgWorkload * 1.5);',
'            foreach (var personnel in context.AvailablePersonnel)',
'            {',
'                var workloadVarKey = $"workload_{personnel.Id}";',
'                var historicalWorkload = historicalWorkloads.GetValueOrDefault(personnel.Id);',
'                if (auxiliaryVars.ContainsKey(workloadVarKey))',
'                {',
'                    var constraint = solver.MakeConstraint(0, Math.Max(0.0, maxTotalWorkload - historicalWorkload),',
'                        $"max_workload_{personnel.Id}");',
'                    constraint.SetCoefficient(auxiliaryVars[workloadVarKey], 1);',
'                    constraintCount++;',
'                }',
'            }',
'',
'            // 公平性约束3：最小人员利用率约束 - 确保不会过度集中',
'            var minPersonnelUtilization = totalPersonnel == 0',
'                ? 0',
'                : (totalTasks > 10 ? Math.Max(3, Math.Ceiling(totalPersonnel * 0.4)) : Math.Min((double)totalPersonnel, 2));',
'',
'            // 创建人员参与指示变量',
'            var participationVars = new List<Variable>();',
'            foreach (var personnel in context.AvailablePersonnel)',
'            {',
'                var participationVar = solver.MakeBoolVar($"participation_{personnel.Id}");',
'                participationVars.Add(participationVar);',
'',
'                // 如果人员参与，则至少分配1个任务',
'                var constraint = solver.MakeConstraint(0, double.PositiveInfinity,',
'                    $"participation_min_{personnel.Id}");',
'',
'                constraint.SetCoefficient(participationVar, -1);',
'',
'                var personnelTasks = decisionVars.Where(v => v.Key.PersonnelId == personnel.Id);',
'                foreach (var kvp in personnelTasks)',
'                {',
'                    constraint.SetCoefficient(kvp.Value, 1);',
'                }',
'                constraintCount++;',
'            }',
'',
'            // 最小参与人数约束',
'            var minParticipationConstraint = solver.MakeConstraint(minPersonnelUtilization, double.PositiveInfinity,',
'                "min_personnel_utilization");',
'',
'            foreach (var participationVar in participationVars)',
'            {',
'                minParticipationConstraint.SetCoefficient(participationVar, 1);',
'            }',
'            constraintCount++;',
'',
'            _logger.LogDebug("✅ 公平性约束添加完成 - 约束数量：{ConstraintCount}，平均负载：{AvgWorkload:F2}，最大负载：{MaxWorkload:F2}，最小参与人数：{MinParticipation}",',
'                constraintCount, avgWorkload, maxTotalWorkload, minPersonnelUtilization);',
'        }'
        )
        $lines.InsertRange($start, $newFairness)
    }
}

# Update LogWorkloadAnalysis call
$index = FindContainsIndex $lines 'LogWorkloadAnalysis(workloadDistribution, context.Tasks.Count, context.AvailablePersonnel.Count);'
if ($index -ge 0) { $lines[$index] = '                LogWorkloadAnalysis(workloadDistribution, context.Tasks.Count, context.AvailablePersonnel.Count, context);' }

# ValidateSolutionQuality adjustments
$index = FindContainsIndex $lines 'var totalChecks = 0;'
if ($index -ge 0 -and -not $lines[$index + 1].Contains('BuildHistoricalWorkloadMap')) {
    $lines.Insert($index + 1, '            var historicalWorkloads = BuildHistoricalWorkloadMap(context, out _);')
}
$start = FindContainsIndex $lines '// 检查3：负载均衡评估'
if ($start -ge 0) {
    $lines.RemoveRange($start, 8)
    $lines.InsertRange($start, [string[]]@(
'            // 检查3：负载均衡评估（纳入历史任务）',
'            var currentWorkloadMap = assignments',
'                .GroupBy(a => a.Value)',
'                .ToDictionary(g => g.Key, g => g.Count());',
'',
'            var combinedWorkloads = context.AvailablePersonnel.ToDictionary(',
'                p => p.Id,',
'                p => historicalWorkloads.GetValueOrDefault(p.Id) + currentWorkloadMap.GetValueOrDefault(p.Id));',
'',
'            if (combinedWorkloads.Any())',
'            {',
'                var workloadValues = combinedWorkloads.Values.Select(v => (decimal)v).ToList();',
'                var giniCoefficient = CalculateGiniCoefficient(workloadValues);',
'                metrics.LoadBalanceScore = Math.Max(0.0, 1.0 - giniCoefficient);',
'',
'                var utilizedCount = combinedWorkloads.Count(kv => kv.Value > 0);',
'                metrics.PersonnelUtilizationRate = context.AvailablePersonnel.Count > 0',
'                    ? (double)utilizedCount / context.AvailablePersonnel.Count',
'                    : 0.0;',
'            }'
    ))
}

# Replace LogWorkloadAnalysis method
$logStart = FindContainsIndex $lines 'private void LogWorkloadAnalysis('
if ($logStart -ge 0) {
    $logEnd = FindBlockIndices $lines $logStart
    if ($logEnd -ge $logStart) {
        $lines.RemoveRange($logStart, $logEnd - $logStart + 1)
        $newLog = [string[]]@(
'        private void LogWorkloadAnalysis(',
'            Dictionary<long, decimal> workloadDistribution,',
'            int totalTasks,',
'            int totalPersonnel,',
'            GlobalAllocationContext context)',
'        {',
'            var historicalWorkloads = BuildHistoricalWorkloadMap(context, out _);',
'',
'            if (!workloadDistribution.Any() && historicalWorkloads.Values.All(value => value == 0))',
'            {',
'                return;',
'            }',
'',
'            var combinedWorkloads = context.AvailablePersonnel.ToDictionary(',
'                p => p.Id,',
'                p => workloadDistribution.GetValueOrDefault(p.Id) + historicalWorkloads.GetValueOrDefault(p.Id));',
'',
'            if (!combinedWorkloads.Any())',
'            {',
'                return;',
'            }',
'',
'            var combinedValues = combinedWorkloads.Values.Select(value => (decimal)value).ToList();',
'            var avgWorkload = combinedValues.Average(value => (double)value);',
'            var maxWorkload = combinedValues.Max();',
'            var minWorkload = combinedValues.Min();',
'            var utilizedCount = combinedWorkloads.Count(kv => kv.Value > 0);',
'            var utilizationRate = totalPersonnel > 0 ? (double)utilizedCount / totalPersonnel : 0.0;',
'',
'            _logger.LogInformation("📈 工作负载分析(含历史) - 平均：{Avg:F2}，最大：{Max}，最小：{Min}，当前批次任务数：{CurrentTasks}，人员利用率：{Util:P2}，基尼系数：{Gini:F4}",',
'                avgWorkload, maxWorkload, minWorkload, totalTasks, utilizationRate, CalculateGiniCoefficient(combinedValues));',
'',
'            var currentDistributionLog = string.Join(", ",',
'                workloadDistribution.OrderBy(kv => kv.Key)',
'                                    .Select(kv => $"人员{kv.Key}:{kv.Value}任务"));',
'            if (!string.IsNullOrWhiteSpace(currentDistributionLog))',
'            {',
'                _logger.LogDebug("📊 本次任务负载：{Distribution}", currentDistributionLog);',
'            }',
'',
'            var historicalDistributionLog = string.Join(", ",',
'                historicalWorkloads.OrderBy(kv => kv.Key)',
'                                   .Select(kv => $"人员{kv.Key}:{kv.Value}历史任务"));',
'            if (!string.IsNullOrWhiteSpace(historicalDistributionLog))',
'            {',
'                _logger.LogDebug("🕰️ 历史任务负载：{Distribution}", historicalDistributionLog);',
'            }',
'',
'            var cumulativeDistributionLog = string.Join(", ",',
'                combinedWorkloads.OrderBy(kv => kv.Key)',
'                                 .Select(kv => $"人员{kv.Key}:{kv.Value}累计任务"));',
'            _logger.LogDebug("⚖️ 累计任务负载：{Distribution}", cumulativeDistributionLog);',
'        }'
        )
        $lines.InsertRange($logStart, $newLog)
    }
}

# Insert helper method after 辅助方法 region line
$regionIndex = FindContainsIndex $lines '#region 辅助方法'
if ($regionIndex -ge 0) {
    $lines.InsertRange($regionIndex + 1, [string[]]@(
'',
'        private Dictionary<long, int> BuildHistoricalWorkloadMap(GlobalAllocationContext context, out int totalHistoricalTasks)',
'        {',
'            var historicalWorkloads = new Dictionary<long, int>();',
'            totalHistoricalTasks = 0;',
'',
'            foreach (var personnel in context.AvailablePersonnel)',
'            {',
'                var historyCount = 0;',
'                if (context.PersonnelHistoryTasks.TryGetValue(personnel.Id, out var historyTasks) && historyTasks != null)',
'                {',
'                    historyCount = historyTasks.Count;',
'                }',
'',
'                historicalWorkloads[personnel.Id] = historyCount;',
'                totalHistoricalTasks += historyCount;',
'            }',
'',
'            return historicalWorkloads;',
'        }',
''
    ))
}

# Update CreateBatchIntegrityConstraints block
$blockStart = FindContainsIndex $lines 'private int CreateBatchIntegrityConstraints('
if ($blockStart -ge 0) {
    $blockEnd = FindBlockIndices $lines $blockStart
    $lines.RemoveRange($blockStart, $blockEnd - $blockStart + 1)
    $newBlock = [string[]]@(
'        private int CreateBatchIntegrityConstraints(',
'            Solver solver,',
'            Dictionary<(long TaskId, long PersonnelId), Variable> decisionVars,',
'            Dictionary<string, Variable> auxiliaryVars,',
'            GlobalAllocationContext context)',
'        {',
'            var constraintCount = 0;',
'',
'            // 1. 项目连续性约束增强',
'            var projectGroups = context.Tasks',
'                .GroupBy(t => ExtractProjectFromWorkOrderCode(t.WorkOrderCode))',
'                .Where(g => g.Count() > 1)',
'                .ToList();',
'',
'            foreach (var projectGroup in projectGroups)',
'            {',
'                var projectTasks = projectGroup.ToList();',
'                var projectCode = projectGroup.Key;',
'',
'                // 创建项目一致性指示变量',
'                foreach (var personnel in context.AvailablePersonnel)',
'                {',
'                    var projectParticipationVars = projectTasks',
'                        .Where(task => decisionVars.ContainsKey((task.Id, personnel.Id)))',
'                        .Select(task => decisionVars[(task.Id, personnel.Id)])',
'                        .ToList();',
'',
'                    if (projectParticipationVars.Count > 1)',
'                    {',
'                        var participationVar = solver.MakeBoolVar(',
'                            $"project_participation_{projectCode}_{personnel.Id}");',
'',
'                        // 如果参与项目，则至少分配一个任务',
'                        var constraint = solver.MakeConstraint(0, double.PositiveInfinity,',
'                            $"project_integrity_{projectCode}_{personnel.Id}");',
'',
'                        constraint.SetCoefficient(participationVar, -1);',
'                        foreach (var taskVar in projectParticipationVars)',
'                        {',
'                            constraint.SetCoefficient(taskVar, 1);',
'                        }',
'                        constraintCount++;',
'',
'                        // 限制项目参与人员数量',
'                        auxiliaryVars[$"project_participation_{projectCode}_{personnel.Id}"] = participationVar;',
'                    }',
'                }',
'            }',
'',
'            // 2. 工作负载平衡约束',
'            var totalTasks = context.Tasks.Count;',
'            var totalPersonnel = context.AvailablePersonnel.Count;',
'            var historicalWorkloads = BuildHistoricalWorkloadMap(context, out var totalHistoricalWorkload);',
'            var totalWorkload = totalTasks + totalHistoricalWorkload;',
'            var avgWorkload = totalPersonnel > 0 ? (double)totalWorkload / totalPersonnel : 0.0;',
'            var maxDeviation = Math.Ceiling(avgWorkload * 0.3); // 允许30%偏差',
'',
'            foreach (var personnel in context.AvailablePersonnel)',
'            {',
'                var personnelTasks = decisionVars',
'                    .Where(kvp => kvp.Key.PersonnelId == personnel.Id)',
'                    .Select(kvp => kvp.Value)',
'                    .ToList();',
'                var historicalWorkload = historicalWorkloads.GetValueOrDefault(personnel.Id);',
'',
'                if (personnelTasks.Any())',
'                {',
'                    // 工作负载总量（含历史）不应过度偏离平均值',
'                    var lowerBound = Math.Max(0.0, (avgWorkload - maxDeviation) - historicalWorkload);',
'                    var upperBound = Math.Max(lowerBound, (avgWorkload + maxDeviation) - historicalWorkload);',
'                    var constraint = solver.MakeConstraint(',
'                        lowerBound,',
'                        upperBound,',
'                        $"workload_balance_{personnel.Id}");',
'',
'                    foreach (var taskVar in personnelTasks)',
'                    {',
'                        constraint.SetCoefficient(taskVar, 1);',
'                    }',
'                    constraintCount++;',
'                }',
'            }',
'',
'            return constraintCount;',
'        }'
    )
    $lines.InsertRange($blockStart, $newBlock)
}

[System.IO.File]::WriteAllLines($path, $lines)
