fix: Quantity expand + PlatformIndex 映射修正

- ApplyDefensePlan 展开 EquipmentDeployment.Quantity → 多个 FireUnit
- Planner 分配后用 fireUnits.IndexOf 修正 PlatformIndex
- 新增 FullPipeline_Piston_VerifiesRoundAllocation 验证 ≥8 发
- Piston 集成测试加入计划大小断言
This commit is contained in:
tian 2026-06-13 09:50:24 +08:00
parent 5667aef495
commit 4411a452dc
3 changed files with 42 additions and 12 deletions

View File

@ -141,6 +141,11 @@ namespace CounterDrone.Core.Algorithms
foreach (var (unit, rounds, fireEvents) in assignedUnits)
{
// 平台索引 = 该单元在 fireUnits 列表中的位置
int platIndex = fireUnits.IndexOf(unit);
// 修正 FireEvent 的平台索引
foreach (var fe in fireEvents) fe.PlatformIndex = platIndex;
plan.Assignments.Add(new UnitAssignment
{
FireUnitId = unit.Id,
@ -405,7 +410,7 @@ namespace CounterDrone.Core.Algorithms
events.Add(new FireEvent
{
FireTime = fireTime,
PlatformIndex = i % rounds,
PlatformIndex = 0, // 由调用方在分配后覆盖为正确索引
TargetX = tx,
TargetY = mid.Y,
TargetZ = tz,

View File

@ -427,5 +427,24 @@ namespace CounterDrone.Core.Tests
Assert.True(fe.FireTime < arrivalTime,
$"FireTime={fe.FireTime:F0} >= ArrivalTime={arrivalTime:F0}"));
}
[Fact]
public void FullPipeline_Piston_VerifiesRoundAllocation()
{
var units = MakeGroundUnits(8);
var threat = MakeThreat(PowerType.Piston, 200); // 集成测试同参数——速度设为 200
threat.Waypoints.Clear();
threat.Waypoints.Add(new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 });
threat.Waypoints.Add(new Waypoint { PosX = 20000, PosY = 500, PosZ = 0, Speed = 200 });
var planner = new DefaultDefensePlanner(TestAmmo);
var result = planner.Plan(units, new() { threat }, new CombatScene { WindSpeed = 3 });
Assert.True(result.Best.ThreatsEngaged == 1);
Assert.True(result.Best.MergedSchedule.Count >= 8,
$"只有 {result.Best.MergedSchedule.Count} 发,集成测试场景应>=8发");
// 验证 PlatformIndex 有效
Assert.All(result.Best.MergedSchedule, fe =>
Assert.True(fe.PlatformIndex >= 0 && fe.PlatformIndex < units.Count,
$"PlatformIndex={fe.PlatformIndex} out of [0,{units.Count})"));
}
}
}

View File

@ -88,18 +88,22 @@ namespace CounterDrone.Core.Tests
var idx = 0;
foreach (var eq in detail.Equipment.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform))
{
fireUnits.Add(new FireUnit
int qty = Math.Max(1, eq.Quantity);
for (int i = 0; i < qty; i++)
{
Id = $"u{idx++}",
Type = platType,
Position = new Vector3((float)eq.PositionX, (float)eq.PositionY, (float)eq.PositionZ),
CruiseSpeed = (float)(eq.CruiseSpeed ?? 55f),
ReleaseAltitude = (float)(eq.ReleaseAltitude ?? 0f),
MuzzleVelocity = (float)(eq.MuzzleVelocity ?? 800f),
TotalMunitions = eq.MunitionCount ?? 1,
AmmoTypes = new List<AerosolType> { (AerosolType)(eq.AerosolType ?? 0) },
Cooldown = (float)eq.Cooldown,
});
fireUnits.Add(new FireUnit
{
Id = $"u{idx++}",
Type = platType,
Position = new Vector3((float)eq.PositionX + i * 50, (float)eq.PositionY, (float)eq.PositionZ),
CruiseSpeed = (float)(eq.CruiseSpeed ?? 55f),
ReleaseAltitude = (float)(eq.ReleaseAltitude ?? 0f),
MuzzleVelocity = (float)(eq.MuzzleVelocity ?? 800f),
TotalMunitions = eq.MunitionCount ?? 1,
AmmoTypes = new List<AerosolType> { (AerosolType)(eq.AerosolType ?? 0) },
Cooldown = (float)eq.Cooldown,
});
}
}
// 如果没装备,生成默认的地面单元
@ -298,6 +302,8 @@ namespace CounterDrone.Core.Tests
var plan = ApplyDefensePlan();
Assert.True(plan.ThreatsEngaged > 0);
Assert.NotEmpty(plan.MergedSchedule);
Assert.True(plan.MergedSchedule.Count >= 8,
$"Piston Planner 只生成了 {plan.MergedSchedule.Count} 发,预期 >= 8");
var eng = RunSimulation(8000);