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(预留飞行+膨胀时间)");
}
}
}