diff --git a/CHANGELOG.md b/CHANGELOG.md index 261dff4..f18c33c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ - **空基/地基物理统一**:去除 DefensePlanner 所有平台类型分支,统一用 `InterceptCalculator.Compute`(删 `ComputeHorizontal`),统一用 `MuzzleVelocity`(删 `CruiseSpeed` 分支) - **抛物线选解策略**:两解逐一计算距离匹配 + `fireTime>0` 可行性,选最早拦截的解(非简单选高角/低角) - **`TargetType` → `DroneType`**:删 `Electric`/`Piston`,重编号 `HighSpeed=2`,`TargetConfig.DroneType` 属性同步改名 -- **`TargetConfig` → `DroneProfile`**:核心模型重命名 +- **`TargetConfig` → `ScenarioDrone`**:核心模型重命名 - **`SimTask` → `Scenario`**:想定主表重命名,`ScenarioNumber` 取代 `TaskNumber` - **`TaskFullConfig` → `ScenarioConfig`**:聚合配置重命名,`Task` 属性 → `Info` - **`TaskId` → `ScenarioId`**:所有 FK 重命名 @@ -17,9 +17,9 @@ ### Added — 模型业务属性 -- **`DroneProfile` / `DroneSpec`**:+`Model`(型号)、+`Description`(描述/用途) +- **`ScenarioDrone` / `DroneSpec`**:+`Model`(型号)、+`Description`(描述/用途) - **`Scenario`**:+`Description`(想定描述) -- **`EquipmentDeployment` / `FireUnitSpec`**:+`Description` +- **`ScenarioUnit` / `FireUnitSpec`**:+`Description` - **`ReportManager.Export(reportId, outputDir)`**:支持指定导出路径 ### Changed — 数据库迁移 @@ -96,7 +96,7 @@ - **EarliestDetection 采样法**:线段-圆求交改为沿航路采样(步长≤50m)调 `IsInCoverage` - **DetectionEntity**:运行时探测实体 + per-drone 状态机(Undetected ⇄ Detected),Tick 第5步扫描 - **实时探测事件**:`OnTargetDetected` / `SimEventType.TargetDetected` / `PlanningFailed` -- **EquipmentDeployment + DetectionSource**:+4 个 3D 球冠字段(MinElevation/MaxElevation/MinDetectAlt/MaxDetectAlt) +- **ScenarioUnit + DetectionSource**:+4 个 3D 球冠字段(MinElevation/MaxElevation/MinDetectAlt/MaxDetectAlt) - **默认数据全部加入 3D 球冠参数**(地基 -5°~85°、空基 -80°~30°) ### Added — Planner 诊断 + 拦截点计算 @@ -109,7 +109,7 @@ ### Changed — 消除硬编码 -- **速度从 waypoint.Speed 读取**:`DroneEntity.CruiseSpeed` / `GetDroneSpeedKph` 不再用 `DroneProfile.TypicalSpeed` +- **速度从 waypoint.Speed 读取**:`DroneEntity.CruiseSpeed` / `GetDroneSpeedKph` 不再用 `ScenarioDrone.TypicalSpeed` - **`AmmunitionSpec` +`Phase2Duration`**(30s):`CloudExpansionModel` 不再写死 `30f` - **`GetArrivalTime` 基于 DetectArc**:从探测点到中点算到达时间(而非航路起点) - **TestData 改为从 seeded 数据库读取**(不再内嵌 JSON 重复 defaults.json) @@ -137,7 +137,7 @@ ### Changed — 数据模型重命名 -- **`GroupId` → `WaveId`**DroneProfile 四表的编组外键重命名为批次外键 +- **`GroupId` → `WaveId`**ScenarioDrone 四表的编组外键重命名为批次外键 - **RoutePlan 索引重命名**:`(ScenarioId, GroupId)` → `(ScenarioId, WaveId)` - **RoutePlanRepository / WaypointRepository**:`GetByScenarioAndGroup` → `GetByScenarioAndWave` - **IScenarioService.SaveRoute**:`groupId` 参数 → `waveId` @@ -173,8 +173,8 @@ - **DetectionCalculator 静态工具类**:探测能力评估的唯一实现(与 Kinematics/RouteGeometry 同范式)。光电受 Visibility 衰减(`有效=基准×min(1,Visibility/基准)`),雷达/红外不受影响;统一信息网络找最早探测点(线段-圆求交) - **探测源模型**(DetectionSource):独立探测设备 + 火力单元自带探测统一表达(雷达/光电/红外三距离 + 精度) -- **EquipmentDeployment 扩展**:删单一 `DetectionRadius`,加 `RadarRange/EORange/IRange/DetectionAccuracy` 四字段 -- **FireUnit 探测字段激活**:BuildFireUnits 从 EquipmentDeployment 读取并赋值(原为死代码) +- **ScenarioUnit 扩展**:删单一 `DetectionRadius`,加 `RadarRange/EORange/IRange/DetectionAccuracy` 四字段 +- **FireUnit 探测字段激活**:BuildFireUnits 从 ScenarioUnit 读取并赋值(原为死代码) - **planner 接口扩展**:`IDefensePlanner.Plan` 加第 4 参数 `detectionSources` - **PlannerConfig 加 DefaultDetectionAccuracy**(无探测时回退精度) - 单元测试:DetectionCalculator 13 项、探测驱动规划 2 项 diff --git a/docs/design/architecture/总体架构设计.md b/docs/design/architecture/总体架构设计.md index 9731286..186bba1 100644 --- a/docs/design/architecture/总体架构设计.md +++ b/docs/design/architecture/总体架构设计.md @@ -6,7 +6,7 @@ > **变更**:V14 新增 DataService 基础数据 CRUD + FrameDataStore 内存回放架构 > **Unity 版本**:22.3.62 > **.NET 版本**:.NET Standard 2.1 -> **变更**:V13 探测行为决策固化——5 项规则确认(回退 Undetected / 融合取最早-同刻取精度高 / 不影响 FireSchedule / 盲区仅可视化 / 3D 球冠);新增 14.2.1 三维球冠几何(IsInCoverage)+ 14.7 数据模型变更清单;EquipmentDeployment 表加 4 个 3D 探测字段;DetectionSource 同步扩展 +> **变更**:V13 探测行为决策固化——5 项规则确认(回退 Undetected / 融合取最早-同刻取精度高 / 不影响 FireSchedule / 盲区仅可视化 / 3D 球冠);新增 14.2.1 三维球冠几何(IsInCoverage)+ 14.7 数据模型变更清单;ScenarioUnit 表加 4 个 3D 探测字段;DetectionSource 同步扩展 > **历史变更**:V12 探测双链路设计(静态规划+实时探测待实现);V11 文档校准 + 第十三章性能设计;V10 Group 表移除,批次+火力单元概念升级 --- @@ -207,13 +207,13 @@ enum FormationMode { Single = 0, Formation = 1, Swarm = 2 } // === 核心作战概念 === // 火力单元(FireUnit):能独立完成搜索、跟踪、瞄准并实施打击的最小作战实体。 // 包含探测(雷达/光电/红外)+ 打击(发射架/火炮)的完整闭环系统。 -// 配置层 = EquipmentDeployment(LaunchPlatform),含探测字段 + 打击字段。 +// 配置层 = ScenarioUnit(LaunchPlatform),含探测字段 + 打击字段。 // 独立探测节点(DetectionNode):只探测不打击的侦查节点(如前沿警戒雷达)。 -// 配置层 = EquipmentDeployment(Detection),仅含探测字段。 +// 配置层 = ScenarioUnit(Detection),仅含探测字段。 // 两者都往统一信息网络送探测信息,planner 基于融合后的探测边界规划。 // 无人机批次(DroneWave):有共同航路的一组无人机(攻击方)。 // 批次关联航路但不独占(多个批次可共享同一条航路)。 -// 配置层 = DroneProfile(含 WaveId) + RoutePlan(ScenarioId, WaveId) + Waypoints。 +// 配置层 = ScenarioDrone(含 WaveId) + RoutePlan(ScenarioId, WaveId) + Waypoints。 // === 运行时 === enum EntityType { Drone = 0, Platform = 1, DetectionEquip = 2, Cloud = 3, Munition = 4 } @@ -266,10 +266,10 @@ CounterDroneBackend_Data/ Scenario — 仿真任务主表 CombatScene — 步骤1:作战场景(含24h时间、天气) ControlZone — 步骤1+:管控区域/电子围栏(NEW) - DroneProfile — 步骤2:目标配置(含 WaveId 关联批次) - EquipmentDeployment — 步骤3:装备部署(火力单元含探测+打击,或独立探测节点) + ScenarioDrone — 步骤2:目标配置(含 WaveId 关联批次) + ScenarioUnit — 步骤3:装备部署(火力单元含探测+打击,或独立探测节点) CloudDispersal — 步骤4:云团抛撒配置 - RoutePlan — 步骤5:航路规划(1:N Scenario,多批次;批次关联但不独占航路,FK 关联 DroneProfile.WaveId) + RoutePlan — 步骤5:航路规划(1:N Scenario,多批次;批次关联但不独占航路,FK 关联 ScenarioDrone.WaveId) Waypoint — 航路点 SimulationReport — 仿真报告 SimEvent — 仿真事件(时序图数据源) @@ -279,9 +279,9 @@ CounterDroneBackend_Data/ ``` > **核心作战概念**: -> - **火力单元(FireUnit)**:能独立完成搜索、跟踪、瞄准并实施打击的最小作战实体。包含探测(雷达/光电/红外)+ 打击(发射架/火炮)的完整闭环。配置层 = `EquipmentDeployment(LaunchPlatform)`。 -> - **独立探测节点(DetectionNode)**:只探测不打击的侦查节点(如前沿警戒雷达)。配置层 = `EquipmentDeployment(Detection)`。 -> - **无人机批次(DroneWave)**:有共同航路的一组无人机(攻击方)。批次关联航路但不独占(多个批次可共享同一条航路)。配置层 = `DroneProfile(WaveId)` + `RoutePlan(ScenarioId, WaveId)` + `Waypoints`。 +> - **火力单元(FireUnit)**:能独立完成搜索、跟踪、瞄准并实施打击的最小作战实体。包含探测(雷达/光电/红外)+ 打击(发射架/火炮)的完整闭环。配置层 = `ScenarioUnit(LaunchPlatform)`。 +> - **独立探测节点(DetectionNode)**:只探测不打击的侦查节点(如前沿警戒雷达)。配置层 = `ScenarioUnit(Detection)`。 +> - **无人机批次(DroneWave)**:有共同航路的一组无人机(攻击方)。批次关联航路但不独占(多个批次可共享同一条航路)。配置层 = `ScenarioDrone(WaveId)` + `RoutePlan(ScenarioId, WaveId)` + `Waypoints`。 > - 原来的 `Group`(编组)表已移除:无人机编队概念升级为"批次",装备编组概念不再需要(火力单元是独立作战单位)。 ### 4.3 业务表详细设计 @@ -349,7 +349,7 @@ CounterDroneBackend_Data/ > 管控区域在场景设置(地形+天气)之后配置。无人机进入管控区域 → 触发 ZoneIntruded 事件 → 该无人机任务失败。 -#### DroneProfile — 步骤2:无人机批次参数 +#### ScenarioDrone — 步骤2:无人机批次参数 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| @@ -373,7 +373,7 @@ CounterDroneBackend_Data/ | 固定翼 | 3.5 | 150 | 1000 | | 高速目标 | 1.5 | 300 | 2000 | -#### EquipmentDeployment — 步骤3:装备部署(火力单元 + 独立探测节点) +#### ScenarioUnit — 步骤3:装备部署(火力单元 + 独立探测节点) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| @@ -468,10 +468,10 @@ CounterDroneBackend_Data/ #### ~~Group~~ — 编组(已移除) > **概念升级**:原 Group 表的两种类型已分别升级: -> - `DroneFleet`(无人机编队)→ **无人机批次(DroneWave)**:由 `DroneProfile(WaveId)` + `RoutePlan(ScenarioId, WaveId)` + `Waypoints` 隐式表达。批次关联航路但不独占(多个批次可共享同一条航路)。 +> - `DroneFleet`(无人机编队)→ **无人机批次(DroneWave)**:由 `ScenarioDrone(WaveId)` + `RoutePlan(ScenarioId, WaveId)` + `Waypoints` 隐式表达。批次关联航路但不独占(多个批次可共享同一条航路)。 > - `EquipmentGroup`(装备编组)→ **不再需要**。火力单元是独立作战的最小单位,不需要上层编组。 > -> 数据层:`Group` 表保留但不再主动使用(向后兼容)。`DroneProfile.WaveId` 语义为"批次 ID"。 +> 数据层:`Group` 表保留但不再主动使用(向后兼容)。`ScenarioDrone.WaveId` 语义为"批次 ID"。 ### 4.4 运行时表 @@ -1395,8 +1395,8 @@ interface IScenarioService // 步骤保存 void SaveScene(string scenarioId, CombatScene scene); void SaveControlZones(string scenarioId, List zones); // NEW - void SaveDroneProfile(string scenarioId, DroneProfile target); - void SaveDeployment(string scenarioId, List equips); // 重构 + void SaveScenarioDrone(string scenarioId, ScenarioDrone target); + void SaveDeployment(string scenarioId, List equips); // 重构 void SaveCloudDispersal(string scenarioId, CloudDispersal cloud); void SaveRoute(string scenarioId, RoutePlan route, List wps); void UpdateStep(string scenarioId, int step); @@ -1457,17 +1457,17 @@ Scenario "城市防御演习" ├── CloudDispersal(共享:云团参数,具体拦截方案由算法确定) │ ├── 批次 A(活塞×3) ← WaveId -│ ├── DroneProfile(WaveId=A,类型=活塞,数量=3) +│ ├── ScenarioDrone(WaveId=A,类型=活塞,数量=3) │ ├── RoutePlan(ScenarioId + WaveId=A,航路 A:北→南) │ └── Waypoint[] │ ├── 批次 B(喷气×2) ← WaveId -│ ├── DroneProfile(WaveId=B,类型=高速,数量=2) +│ ├── ScenarioDrone(WaveId=B,类型=高速,数量=2) │ ├── RoutePlan(ScenarioId + WaveId=B,航路 B:西→东) │ └── Waypoint[] │ └── 批次 C(旋翼×5) ← WaveId - ├── DroneProfile(WaveId=C,类型=旋翼,数量=5) + ├── ScenarioDrone(WaveId=C,类型=旋翼,数量=5) ├── RoutePlan(ScenarioId + WaveId=C,航路 C) └── Waypoint[] ``` @@ -1518,7 +1518,7 @@ engine.SetFireSchedule(merged); | 表 | 变更 | |------|------| | `RoutePlan` | PK 为 (ScenarioId, WaveId) 复合键 | -| `DroneProfile` | 不变(已有 WaveId) | +| `ScenarioDrone` | 不变(已有 WaveId) | | `Waypoint` | 关联 `(ScenarioId, WaveId)` 定位航路 | `IScenarioService` 的 `SaveRoute` 签名: @@ -1909,7 +1909,7 @@ FOR EACH 飞行无人机(维护"本帧已发现该目标的最优探测设备" | 改动项 | 位置 | 内容 | 状态 | |--------|------|------|------| -| **EquipmentDeployment 表加字段** | 4.3 | `MinElevation`/`MaxElevation`(度)、`MinDetectAlt`/`MaxDetectAlt`(m),均可空 | 待加列 | +| **ScenarioUnit 表加字段** | 4.3 | `MinElevation`/`MaxElevation`(度)、`MinDetectAlt`/`MaxDetectAlt`(m),均可空 | 待加列 | | **DetectionSource 类加字段** | 14.5.1 | 同上 4 个三维几何字段 | 待加属性 | | **DetectionCalculator.IsInCoverage** | 14.2.1 | 三维球冠判定(水平距离 + 俯仰角 + 高度门限),planner 与实时探测共用 | 待实现 | | **DetectionCalculator.EffectiveRange** | 14.2 | 现有签名不变(返回综合水平距离基准),3D 判定在其上层 | 已实现(基础) | @@ -1917,7 +1917,7 @@ FOR EACH 飞行无人机(维护"本帧已发现该目标的最优探测设备" | **SimulationEngine 加 _detectionEntities** | 5.1 | Initialize 时从配置构建 `List`,Tick 第5步遍历 | 待实现 | | **Tick 第5步实时探测** | 5.3 / 14.5.2 | 扫描 + 状态机 + 决策1/2/3/4 落地,触发 `TargetDetected` | 待实现 | -> **数据库迁移**:`EquipmentDeployment` 新增 4 列均为 NULLABLE,不影响存量数据;`SimulationEngine.BuildDetectionSources` 读取新字段构造 `DetectionSource`(缺失时按"无角度/高度限制"的退化球冠处理,等价当前 2D 行为,保证平滑过渡)。 +> **数据库迁移**:`ScenarioUnit` 新增 4 列均为 NULLABLE,不影响存量数据;`SimulationEngine.BuildDetectionSources` 读取新字段构造 `DetectionSource`(缺失时按"无角度/高度限制"的退化球冠处理,等价当前 2D 行为,保证平滑过渡)。 --- diff --git a/docs/design/technical/DefensePlanner-技术方案.md b/docs/design/technical/DefensePlanner-技术方案.md index c2a9996..1dc3c1a 100644 --- a/docs/design/technical/DefensePlanner-技术方案.md +++ b/docs/design/technical/DefensePlanner-技术方案.md @@ -59,7 +59,7 @@ class FireUnit { ```csharp class DroneWave { string WaveId; // 批次 ID - DroneProfile Profile; // 类型、数量、动力、翼展、速度、高度 + ScenarioDrone Profile; // 类型、数量、动力、翼展、速度、高度 List Waypoints; // 航路点 float ArrivalTime; // 预计算:到达防御区域中点的时间 s } @@ -344,7 +344,7 @@ PlannerResult.Best.MergedSchedule ### 🔒 不变 - `Kinematics` / `GaussianPuffDispersion` / `DamageModelRouter` -- 所有 Repository 和数据模型(EquipmentDeployment 新增 GunCount/ChannelsPerGun/ChannelInterval) +- 所有 Repository 和数据模型(ScenarioUnit 新增 GunCount/ChannelsPerGun/ChannelInterval) - `ScenarioService` 接口 --- diff --git a/docs/design/technical/仿真器实体与事件映射.md b/docs/design/technical/仿真器实体与事件映射.md index 644bafb..50df606 100644 --- a/docs/design/technical/仿真器实体与事件映射.md +++ b/docs/design/technical/仿真器实体与事件映射.md @@ -39,7 +39,7 @@ ## 数据流 ``` -想定配置(EquipmentDeployment + DroneProfile + RoutePlan + CombatScene) +想定配置(ScenarioUnit + ScenarioDrone + RoutePlan + CombatScene) │ ▼ SimulationEngine.Initialize() diff --git a/docs/implementation/tasks/实施计划与任务跟踪.md b/docs/implementation/tasks/实施计划与任务跟踪.md index e560463..ab7c29b 100644 --- a/docs/implementation/tasks/实施计划与任务跟踪.md +++ b/docs/implementation/tasks/实施计划与任务跟踪.md @@ -181,7 +181,7 @@ Phase 12 ✅ 空基/地基统一规划 + 编队轴 + LaneDivider | 8.1.1 | 探测设备搜索逻辑 | ✅ 事前规划:`DetectionCalculator` 算统一信息网络最早探测点,planner 基于探测边界算到达时间;天气衰减光电;精度影响散布。**实时探测设计完成**(总体架构设计第十四章),待 Phase 10 开发 | | 8.1.2 | 蜂群运动模型 | ⬜ `FormationMode.Swarm` 枚举已定义,需差异化行为(随机扰动、个体差异) | | 8.1.3 | 空基平台 + DefensePlanner | ✅ 五步规划引擎,通道模型,物理间隔错发,路径积分毁伤判定 | -| 8.1.4 | 预置典型目标库 | ⬜ 具体无人机型号 JSON 配置(如 DJI Mavic 3、Shahed-136 等),导入 `DroneProfile` 默认值 | +| 8.1.4 | 预置典型目标库 | ⬜ 具体无人机型号 JSON 配置(如 DJI Mavic 3、Shahed-136 等),导入 `ScenarioDrone` 默认值 | | 8.1.5 | 毁伤曲线参数校准 | ✅ RequiredExposureSeconds 替代硬编码,密度阈值统一在引擎检查 | | 8.1.6 | Fallback/default 清理 | ✅ 删除所有硬编码默认值和静默 fallback,参数缺失即报错 | @@ -241,7 +241,7 @@ Phase 12 ✅ 空基/地基统一规划 + 编队轴 + LaneDivider | # | 任务 | 预估 | 状态 | 说明 | |---|------|------|------|------| -| T1.1 | EquipmentDeployment 加 4 列 | 0.5h | ✅ | `MinElevation`/`MaxElevation`/`MinDetectAlt`/`MaxDetectAlt`,均 NULLABLE | +| T1.1 | ScenarioUnit 加 4 列 | 0.5h | ✅ | `MinElevation`/`MaxElevation`/`MinDetectAlt`/`MaxDetectAlt`,均 NULLABLE | | T1.2 | DetectionSource 类扩展 | 0.5h | ✅ | 同步加 4 个三维几何属性(float.MaxValue=无限制,退化 2D) | | T1.3 | BuildDetectionSources 读取新字段 | 0.5h | ✅ | 缺失时退化球冠(float.MaxValue),保证存量数据平滑过渡 | diff --git a/docs/requirements/changes/2026-06-15-探测驱动规划.md b/docs/requirements/changes/2026-06-15-探测驱动规划.md index 7c7a4d0..879e438 100644 --- a/docs/requirements/changes/2026-06-15-探测驱动规划.md +++ b/docs/requirements/changes/2026-06-15-探测驱动规划.md @@ -14,14 +14,14 @@ planner 是参谋,只能基于侦查信息制定方案。假设我方有统一 ### 变更内容 1. **新增 DetectionCalculator**:探测能力评估的唯一实现。光电受 Visibility 衰减,雷达/红外不受影响;统一信息网络找最早探测点 -2. **EquipmentDeployment 扩展**:删单一 DetectionRadius,加 RadarRange/EORange/IRange/DetectionAccuracy +2. **ScenarioUnit 扩展**:删单一 DetectionRadius,加 RadarRange/EORange/IRange/DetectionAccuracy 3. **FireUnit 探测字段激活**:BuildFireUnits 赋值(原为死代码) 4. **planner 接口扩展**:Plan 加第 4 参数 detectionSources;到达时间基于探测边界 5. **SimulationEngine 构建探测源**:独立探测 + 火力单元自带探测统一传入 planner ## 影响范围 -- [x] 接口变更:IDefensePlanner.Plan 加参数;EquipmentDeployment 字段变更(删 DetectionRadius) +- [x] 接口变更:IDefensePlanner.Plan 加参数;ScenarioUnit 字段变更(删 DetectionRadius) - [ ] 数据库变更:新字段为 nullable,SQLite 自动处理 - [ ] UI 变更 - [x] 文档变更:实施计划 8.1.1、CHANGELOG、VERSION diff --git a/docs/对接文档_Unity前端.md b/docs/对接文档_Unity前端.md index 6c699fa..d9c7a32 100644 --- a/docs/对接文档_Unity前端.md +++ b/docs/对接文档_Unity前端.md @@ -72,7 +72,7 @@ var scenarioId = demos.Items[0].Id; // 方式 B:自定义 var sc = scenario.CreateScenario("我的想定", ""); scenario.SaveScene(sc.Id, new CombatScene { WindSpeed = 5, WindDirection = (int)WindDirection.E }); -scenario.SaveDroneProfile(sc.Id, new DroneProfile { +scenario.SaveScenarioDrone(sc.Id, new ScenarioDrone { WaveId = "w1", Model = "Shahed-136", Description = "活塞巡飞弹", Quantity = 1, DroneType = (int)DroneType.FixedWing, TypicalSpeed = 200, TypicalAltitude = 500 @@ -81,7 +81,7 @@ scenario.SaveRoute(sc.Id, "w1", new RoutePlan(), new List { new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, new() { PosX = 10000, PosY = 500, PosZ = 0, Speed = 200 } }); -scenario.SaveDeployment(sc.Id, new List { +scenario.SaveDeployment(sc.Id, new List { new() { EquipmentRole = 1, PlatformType = 1, Quantity = 1, PositionX = 5000, AerosolType = 0, MunitionCount = 8, Description = "地面轻型平台" } @@ -150,7 +150,7 @@ mgr.DataService.GetAllEnvironments() / GetAllFormations() / GetAllRoutes() // 想定 CRUD mgr.CreateScenario(name, number) / mgr.DeleteScenario(id) mgr.Search(kw, from, to, page, size) -mgr.SaveScene / SaveDroneProfile / SaveDeployment / SaveCloud / SaveRoute / UpdateStep +mgr.SaveScene / SaveScenarioDrone / SaveDeployment / SaveCloud / SaveRoute / UpdateStep mgr.GetDetail(id) → ScenarioConfig ``` @@ -223,8 +223,8 @@ replay.TotalFrames / replay.GetFrame(index) |------|------|------| | `Scenario` | `Scenario` | 想定任务 | | `CombatScene` | `CombatScene` | 作战环境 | -| `DroneProfile` | `DroneProfile` | 无人机批次参数 | -| `EquipmentDeployment` | `EquipmentDeployment` | 装备部署 | +| `ScenarioDrone` | `ScenarioDrone` | 无人机批次参数 | +| `ScenarioUnit` | `ScenarioUnit` | 装备部署 | | `CloudDispersal` | `CloudDispersal` | 云团抛撒配置 | | `RoutePlan` | `RoutePlan` | 航路规划 | | `Waypoint` | `Waypoint` | 航路点 | @@ -243,17 +243,17 @@ replay.TotalFrames / replay.GetFrame(index) | 模型 | 属性 | 类型 | 说明 | |------|------|------|------| -| `DroneProfile` | `Model` | string | 型号 | -| `DroneProfile` | `Description` | string | 描述/用途 | -| `DroneProfile` | `DroneType` | DroneType | Rotor / FixedWing / HighSpeed | -| `DroneProfile` | `PowerType` | PowerType | Electric / Piston / Jet | -| `DroneProfile` | `TypicalSpeed` | double | 典型速度 (km/h) | -| `DroneProfile` | `TypicalAltitude` | double | 典型高度 (m) | +| `ScenarioDrone` | `Model` | string | 型号 | +| `ScenarioDrone` | `Description` | string | 描述/用途 | +| `ScenarioDrone` | `DroneType` | DroneType | Rotor / FixedWing / HighSpeed | +| `ScenarioDrone` | `PowerType` | PowerType | Electric / Piston / Jet | +| `ScenarioDrone` | `TypicalSpeed` | double | 典型速度 (km/h) | +| `ScenarioDrone` | `TypicalAltitude` | double | 典型高度 (m) | | `Scenario` | `ScenarioNumber` | string | 想定编号(唯一) | | `Scenario` | `Description` | string | 想定描述 | -| `EquipmentDeployment` | `Description` | string | 部署备注 | -| `EquipmentDeployment` | `MuzzleVelocity` | double? | 初速 (m/s) | -| `EquipmentDeployment` | `CruiseSpeed` | double? | 巡航速度 (m/s),空基专用 | +| `ScenarioUnit` | `Description` | string | 部署备注 | +| `ScenarioUnit` | `MuzzleVelocity` | double? | 初速 (m/s) | +| `ScenarioUnit` | `CruiseSpeed` | double? | 巡航速度 (m/s),空基专用 | | `DroneSpec` | `Model` | string | 型号 | | `DroneSpec` | `Description` | string | 描述/用途 | | `FireUnitSpec` | `Description` | string | 描述/用途 | diff --git a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs index 8bc0c70..b9a2d3a 100644 --- a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs +++ b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs @@ -51,7 +51,7 @@ namespace CounterDrone.Core.Algorithms public class DroneWave { public string WaveId { get; set; } = string.Empty; - public DroneProfile Profile { get; set; } = new(); + public ScenarioDrone Profile { get; set; } = new(); public RoutePlan Route { get; set; } = new(); public List Waypoints { get; set; } = new(); diff --git a/src/CounterDrone.Core/Algorithms/DefensePlanner.cs b/src/CounterDrone.Core/Algorithms/DefensePlanner.cs index e182b24..93f87e2 100644 --- a/src/CounterDrone.Core/Algorithms/DefensePlanner.cs +++ b/src/CounterDrone.Core/Algorithms/DefensePlanner.cs @@ -90,7 +90,7 @@ namespace CounterDrone.Core.Algorithms // Step 1: 威胁指数 // ═══════════════════════════════════════════════ - private static float CalcThreatIndex(PlannerConfig config, DroneProfile target) + private static float CalcThreatIndex(PlannerConfig config, ScenarioDrone target) { float typeCoef = config.TypeCoefficient.GetValueOrDefault((DroneType)target.DroneType, 1f); float speedCoef = (float)target.TypicalSpeed / 60f; diff --git a/src/CounterDrone.Core/DatabaseManager.cs b/src/CounterDrone.Core/DatabaseManager.cs index 975b621..706b1d9 100644 --- a/src/CounterDrone.Core/DatabaseManager.cs +++ b/src/CounterDrone.Core/DatabaseManager.cs @@ -82,34 +82,36 @@ namespace CounterDrone.Core .FirstOrDefault(m => m.Key == "scenariosVersion")?.Value; // 版本未变 → 跳过 - if (currentVersion == "4") return; + if (currentVersion == "5") return; var defaults = DefaultData.Load(_paths); var scenario = new ScenarioService( new ScenarioRepository(db), new CombatSceneRepository(db), - new ControlZoneRepository(db), new DroneProfileRepository(db), - new EquipmentDeploymentRepository(db), new CloudDispersalRepository(db), + new ControlZoneRepository(db), new ScenarioDroneRepository(db), + new ScenarioUnitRepository(db), new CloudDispersalRepository(db), new RoutePlanRepository(db), new WaypointRepository(db)); DefaultScenarios.Seed(scenario, defaults); - db.InsertOrReplace(new MetaEntry { Key = "scenariosVersion", Value = "4" }); + db.InsertOrReplace(new MetaEntry { Key = "scenariosVersion", Value = "5" }); } private void CreateMainTables(SQLiteConnection db) { - // 删除旧版本残留表(V1.6 重命名) + // 删除旧版本残留表 db.Execute("DROP TABLE IF EXISTS SimTask"); db.Execute("DROP TABLE IF EXISTS TargetConfig"); - db.Execute("DROP TABLE IF EXISTS SimulationReport"); // TaskNumber→ScenarioNumber + db.Execute("DROP TABLE IF EXISTS DroneProfile"); + db.Execute("DROP TABLE IF EXISTS EquipmentDeployment"); + db.Execute("DROP TABLE IF EXISTS SimulationReport"); db.CreateTable(); db.CreateTable(); db.CreateTable(); db.CreateTable(); db.CreateTable(); - db.CreateTable(); - db.CreateTable(); + db.CreateTable(); + db.CreateTable(); db.CreateTable(); db.CreateTable(); db.CreateIndex("RoutePlan", new[] { "ScenarioId", "WaveId" }, true); @@ -124,8 +126,8 @@ namespace CounterDrone.Core db.CreateIndex("Scenario", "ScenarioNumber"); db.CreateIndex("ControlZone", "ScenarioId"); - db.CreateIndex("DroneProfile", "ScenarioId"); - db.CreateIndex("EquipmentDeployment", "ScenarioId"); + db.CreateIndex("ScenarioDrone", "ScenarioId"); + db.CreateIndex("ScenarioUnit", "ScenarioId"); db.CreateIndex("Waypoint", "ScenarioId"); db.CreateIndex("SimulationReport", "ScenarioId"); } diff --git a/src/CounterDrone.Core/DefaultData.cs b/src/CounterDrone.Core/DefaultData.cs index 6f54dd1..8b17ca5 100644 --- a/src/CounterDrone.Core/DefaultData.cs +++ b/src/CounterDrone.Core/DefaultData.cs @@ -125,10 +125,10 @@ namespace CounterDrone.Core public double? MinDetectAlt { get; set; } public double? MaxDetectAlt { get; set; } - public EquipmentDeployment ToEquipmentDeployment(AerosolType ammoType, int quantity, + public ScenarioUnit ToScenarioUnit(AerosolType ammoType, int quantity, double posX, double posY, double posZ) { - return new EquipmentDeployment + return new ScenarioUnit { EquipmentRole = (int)Models.EquipmentRole.LaunchPlatform, PlatformType = PlatformType, @@ -171,9 +171,9 @@ namespace CounterDrone.Core public double TypicalSpeed { get; set; } public double TypicalAltitude { get; set; } - public DroneProfile ToDroneProfile(string waveId = "default") + public ScenarioDrone ToScenarioDrone(string waveId = "default") { - return new DroneProfile + return new ScenarioDrone { WaveId = waveId, DroneType = DroneType, @@ -205,9 +205,9 @@ namespace CounterDrone.Core public double? MinDetectAlt { get; set; } public double? MaxDetectAlt { get; set; } - public EquipmentDeployment ToEquipmentDeployment(double posX, double posY, double posZ) + public ScenarioUnit ToScenarioUnit(double posX, double posY, double posZ) { - return new EquipmentDeployment + return new ScenarioUnit { EquipmentRole = (int)Models.EquipmentRole.Detection, Quantity = 1, diff --git a/src/CounterDrone.Core/DefaultScenarios.cs b/src/CounterDrone.Core/DefaultScenarios.cs index 42f0529..e0be922 100644 --- a/src/CounterDrone.Core/DefaultScenarios.cs +++ b/src/CounterDrone.Core/DefaultScenarios.cs @@ -37,10 +37,10 @@ namespace CounterDrone.Core { var t = s.CreateScenario("[Demo] 无防御-无人机抵达目标", ""); s.SaveScene(t.Id, d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); - s.SaveDroneProfile(t.Id, d.Drones.First(p => p.Id == "shahed").ToDroneProfile()); + s.SaveScenarioDrone(t.Id, d.Drones.First(p => p.Id == "shahed").ToScenarioDrone()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), R("3km-h400", 600, d)); s.SaveCloudDispersal(t.Id, new CloudDispersal()); - s.SaveDeployment(t.Id, new List()); + s.SaveDeployment(t.Id, new List()); s.UpdateStep(t.Id, 5); } @@ -48,10 +48,10 @@ namespace CounterDrone.Core { var t = s.CreateScenario("[Demo] 管控区域侵入", ""); s.SaveScene(t.Id, d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); - s.SaveDroneProfile(t.Id, d.Drones.First(p => p.Id == "electric-scout").ToDroneProfile()); + s.SaveScenarioDrone(t.Id, d.Drones.First(p => p.Id == "electric-scout").ToScenarioDrone()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), R("3km-h300", 300, d)); s.SaveCloudDispersal(t.Id, new CloudDispersal()); - s.SaveDeployment(t.Id, new List()); + s.SaveDeployment(t.Id, new List()); s.SaveControlZones(t.Id, new List { new ControlZone @@ -71,15 +71,15 @@ namespace CounterDrone.Core scene.WindSpeed = 5; scene.WindDirection = (int)WindDirection.W; s.SaveScene(t.Id, scene); - s.SaveDroneProfile(t.Id, d.Drones.First(p => p.Id == "shahed").ToDroneProfile()); + s.SaveScenarioDrone(t.Id, d.Drones.First(p => p.Id == "shahed").ToScenarioDrone()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), new List { new() { PosX = 6600, PosY = 500, PosZ = 0, Speed = 200 }, new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, }); - s.SaveDeployment(t.Id, new List + s.SaveDeployment(t.Id, new List { - d.FireUnits.First(f => f.Id == "ground-light").ToEquipmentDeployment(AerosolType.InertGas, 1, 0, 0, 50), + d.FireUnits.First(f => f.Id == "ground-light").ToScenarioUnit(AerosolType.InertGas, 1, 0, 0, 50), }); s.SaveCloudDispersal(t.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 500 }); s.UpdateStep(t.Id, 5); @@ -89,15 +89,15 @@ namespace CounterDrone.Core { var t = s.CreateScenario("[Demo] 喷气式拦截-活性材料", ""); s.SaveScene(t.Id, d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); - s.SaveDroneProfile(t.Id, d.Drones.First(p => p.Id == "cruise-missile").ToDroneProfile()); + s.SaveScenarioDrone(t.Id, d.Drones.First(p => p.Id == "cruise-missile").ToScenarioDrone()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), new List { new() { PosX = 18000, PosY = 500, PosZ = 0, Speed = 200 }, new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, }); - s.SaveDeployment(t.Id, new List + s.SaveDeployment(t.Id, new List { - d.FireUnits.First(f => f.Id == "ground-standard").ToEquipmentDeployment(AerosolType.ActiveMaterial, 1, 0, 0, 50), + d.FireUnits.First(f => f.Id == "ground-standard").ToScenarioUnit(AerosolType.ActiveMaterial, 1, 0, 0, 50), }); s.SaveCloudDispersal(t.Id, new CloudDispersal { AerosolType = (int)AerosolType.ActiveMaterial, DisperseHeight = 500 }); s.UpdateStep(t.Id, 5); @@ -110,15 +110,15 @@ namespace CounterDrone.Core scene.WindSpeed = 5; scene.WindDirection = (int)WindDirection.E; s.SaveScene(t.Id, scene); - s.SaveDroneProfile(t.Id, d.Drones.First(p => p.Id == "shahed").ToDroneProfile()); + s.SaveScenarioDrone(t.Id, d.Drones.First(p => p.Id == "shahed").ToScenarioDrone()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), new List { new() { PosX = 9500, PosY = 500, PosZ = 0, Speed = 200 }, new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, }); - s.SaveDeployment(t.Id, new List + s.SaveDeployment(t.Id, new List { - d.FireUnits.First(f => f.Id == "air-standard").ToEquipmentDeployment(AerosolType.InertGas, 3, 5000, 1000, 0), + d.FireUnits.First(f => f.Id == "air-standard").ToScenarioUnit(AerosolType.InertGas, 3, 5000, 1000, 0), }); s.SaveCloudDispersal(t.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 500 }); s.UpdateStep(t.Id, 5); @@ -131,19 +131,19 @@ namespace CounterDrone.Core scene.WindSpeed = 5; scene.WindDirection = (int)WindDirection.E; s.SaveScene(t.Id, scene); - var target = d.Drones.First(p => p.Id == "shahed").ToDroneProfile(); + var target = d.Drones.First(p => p.Id == "shahed").ToScenarioDrone(); target.Quantity = 3; - s.SaveDroneProfile(t.Id, target); + s.SaveScenarioDrone(t.Id, target); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "line-3").ToRoutePlan(), new List { new() { PosX = 10000, PosY = 500, PosZ = 0, Speed = 200 }, new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, }); - s.SaveDeployment(t.Id, new List + s.SaveDeployment(t.Id, new List { - d.FireUnits.First(f => f.Id == "air-standard").ToEquipmentDeployment(AerosolType.InertGas, 1, 5000, 1000, 0), - d.FireUnits.First(f => f.Id == "air-standard").ToEquipmentDeployment(AerosolType.InertGas, 1, 5300, 1000, 0), - d.FireUnits.First(f => f.Id == "air-standard").ToEquipmentDeployment(AerosolType.InertGas, 1, 5600, 1000, 0), + d.FireUnits.First(f => f.Id == "air-standard").ToScenarioUnit(AerosolType.InertGas, 1, 5000, 1000, 0), + d.FireUnits.First(f => f.Id == "air-standard").ToScenarioUnit(AerosolType.InertGas, 1, 5300, 1000, 0), + d.FireUnits.First(f => f.Id == "air-standard").ToScenarioUnit(AerosolType.InertGas, 1, 5600, 1000, 0), }); s.SaveCloudDispersal(t.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 500 }); s.UpdateStep(t.Id, 5); diff --git a/src/CounterDrone.Core/Models/ScenarioConfig.cs b/src/CounterDrone.Core/Models/ScenarioConfig.cs index a7e9200..5d408bb 100644 --- a/src/CounterDrone.Core/Models/ScenarioConfig.cs +++ b/src/CounterDrone.Core/Models/ScenarioConfig.cs @@ -8,8 +8,8 @@ namespace CounterDrone.Core.Models public Scenario Info { get; set; } = new(); public CombatScene Scene { get; set; } = new(); public List ControlZones { get; set; } = new(); - public List Drones { get; set; } = new(); - public List Equipment { get; set; } = new(); + public List Drones { get; set; } = new(); + public List Units { get; set; } = new(); public CloudDispersal Cloud { get; set; } = new(); /// 多批次航路(多批次支持) public List Routes { get; set; } = new(); diff --git a/src/CounterDrone.Core/Models/DroneProfile.cs b/src/CounterDrone.Core/Models/ScenarioDrone.cs similarity index 94% rename from src/CounterDrone.Core/Models/DroneProfile.cs rename to src/CounterDrone.Core/Models/ScenarioDrone.cs index 8e4fdfc..ff82294 100644 --- a/src/CounterDrone.Core/Models/DroneProfile.cs +++ b/src/CounterDrone.Core/Models/ScenarioDrone.cs @@ -4,8 +4,8 @@ using SQLite; namespace CounterDrone.Core.Models { /// 步骤2:目标配置 - [Table("DroneProfile")] - public class DroneProfile + [Table("ScenarioDrone")] + public class ScenarioDrone { [PrimaryKey] public string Id { get; set; } = Guid.NewGuid().ToString(); diff --git a/src/CounterDrone.Core/Models/EquipmentDeployment.cs b/src/CounterDrone.Core/Models/ScenarioUnit.cs similarity index 97% rename from src/CounterDrone.Core/Models/EquipmentDeployment.cs rename to src/CounterDrone.Core/Models/ScenarioUnit.cs index 50a1ec6..50230b2 100644 --- a/src/CounterDrone.Core/Models/EquipmentDeployment.cs +++ b/src/CounterDrone.Core/Models/ScenarioUnit.cs @@ -4,8 +4,8 @@ using SQLite; namespace CounterDrone.Core.Models { /// 步骤3:装备部署 - [Table("EquipmentDeployment")] - public class EquipmentDeployment + [Table("ScenarioUnit")] + public class ScenarioUnit { [PrimaryKey] public string Id { get; set; } = Guid.NewGuid().ToString(); diff --git a/src/CounterDrone.Core/Repository/DroneProfileRepository.cs b/src/CounterDrone.Core/Repository/ScenarioDroneRepository.cs similarity index 54% rename from src/CounterDrone.Core/Repository/DroneProfileRepository.cs rename to src/CounterDrone.Core/Repository/ScenarioDroneRepository.cs index 5ba539b..eb80f09 100644 --- a/src/CounterDrone.Core/Repository/DroneProfileRepository.cs +++ b/src/CounterDrone.Core/Repository/ScenarioDroneRepository.cs @@ -5,13 +5,13 @@ using SQLite; namespace CounterDrone.Core.Repository { - public class DroneProfileRepository : BaseRepository + public class ScenarioDroneRepository : BaseRepository { - public DroneProfileRepository(SQLiteConnection db) : base(db) { } + public ScenarioDroneRepository(SQLiteConnection db) : base(db) { } - public List GetByScenarioId(string scenarioId) + public List GetByScenarioId(string scenarioId) { - return Db.Table().Where(t => t.ScenarioId == scenarioId).ToList(); + return Db.Table().Where(t => t.ScenarioId == scenarioId).ToList(); } public void DeleteByScenarioId(string scenarioId) diff --git a/src/CounterDrone.Core/Repository/EquipmentDeploymentRepository.cs b/src/CounterDrone.Core/Repository/ScenarioUnitRepository.cs similarity index 55% rename from src/CounterDrone.Core/Repository/EquipmentDeploymentRepository.cs rename to src/CounterDrone.Core/Repository/ScenarioUnitRepository.cs index 4500f27..08a4556 100644 --- a/src/CounterDrone.Core/Repository/EquipmentDeploymentRepository.cs +++ b/src/CounterDrone.Core/Repository/ScenarioUnitRepository.cs @@ -5,19 +5,19 @@ using SQLite; namespace CounterDrone.Core.Repository { - public class EquipmentDeploymentRepository : BaseRepository + public class ScenarioUnitRepository : BaseRepository { - public EquipmentDeploymentRepository(SQLiteConnection db) : base(db) { } + public ScenarioUnitRepository(SQLiteConnection db) : base(db) { } - public List GetByScenarioId(string scenarioId) + public List GetByScenarioId(string scenarioId) { - return Db.Table().Where(e => e.ScenarioId == scenarioId).ToList(); + return Db.Table().Where(e => e.ScenarioId == scenarioId).ToList(); } /// 按任务和角色查询装备(EquipmentRole: 0=Detection, 1=LaunchPlatform) - public List GetByScenarioIdAndRole(string scenarioId, int equipmentRole) + public List GetByScenarioIdAndRole(string scenarioId, int equipmentRole) { - return Db.Table() + return Db.Table() .Where(e => e.ScenarioId == scenarioId && e.EquipmentRole == equipmentRole) .ToList(); } diff --git a/src/CounterDrone.Core/Services/IScenarioService.cs b/src/CounterDrone.Core/Services/IScenarioService.cs index 743f871..de605cd 100644 --- a/src/CounterDrone.Core/Services/IScenarioService.cs +++ b/src/CounterDrone.Core/Services/IScenarioService.cs @@ -13,15 +13,15 @@ namespace CounterDrone.Core.Services void SaveScene(string scenarioId, CombatScene scene); void SaveControlZones(string scenarioId, List zones); - void SaveDroneProfile(string scenarioId, DroneProfile target); - void SaveDeployment(string scenarioId, List equips); + void SaveScenarioDrone(string scenarioId, ScenarioDrone target); + void SaveDeployment(string scenarioId, List equips); /// 添加单个探测设备(独立于 SaveDeployment,不覆盖火力单元) - void AddDetection(string scenarioId, EquipmentDeployment detection); + void AddDetection(string scenarioId, ScenarioUnit detection); /// 删除探测设备 void DeleteDetection(string detectionId); /// 获取任务的所有探测设备(EquipmentRole.Detection) - List GetDetections(string scenarioId); + List GetDetections(string scenarioId); void SaveCloudDispersal(string scenarioId, CloudDispersal cloud); void SaveRoute(string scenarioId, string waveId, RoutePlan route, List waypoints); diff --git a/src/CounterDrone.Core/Services/ReportGenerator.cs b/src/CounterDrone.Core/Services/ReportGenerator.cs index 926d227..096c5a9 100644 --- a/src/CounterDrone.Core/Services/ReportGenerator.cs +++ b/src/CounterDrone.Core/Services/ReportGenerator.cs @@ -13,7 +13,7 @@ namespace CounterDrone.Core.Services Simulation.DroneStatus finalDroneStatus, float simulationDuration) { var sb = new StringBuilder(); - var platforms = config.Equipment.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform).ToList(); + var platforms = config.Units.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform).ToList(); var target = config.Drones.FirstOrDefault(); var scene = config.Scene; var destroyed = events.Count(e => e.Type == SimEventType.DroneDestroyed); @@ -106,9 +106,9 @@ namespace CounterDrone.Core.Services var platToEquip = new Dictionary(); var unitLaunchCounts = new Dictionary(); int platIdx = 1, unitNum = 0; - for (int ei = 0; ei < config.Equipment.Count; ei++) + for (int ei = 0; ei < config.Units.Count; ei++) { - var eq = config.Equipment[ei]; + var eq = config.Units[ei]; if (eq.EquipmentRole != (int)EquipmentRole.LaunchPlatform) continue; int channels = (eq.GunCount ?? 1) * (eq.ChannelsPerGun ?? 1); for (int j = 0; j < eq.Quantity; j++) @@ -132,7 +132,7 @@ namespace CounterDrone.Core.Services sb.AppendLine($"| # | 平台类型 | 位置 (X,Y,Z) | 弹药类型 | 挂载量 | 发射数 |"); sb.AppendLine($"|---|---------|-------------|---------|:------:|:------:|"); int unitNum2 = 0; - foreach (var eq in config.Equipment.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform)) + foreach (var eq in config.Units.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform)) { int channels = (eq.GunCount ?? 1) * (eq.ChannelsPerGun ?? 1); for (int j = 0; j < eq.Quantity; j++) @@ -146,7 +146,7 @@ namespace CounterDrone.Core.Services } sb.AppendLine(); // 探测设备 - var detections = config.Equipment.Where(e => e.EquipmentRole == (int)EquipmentRole.Detection).ToList(); + var detections = config.Units.Where(e => e.EquipmentRole == (int)EquipmentRole.Detection).ToList(); if (detections.Count > 0) { sb.AppendLine($"### 探测设备"); diff --git a/src/CounterDrone.Core/Services/ReportService.cs b/src/CounterDrone.Core/Services/ReportService.cs index d45f199..3b161c5 100644 --- a/src/CounterDrone.Core/Services/ReportService.cs +++ b/src/CounterDrone.Core/Services/ReportService.cs @@ -36,7 +36,7 @@ namespace CounterDrone.Core.Services ScenarioNumber = config.Info.ScenarioNumber, CompletedAt = DateTime.UtcNow.ToString("o"), TargetCount = total, - EquipmentCount = config.Equipment.Count, + EquipmentCount = config.Units.Count, InterceptResult = (int)result, Content = _generator.Generate(config, events, Simulation.DroneStatus.Flying, duration), }; diff --git a/src/CounterDrone.Core/Services/ScenarioService.cs b/src/CounterDrone.Core/Services/ScenarioService.cs index 7a759ab..d04dea2 100644 --- a/src/CounterDrone.Core/Services/ScenarioService.cs +++ b/src/CounterDrone.Core/Services/ScenarioService.cs @@ -12,8 +12,8 @@ namespace CounterDrone.Core.Services private readonly ScenarioRepository _scenarioRepo; private readonly CombatSceneRepository _sceneRepo; private readonly ControlZoneRepository _zoneRepo; - private readonly DroneProfileRepository _targetRepo; - private readonly EquipmentDeploymentRepository _equipRepo; + private readonly ScenarioDroneRepository _droneRepo; + private readonly ScenarioUnitRepository _unitRepo; private readonly CloudDispersalRepository _cloudRepo; private readonly RoutePlanRepository _routeRepo; private readonly WaypointRepository _waypointRepo; @@ -22,8 +22,8 @@ namespace CounterDrone.Core.Services ScenarioRepository scenarioRepo, CombatSceneRepository sceneRepo, ControlZoneRepository zoneRepo, - DroneProfileRepository targetRepo, - EquipmentDeploymentRepository equipRepo, + ScenarioDroneRepository targetRepo, + ScenarioUnitRepository equipRepo, CloudDispersalRepository cloudRepo, RoutePlanRepository routeRepo, WaypointRepository waypointRepo) @@ -31,8 +31,8 @@ namespace CounterDrone.Core.Services _scenarioRepo = scenarioRepo; _sceneRepo = sceneRepo; _zoneRepo = zoneRepo; - _targetRepo = targetRepo; - _equipRepo = equipRepo; + _droneRepo = targetRepo; + _unitRepo = equipRepo; _cloudRepo = cloudRepo; _routeRepo = routeRepo; _waypointRepo = waypointRepo; @@ -96,8 +96,8 @@ namespace CounterDrone.Core.Services Info = scenario, Scene = _sceneRepo.GetById(id) ?? new CombatScene { ScenarioId = id }, ControlZones = _zoneRepo.GetByScenarioId(id), - Drones = _targetRepo.GetByScenarioId(id), - Equipment = _equipRepo.GetByScenarioId(id), + Drones = _droneRepo.GetByScenarioId(id), + Units = _unitRepo.GetByScenarioId(id), Cloud = _cloudRepo.GetById(id) ?? new CloudDispersal { ScenarioId = id }, Routes = _routeRepo.GetByScenarioId(id), WaypointGroups = _waypointRepo.GetByScenarioId(id) @@ -131,51 +131,51 @@ namespace CounterDrone.Core.Services TouchScenario(scenarioId); } - public void SaveDroneProfile(string scenarioId, DroneProfile target) + public void SaveScenarioDrone(string scenarioId, ScenarioDrone target) { target.ScenarioId = scenarioId; if (string.IsNullOrEmpty(target.Id)) target.Id = Guid.NewGuid().ToString(); - var existing = _targetRepo.GetById(target.Id); + var existing = _droneRepo.GetById(target.Id); if (existing != null) - _targetRepo.Update(target); + _droneRepo.Update(target); else - _targetRepo.Insert(target); + _droneRepo.Insert(target); TouchScenario(scenarioId); } - public void SaveDeployment(string scenarioId, List equips) + public void SaveDeployment(string scenarioId, List equips) { - _equipRepo.DeleteByScenarioId(scenarioId); + _unitRepo.DeleteByScenarioId(scenarioId); foreach (var e in equips) { e.ScenarioId = scenarioId; if (string.IsNullOrEmpty(e.Id)) e.Id = Guid.NewGuid().ToString(); } - _equipRepo.InsertAll(equips); + _unitRepo.InsertAll(equips); TouchScenario(scenarioId); } - public void AddDetection(string scenarioId, EquipmentDeployment detection) + public void AddDetection(string scenarioId, ScenarioUnit detection) { detection.ScenarioId = scenarioId; detection.EquipmentRole = (int)EquipmentRole.Detection; if (string.IsNullOrEmpty(detection.Id)) detection.Id = Guid.NewGuid().ToString(); - _equipRepo.Insert(detection); + _unitRepo.Insert(detection); TouchScenario(scenarioId); } public void DeleteDetection(string detectionId) { - _equipRepo.Delete(detectionId); + _unitRepo.Delete(detectionId); } - public List GetDetections(string scenarioId) + public List GetDetections(string scenarioId) { - return _equipRepo.GetByScenarioIdAndRole(scenarioId, (int)EquipmentRole.Detection); + return _unitRepo.GetByScenarioIdAndRole(scenarioId, (int)EquipmentRole.Detection); } public void SaveCloudDispersal(string scenarioId, CloudDispersal cloud) diff --git a/src/CounterDrone.Core/Simulation/DroneEntity.cs b/src/CounterDrone.Core/Simulation/DroneEntity.cs index cfee381..d386430 100644 --- a/src/CounterDrone.Core/Simulation/DroneEntity.cs +++ b/src/CounterDrone.Core/Simulation/DroneEntity.cs @@ -38,7 +38,7 @@ namespace CounterDrone.Core.Simulation /// 查找弧长 s 所在段:最大的 i 使 _cumArc[i] >= s。 private readonly float[] _cumArc; - public DroneEntity(string id, string waveId, DroneProfile config, List route, + public DroneEntity(string id, string waveId, ScenarioDrone config, List route, int formationIndex, float lateralSpacing, int longitudinalIndex, float longitudinalSpacing, FormationMode mode, int lateralAxis = 2, int longitudinalAxis = 0) { diff --git a/src/CounterDrone.Core/Simulation/PlatformEntity.cs b/src/CounterDrone.Core/Simulation/PlatformEntity.cs index f9e1b2c..85d3c04 100644 --- a/src/CounterDrone.Core/Simulation/PlatformEntity.cs +++ b/src/CounterDrone.Core/Simulation/PlatformEntity.cs @@ -46,7 +46,7 @@ namespace CounterDrone.Core.Simulation /// Ready 包含:冷却就绪 + 有弹药 + 非飞行中 public bool Ready => CooldownRemaining <= 0 && MunitionCount > 0 && State != PlatformState.FlyingToTarget; - public PlatformEntity(string id, EquipmentDeployment config) + public PlatformEntity(string id, ScenarioUnit config) { Id = id; Role = (EquipmentRole)config.EquipmentRole; diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index 4e539be..b1af7b0 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -127,7 +127,7 @@ namespace CounterDrone.Core.Simulation _entityCounter = 0; _platforms.Clear(); - foreach (var equip in config.Equipment) + foreach (var equip in config.Units) if (equip.EquipmentRole != (int)EquipmentRole.Detection) for (int i = 0; i < equip.Quantity; i++) { @@ -430,7 +430,7 @@ namespace CounterDrone.Core.Simulation private static List BuildFireUnits(ScenarioConfig config) { var units = new List(); - foreach (var eq in config.Equipment.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform)) + foreach (var eq in config.Units.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform)) { int qty = Math.Max(1, eq.Quantity); int gunCount = eq.GunCount ?? 1; @@ -467,7 +467,7 @@ namespace CounterDrone.Core.Simulation private static List BuildDetectionSources(ScenarioConfig config) { var sources = new List(); - foreach (var eq in config.Equipment) + foreach (var eq in config.Units) { // 只要有任何探测字段非 null 且 > 0,就是有效探测源(无论是否独立探测设备) bool hasDetection = (eq.RadarRange ?? 0) > 0 || (eq.EORange ?? 0) > 0 || (eq.IRRange ?? 0) > 0; diff --git a/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll b/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll index f469d2a..b84f695 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 a2f7fe3..2be6f64 100644 --- a/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs +++ b/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs @@ -33,7 +33,7 @@ namespace CounterDrone.Unity Debug.Log($"2. ScenarioManager OK. scenario: {scenarioId}"); scenarioMgr.SaveScene(scenarioId, new CombatScene { WindSpeed = 0 }); - scenarioMgr.SaveDroneProfile(scenarioId, new DroneProfile + scenarioMgr.SaveScenarioDrone(scenarioId, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, PowerType = (int)PowerType.Piston, @@ -80,9 +80,9 @@ namespace CounterDrone.Unity DisperseHeight = droneGroup.Profile.TypicalAltitude, }); - var equips = new List(); + var equips = new List(); foreach (var u in fireUnits) - equips.Add(new EquipmentDeployment + equips.Add(new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, PlatformType = (int)u.Type, Quantity = 1, diff --git a/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs b/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs index 4835d16..c19eeb4 100644 --- a/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs +++ b/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs @@ -27,8 +27,8 @@ namespace CounterDrone.Unity SqliteConnectionTracker.Track(_db); _service = new ScenarioService( new ScenarioRepository(_db), new CombatSceneRepository(_db), - new ControlZoneRepository(_db), new DroneProfileRepository(_db), - new EquipmentDeploymentRepository(_db), new CloudDispersalRepository(_db), + new ControlZoneRepository(_db), new ScenarioDroneRepository(_db), + new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db), new RoutePlanRepository(_db), new WaypointRepository(_db)); _dataService = new DataService( new AmmunitionSpecRepository(_db), new FireUnitSpecRepository(_db), @@ -52,8 +52,8 @@ namespace CounterDrone.Unity => _service.SearchScenarios(kw, from, to, page, size); public void SaveScene(string scenarioId, CombatScene s) => _service.SaveScene(scenarioId, s); - public void SaveDroneProfile(string scenarioId, DroneProfile t) => _service.SaveDroneProfile(scenarioId, t); - public void SaveDeployment(string scenarioId, List e) => _service.SaveDeployment(scenarioId, e); + public void SaveScenarioDrone(string scenarioId, ScenarioDrone t) => _service.SaveScenarioDrone(scenarioId, t); + public void SaveDeployment(string scenarioId, List e) => _service.SaveDeployment(scenarioId, e); public void SaveCloud(string scenarioId, CloudDispersal c) => _service.SaveCloudDispersal(scenarioId, c); public void SaveRoute(string scenarioId, string waveId, RoutePlan r, List w) => _service.SaveRoute(scenarioId, waveId, r, w); public void UpdateStep(string scenarioId, int step) => _service.UpdateStep(scenarioId, step); diff --git a/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs b/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs index e57fe95..a8ee2e2 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs @@ -43,8 +43,8 @@ namespace CounterDrone.Unity var scenario = new ScenarioService( new ScenarioRepository(db), new CombatSceneRepository(db), - new ControlZoneRepository(db), new DroneProfileRepository(db), - new EquipmentDeploymentRepository(db), new CloudDispersalRepository(db), + new ControlZoneRepository(db), new ScenarioDroneRepository(db), + new ScenarioUnitRepository(db), new CloudDispersalRepository(db), new RoutePlanRepository(db), new WaypointRepository(db)); string scenarioId; @@ -70,7 +70,7 @@ namespace CounterDrone.Unity scenarioId = sc.Id; scenario.SaveScene(scenarioId, defaults.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); - scenario.SaveDroneProfile(scenarioId, defaults.Drones.First(p => p.Id == "shahed").ToDroneProfile()); + scenario.SaveScenarioDrone(scenarioId, defaults.Drones.First(p => p.Id == "shahed").ToScenarioDrone()); scenario.SaveRoute(scenarioId, "default", defaults.Formations.First(f => f.Id == "single").ToRoutePlan(), defaults.Routes.First(r => _routeLength > 6000 ? r.Id == "10km-h500" : r.Id == "5km-h500") @@ -102,10 +102,10 @@ namespace CounterDrone.Unity DisperseHeight = detail.Drones[0].TypicalAltitude, Source = "Algorithm", }); - scenario.SaveDeployment(scenarioId, new List + scenario.SaveDeployment(scenarioId, new List { defaults.FireUnits.First(f => f.Id == "ground-light") - .ToEquipmentDeployment(AerosolType.InertGas, 1, _routeLength / 2f, 0, 50), + .ToScenarioUnit(AerosolType.InertGas, 1, _routeLength / 2f, 0, 50), }); scenario.UpdateStep(scenarioId, 5); diff --git a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs index 0991bc1..2422b81 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs @@ -44,8 +44,8 @@ namespace CounterDrone.Unity _scenario = new ScenarioService( new ScenarioRepository(_db), new CombatSceneRepository(_db), - new ControlZoneRepository(_db), new DroneProfileRepository(_db), - new EquipmentDeploymentRepository(_db), new CloudDispersalRepository(_db), + new ControlZoneRepository(_db), new ScenarioDroneRepository(_db), + new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db), new RoutePlanRepository(_db), new WaypointRepository(_db)); _frameStore = new FrameDataStore(_paths); diff --git a/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs b/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs index 98f0210..2e06e47 100644 --- a/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs +++ b/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs @@ -35,7 +35,7 @@ namespace CounterDrone.Core.Tests var tables = new[] { "ModelInfo", "AmmunitionSpec", "Scenario", "CombatScene", - "ControlZone", "DroneProfile", "EquipmentDeployment", + "ControlZone", "ScenarioDrone", "ScenarioUnit", "CloudDispersal", "RoutePlan", "Waypoint", "SimulationReport" }; diff --git a/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs b/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs index 0be1670..f9e91b4 100644 --- a/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs +++ b/test/unit/CounterDrone.Core.Tests/DefensePlannerTests.cs @@ -43,7 +43,7 @@ namespace CounterDrone.Core.Tests var t = new DroneWave { WaveId = "default", - Profile = new DroneProfile + Profile = new ScenarioDrone { DroneType = (int)DroneType.FixedWing, PowerType = (int)power, Quantity = 1, TypicalSpeed = speed, TypicalAltitude = alt, @@ -378,7 +378,7 @@ namespace CounterDrone.Core.Tests var threat = new DroneWave { WaveId = "default", - Profile = new DroneProfile + Profile = new ScenarioDrone { DroneType = (int)DroneType.FixedWing, PowerType = (int)PowerType.Piston, Quantity = 1, TypicalSpeed = 200, TypicalAltitude = 500, diff --git a/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs b/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs index 2329c13..c7748f4 100644 --- a/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs +++ b/test/unit/CounterDrone.Core.Tests/DroneEntityTests.cs @@ -8,9 +8,9 @@ namespace CounterDrone.Core.Tests { public class DroneEntityTests { - private DroneProfile CreateConfig(float speed = 120, float altitude = 300) + private ScenarioDrone CreateConfig(float speed = 120, float altitude = 300) { - return new DroneProfile + return new ScenarioDrone { DroneType = (int)DroneType.FixedWing, PowerType = (int)PowerType.Piston, diff --git a/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs b/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs index f20202f..c68f686 100644 --- a/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs +++ b/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs @@ -28,8 +28,8 @@ namespace CounterDrone.Core.Tests _scenario = new ScenarioService( new ScenarioRepository(_db), new CombatSceneRepository(_db), - new ControlZoneRepository(_db), new DroneProfileRepository(_db), - new EquipmentDeploymentRepository(_db), new CloudDispersalRepository(_db), + new ControlZoneRepository(_db), new ScenarioDroneRepository(_db), + new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db), new RoutePlanRepository(_db), new WaypointRepository(_db)); } @@ -46,7 +46,7 @@ namespace CounterDrone.Core.Tests _scenarioId = scenario.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 }); - _scenario.SaveDroneProfile(_scenarioId, new DroneProfile + _scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, @@ -54,7 +54,7 @@ namespace CounterDrone.Core.Tests TypicalSpeed = 100, TypicalAltitude = 300, }); - _scenario.SaveDeployment(_scenarioId, new List()); + _scenario.SaveDeployment(_scenarioId, new List()); _scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal()); _scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single }, new List @@ -89,14 +89,14 @@ namespace CounterDrone.Core.Tests WindSpeed = 30, // 最大风速 WindDirection = (int)WindDirection.E, }); - _scenario.SaveDroneProfile(_scenarioId, new DroneProfile + _scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, Quantity = 1, TypicalSpeed = 600, // 高速对抗强风 }); - _scenario.SaveDeployment(_scenarioId, new List()); + _scenario.SaveDeployment(_scenarioId, new List()); _scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal()); _scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single }, new List @@ -128,14 +128,14 @@ namespace CounterDrone.Core.Tests _scenarioId = scenario.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 }); - _scenario.SaveDroneProfile(_scenarioId, new DroneProfile + _scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.HighSpeed, Quantity = 1, TypicalSpeed = 500, }); - _scenario.SaveDeployment(_scenarioId, new List()); + _scenario.SaveDeployment(_scenarioId, new List()); _scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal()); // 500 km/h, 100km 航程 diff --git a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs index fe72add..17f80b0 100644 --- a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs +++ b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs @@ -33,8 +33,8 @@ namespace CounterDrone.Core.Tests _scenario = new ScenarioService( new ScenarioRepository(_mainDb), new CombatSceneRepository(_mainDb), - new ControlZoneRepository(_mainDb), new DroneProfileRepository(_mainDb), - new EquipmentDeploymentRepository(_mainDb), new CloudDispersalRepository(_mainDb), + new ControlZoneRepository(_mainDb), new ScenarioDroneRepository(_mainDb), + new ScenarioUnitRepository(_mainDb), new CloudDispersalRepository(_mainDb), new RoutePlanRepository(_mainDb), new WaypointRepository(_mainDb)); _frameStore = new FrameDataStore(_paths); @@ -185,7 +185,7 @@ namespace CounterDrone.Core.Tests var scenarioA = _scenario.CreateScenario("无探测远航路", ""); _scenarioId = scenarioA.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0, Visibility = 10000 }); - _scenario.SaveDroneProfile(_scenarioId, new DroneProfile + _scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, PowerType = (int)PowerType.Piston, Quantity = 1, TypicalSpeed = 200, TypicalAltitude = 500, @@ -196,9 +196,9 @@ namespace CounterDrone.Core.Tests new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, new Waypoint { PosX = 20000, PosY = 500, PosZ = 0, Speed = 200 }, }); - _scenario.SaveDeployment(_scenarioId, new List + _scenario.SaveDeployment(_scenarioId, new List { - TestData.All.FireUnits.First(f => f.Id == "ground-light").ToEquipmentDeployment(AerosolType.InertGas, 1, 8000, 0, 50), + TestData.All.FireUnits.First(f => f.Id == "ground-light").ToScenarioUnit(AerosolType.InertGas, 1, 8000, 0, 50), }); _scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 500 }); var engA = RunSimulation(8000); @@ -210,7 +210,7 @@ namespace CounterDrone.Core.Tests var scenarioB = _scenario.CreateScenario("有探测远航路", ""); _scenarioId = scenarioB.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0, Visibility = 10000 }); - _scenario.SaveDroneProfile(_scenarioId, new DroneProfile + _scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, PowerType = (int)PowerType.Piston, Quantity = 1, TypicalSpeed = 200, TypicalAltitude = 500, @@ -221,11 +221,11 @@ namespace CounterDrone.Core.Tests new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, new Waypoint { PosX = 20000, PosY = 500, PosZ = 0, Speed = 200 }, }); - _scenario.SaveDeployment(_scenarioId, new List + _scenario.SaveDeployment(_scenarioId, new List { - TestData.All.FireUnits.First(f => f.Id == "ground-light").ToEquipmentDeployment(AerosolType.InertGas, 1, 8000, 0, 50), + TestData.All.FireUnits.First(f => f.Id == "ground-light").ToScenarioUnit(AerosolType.InertGas, 1, 8000, 0, 50), // 独立探测设备 - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1, diff --git a/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs b/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs index b227b6b..0bbaa45 100644 --- a/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs +++ b/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs @@ -36,11 +36,11 @@ namespace CounterDrone.Core.Tests var config = new ScenarioConfig { Info = new Scenario { Name = "测试任务", ScenarioNumber = "SIM-001" }, - Drones = new List { new DroneProfile { Quantity = 1 } }, - Equipment = new List + Drones = new List { new ScenarioDrone { Quantity = 1 } }, + Units = new List { - new EquipmentDeployment { EquipmentRole = (int)EquipmentRole.LaunchPlatform, Quantity = 3 }, - new EquipmentDeployment { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1 }, + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, Quantity = 3 }, + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1 }, }, Cloud = new CloudDispersal { AerosolType = (int)AerosolType.InertGas }, }; diff --git a/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs b/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs index bc48058..9287be3 100644 --- a/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs +++ b/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs @@ -37,8 +37,8 @@ namespace CounterDrone.Core.Tests var config = new ScenarioConfig { Info = new Scenario { Name = "Test", ScenarioNumber = "SIM-001" }, - Drones = new List { new DroneProfile { Quantity = 1 } }, - Equipment = new List(), + Drones = new List { new ScenarioDrone { Quantity = 1 } }, + Units = new List(), Cloud = new CloudDispersal(), }; @@ -59,8 +59,8 @@ namespace CounterDrone.Core.Tests var config = new ScenarioConfig { Info = new Scenario { Name = "Del", ScenarioNumber = "SIM-DEL" }, - Drones = new List { new DroneProfile { Quantity = 1 } }, - Equipment = new List(), + Drones = new List { new ScenarioDrone { Quantity = 1 } }, + Units = new List(), Cloud = new CloudDispersal(), }; @@ -75,8 +75,8 @@ namespace CounterDrone.Core.Tests var cfg = new ScenarioConfig { Info = new Scenario { Name = "城市防御", ScenarioNumber = "SIM-A" }, - Drones = new List { new DroneProfile { Quantity = 1 } }, - Equipment = new List(), + Drones = new List { new ScenarioDrone { Quantity = 1 } }, + Units = new List(), Cloud = new CloudDispersal(), }; diff --git a/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs b/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs index b5f01a9..7cc6e15 100644 --- a/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs +++ b/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs @@ -22,12 +22,12 @@ namespace CounterDrone.Core.Tests public void Dispose() { _db?.Close(); if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true); } [Fact] - public void DroneProfile_DeleteByScenarioId_RemovesAll() + public void ScenarioDrone_DeleteByScenarioId_RemovesAll() { - var repo = new DroneProfileRepository(_db); - repo.Insert(new DroneProfile { Id = "t1", ScenarioId = "scenarioA", Quantity = 1 }); - repo.Insert(new DroneProfile { Id = "t2", ScenarioId = "scenarioA", Quantity = 2 }); - repo.Insert(new DroneProfile { Id = "t3", ScenarioId = "scenarioB", Quantity = 1 }); + var repo = new ScenarioDroneRepository(_db); + repo.Insert(new ScenarioDrone { Id = "t1", ScenarioId = "scenarioA", Quantity = 1 }); + repo.Insert(new ScenarioDrone { Id = "t2", ScenarioId = "scenarioA", Quantity = 2 }); + repo.Insert(new ScenarioDrone { Id = "t3", ScenarioId = "scenarioB", Quantity = 1 }); repo.DeleteByScenarioId("scenarioA"); @@ -50,11 +50,11 @@ namespace CounterDrone.Core.Tests } [Fact] - public void EquipmentDeployment_DeleteByScenarioId_Works() + public void ScenarioUnit_DeleteByScenarioId_Works() { - var repo = new EquipmentDeploymentRepository(_db); - repo.Insert(new EquipmentDeployment { Id = "e1", ScenarioId = "eqA" }); - repo.Insert(new EquipmentDeployment { Id = "e2", ScenarioId = "eqA" }); + var repo = new ScenarioUnitRepository(_db); + repo.Insert(new ScenarioUnit { Id = "e1", ScenarioId = "eqA" }); + repo.Insert(new ScenarioUnit { Id = "e2", ScenarioId = "eqA" }); repo.DeleteByScenarioId("eqA"); Assert.Empty(repo.GetByScenarioId("eqA")); diff --git a/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs b/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs index 71faada..731ca3a 100644 --- a/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs +++ b/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs @@ -27,8 +27,8 @@ namespace CounterDrone.Core.Tests new ScenarioRepository(_db), new CombatSceneRepository(_db), new ControlZoneRepository(_db), - new DroneProfileRepository(_db), - new EquipmentDeploymentRepository(_db), + new ScenarioDroneRepository(_db), + new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db), new RoutePlanRepository(_db), new WaypointRepository(_db)); @@ -101,7 +101,7 @@ namespace CounterDrone.Core.Tests Temperature = 25.0, }); - _service.SaveDroneProfile(scenario.Id, new DroneProfile + _service.SaveScenarioDrone(scenario.Id, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, @@ -196,10 +196,10 @@ namespace CounterDrone.Core.Tests } [Fact] - public void SaveDroneProfile_SavesCorrectly() + public void SaveScenarioDrone_SavesCorrectly() { var scenario = _service.CreateScenario("Drone Test", ""); - _service.SaveDroneProfile(scenario.Id, new DroneProfile + _service.SaveScenarioDrone(scenario.Id, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, @@ -221,9 +221,9 @@ namespace CounterDrone.Core.Tests public void SaveDeployment_SavesMultiple() { var scenario = _service.CreateScenario("Equip Test", ""); - var equips = new List + var equips = new List { - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, PlatformType = (int)PlatformType.GroundBased, @@ -232,7 +232,7 @@ namespace CounterDrone.Core.Tests MuzzleVelocity = 800.0, MunitionCount = 3, }, - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1, @@ -243,9 +243,9 @@ namespace CounterDrone.Core.Tests _service.SaveDeployment(scenario.Id, equips); var detail = _service.GetScenarioDetail(scenario.Id); - Assert.Equal(2, detail.Equipment.Count); + Assert.Equal(2, detail.Units.Count); - var platform = detail.Equipment.Find(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform); + var platform = detail.Units.Find(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform); Assert.NotNull(platform); Assert.Equal(2, platform.Quantity); Assert.Equal(800.0, platform.MuzzleVelocity); @@ -392,7 +392,7 @@ namespace CounterDrone.Core.Tests }); // 4. 步骤2:目标配置 - _service.SaveDroneProfile(scenario.Id, new DroneProfile + _service.SaveScenarioDrone(scenario.Id, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.HighSpeed, @@ -403,15 +403,15 @@ namespace CounterDrone.Core.Tests _service.UpdateStep(scenario.Id, 2); // 5. 步骤3:装备部署 - _service.SaveDeployment(scenario.Id, new List + _service.SaveDeployment(scenario.Id, new List { - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1, RadarRange = 6000.0, }, - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, PlatformType = (int)PlatformType.GroundBased, @@ -469,7 +469,7 @@ namespace CounterDrone.Core.Tests Assert.Equal(300.0, detail.Drones[0].TypicalSpeed); // 装备 - Assert.Equal(2, detail.Equipment.Count); + Assert.Equal(2, detail.Units.Count); // 云团 Assert.Equal((int)AerosolType.ActiveMaterial, detail.Cloud.AerosolType); @@ -493,7 +493,7 @@ namespace CounterDrone.Core.Tests public void AddDetection_PersistsAndQueryable() { var scenario = _service.CreateScenario("探测设备测试", ""); - _service.AddDetection(scenario.Id, new EquipmentDeployment + _service.AddDetection(scenario.Id, new ScenarioUnit { Quantity = 1, PositionX = 5000, PositionY = 0, PositionZ = 0, @@ -513,17 +513,17 @@ namespace CounterDrone.Core.Tests { var scenario = _service.CreateScenario("探测过滤测试", ""); // 一个火力单元 - _service.SaveDeployment(scenario.Id, new List + _service.SaveDeployment(scenario.Id, new List { - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, Quantity = 1, PositionX = 1000, }, }); // 两个探测设备(独立添加) - _service.AddDetection(scenario.Id, new EquipmentDeployment { RadarRange = 5000 }); - _service.AddDetection(scenario.Id, new EquipmentDeployment { EORange = 3000 }); + _service.AddDetection(scenario.Id, new ScenarioUnit { RadarRange = 5000 }); + _service.AddDetection(scenario.Id, new ScenarioUnit { EORange = 3000 }); var detections = _service.GetDetections(scenario.Id); Assert.Equal(2, detections.Count); // 只有探测设备,不含火力单元 @@ -533,8 +533,8 @@ namespace CounterDrone.Core.Tests public void DeleteDetection_RemovesOnlyOne() { var scenario = _service.CreateScenario("探测删除测试", ""); - _service.AddDetection(scenario.Id, new EquipmentDeployment { RadarRange = 5000 }); - var det2 = new EquipmentDeployment { EORange = 3000 }; + _service.AddDetection(scenario.Id, new ScenarioUnit { RadarRange = 5000 }); + var det2 = new ScenarioUnit { EORange = 3000 }; _service.AddDetection(scenario.Id, det2); _service.DeleteDetection(det2.Id); @@ -548,17 +548,17 @@ namespace CounterDrone.Core.Tests public void GetScenarioDetail_IncludesDetections() { var scenario = _service.CreateScenario("想定含探测", ""); - _service.SaveDeployment(scenario.Id, new List + _service.SaveDeployment(scenario.Id, new List { - new EquipmentDeployment { EquipmentRole = (int)EquipmentRole.LaunchPlatform, Quantity = 1 }, + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, Quantity = 1 }, }); - _service.AddDetection(scenario.Id, new EquipmentDeployment { RadarRange = 10000 }); + _service.AddDetection(scenario.Id, new ScenarioUnit { RadarRange = 10000 }); var detail = _service.GetScenarioDetail(scenario.Id); // Equipment 包含火力单元 + 探测设备 - Assert.Equal(2, detail.Equipment.Count); - Assert.Contains(detail.Equipment, e => e.EquipmentRole == (int)EquipmentRole.Detection); - Assert.Contains(detail.Equipment, e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform); + Assert.Equal(2, detail.Units.Count); + Assert.Contains(detail.Units, e => e.EquipmentRole == (int)EquipmentRole.Detection); + Assert.Contains(detail.Units, e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform); } } } diff --git a/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs b/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs index 871aa3a..6d4d543 100644 --- a/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs +++ b/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs @@ -30,8 +30,8 @@ namespace CounterDrone.Core.Tests _scenarioService = new ScenarioService( new ScenarioRepository(_mainDb), new CombatSceneRepository(_mainDb), - new ControlZoneRepository(_mainDb), new DroneProfileRepository(_mainDb), - new EquipmentDeploymentRepository(_mainDb), new CloudDispersalRepository(_mainDb), + new ControlZoneRepository(_mainDb), new ScenarioDroneRepository(_mainDb), + new ScenarioUnitRepository(_mainDb), new CloudDispersalRepository(_mainDb), new RoutePlanRepository(_mainDb), new WaypointRepository(_mainDb)); _engine = new SimulationEngine(_scenarioService, new FrameDataStore(paths), @@ -50,7 +50,7 @@ namespace CounterDrone.Core.Tests var scenario = _scenarioService.CreateScenario("Test", ""); _scenarioId = scenario.Id; _scenarioService.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 }); - _scenarioService.SaveDroneProfile(_scenarioId, new DroneProfile + _scenarioService.SaveScenarioDrone(_scenarioId, new ScenarioDrone { WaveId = "default", DroneType = (int)DroneType.FixedWing, @@ -58,9 +58,9 @@ namespace CounterDrone.Core.Tests PowerType = (int)PowerType.Piston, TypicalSpeed = 60, }); - _scenarioService.SaveDeployment(_scenarioId, new List + _scenarioService.SaveDeployment(_scenarioId, new List { - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, PlatformType = (int)PlatformType.GroundBased, @@ -151,7 +151,7 @@ namespace CounterDrone.Core.Tests var scenario = _scenarioService.CreateScenario("Detect", ""); _scenarioId = scenario.Id; _scenarioService.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0, Visibility = 10000 }); - _scenarioService.SaveDroneProfile(_scenarioId, new DroneProfile + _scenarioService.SaveScenarioDrone(_scenarioId, new ScenarioDrone { WaveId = "w1", DroneType = (int)DroneType.FixedWing, @@ -161,15 +161,15 @@ namespace CounterDrone.Core.Tests TypicalAltitude = 300, }); // 探测设备在 (5000, 0, 0),雷达 3000m,无角度/高度限制 - _scenarioService.SaveDeployment(_scenarioId, new List + _scenarioService.SaveDeployment(_scenarioId, new List { - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1, PositionX = 5000, PositionY = 0, PositionZ = 0, RadarRange = 3000, }, - new EquipmentDeployment + new ScenarioUnit { EquipmentRole = (int)EquipmentRole.LaunchPlatform, PlatformType = (int)PlatformType.GroundBased, @@ -224,11 +224,11 @@ namespace CounterDrone.Core.Tests // 探测设备在 X=5000 半径 1000 → 入口 X=4000,出口 X=6000 var scenario = _scenarioService.CreateScenario("Reenter", ""); _scenarioService.SaveScene(scenario.Id, new CombatScene { WindSpeed = 0, Visibility = 10000 }); - _scenarioService.SaveDroneProfile(scenario.Id, new DroneProfile + _scenarioService.SaveScenarioDrone(scenario.Id, new ScenarioDrone { WaveId = "w1", Quantity = 1, TypicalSpeed = 120, PowerType = (int)PowerType.Piston, TypicalAltitude = 300, }); - _scenarioService.SaveDeployment(scenario.Id, new List + _scenarioService.SaveDeployment(scenario.Id, new List { new() { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1, PositionX = 5000, PositionY = 0, PositionZ = 0, RadarRange = 1000 }, new() { EquipmentRole = (int)EquipmentRole.LaunchPlatform, PlatformType = (int)PlatformType.GroundBased, @@ -275,11 +275,11 @@ namespace CounterDrone.Core.Tests // D1 边界 X=1000,D2 边界 X=3000 → D1 更早发现 var scenario = _scenarioService.CreateScenario("Fuse", ""); _scenarioService.SaveScene(scenario.Id, new CombatScene { WindSpeed = 0, Visibility = 10000 }); - _scenarioService.SaveDroneProfile(scenario.Id, new DroneProfile + _scenarioService.SaveScenarioDrone(scenario.Id, new ScenarioDrone { WaveId = "w1", Quantity = 1, TypicalSpeed = 60, PowerType = (int)PowerType.Piston, TypicalAltitude = 300, }); - _scenarioService.SaveDeployment(scenario.Id, new List + _scenarioService.SaveDeployment(scenario.Id, new List { new() { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1, PositionX = 3000, PositionY = 0, PositionZ = 0, RadarRange = 2000, DetectionAccuracy = 50 }, new() { EquipmentRole = (int)EquipmentRole.Detection, Quantity = 1, PositionX = 7000, PositionY = 0, PositionZ = 0, RadarRange = 4000, DetectionAccuracy = 30 }, diff --git a/unity_plugins/CounterDrone.Core.dll b/unity_plugins/CounterDrone.Core.dll index f469d2a..b84f695 100644 Binary files a/unity_plugins/CounterDrone.Core.dll and b/unity_plugins/CounterDrone.Core.dll differ