using System.Collections.Generic; using CounterDrone.Core.Algorithms; using CounterDrone.Core.Models; using Xunit; namespace CounterDrone.Core.Tests { public class DefenseAdvisorRealityTests { private static readonly List TestAmmo = new() { new AmmunitionSpec { AerosolType = (int)AerosolType.InertGas, InitialRadius = 50, CoreDensity = 1.0, DispersionRateBase = 5, MaxRadius = 200, MaxDuration = 60 }, new AmmunitionSpec { AerosolType = (int)AerosolType.ActiveMaterial, InitialRadius = 30, CoreDensity = 2.0, DispersionRateBase = 3, MaxRadius = 150, MaxDuration = 45 }, }; [Fact] public void PistonDrone_RecommendsReachableCloudPosition() { var threat = new ThreatProfile { Environment = new CombatScene { WindSpeed = 3, WindDirection = (int)WindDirection.W, }, Targets = new List { new TargetConfig { TargetType = (int)TargetType.Piston, PowerType = (int)PowerType.Piston, Quantity = 1, TypicalSpeed = 200, TypicalAltitude = 500, }, }, Route = new RoutePlan { FormationMode = (int)FormationMode.Single }, Waypoints = new List { new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, new Waypoint { PosX = 20000, PosY = 500, PosZ = 0, Speed = 200 }, }, }; var advisor = new DefaultDefenseAdvisor(TestAmmo); var rec = advisor.Recommend(threat); // 1. 选型正确 Assert.Equal(AerosolType.InertGas, rec.Best.RecommendedAerosolType); // 2. 云团位置应在航路上 var c = rec.Best.RecommendedCloud; Assert.True(c.PositionX > 0 && c.PositionX < 20000, $"云团 X={c.PositionX} 应在航路范围内"); Assert.True(c.PositionY >= 400 && c.PositionY <= 600, $"云团 Y={c.PositionY} 应接近飞行高度 500"); // 3. 平台部署应有合理位置 Assert.NotEmpty(rec.Best.Platforms); var p = rec.Best.Platforms[0]; // 4. 炮弹能打到吗?用运动学验证 var muzzleV = 800f; var releaseAlt = (float)c.DisperseHeight; var targetDist = (float)System.Math.Sqrt( (c.PositionX - p.Position.X) * (c.PositionX - p.Position.X) + (c.PositionZ - p.Position.Z) * (c.PositionZ - p.Position.Z)); var launchAngle = Kinematics.CalculateLaunchAngle(targetDist, muzzleV, releaseAlt); Assert.True(launchAngle > 0 && launchAngle < 1.57f, $"发射角 {launchAngle * 180 / System.Math.PI:F1}° 应在 0-90°"); // 5. 弹道能到达释放高度 var peakHeight = muzzleV * muzzleV * (float)System.Math.Sin(launchAngle) * (float)System.Math.Sin(launchAngle) / (2f * 9.81f); Assert.True(peakHeight >= releaseAlt, $"弹道顶点 {peakHeight:F0}m ≥ 释放高度 {releaseAlt:F0}m"); } } }