From 45387fee736073fbf1b42aee254e3a4c68eb32de Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sat, 13 Jun 2026 12:19:21 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=88=A0=E9=99=A4=E6=89=80?= =?UTF-8?q?=E6=9C=89=E9=80=BB=E8=BE=91fallback=E2=80=94=E2=80=94=E7=BC=BA?= =?UTF-8?q?=E5=A4=B1=E9=85=8D=E7=BD=AE=E6=8A=A5=E9=94=99=E8=80=8C=E9=9D=9E?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E8=B7=B3=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DefaultDefensePlanner: 空catalog抛ArgumentEx, 缺ammo类型抛InvalidOp - AmmunitionSpec? → AmmunitionSpec(非空), 删除 ==null 静默返回 - 删除 0.8f射程安全系数, 1.5f时间窗口乘数 - AlgorithmFactory 移除IDefensePlanner(null)注册 - SimulationEngine 构造必须传planner,6个调用点全部更新 --- .../Algorithms/AlgorithmFactory.cs | 1 - .../Algorithms/DefaultDefensePlanner.cs | 33 +++++++++++-------- .../Simulation/SimulationEngine.cs | 4 +-- .../Scripts/Managers/SimulationRunner.cs | 2 +- .../AlgorithmFactoryTests.cs | 3 -- .../CounterDrone.Core.Tests/EdgeCaseTests.cs | 6 ++-- .../FullPipelineTests.cs | 2 +- .../SimulationEngineTests.cs | 2 +- 8 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/CounterDrone.Core/Algorithms/AlgorithmFactory.cs b/src/CounterDrone.Core/Algorithms/AlgorithmFactory.cs index ff8eb02..fb9c208 100644 --- a/src/CounterDrone.Core/Algorithms/AlgorithmFactory.cs +++ b/src/CounterDrone.Core/Algorithms/AlgorithmFactory.cs @@ -10,7 +10,6 @@ namespace CounterDrone.Core.Algorithms { [typeof(ICloudDispersionModel)] = () => new GaussianPuffDispersion(), [typeof(IDamageModel)] = () => new DamageModelRouter(), - [typeof(IDefensePlanner)] = () => new DefaultDefensePlanner(null), }; public static void Register(Func factory) diff --git a/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs b/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs index d6a2e61..5f42f63 100644 --- a/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs +++ b/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs @@ -12,7 +12,9 @@ namespace CounterDrone.Core.Algorithms public DefaultDefensePlanner(List ammoCatalog) { - _ammoCatalog = ammoCatalog ?? new List(); + _ammoCatalog = ammoCatalog ?? throw new ArgumentNullException(nameof(ammoCatalog)); + if (_ammoCatalog.Count == 0) + throw new ArgumentException("弹药规格目录不能为空"); } private static readonly Dictionary MatchTable = new() @@ -60,6 +62,17 @@ namespace CounterDrone.Core.Algorithms var sorted = threats.OrderByDescending(t => t.Priority).ToList(); // Step 2-4: 贪心分配求解 + // 预先检查:所有需要的弹药类型都在目录中 + var neededTypes = sorted + .Select(t => MatchAmmo((PowerType)t.Target.PowerType)) + .Distinct() + .ToList(); + foreach (var t in neededTypes) + { + if (!_ammoCatalog.Any(a => a.AerosolType == (int)t)) + throw new InvalidOperationException($"弹药规格目录中缺少类型: {t}"); + } + result.Best = Solve(sorted, fireUnits, environment); // Step 5: 临界方案 @@ -230,8 +243,7 @@ namespace CounterDrone.Core.Algorithms { var candidates = new List(); var neededAmmo = MatchAmmo((PowerType)threat.Target.PowerType); - var ammo = _ammoCatalog.FirstOrDefault(a => a.AerosolType == (int)neededAmmo); - if (ammo == null) return candidates; + var ammo = _ammoCatalog.First(a => a.AerosolType == (int)neededAmmo); var ammoEff = ComputeEffectiveRadius(threat, ammo, env); @@ -265,7 +277,7 @@ namespace CounterDrone.Core.Algorithms if (unit.MuzzleVelocity <= 0) return null; float maxRange = unit.MuzzleVelocity * unit.MuzzleVelocity / 9.81f; - if (dist > maxRange * 0.8f) return null; + if (dist > maxRange) return null; float shellTime = dist / unit.MuzzleVelocity; float interceptTime = threat.ArrivalTime; @@ -302,7 +314,7 @@ namespace CounterDrone.Core.Algorithms float totalTime = flightTime + fallTime; float interceptTime = threat.ArrivalTime; - if (totalTime > interceptTime * 1.5f) return null; + if (totalTime > interceptTime) return null; float avgSpeed = (float)threat.Target.TypicalSpeed / 3.6f; float neededExposure = ammoType == AerosolType.ActiveMaterial ? 2f : 6f; @@ -365,11 +377,9 @@ namespace CounterDrone.Core.Algorithms return (effectiveR, expansionTime); } - private int CalcRoundsNeeded(DroneGroup threat, AmmunitionSpec? ammo, + private int CalcRoundsNeeded(DroneGroup threat, AmmunitionSpec ammo, CombatScene env, bool isAirBased) { - if (ammo == null) return 1; - float avgSpeed = (float)threat.Target.TypicalSpeed / 3.6f; var (effectiveR, _) = ComputeEffectiveRadius(threat, ammo, env); float spacing = effectiveR * 1.5f; @@ -383,10 +393,8 @@ namespace CounterDrone.Core.Algorithms } private float ComputeInterceptProbability(DroneGroup threat, - AmmunitionSpec? ammo, int rounds, CombatScene env) + AmmunitionSpec ammo, int rounds, CombatScene env) { - if (ammo == null) return 0f; - float avgSpeed = (float)threat.Target.TypicalSpeed / 3.6f; var (effectiveR, _) = ComputeEffectiveRadius(threat, ammo, env); float spacing = effectiveR * 1.5f; @@ -404,10 +412,9 @@ namespace CounterDrone.Core.Algorithms // ═══════════════════════════════════════════════ private List GenerateFireEventsAt(DroneGroup threat, FireUnit unit, - AerosolType ammoType, AmmunitionSpec? ammo, CombatScene env, float targetOffset) + AerosolType ammoType, AmmunitionSpec ammo, CombatScene env, float targetOffset) { var events = new List(); - if (ammo == null) return events; var mid = ThreatMidpoint(threat); var (effectiveR, expansionTime) = ComputeEffectiveRadius(threat, ammo, env); diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index 284761e..0faa539 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -53,13 +53,13 @@ namespace CounterDrone.Core.Simulation private int _entityCounter; public SimulationEngine(IScenarioService scenarioService, FrameDataStore frameStore, - IDamageModel damageModel, IPathProvider paths, IDefensePlanner? planner = null) + IDamageModel damageModel, IPathProvider paths, IDefensePlanner planner) { _scenarioService = scenarioService; _frameStore = frameStore; _damageModel = damageModel; _paths = paths; - _planner = planner ?? new DefaultDefensePlanner(new List()); + _planner = planner; } public void SetFireSchedule(List schedule) diff --git a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs index c3d471b..a09eb50 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs @@ -47,7 +47,7 @@ namespace CounterDrone.Unity new RoutePlanRepository(_db), new WaypointRepository(_db)); _frameStore = new FrameDataStore(_paths); - _engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths); + _engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefaultDefensePlanner(DefaultAmmunition.GetAll())); } public void LoadAndStart(string taskId) diff --git a/test/unit/CounterDrone.Core.Tests/AlgorithmFactoryTests.cs b/test/unit/CounterDrone.Core.Tests/AlgorithmFactoryTests.cs index 6dd0054..3edd513 100644 --- a/test/unit/CounterDrone.Core.Tests/AlgorithmFactoryTests.cs +++ b/test/unit/CounterDrone.Core.Tests/AlgorithmFactoryTests.cs @@ -13,9 +13,6 @@ namespace CounterDrone.Core.Tests var damage = AlgorithmFactory.Create(); Assert.IsType(damage); - - var planner = AlgorithmFactory.Create(); - Assert.IsType(planner); } [Fact] diff --git a/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs b/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs index 78ba518..109c3f2 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 DamageModelRouter(), new TestPathProvider(_testDir), new DefaultDefensePlanner(DefaultAmmunition.GetAll())); 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 DamageModelRouter(), new TestPathProvider(_testDir), new DefaultDefensePlanner(DefaultAmmunition.GetAll())); 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 DamageModelRouter(), new TestPathProvider(_testDir), new DefaultDefensePlanner(DefaultAmmunition.GetAll())); 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 a6246a5..739adb4 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) { - var engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths); + var engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths, new DefaultDefensePlanner(_ammoCatalog)); engine.Initialize(_taskId); engine.TimeScale = 8f; // 8倍速加速 diff --git a/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs b/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs index deb0de9..3047d25 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 DamageModelRouter(), paths, new DefaultDefensePlanner(DefaultAmmunition.GetAll())); } public void Dispose()