From e3ea595204a9467b8d2c4cec06a9256c4f5ee30b Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sat, 13 Jun 2026 09:53:08 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20SimulationEngine=20=E5=86=85?= =?UTF-8?q?=E9=83=A8=E8=B0=83=E7=94=A8=20Planner=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E4=BE=9D=E8=B5=96=E5=A4=96=E9=83=A8=E4=BC=A0=20SetFir?= =?UTF-8?q?eSchedule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Initialize 内建 BuildFireUnits/BuildDroneGroups - 自动从 DB 取 AmmunitionSpec 创建 DefaultDefensePlanner - SetFireSchedule 保留为手动覆盖(测试可用) - fireSchedule 空时才自动生成 --- .../Simulation/SimulationEngine.cs | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index 54ffb51..8fa23b6 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -49,15 +49,17 @@ namespace CounterDrone.Core.Simulation private readonly List _allEvents = new(); private SQLiteConnection _frameDb = null!; private string _taskId = string.Empty; + private readonly IDefensePlanner _planner; private int _entityCounter; public SimulationEngine(IScenarioService scenarioService, FrameDataStore frameStore, - IDamageModel damageModel, IPathProvider paths) + IDamageModel damageModel, IPathProvider paths, IDefensePlanner? planner = null) { _scenarioService = scenarioService; _frameStore = frameStore; _damageModel = damageModel; _paths = paths; + _planner = planner ?? new DefaultDefensePlanner(new List()); } public void SetFireSchedule(List schedule) @@ -114,6 +116,26 @@ namespace CounterDrone.Core.Simulation SimulationTime = 0; _entityCounter = 0; _nextFireIndex = 0; + + // 自动从 Planner 生成发射计划 + if (_fireSchedule.Count == 0) + { + var fireUnits = BuildFireUnits(config); + var threats = BuildDroneGroups(config); + if (fireUnits.Count > 0 && threats.Count > 0) + { + using (var ammoDb = new SQLiteConnection(_paths.GetMainDbPath())) + { + var catalog = new List(ammoDb.Table().ToList()); + if (catalog.Count == 0) + catalog = DefaultAmmunition.GetAll(); + var planner = new DefaultDefensePlanner(catalog); + var result = planner.Plan(fireUnits, threats, _scene); + SetFireSchedule(result.Best.MergedSchedule); + } + } + } + _frameDb = _frameStore.CreateOrOpen(_taskId); State = SimulationState.Running; } @@ -264,6 +286,50 @@ namespace CounterDrone.Core.Simulation public void Resume() { if (State == SimulationState.Paused) State = SimulationState.Running; } public void Stop() { State = SimulationState.Stopped; _frameDb?.Close(); } + private static List BuildFireUnits(TaskFullConfig config) + { + var units = new List(); + int idx = 0; + foreach (var eq in config.Equipment.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform)) + { + int qty = Math.Max(1, eq.Quantity); + for (int i = 0; i < qty; i++) + { + units.Add(new FireUnit + { + Id = $"fu{idx++}", + Type = (PlatformType)(eq.PlatformType ?? (int)PlatformType.GroundBased), + Position = new Algorithms.Vector3((float)eq.PositionX + i * 50, (float)eq.PositionY, (float)eq.PositionZ), + CruiseSpeed = (float)(eq.CruiseSpeed ?? 55f), + ReleaseAltitude = (float)(eq.ReleaseAltitude ?? 1000f), + MuzzleVelocity = (float)(eq.MuzzleVelocity ?? 800f), + TotalMunitions = eq.MunitionCount ?? 1, + AmmoTypes = new List { (AerosolType)(eq.AerosolType ?? 0) }, + Cooldown = (float)eq.Cooldown, + }); + } + } + return units; + } + + private static List BuildDroneGroups(TaskFullConfig config) + { + var groups = new List(); + foreach (var t in config.Targets) + { + var route = config.Routes.FirstOrDefault(r => r.GroupId == t.GroupId); + var wps = config.WaypointGroups.GetValueOrDefault(t.GroupId, new List()); + groups.Add(new DroneGroup + { + GroupId = t.GroupId, + Target = t, + Route = route ?? new RoutePlan(), + Waypoints = wps, + }); + } + return groups; + } + private List CollectSnapshots() { var list = new List();