| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Linq; |
| | | 4 | | using System.Text; |
| | | 5 | | using CounterDrone.Core.Models; |
| | | 6 | | using SimEvent = CounterDrone.Core.Simulation.SimEvent; |
| | | 7 | | |
| | | 8 | | namespace CounterDrone.Core.Services |
| | | 9 | | { |
| | | 10 | | public class ReportGenerator |
| | | 11 | | { |
| | | 12 | | /// <summary>根据仿真结果生成报告内容</summary> |
| | | 13 | | public string Generate(TaskFullConfig config, List<SimEvent> events, |
| | | 14 | | Simulation.DroneStatus finalDroneStatus, float simulationDuration) |
| | 9 | 15 | | { |
| | 9 | 16 | | var sb = new StringBuilder(); |
| | | 17 | | |
| | | 18 | | // === 仿真前:我方配置 === |
| | 9 | 19 | | sb.AppendLine("# 仿真评估报告"); |
| | 9 | 20 | | sb.AppendLine(); |
| | 9 | 21 | | sb.AppendLine($"**任务名称**:{config.Task.Name}"); |
| | 9 | 22 | | sb.AppendLine($"**任务编号**:{config.Task.TaskNumber}"); |
| | 9 | 23 | | sb.AppendLine($"**仿真耗时**:{simulationDuration:F1} 秒"); |
| | 9 | 24 | | sb.AppendLine(); |
| | | 25 | | |
| | 9 | 26 | | sb.AppendLine("## 一、仿真前 — 我方配置"); |
| | 9 | 27 | | sb.AppendLine(); |
| | 9 | 28 | | var deployment = config.Equipment; |
| | 37 | 29 | | var platforms = deployment.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform).ToList(); |
| | 37 | 30 | | var detections = deployment.Where(e => e.EquipmentRole == (int)EquipmentRole.Detection).ToList(); |
| | | 31 | | |
| | 9 | 32 | | sb.AppendLine($"| 配置项 | 值 |"); |
| | 9 | 33 | | sb.AppendLine($"|--------|-----|"); |
| | 18 | 34 | | sb.AppendLine($"| 目标数量 | {config.Targets.Sum(t => t.Quantity)} |"); |
| | 32 | 35 | | sb.AppendLine($"| 发射平台 | {platforms.Sum(p => p.Quantity)} 台 |"); |
| | 14 | 36 | | sb.AppendLine($"| 探测设备 | {detections.Sum(d => d.Quantity)} 台 |"); |
| | 9 | 37 | | sb.AppendLine($"| 气溶胶类型 | {(AerosolType)config.Cloud.AerosolType} |"); |
| | 9 | 38 | | sb.AppendLine(); |
| | | 39 | | |
| | | 40 | | // === 仿真中:关键事件时序 === |
| | 9 | 41 | | sb.AppendLine("## 二、仿真中 — 关键事件时序"); |
| | 9 | 42 | | sb.AppendLine(); |
| | 9 | 43 | | sb.AppendLine("| 时间(s) | 事件 | 描述 |"); |
| | 9 | 44 | | sb.AppendLine("|---------|------|------|"); |
| | 198 | 45 | | foreach (var e in events.OrderBy(e => e.OccurredAt)) |
| | 57 | 46 | | { |
| | 57 | 47 | | sb.AppendLine($"| {e.OccurredAt:F1} | {e.Type} | {e.Description} |"); |
| | 57 | 48 | | } |
| | 9 | 49 | | sb.AppendLine(); |
| | | 50 | | |
| | | 51 | | // === 仿真后:统计分析 === |
| | 9 | 52 | | sb.AppendLine("## 三、仿真后 — 数据统计"); |
| | 9 | 53 | | sb.AppendLine(); |
| | | 54 | | |
| | 66 | 55 | | var destroyed = events.Count(e => e.Type == SimEventType.DroneDestroyed); |
| | 66 | 56 | | var reached = events.Count(e => e.Type == SimEventType.DroneReachedTarget); |
| | 66 | 57 | | var intruded = events.Count(e => e.Type == SimEventType.ZoneIntruded); |
| | 66 | 58 | | var cloudCount = events.Count(e => e.Type == SimEventType.CloudGenerated); |
| | 66 | 59 | | var launchCount = events.Count(e => e.Type == SimEventType.MunitionLaunched); |
| | 18 | 60 | | var totalDrones = config.Targets.Sum(t => t.Quantity); |
| | | 61 | | |
| | 9 | 62 | | sb.AppendLine($"| 统计项 | 值 |"); |
| | 9 | 63 | | sb.AppendLine($"|--------|-----|"); |
| | 9 | 64 | | sb.AppendLine($"| 无人机总数 | {totalDrones} |"); |
| | 9 | 65 | | sb.AppendLine($"| 被摧毁 | {destroyed} |"); |
| | 9 | 66 | | sb.AppendLine($"| 到达目标 | {reached} |"); |
| | 9 | 67 | | sb.AppendLine($"| 侵入管控区 | {intruded} |"); |
| | 9 | 68 | | sb.AppendLine($"| 弹药发射次数 | {launchCount} |"); |
| | 9 | 69 | | sb.AppendLine($"| 云团生成次数 | {cloudCount} |"); |
| | 9 | 70 | | sb.AppendLine(); |
| | | 71 | | |
| | | 72 | | // 对抗结果 |
| | 9 | 73 | | var result = DetermineInterceptResult(destroyed, reached + intruded, totalDrones); |
| | 9 | 74 | | sb.AppendLine($"**对抗结果**:{TranslateResult(result)}"); |
| | 9 | 75 | | sb.AppendLine(); |
| | | 76 | | |
| | 9 | 77 | | return sb.ToString(); |
| | 9 | 78 | | } |
| | | 79 | | |
| | | 80 | | public InterceptResult DetermineInterceptResult(int destroyed, int reachedOrIntruded, int total) |
| | 18 | 81 | | { |
| | 18 | 82 | | if (total == 0) return InterceptResult.Failed; |
| | 26 | 83 | | if (destroyed >= total) return InterceptResult.Success; |
| | 11 | 84 | | if (destroyed > 0) return InterceptResult.Partial; |
| | 9 | 85 | | return InterceptResult.Failed; |
| | 18 | 86 | | } |
| | | 87 | | |
| | 9 | 88 | | private static string TranslateResult(InterceptResult r) => r switch |
| | 9 | 89 | | { |
| | 5 | 90 | | InterceptResult.Success => "成功拦截", |
| | 0 | 91 | | InterceptResult.Partial => "部分拦截", |
| | 4 | 92 | | InterceptResult.Failed => "拦截失败", |
| | 0 | 93 | | _ => "未知", |
| | 9 | 94 | | }; |
| | | 95 | | } |
| | | 96 | | } |