refactor: SimulationEngine 内部调用 Planner,不再依赖外部传 SetFireSchedule
- Initialize 内建 BuildFireUnits/BuildDroneGroups - 自动从 DB 取 AmmunitionSpec 创建 DefaultDefensePlanner - SetFireSchedule 保留为手动覆盖(测试可用) - fireSchedule 空时才自动生成
This commit is contained in:
parent
4411a452dc
commit
e3ea595204
@ -49,15 +49,17 @@ namespace CounterDrone.Core.Simulation
|
||||
private readonly List<SimEvent> _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<AmmunitionSpec>());
|
||||
}
|
||||
|
||||
public void SetFireSchedule(List<FireEvent> 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<AmmunitionSpec>(ammoDb.Table<AmmunitionSpec>().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<FireUnit> BuildFireUnits(TaskFullConfig config)
|
||||
{
|
||||
var units = new List<FireUnit>();
|
||||
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> { (AerosolType)(eq.AerosolType ?? 0) },
|
||||
Cooldown = (float)eq.Cooldown,
|
||||
});
|
||||
}
|
||||
}
|
||||
return units;
|
||||
}
|
||||
|
||||
private static List<DroneGroup> BuildDroneGroups(TaskFullConfig config)
|
||||
{
|
||||
var groups = new List<DroneGroup>();
|
||||
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<Waypoint>());
|
||||
groups.Add(new DroneGroup
|
||||
{
|
||||
GroupId = t.GroupId,
|
||||
Target = t,
|
||||
Route = route ?? new RoutePlan(),
|
||||
Waypoints = wps,
|
||||
});
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
private List<EntitySnapshot> CollectSnapshots()
|
||||
{
|
||||
var list = new List<EntitySnapshot>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user