using System; using System.Collections.Generic; using System.Linq; using CounterDrone.Core.Models; namespace CounterDrone.Core.Algorithms { public class DefaultDefenseAdvisor : IDefenseAdvisor { private readonly List _ammoCatalog; public DefaultDefenseAdvisor(List ammoCatalog) { _ammoCatalog = ammoCatalog ?? new List(); } private static readonly Dictionary MatchTable = new() { { PowerType.Electric, AerosolType.InertGas }, { PowerType.Piston, AerosolType.InertGas }, { PowerType.Jet, AerosolType.ActiveMaterial }, }; public DefenseRecommendation Recommend(ThreatProfile threat) { var result = new DefenseRecommendation { Best = new DefenseSolution(), Critical = new DefenseSolution(), }; // ===== 输入校验 ===== if (threat.Targets.Count == 0) { result.Best.SummaryRationale = "失败:未配置威胁目标"; return result; } if (threat.Waypoints.Count < 2) { result.Best.SummaryRationale = "失败:需要至少两个航路点"; return result; } var target = threat.Targets[0]; if (target.TypicalSpeed <= 0) { result.Best.SummaryRationale = "失败:目标速度为 0"; return result; } // ===== Step A:气溶胶选型 ===== var powerType = (PowerType)target.PowerType; var aerosolType = MatchTable.TryGetValue(powerType, out var match) ? match : AerosolType.InertGas; var ammo = _ammoCatalog.FirstOrDefault(a => a.AerosolType == (int)aerosolType); if (ammo == null) { result.Best.SummaryRationale = $"失败:弹药库中未找到 {aerosolType} 类型的弹药规格"; return result; } var rationale = powerType switch { PowerType.Electric or PowerType.Piston => $"{powerType}发动机依赖氧气,推荐惰性气体窒息方案", PowerType.Jet => $"{powerType}发动机高温表面可触发活性材料爆燃反应", _ => "默认推荐惰性气体方案", }; // ===== Step B:时空交汇优化 ===== var start = ToV3(threat.Waypoints[0]); var end = ToV3(threat.Waypoints[^1]); var mid = new Vector3((start.X + end.X) / 2f, (start.Y + end.Y) / 2f, (start.Z + end.Z) / 2f); var routeLength = start.DistanceTo(end); var avgSpeed = (float)target.TypicalSpeed / 3.6f; var totalFlightTime = routeLength / avgSpeed; if (routeLength < 100) { result.Best.SummaryRationale = "失败:航路太短(<100m)"; return result; } // 弹药参数 var initialR = (float)ammo.InitialRadius; var maxDur = (float)ammo.MaxDuration; // 无人机穿过单个云团的时间 var crossTime = (2f * initialR) / avgSpeed; var neededExposure = aerosolType == AerosolType.ActiveMaterial ? 2f : 6f; var spacing = initialR * 1.5f; // 云团间隔 // 有效覆盖距离 = 间距×(N-1) + 直径,需 ≥ 所需暴露时间 × 速度 var requiredCoverage = neededExposure * avgSpeed; var roundsNeeded = Math.Max(1, (int)Math.Ceiling((requiredCoverage - 2f * initialR) / spacing) + 1); // 实际有效暴露时间 var actualCoverage = spacing * (roundsNeeded - 1) + 2f * initialR; var actualExposure = actualCoverage / avgSpeed; var prob = Math.Min(0.95f, actualExposure / neededExposure); // 多轮次云团:沿航路等距分布 var cloudSalvo = new List(); for (int i = 0; i < roundsNeeded; i++) { var offset = (i - (roundsNeeded - 1) / 2f) * spacing; cloudSalvo.Add(new CloudDispersal { AerosolType = (int)aerosolType, PositionX = mid.X + offset, PositionY = mid.Y, PositionZ = mid.Z, DisperseHeight = (float)target.TypicalAltitude, TriggerMode = (int)TriggerMode.Time, Duration = (int)maxDur, InitialScale = ammo.InitialVolume, ReleaseMode = (int)ReleaseMode.Single, Source = "Algorithm", PositionMode = (int)PositionMode.AlgorithmRecommended, RecommendedTiming = totalFlightTime / 2f, }); } // 平台部署:假设齐射(同时发射),每门炮打一发后冷却 5s // 需要 roundsNeeded 门炮同时发射 var gunCount = roundsNeeded; var platforms = new List(); for (int i = 0; i < gunCount; i++) platforms.Add(new RecommendedPlatform { Type = PlatformType.GroundBased, Position = new Vector3(mid.X + i * 50, 0, 50), Quantity = 1, MunitionCount = 1, CoverageVolume = (float)ammo.InitialVolume, Cooldown = 5f, MuzzleVelocity = 800f, }); result.Best = new DefenseSolution { RecommendedAerosolType = aerosolType, AerosolRationale = rationale, RecommendedCloud = cloudSalvo[0], CloudSalvo = cloudSalvo, Platforms = platforms, Detections = new List { new RecommendedDetection { Position = new Vector3(mid.X, mid.Y, 0), DetectionRadius = Math.Max(3000f, routeLength * 0.4f), Quantity = 1, } }, InterceptProbability = prob, SummaryRationale = $"{aerosolType}方案,{roundsNeeded}发,预计拦截概率 {prob:P0}", }; result.Critical = new DefenseSolution { RecommendedAerosolType = aerosolType, RecommendedCloud = new CloudDispersal { AerosolType = (int)aerosolType, PositionX = start.X + (end.X - start.X) * 0.25f, PositionY = start.Y, PositionZ = start.Z, DisperseHeight = (float)target.TypicalAltitude, Duration = (int)maxDur, Source = "Algorithm", PositionMode = (int)PositionMode.AlgorithmRecommended, RecommendedTiming = totalFlightTime * 0.25f, }, Platforms = platforms, InterceptProbability = prob * 0.3f, SummaryRationale = $"临界方案:拦截概率仅 {prob * 0.3f:P0}", }; return result; } private static Vector3 ToV3(Waypoint wp) => new((float)wp.PosX, (float)wp.PosY, (float)wp.PosZ); } }