diff --git a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs index 5433b6c..913bcbf 100644 --- a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs +++ b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs @@ -3,53 +3,6 @@ using CounterDrone.Core.Models; namespace CounterDrone.Core.Algorithms { - /// 威胁画像 - public class ThreatProfile - { - public CombatScene Environment { get; set; } = new(); - public List Targets { get; set; } = new(); - public RoutePlan Route { get; set; } = new(); - public List Waypoints { get; set; } = new(); - public List ControlZones { get; set; } = new(); - /// 偏好平台类型(null = 算法自行决定,当前默认地基) - public PlatformType? PreferredPlatformType { get; set; } - } - - /// 防御推荐方案 - public class DefenseRecommendation - { - public DefenseSolution Best { get; set; } = new(); - public DefenseSolution Critical { get; set; } = new(); - } - - /// 单套防御方案 - public class DefenseSolution - { - public AerosolType RecommendedAerosolType { get; set; } - public string AerosolRationale { get; set; } = string.Empty; - public CloudDispersal RecommendedCloud { get; set; } = new(); - - public List Platforms { get; set; } = new(); - public List Detections { get; set; } = new(); - - public float InterceptProbability { get; set; } - public string SummaryRationale { get; set; } = string.Empty; - - public List FireSchedule { get; set; } = new(); - - /// 此方案占用的平台起始索引(多编队合并用) - public int PlatformOffset { get; set; } - } - - /// 多编队推荐结果 - public class MultiGroupRecommendation - { - /// 每组的独立方案 - public List GroupSolutions { get; set; } = new(); - /// 合并后的总发射计划 - public List MergedFireSchedule { get; set; } = new(); - } - /// 火力单元(完整的武器系统) public class FireUnit { @@ -121,47 +74,17 @@ namespace CounterDrone.Core.Algorithms } } - public class RecommendedPlatform - { - public PlatformType Type { get; set; } - public Vector3 Position { get; set; } - public int Quantity { get; set; } - public int MunitionCount { get; set; } - public float CoverageVolume { get; set; } - public float Cooldown { get; set; } = 5f; - public float MuzzleVelocity { get; set; } = 800f; - /// 空基平台巡航速度 m/s - public float CruiseSpeed { get; set; } = 55f; - /// 空基平台投放高度 m - public float ReleaseAltitude { get; set; } - } - - public class RecommendedDetection - { - public Vector3 Position { get; set; } - public float DetectionRadius { get; set; } - public int Quantity { get; set; } - } - /// 三维向量(纯 C#,不依赖 UnityEngine) public struct Vector3 { public float X, Y, Z; public Vector3(float x, float y, float z) { X = x; Y = y; Z = z; } - - public static Vector3 operator +(Vector3 a, Vector3 b) => new(a.X + b.X, a.Y + b.Y, a.Z + b.Z); - public static Vector3 operator -(Vector3 a, Vector3 b) => new(a.X - b.X, a.Y - b.Y, a.Z - b.Z); - public static Vector3 operator *(Vector3 a, float s) => new(a.X * s, a.Y * s, a.Z * s); - public float Length => (float)System.Math.Sqrt(X * X + Y * Y + Z * Z); - public float DistanceTo(Vector3 other) => (this - other).Length; } /// 粒子渲染参数 public class ParticleParams { - public float EmitRate { get; set; } = 100; public float Opacity { get; set; } = 1.0f; - public string ColorHex { get; set; } = "#FFFFFF"; public float SizeMultiplier { get; set; } = 1.0f; } @@ -184,10 +107,7 @@ namespace CounterDrone.Core.Algorithms public FireUnit Unit { get; set; } = null!; public AerosolType AmmoType { get; set; } public float EarliestInterceptTime { get; set; } - public float CoverageDuration { get; set; } public float KillProbability { get; set; } - public float FlightTime { get; set; } // 弹药/平台飞行时间 - public float ShellFlightTime { get; set; } // 仅地基用 } /// 单元分配:一个火力单元被分配给一个威胁的配置 diff --git a/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs b/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs index 713b207..a007717 100644 --- a/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs +++ b/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs @@ -20,8 +20,6 @@ namespace CounterDrone.Core.Algorithms /// Phase 2 结束时的有效半径(30s 湍流膨胀) public float TurbulentRadius => RadiusAt(30f); - /// Phase 2 边界时间 - public float Phase2Duration => 30f; /// 湍流膨胀系数 k public float TurbulentExpansionK => (float)_ammo.TurbulentExpansionK; @@ -55,17 +53,6 @@ namespace CounterDrone.Core.Algorithms return volume > 0.001f ? (float)_ammo.SourceStrength / volume : (float)_ammo.CoreDensity; } - /// 达到指定浓度所需时间(密度随膨胀下降,较晚时间密度更低) - /// 浓度首次低于threshold的时间(s),如果不会低于则返回MaxDuration - public float TimeToDensity(float threshold) - { - // 密度 ≈ SourceStrength / (4/3 π R³),随R增大而下降 - // 求R使得密度=threshold: R³ = SourceStrength / (threshold * 4π/3) - float src = (float)_ammo.SourceStrength; - float volume = src / Math.Max(threshold, 0.000001f); - float r = (float)Math.Pow(volume * 3f / (4f * (float)Math.PI), 1f / 3f); - return TimeToReach(r); - } /// 覆盖指定距离需要的云团数量 /// 需要覆盖的距离 (m) diff --git a/src/CounterDrone.Core/Algorithms/DamageAssessment.cs b/src/CounterDrone.Core/Algorithms/DamageAssessment.cs index ab6d39c..b44c6ae 100644 --- a/src/CounterDrone.Core/Algorithms/DamageAssessment.cs +++ b/src/CounterDrone.Core/Algorithms/DamageAssessment.cs @@ -3,7 +3,7 @@ using CounterDrone.Core.Models; namespace CounterDrone.Core.Algorithms { - /// 毁伤评估——路径积分计算无人机穿过云团的暴露时间 + /// 毁伤评估——路径积分计算无人机穿过云团的路径长度(米),用于换算暴露时间 public static class DamageAssessment { /// 线段 (p1→p2) 在球体内的长度,换算为路径长度 (m) diff --git a/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs b/src/CounterDrone.Core/Algorithms/DefensePlanner.cs similarity index 97% rename from src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs rename to src/CounterDrone.Core/Algorithms/DefensePlanner.cs index 22c8ac2..593954e 100644 --- a/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs +++ b/src/CounterDrone.Core/Algorithms/DefensePlanner.cs @@ -5,15 +5,15 @@ using CounterDrone.Core.Models; namespace CounterDrone.Core.Algorithms { - /// 默认防御规划器 — 五步流水线,全部调用与引擎共享的物理工具类 - public class DefaultDefensePlanner : IDefensePlanner + /// 防御规划器 — 五步流水线,全部调用与引擎共享的物理工具类 + public class DefensePlanner : IDefensePlanner { private readonly List _ammoCatalog; private readonly IDamageModel _damageModel; private readonly PlannerConfig _config; - public DefaultDefensePlanner(List ammoCatalog, PlannerConfig config, - IDamageModel damageModel = null) + public DefensePlanner(List ammoCatalog, PlannerConfig config, + IDamageModel? damageModel = null) { _ammoCatalog = ammoCatalog ?? throw new ArgumentNullException(nameof(ammoCatalog)); _config = config ?? throw new ArgumentNullException(nameof(config)); @@ -290,10 +290,7 @@ namespace CounterDrone.Core.Algorithms Unit = unit, AmmoType = ammoType, EarliestInterceptTime = interceptTime, - CoverageDuration = effectiveR * 2f, KillProbability = prob, - FlightTime = shellTime, - ShellFlightTime = shellTime, }; } @@ -324,10 +321,7 @@ namespace CounterDrone.Core.Algorithms Unit = unit, AmmoType = ammoType, EarliestInterceptTime = interceptTime, - CoverageDuration = effectiveR * 2f, KillProbability = prob, - FlightTime = totalTime, - ShellFlightTime = fallTime, }; } diff --git a/src/CounterDrone.Core/Algorithms/Kinematics.cs b/src/CounterDrone.Core/Algorithms/Kinematics.cs index 9528f88..d9421d5 100644 --- a/src/CounterDrone.Core/Algorithms/Kinematics.cs +++ b/src/CounterDrone.Core/Algorithms/Kinematics.cs @@ -55,12 +55,6 @@ namespace CounterDrone.Core.Algorithms return range / (muzzleVelocity * cosAngle); } - /// 炮弹飞行时间:抛物线轨迹到目标点的时间(自动求解发射角,下行段命中) - public static float EstimatedShellTime(float horizontalDist, float muzzleVelocity) - { - return ParabolicShellTime(horizontalDist, 0f, muzzleVelocity); - } - /// 抛物线飞行时间:解 tan(θ) 二次方程求到达 (horizontalDist, heightDiff) 的时间 public static float ParabolicShellTime(float horizontalDist, float heightDiff, float muzzleVelocity) { @@ -232,16 +226,6 @@ namespace CounterDrone.Core.Algorithms var denom = (float)Math.Pow(2f * (float)Math.PI, 1.5f) * sigmaY * sigmaY * sigmaZ; return denom > 0.001f ? sourceStrength / denom : 0f; } - - /// 高斯烟团某点浓度 C(x,y,z) — 简化:相对中心的偏移 - public static float GaussianConcentration(float q, float sx, float sy, float sz, float offsetY, float offsetZ) - { - var norm = q / ((float)Math.Pow(2f * (float)Math.PI, 1.5f) * sx * sy * sz); - var ey = (float)Math.Exp(-0.5f * offsetY * offsetY / (sy * sy)); - var ez = (float)Math.Exp(-0.5f * offsetZ * offsetZ / (sz * sz)); - var ezr = (float)Math.Exp(-0.5f * offsetZ * offsetZ / (sz * sz)); - return norm * ey * (ez + ezr); - } public static bool PointInPolygon(float px, float pz, ReadOnlySpan<(float X, float Z)> vertices) { if (vertices.Length < 3) return false; diff --git a/src/CounterDrone.Core/DefaultFireUnits.cs b/src/CounterDrone.Core/DefaultFireUnits.cs index 19756d8..7afd5c6 100644 --- a/src/CounterDrone.Core/DefaultFireUnits.cs +++ b/src/CounterDrone.Core/DefaultFireUnits.cs @@ -4,7 +4,7 @@ namespace CounterDrone.Core { public static class DefaultFireUnits { - private static List _cache; + private static List? _cache; public static List GetAll() { diff --git a/src/CounterDrone.Core/DefaultFormations.cs b/src/CounterDrone.Core/DefaultFormations.cs deleted file mode 100644 index d0fb979..0000000 --- a/src/CounterDrone.Core/DefaultFormations.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Collections.Generic; - -namespace CounterDrone.Core -{ - public static class DefaultFormations - { - private static List _cache; - - public static List GetAll() - { - if (_cache != null) return _cache; - _cache = new List - { - new() { Id = "single", Name = "单机", FormationMode = 0, LateralCount = 1, LongitudinalCount = 1 }, - new() { Id = "line-abreast-3", Name = "3机横队", FormationMode = 1, LateralCount = 3, LongitudinalCount = 1, - LateralSpacing = 50 }, - new() { Id = "line-abreast-5", Name = "5机横队", FormationMode = 1, LateralCount = 5, LongitudinalCount = 1, - LateralSpacing = 50 }, - new() { Id = "column-3", Name = "3机纵队", FormationMode = 1, LateralCount = 1, LongitudinalCount = 3, - LongitudinalSpacing = 100 }, - new() { Id = "box-2x2", Name = "2×2方队", FormationMode = 1, LateralCount = 2, LongitudinalCount = 2, - LateralSpacing = 50, LongitudinalSpacing = 100 }, - new() { Id = "swarm-10", Name = "蜂群(10架)", FormationMode = 2, LateralCount = 10, LongitudinalCount = 1, - LateralSpacing = 30 }, - }; - return _cache; - } - - public static FormationTemplate GetById(string id) => GetAll().Find(t => t.Id == id); - } - - public class FormationTemplate - { - public string Id { get; set; } = ""; - public string Name { get; set; } = ""; - public int FormationMode { get; set; } - public int LateralCount { get; set; } = 1; - public int LongitudinalCount { get; set; } = 1; - public double LateralSpacing { get; set; } - public double LongitudinalSpacing { get; set; } - } -} diff --git a/src/CounterDrone.Core/Simulation/DroneEntity.cs b/src/CounterDrone.Core/Simulation/DroneEntity.cs index 8ecf7e2..2240195 100644 --- a/src/CounterDrone.Core/Simulation/DroneEntity.cs +++ b/src/CounterDrone.Core/Simulation/DroneEntity.cs @@ -14,7 +14,6 @@ namespace CounterDrone.Core.Simulation public float Wingspan { get; } public float TypicalSpeed { get; } public List Route { get; } - public int CurrentWaypointIndex { get; private set; } public float PosX { get; private set; } public float PosY { get; private set; } public float PosZ { get; private set; } @@ -25,8 +24,6 @@ namespace CounterDrone.Core.Simulation public float PrevX { get; private set; } public float PrevY { get; private set; } public float PrevZ { get; private set; } - public float FormationOffsetX { get; set; } - public float FormationOffsetY { get; set; } /// 沿航路已飞行弧长(米),由 RouteGeometry 驱动 private float _traveledArc; @@ -79,36 +76,19 @@ namespace CounterDrone.Core.Simulation } } - private void ApplyFormationOffset(int latIdx, float latSpacing, int longIdx, float longSpacing, FormationMode mode) - { - if (latIdx == 0 && longIdx == 0) return; - switch (mode) - { - case FormationMode.Formation: - FormationOffsetY = latIdx * latSpacing; - FormationOffsetX = -longIdx * longSpacing; - break; - case FormationMode.Swarm: - var rng = new Random((latIdx + longIdx * 100) * 137); - FormationOffsetX = (float)(rng.NextDouble() - 0.5) * latSpacing * 3; - FormationOffsetY = (float)(rng.NextDouble() - 0.5) * latSpacing * 3; - break; - } - } - public void SavePreviousPosition() { PrevX = PosX; PrevY = PosY; PrevZ = PosZ; } - public void Update(float deltaTime, float windSpeed, WindDirection windDir) + public void Update(float deltaTime) { if (Status != DroneStatus.Flying) return; if (Route.Count == 0) return; // 运动模型统一在 RouteGeometry:弧长推进 + 位置查询。 - // 无人机严格沿航路匀速飞行,不受风偏影响(风偏已移除,见风偏补偿说明)。 - // windSpeed/windDir 保留签名供未来飞控模型使用,当前不参与运动。 + // 无人机严格按航路匀速飞行。无人机不受风偏影响(真实无人机有飞控修正航向), + // 但云团受风偏影响(见 SimulationEngine 毁伤判定的云团参考系修正)。 float totalLen = RouteGeometry.TotalLength(Route); if (totalLen <= 0f) { diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index 3ef9ba9..4141624 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -28,12 +28,12 @@ namespace CounterDrone.Core.Simulation public IReadOnlyList Munitions => _munitions; public IReadOnlyList Events => _allEvents; - public event Action OnMunitionLaunched; - public event Action OnCloudGenerated; - public event Action OnDroneDestroyed; - public event Action OnDroneReachedTarget; - public event Action OnZoneIntruded; - public event Action OnSimulationEnded; + public event Action? OnMunitionLaunched; + public event Action? OnCloudGenerated; + public event Action? OnDroneDestroyed; + public event Action? OnDroneReachedTarget; + public event Action? OnZoneIntruded; + public event Action? OnSimulationEnded; private List _drones = new(); private List _platforms = new(); @@ -237,7 +237,7 @@ namespace CounterDrone.Core.Simulation // 5. 无人机移动 foreach (var drone in _drones.Where(d => d.Status == DroneStatus.Flying)) { - drone.Update(scaledDt, (float)_scene.WindSpeed, (WindDirection)_scene.WindDirection); + drone.Update(scaledDt); if (drone.Status == DroneStatus.ReachedTarget) { OnDroneReachedTarget?.Invoke(drone); @@ -257,14 +257,14 @@ namespace CounterDrone.Core.Simulation { float ccx = cloud.Dispersion.Center.X, ccy = cloud.Dispersion.Center.Y, ccz = cloud.Dispersion.Center.Z; // 无人机线段换算到云团参考系:相对位置 = drone - cloud - float inCloudTime = DamageAssessment.PathInSphere( + float inCloudDistance = DamageAssessment.PathInSphere( drone.PrevX - (ccx - cloudDx), drone.PrevY - (ccy - cloudDy), drone.PrevZ - (ccz - cloudDz), drone.PosX - ccx, drone.PosY - ccy, drone.PosZ - ccz, 0f, 0f, 0f, cloud.Dispersion.EffectiveRadius); - if (inCloudTime > 0 && cloud.Dispersion.CoreDensity >= (float)_ammoSpec.EffectiveConcentration) + if (inCloudDistance > 0 && cloud.Dispersion.CoreDensity >= (float)_ammoSpec.EffectiveConcentration) { - float exposureIncrement = inCloudTime / (drone.TypicalSpeed / 3.6f); + float exposureIncrement = inCloudDistance / (drone.TypicalSpeed / 3.6f); drone.ExposureTime += exposureIncrement; var dmg = _damageModel.CalculateDamage(drone.TargetType, drone.PowerType, cloud.AerosolType, cloud.Dispersion.CoreDensity, drone.ExposureTime, exposureIncrement); drone.ApplyDamage(dmg); diff --git a/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll b/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll index 34d7ca7..5e2c73c 100644 Binary files a/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll and b/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll differ diff --git a/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs b/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs index 7faf40c..6a395bb 100644 --- a/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs +++ b/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs @@ -72,7 +72,7 @@ namespace CounterDrone.Unity TotalMunitions = 3, AmmoTypes = new() { AerosolType.InertGas, AerosolType.ActiveMaterial, AerosolType.ActiveFuel }, }); - var result = new DefaultDefensePlanner(ammoCatalog, PlannerConfig.Load(paths)).Plan(fireUnits, new List { droneGroup }, detail.Scene); + var result = new DefensePlanner(ammoCatalog, PlannerConfig.Load(paths)).Plan(fireUnits, new List { droneGroup }, detail.Scene); scenarioMgr.SaveCloud(taskId, new CloudDispersal { PositionX = (droneGroup.Waypoints[0].PosX + droneGroup.Waypoints[^1].PosX) / 2, diff --git a/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs b/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs index a459f71..e102a83 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs @@ -67,7 +67,7 @@ namespace CounterDrone.Unity // 推荐方案 var detail = scenario.GetTaskDetail(taskId); var ammoCatalog = db.Table().ToList(); - var planner = new DefaultDefensePlanner(ammoCatalog, PlannerConfig.Load(paths)); + var planner = new DefensePlanner(ammoCatalog, PlannerConfig.Load(paths)); var droneGroup = new DroneGroup { GroupId = "default", diff --git a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs index fcaa156..78ee901 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs @@ -48,7 +48,7 @@ namespace CounterDrone.Unity new RoutePlanRepository(_db), new WaypointRepository(_db)); _frameStore = new FrameDataStore(_paths); - _engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefaultDefensePlanner(DefaultAmmunition.GetAll(), PlannerConfig.Load(_paths))); + _engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefensePlanner(DefaultAmmunition.GetAll(), PlannerConfig.Load(_paths))); } public void LoadAndStart(string taskId) diff --git a/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs b/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs index 94af12c..81bb3d6 100644 --- a/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs +++ b/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs @@ -59,7 +59,7 @@ namespace CounterDrone.Core.Tests private PlannerResult Plan(List units, DroneGroup threat, CombatScene? env = null) - => new DefaultDefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan(units, new() { threat }, env ?? new CombatScene()); + => new DefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan(units, new() { threat }, env ?? new CombatScene()); // ═══════════════════════════════════════ // 威胁排序 @@ -233,7 +233,7 @@ namespace CounterDrone.Core.Tests [Fact] public void Allocation_MultiUnit_PoolsChannels() { - var result = new DefaultDefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan( + var result = new DefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan( new() { MakeGroundUnit("u0", 5000), MakeGroundUnit("u1", 5100) }, new() { MakeThreat(speed: 200) }, new CombatScene()); Assert.True(result.Best.ThreatsEngaged == 1); @@ -259,8 +259,8 @@ namespace CounterDrone.Core.Tests // 边界 // ═══════════════════════════════════════ - [Fact] public void Edge_NoUnits_Unengaged() => Assert.Equal(1, new DefaultDefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan(new(), new() { MakeThreat() }, new CombatScene()).Best.ThreatsUnengaged); - [Fact] public void Edge_NoThreats_Empty() => Assert.Equal(0, new DefaultDefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan(new() { MakeGroundUnit("u0", 5000) }, new(), new CombatScene()).Best.ThreatsEngaged); + [Fact] public void Edge_NoUnits_Unengaged() => Assert.Equal(1, new DefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan(new(), new() { MakeThreat() }, new CombatScene()).Best.ThreatsUnengaged); + [Fact] public void Edge_NoThreats_Empty() => Assert.Equal(0, new DefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan(new() { MakeGroundUnit("u0", 5000) }, new(), new CombatScene()).Best.ThreatsEngaged); [Fact] public void Edge_OutOfRange_Ground() @@ -293,7 +293,7 @@ namespace CounterDrone.Core.Tests { var a = MakeThreat(PowerType.Piston, 120); a.GroupId = "g0"; var b = MakeThreat(PowerType.Jet, 300); b.GroupId = "g1"; - var result = new DefaultDefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan( + var result = new DefensePlanner(TestAmmo, TestPlannerConfig.Instance).Plan( new() { MakeGroundUnit("u0", 5000), MakeGroundUnit("u1", 5100) }, new() { a, b }, new CombatScene()); Assert.Equal(2, result.Best.ThreatsEngaged); diff --git a/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs b/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs index 748736e..9f19c51 100644 --- a/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs +++ b/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs @@ -44,7 +44,7 @@ namespace CounterDrone.Core.Tests var drone = new DroneEntity("d1", "g1", CreateConfig(), CreateRoute(0, 1000, 300, 120), 0, 50, 0, 0, FormationMode.Single); float prevX = drone.PosX; - drone.Update(1f, 0, WindDirection.N); + drone.Update(1f); Assert.True(drone.PosX > prevX); } @@ -53,7 +53,7 @@ namespace CounterDrone.Core.Tests { var drone = new DroneEntity("d1", "g1", CreateConfig(360), CreateRoute(0, 100, 300, 360), 0, 50, 0, 0, FormationMode.Single); - drone.Update(2f, 0, WindDirection.N); + drone.Update(2f); Assert.Equal(DroneStatus.ReachedTarget, drone.Status); } @@ -140,25 +140,25 @@ namespace CounterDrone.Core.Tests 0, 0, 0, 0, FormationMode.Single); // 推进到第一段中点(弧长 50):应在 X=50, Z=0 - drone.Update(50f / (60f / 3.6f), 0, WindDirection.N); + drone.Update(50f / (60f / 3.6f)); Assert.Equal(50f, drone.PosX, 1); Assert.Equal(0f, drone.PosZ, 1); Assert.Equal(DroneStatus.Flying, drone.Status); // 推进到拐点(弧长 100):应在 X=100, Z=0 - drone.Update(50f / (60f / 3.6f), 0, WindDirection.N); + drone.Update(50f / (60f / 3.6f)); Assert.Equal(100f, drone.PosX, 1); Assert.Equal(0f, drone.PosZ, 1); Assert.Equal(DroneStatus.Flying, drone.Status); // 推进到第二段中点(弧长 150):应在 X=100, Z=50 - drone.Update(50f / (60f / 3.6f), 0, WindDirection.N); + drone.Update(50f / (60f / 3.6f)); Assert.Equal(100f, drone.PosX, 1); Assert.Equal(50f, drone.PosZ, 1); Assert.Equal(DroneStatus.Flying, drone.Status); // 推进到终点(弧长 200):应在 X=100, Z=100,状态 ReachedTarget - drone.Update(50f / (60f / 3.6f), 0, WindDirection.N); + drone.Update(50f / (60f / 3.6f)); Assert.Equal(100f, drone.PosX, 1); Assert.Equal(100f, drone.PosZ, 1); Assert.Equal(DroneStatus.ReachedTarget, drone.Status); diff --git a/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs b/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs index 68cce2b..bcd447e 100644 --- a/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs +++ b/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs @@ -65,7 +65,7 @@ namespace CounterDrone.Core.Tests }); var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)), - new DamageModelRouter(), new TestPathProvider(_testDir), new DefaultDefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); + new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); engine.Initialize(_taskId); engine.TimeScale = 4f; @@ -107,7 +107,7 @@ namespace CounterDrone.Core.Tests }); var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)), - new DamageModelRouter(), new TestPathProvider(_testDir), new DefaultDefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); + new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); engine.Initialize(_taskId); engine.TimeScale = 4f; @@ -148,7 +148,7 @@ namespace CounterDrone.Core.Tests }); var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)), - new DamageModelRouter(), new TestPathProvider(_testDir), new DefaultDefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); + new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); engine.Initialize(_taskId); engine.TimeScale = 4f; diff --git a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs index 2f2705d..9b25a8c 100644 --- a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs +++ b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs @@ -49,7 +49,7 @@ namespace CounterDrone.Core.Tests private SimulationEngine RunSimulation(int maxTicks, float tickDt = 1f / 20f, float timeScale = 8f) { - var engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefaultDefensePlanner(_ammoCatalog, TestPlannerConfig.Instance)); + var engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefensePlanner(_ammoCatalog, TestPlannerConfig.Instance)); engine.Initialize(_taskId); engine.TimeScale = timeScale; // 8倍速加速 diff --git a/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs b/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs index 66db8b5..cb873ef 100644 --- a/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs +++ b/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs @@ -36,7 +36,7 @@ namespace CounterDrone.Core.Tests new RoutePlanRepository(_mainDb), new WaypointRepository(_mainDb)); _engine = new SimulationEngine(_scenarioService, new FrameDataStore(paths), - new DamageModelRouter(), paths, new DefaultDefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); + new DamageModelRouter(), paths, new DefensePlanner(DefaultAmmunition.GetAll(), TestPlannerConfig.Instance)); } public void Dispose()