93 lines
4.0 KiB
C#
93 lines
4.0 KiB
C#
using System.Collections.Generic;
|
|
using CounterDrone.Core;
|
|
using CounterDrone.Core.Algorithms;
|
|
using CounterDrone.Core.Models;
|
|
using CounterDrone.Core.Repository;
|
|
using CounterDrone.Core.Services;
|
|
using CounterDrone.Core.Simulation;
|
|
using Xunit;
|
|
|
|
namespace CounterDrone.Core.Tests
|
|
{
|
|
/// <summary>诊断 BuildFireSchedule 是否生成正确计划</summary>
|
|
public class FireScheduleDiagnostics
|
|
{
|
|
private static readonly List<AmmunitionSpec> 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 BuildFireSchedule_WithRecommendation_ProducesEvents()
|
|
{
|
|
// 模拟:活塞无人机威胁 → 算法推荐 → 发射计划
|
|
var threat = new ThreatProfile
|
|
{
|
|
Environment = new CombatScene { WindSpeed = 3 },
|
|
Targets = new List<TargetConfig>
|
|
{
|
|
new TargetConfig { TargetType = (int)TargetType.Piston, PowerType = (int)PowerType.Piston, Quantity = 1, TypicalSpeed = 200 },
|
|
},
|
|
Route = new RoutePlan { FormationMode = (int)FormationMode.Single },
|
|
Waypoints = new List<Waypoint>
|
|
{
|
|
new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
|
|
new Waypoint { PosX = 20000, PosY = 500, PosZ = 0, Speed = 200 },
|
|
},
|
|
};
|
|
|
|
var rec = new DefaultDefenseAdvisor(TestAmmo).Recommend(threat);
|
|
|
|
// 检查推荐
|
|
Assert.True(rec.Best.RecommendedCloud.RecommendedTiming > 0,
|
|
$"推荐时机={rec.Best.RecommendedCloud.RecommendedTiming}");
|
|
Assert.NotEmpty(rec.Best.Platforms);
|
|
|
|
// 模拟持久化后读取
|
|
var cloud = rec.Best.RecommendedCloud;
|
|
var equips = new List<EquipmentDeployment>();
|
|
foreach (var p in rec.Best.Platforms)
|
|
equips.Add(new EquipmentDeployment
|
|
{
|
|
EquipmentRole = (int)EquipmentRole.LaunchPlatform,
|
|
Quantity = p.Quantity,
|
|
PositionX = p.Position.X, PositionY = p.Position.Y, PositionZ = p.Position.Z,
|
|
AerosolType = (int)rec.Best.RecommendedAerosolType,
|
|
MunitionCount = p.MunitionCount, Cooldown = 5,
|
|
MuzzleVelocity = 800,
|
|
});
|
|
|
|
// 手动调用 BuildFireSchedule 同样的逻辑
|
|
var schedule = new List<FireEvent>();
|
|
if (cloud.RecommendedTiming.HasValue && cloud.RecommendedTiming.Value > 0)
|
|
{
|
|
foreach (var p in equips)
|
|
{
|
|
var muzzleV = (float)(p.MuzzleVelocity ?? 800);
|
|
var dx = (float)cloud.PositionX - (float)p.PositionX;
|
|
var dz = (float)cloud.PositionZ - (float)p.PositionZ;
|
|
var dist = (float)System.Math.Sqrt(dx * dx + dz * dz);
|
|
var flightTime = dist / muzzleV;
|
|
var fireTime = (float)cloud.RecommendedTiming.Value - flightTime;
|
|
if (fireTime < 0) fireTime = 0.1f;
|
|
|
|
schedule.Add(new FireEvent
|
|
{
|
|
FireTime = fireTime,
|
|
PlatformIndex = 0,
|
|
TargetX = (float)cloud.PositionX,
|
|
TargetY = (float)cloud.PositionY,
|
|
TargetZ = (float)cloud.PositionZ,
|
|
MuzzleVelocity = muzzleV,
|
|
});
|
|
}
|
|
}
|
|
|
|
Assert.NotEmpty(schedule);
|
|
Assert.True(schedule[0].FireTime > 0);
|
|
Assert.Equal((float)cloud.PositionX, schedule[0].TargetX);
|
|
}
|
|
}
|
|
}
|