using System.Collections.Generic; using CounterDrone.Core.Algorithms; using CounterDrone.Core.Models; using Xunit; namespace CounterDrone.Core.Tests { /// 验证三阶段扩散模型下推荐算法的参数合理性 public class DispersionAdvisorRealityTests { private ThreatProfile CreatePistonThreat(float speed = 200, float length = 20000) { return new ThreatProfile { Environment = new CombatScene { WindSpeed = 3, WindDirection = (int)WindDirection.W }, Targets = new List { new TargetConfig { PowerType = (int)PowerType.Piston, Quantity = 1, TypicalSpeed = speed, TypicalAltitude = 500 }, }, Route = new RoutePlan { FormationMode = (int)FormationMode.Single }, Waypoints = new List { new Waypoint { PosX = 0, PosY = 500, PosZ = 0 }, new Waypoint { PosX = length, PosY = 500, PosZ = 0 }, }, }; } [Fact] public void Piston_200kmh_20km_ProducesReasonableSalvo() { var advisor = new DefaultDefenseAdvisor(DefaultAmmunition.GetAll()); var rec = advisor.Recommend(CreatePistonThreat()); // 基本断言 Assert.Equal(AerosolType.InertGas, rec.Best.RecommendedAerosolType); Assert.True(rec.Best.SalvoRounds >= 1, $"齐射数={rec.Best.SalvoRounds},应≥1"); Assert.True(rec.Best.SalvoSpacing > 0, $"间隔={rec.Best.SalvoSpacing}m,应>0"); Assert.True(rec.Best.RecommendedCloud.RecommendedTiming > 0, $"推荐时机={rec.Best.RecommendedCloud.RecommendedTiming}s,应>0"); // 检查膨胀时间 var ammo = DefaultAmmunition.GetByType(AerosolType.InertGas); var r0 = 3.3f * System.Math.Pow(ammo.BurstChargeKg, 0.32); var k = ammo.TurbulentExpansionK; var halfTime = 20000f / (200f / 3.6f) / 2f; var effectiveR = r0 + k * System.Math.Sqrt(System.Math.Min(halfTime, 30)); if (halfTime > 30) effectiveR += k * System.Math.Sqrt(halfTime - 30) * 0.3f; // 膨胀应在合理范围 Assert.True(effectiveR > 10, $"有效半径={effectiveR:F1}m,应>10m(初始{r0:F1}m)"); Assert.True(effectiveR < 200, $"有效半径={effectiveR:F1}m,应<200m"); } [Fact] public void Timing_AccountsForExpansion() { var advisor = new DefaultDefenseAdvisor(DefaultAmmunition.GetAll()); var rec = advisor.Recommend(CreatePistonThreat()); var timing = rec.Best.RecommendedCloud.RecommendedTiming!.Value; var halfTime = 20000f / (200f / 3.6f) / 2f; // 推荐时机应明显早于无人机到达中点(因为有飞行时间和膨胀时间) Assert.True(timing < halfTime - 5, $"推荐时机={timing:F1}s 应早于中点={halfTime:F1}s(预留飞行+膨胀时间)"); } } }