DroneProfile→ScenarioDrone / EquipmentDeployment→ScenarioUnit 重命名
- 模型表: ScenarioDrone(原DroneProfile) / ScenarioUnit(原EquipmentDeployment) - ScenarioConfig.Equipment→Units - 数据库旧表清理 + scenariosVersion 4→5 - 238 测试全过
This commit is contained in:
parent
7413077514
commit
537671ab3a
16
CHANGELOG.md
16
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 项
|
||||
|
||||
@ -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<ControlZone> zones); // NEW
|
||||
void SaveDroneProfile(string scenarioId, DroneProfile target);
|
||||
void SaveDeployment(string scenarioId, List<EquipmentDeployment> equips); // 重构
|
||||
void SaveScenarioDrone(string scenarioId, ScenarioDrone target);
|
||||
void SaveDeployment(string scenarioId, List<ScenarioUnit> equips); // 重构
|
||||
void SaveCloudDispersal(string scenarioId, CloudDispersal cloud);
|
||||
void SaveRoute(string scenarioId, RoutePlan route, List<Waypoint> 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<DetectionEntity>`,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 行为,保证平滑过渡)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ class FireUnit {
|
||||
```csharp
|
||||
class DroneWave {
|
||||
string WaveId; // 批次 ID
|
||||
DroneProfile Profile; // 类型、数量、动力、翼展、速度、高度
|
||||
ScenarioDrone Profile; // 类型、数量、动力、翼展、速度、高度
|
||||
List<Waypoint> 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` 接口
|
||||
|
||||
---
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
## 数据流
|
||||
|
||||
```
|
||||
想定配置(EquipmentDeployment + DroneProfile + RoutePlan + CombatScene)
|
||||
想定配置(ScenarioUnit + ScenarioDrone + RoutePlan + CombatScene)
|
||||
│
|
||||
▼
|
||||
SimulationEngine.Initialize()
|
||||
|
||||
@ -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),保证存量数据平滑过渡 |
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<Waypoint> {
|
||||
new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
new() { PosX = 10000, PosY = 500, PosZ = 0, Speed = 200 }
|
||||
});
|
||||
scenario.SaveDeployment(sc.Id, new List<EquipmentDeployment> {
|
||||
scenario.SaveDeployment(sc.Id, new List<ScenarioUnit> {
|
||||
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 | 描述/用途 |
|
||||
|
||||
@ -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<Waypoint> Waypoints { get; set; } = new();
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<ModelInfo>();
|
||||
db.CreateTable<AmmunitionSpec>();
|
||||
db.CreateTable<Scenario>();
|
||||
db.CreateTable<CombatScene>();
|
||||
db.CreateTable<ControlZone>();
|
||||
db.CreateTable<DroneProfile>();
|
||||
db.CreateTable<EquipmentDeployment>();
|
||||
db.CreateTable<ScenarioDrone>();
|
||||
db.CreateTable<ScenarioUnit>();
|
||||
db.CreateTable<CloudDispersal>();
|
||||
db.CreateTable<RoutePlan>();
|
||||
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");
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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<EquipmentDeployment>());
|
||||
s.SaveDeployment(t.Id, new List<ScenarioUnit>());
|
||||
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<EquipmentDeployment>());
|
||||
s.SaveDeployment(t.Id, new List<ScenarioUnit>());
|
||||
s.SaveControlZones(t.Id, new List<ControlZone>
|
||||
{
|
||||
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<Waypoint> {
|
||||
new() { PosX = 6600, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
});
|
||||
s.SaveDeployment(t.Id, new List<EquipmentDeployment>
|
||||
s.SaveDeployment(t.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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<Waypoint> {
|
||||
new() { PosX = 18000, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
});
|
||||
s.SaveDeployment(t.Id, new List<EquipmentDeployment>
|
||||
s.SaveDeployment(t.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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<Waypoint> {
|
||||
new() { PosX = 9500, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
});
|
||||
s.SaveDeployment(t.Id, new List<EquipmentDeployment>
|
||||
s.SaveDeployment(t.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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<Waypoint> {
|
||||
new() { PosX = 10000, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
|
||||
});
|
||||
s.SaveDeployment(t.Id, new List<EquipmentDeployment>
|
||||
s.SaveDeployment(t.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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);
|
||||
|
||||
@ -8,8 +8,8 @@ namespace CounterDrone.Core.Models
|
||||
public Scenario Info { get; set; } = new();
|
||||
public CombatScene Scene { get; set; } = new();
|
||||
public List<ControlZone> ControlZones { get; set; } = new();
|
||||
public List<DroneProfile> Drones { get; set; } = new();
|
||||
public List<EquipmentDeployment> Equipment { get; set; } = new();
|
||||
public List<ScenarioDrone> Drones { get; set; } = new();
|
||||
public List<ScenarioUnit> Units { get; set; } = new();
|
||||
public CloudDispersal Cloud { get; set; } = new();
|
||||
/// <summary>多批次航路(多批次支持)</summary>
|
||||
public List<RoutePlan> Routes { get; set; } = new();
|
||||
|
||||
@ -4,8 +4,8 @@ using SQLite;
|
||||
namespace CounterDrone.Core.Models
|
||||
{
|
||||
/// <summary>步骤2:目标配置</summary>
|
||||
[Table("DroneProfile")]
|
||||
public class DroneProfile
|
||||
[Table("ScenarioDrone")]
|
||||
public class ScenarioDrone
|
||||
{
|
||||
[PrimaryKey]
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
@ -4,8 +4,8 @@ using SQLite;
|
||||
namespace CounterDrone.Core.Models
|
||||
{
|
||||
/// <summary>步骤3:装备部署</summary>
|
||||
[Table("EquipmentDeployment")]
|
||||
public class EquipmentDeployment
|
||||
[Table("ScenarioUnit")]
|
||||
public class ScenarioUnit
|
||||
{
|
||||
[PrimaryKey]
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
@ -5,13 +5,13 @@ using SQLite;
|
||||
|
||||
namespace CounterDrone.Core.Repository
|
||||
{
|
||||
public class DroneProfileRepository : BaseRepository<DroneProfile>
|
||||
public class ScenarioDroneRepository : BaseRepository<ScenarioDrone>
|
||||
{
|
||||
public DroneProfileRepository(SQLiteConnection db) : base(db) { }
|
||||
public ScenarioDroneRepository(SQLiteConnection db) : base(db) { }
|
||||
|
||||
public List<DroneProfile> GetByScenarioId(string scenarioId)
|
||||
public List<ScenarioDrone> GetByScenarioId(string scenarioId)
|
||||
{
|
||||
return Db.Table<DroneProfile>().Where(t => t.ScenarioId == scenarioId).ToList();
|
||||
return Db.Table<ScenarioDrone>().Where(t => t.ScenarioId == scenarioId).ToList();
|
||||
}
|
||||
|
||||
public void DeleteByScenarioId(string scenarioId)
|
||||
@ -5,19 +5,19 @@ using SQLite;
|
||||
|
||||
namespace CounterDrone.Core.Repository
|
||||
{
|
||||
public class EquipmentDeploymentRepository : BaseRepository<EquipmentDeployment>
|
||||
public class ScenarioUnitRepository : BaseRepository<ScenarioUnit>
|
||||
{
|
||||
public EquipmentDeploymentRepository(SQLiteConnection db) : base(db) { }
|
||||
public ScenarioUnitRepository(SQLiteConnection db) : base(db) { }
|
||||
|
||||
public List<EquipmentDeployment> GetByScenarioId(string scenarioId)
|
||||
public List<ScenarioUnit> GetByScenarioId(string scenarioId)
|
||||
{
|
||||
return Db.Table<EquipmentDeployment>().Where(e => e.ScenarioId == scenarioId).ToList();
|
||||
return Db.Table<ScenarioUnit>().Where(e => e.ScenarioId == scenarioId).ToList();
|
||||
}
|
||||
|
||||
/// <summary>按任务和角色查询装备(EquipmentRole: 0=Detection, 1=LaunchPlatform)</summary>
|
||||
public List<EquipmentDeployment> GetByScenarioIdAndRole(string scenarioId, int equipmentRole)
|
||||
public List<ScenarioUnit> GetByScenarioIdAndRole(string scenarioId, int equipmentRole)
|
||||
{
|
||||
return Db.Table<EquipmentDeployment>()
|
||||
return Db.Table<ScenarioUnit>()
|
||||
.Where(e => e.ScenarioId == scenarioId && e.EquipmentRole == equipmentRole)
|
||||
.ToList();
|
||||
}
|
||||
@ -13,15 +13,15 @@ namespace CounterDrone.Core.Services
|
||||
|
||||
void SaveScene(string scenarioId, CombatScene scene);
|
||||
void SaveControlZones(string scenarioId, List<ControlZone> zones);
|
||||
void SaveDroneProfile(string scenarioId, DroneProfile target);
|
||||
void SaveDeployment(string scenarioId, List<EquipmentDeployment> equips);
|
||||
void SaveScenarioDrone(string scenarioId, ScenarioDrone target);
|
||||
void SaveDeployment(string scenarioId, List<ScenarioUnit> equips);
|
||||
|
||||
/// <summary>添加单个探测设备(独立于 SaveDeployment,不覆盖火力单元)</summary>
|
||||
void AddDetection(string scenarioId, EquipmentDeployment detection);
|
||||
void AddDetection(string scenarioId, ScenarioUnit detection);
|
||||
/// <summary>删除探测设备</summary>
|
||||
void DeleteDetection(string detectionId);
|
||||
/// <summary>获取任务的所有探测设备(EquipmentRole.Detection)</summary>
|
||||
List<EquipmentDeployment> GetDetections(string scenarioId);
|
||||
List<ScenarioUnit> GetDetections(string scenarioId);
|
||||
|
||||
void SaveCloudDispersal(string scenarioId, CloudDispersal cloud);
|
||||
void SaveRoute(string scenarioId, string waveId, RoutePlan route, List<Waypoint> waypoints);
|
||||
|
||||
@ -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<string, int>();
|
||||
var unitLaunchCounts = new Dictionary<int, int>();
|
||||
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($"### 探测设备");
|
||||
|
||||
@ -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),
|
||||
};
|
||||
|
||||
@ -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<EquipmentDeployment> equips)
|
||||
public void SaveDeployment(string scenarioId, List<ScenarioUnit> 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<EquipmentDeployment> GetDetections(string scenarioId)
|
||||
public List<ScenarioUnit> GetDetections(string scenarioId)
|
||||
{
|
||||
return _equipRepo.GetByScenarioIdAndRole(scenarioId, (int)EquipmentRole.Detection);
|
||||
return _unitRepo.GetByScenarioIdAndRole(scenarioId, (int)EquipmentRole.Detection);
|
||||
}
|
||||
|
||||
public void SaveCloudDispersal(string scenarioId, CloudDispersal cloud)
|
||||
|
||||
@ -38,7 +38,7 @@ namespace CounterDrone.Core.Simulation
|
||||
/// 查找弧长 s 所在段:最大的 i 使 _cumArc[i] >= s。</summary>
|
||||
private readonly float[] _cumArc;
|
||||
|
||||
public DroneEntity(string id, string waveId, DroneProfile config, List<Waypoint> route,
|
||||
public DroneEntity(string id, string waveId, ScenarioDrone config, List<Waypoint> route,
|
||||
int formationIndex, float lateralSpacing, int longitudinalIndex, float longitudinalSpacing,
|
||||
FormationMode mode, int lateralAxis = 2, int longitudinalAxis = 0)
|
||||
{
|
||||
|
||||
@ -46,7 +46,7 @@ namespace CounterDrone.Core.Simulation
|
||||
/// <summary>Ready 包含:冷却就绪 + 有弹药 + 非飞行中</summary>
|
||||
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;
|
||||
|
||||
@ -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<FireUnit> BuildFireUnits(ScenarioConfig config)
|
||||
{
|
||||
var units = new List<FireUnit>();
|
||||
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<DetectionSource> BuildDetectionSources(ScenarioConfig config)
|
||||
{
|
||||
var sources = new List<DetectionSource>();
|
||||
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;
|
||||
|
||||
Binary file not shown.
@ -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<EquipmentDeployment>();
|
||||
var equips = new List<ScenarioUnit>();
|
||||
foreach (var u in fireUnits)
|
||||
equips.Add(new EquipmentDeployment
|
||||
equips.Add(new ScenarioUnit
|
||||
{
|
||||
EquipmentRole = (int)EquipmentRole.LaunchPlatform,
|
||||
PlatformType = (int)u.Type, Quantity = 1,
|
||||
|
||||
@ -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<EquipmentDeployment> e) => _service.SaveDeployment(scenarioId, e);
|
||||
public void SaveScenarioDrone(string scenarioId, ScenarioDrone t) => _service.SaveScenarioDrone(scenarioId, t);
|
||||
public void SaveDeployment(string scenarioId, List<ScenarioUnit> 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<Waypoint> w) => _service.SaveRoute(scenarioId, waveId, r, w);
|
||||
public void UpdateStep(string scenarioId, int step) => _service.UpdateStep(scenarioId, step);
|
||||
|
||||
@ -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<EquipmentDeployment>
|
||||
scenario.SaveDeployment(scenarioId, new List<ScenarioUnit>
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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"
|
||||
};
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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<EquipmentDeployment>());
|
||||
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>());
|
||||
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
|
||||
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
|
||||
new List<Waypoint>
|
||||
@ -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<EquipmentDeployment>());
|
||||
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>());
|
||||
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
|
||||
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
|
||||
new List<Waypoint>
|
||||
@ -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<EquipmentDeployment>());
|
||||
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>());
|
||||
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
|
||||
|
||||
// 500 km/h, 100km 航程
|
||||
|
||||
@ -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<EquipmentDeployment>
|
||||
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>
|
||||
{
|
||||
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<EquipmentDeployment>
|
||||
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>
|
||||
{
|
||||
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,
|
||||
|
||||
@ -36,11 +36,11 @@ namespace CounterDrone.Core.Tests
|
||||
var config = new ScenarioConfig
|
||||
{
|
||||
Info = new Scenario { Name = "测试任务", ScenarioNumber = "SIM-001" },
|
||||
Drones = new List<DroneProfile> { new DroneProfile { Quantity = 1 } },
|
||||
Equipment = new List<EquipmentDeployment>
|
||||
Drones = new List<ScenarioDrone> { new ScenarioDrone { Quantity = 1 } },
|
||||
Units = new List<ScenarioUnit>
|
||||
{
|
||||
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 },
|
||||
};
|
||||
|
||||
@ -37,8 +37,8 @@ namespace CounterDrone.Core.Tests
|
||||
var config = new ScenarioConfig
|
||||
{
|
||||
Info = new Scenario { Name = "Test", ScenarioNumber = "SIM-001" },
|
||||
Drones = new List<DroneProfile> { new DroneProfile { Quantity = 1 } },
|
||||
Equipment = new List<EquipmentDeployment>(),
|
||||
Drones = new List<ScenarioDrone> { new ScenarioDrone { Quantity = 1 } },
|
||||
Units = new List<ScenarioUnit>(),
|
||||
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<DroneProfile> { new DroneProfile { Quantity = 1 } },
|
||||
Equipment = new List<EquipmentDeployment>(),
|
||||
Drones = new List<ScenarioDrone> { new ScenarioDrone { Quantity = 1 } },
|
||||
Units = new List<ScenarioUnit>(),
|
||||
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<DroneProfile> { new DroneProfile { Quantity = 1 } },
|
||||
Equipment = new List<EquipmentDeployment>(),
|
||||
Drones = new List<ScenarioDrone> { new ScenarioDrone { Quantity = 1 } },
|
||||
Units = new List<ScenarioUnit>(),
|
||||
Cloud = new CloudDispersal(),
|
||||
};
|
||||
|
||||
|
||||
@ -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"));
|
||||
|
||||
@ -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<EquipmentDeployment>
|
||||
var equips = new List<ScenarioUnit>
|
||||
{
|
||||
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<EquipmentDeployment>
|
||||
_service.SaveDeployment(scenario.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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<EquipmentDeployment>
|
||||
_service.SaveDeployment(scenario.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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<EquipmentDeployment>
|
||||
_service.SaveDeployment(scenario.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<EquipmentDeployment>
|
||||
_scenarioService.SaveDeployment(_scenarioId, new List<ScenarioUnit>
|
||||
{
|
||||
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<EquipmentDeployment>
|
||||
_scenarioService.SaveDeployment(_scenarioId, new List<ScenarioUnit>
|
||||
{
|
||||
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<EquipmentDeployment>
|
||||
_scenarioService.SaveDeployment(scenario.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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<EquipmentDeployment>
|
||||
_scenarioService.SaveDeployment(scenario.Id, new List<ScenarioUnit>
|
||||
{
|
||||
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 },
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user