diff --git a/CHANGELOG.md b/CHANGELOG.md index 841fd58..7ae7912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,7 +103,7 @@ - **`GroupId` → `WaveId`**DroneProfile 四表的编组外键重命名为批次外键 - **RoutePlan 索引重命名**:`(ScenarioId, GroupId)` → `(ScenarioId, WaveId)` -- **RoutePlanRepository / WaypointRepository**:`GetByTaskAndGroup` → `GetByTaskAndWave` +- **RoutePlanRepository / WaypointRepository**:`GetByScenarioAndGroup` → `GetByScenarioAndWave` - **IScenarioService.SaveRoute**:`groupId` 参数 → `waveId` ### Changed — 算法类型重命名 diff --git a/docs/design/architecture/总体架构设计.md b/docs/design/architecture/总体架构设计.md index 707d2de..a00446b 100644 --- a/docs/design/architecture/总体架构设计.md +++ b/docs/design/architecture/总体架构设计.md @@ -177,7 +177,7 @@ public class SimulationRunner : MonoBehaviour ```csharp // === 任务 === -enum TaskStatus { Draft = 0, Configuring = 1, Completed = 2 } +enum ScenarioStatus { Draft = 0, Configuring = 1, Completed = 2 } // === 场景 === enum SceneType { Urban = 0, Plain = 1, Mountain = 2, Coast = 3 } @@ -307,7 +307,7 @@ CounterDroneBackend_Data/ |------|------|------|------| | Id | TEXT | PK | GUID | | Name | TEXT | NOT NULL | 任务名称 | -| TaskNumber | TEXT | UNIQUE | SIM-yyyyMMdd-xxx | +| ScenarioNumber | TEXT | UNIQUE | SIM-yyyyMMdd-xxx | | Status | INTEGER | DEFAULT 0 | 0=草稿 1=配置中 2=已完成 | | CurrentStep | INTEGER | DEFAULT 1 | 当前配置步骤 1-5 | | TickRate | INTEGER | DEFAULT 20 | 仿真 Tick 频率(Hz) | @@ -1385,10 +1385,10 @@ interface IModelService // === 想定管理 === interface IScenarioService { - Scenario CreateTask(string name, string taskNumber); - void DeleteTask(string id); - PagedResult SearchTasks(string kw, DateTime? from, DateTime? to, int page, int size); - ScenarioConfig GetTaskDetail(string id); + Scenario CreateScenario(string name, string scenarioNumber); + void DeleteScenario(string id); + PagedResult SearchScenarios(string kw, DateTime? from, DateTime? to, int page, int size); + ScenarioConfig GetScenarioDetail(string id); // 步骤保存 void SaveScene(string scenarioId, CombatScene scene); @@ -1425,7 +1425,7 @@ class FrameDataStore void Flush(); // 批量落库 void Discard(); List ReadFrames(string scenarioId, int fromFrame, int toFrame); - void DeleteTaskDb(string scenarioId); + void DeleteScenarioDb(string scenarioId); int CleanupExpired(); // TTL 清理(RetentionDays,默认 180) } diff --git a/docs/对接文档_Unity前端.md b/docs/对接文档_Unity前端.md index 49c5341..4233def 100644 --- a/docs/对接文档_Unity前端.md +++ b/docs/对接文档_Unity前端.md @@ -70,18 +70,18 @@ var demos = scenario.Search("Demo", null, null, 1, 100); var scenarioId = demos.Items[0].Id; // 方式 B:自定义 -var task = scenario.CreateTask("我的想定", ""); -scenario.SaveScene(task.Id, new CombatScene { WindSpeed = 5, WindDirection = (int)WindDirection.E }); -scenario.SaveTarget(task.Id, new DroneProfile { WaveId = "w1", Quantity = 1, TypicalSpeed = 200, TypicalAltitude = 500 }); -scenario.SaveRoute(task.Id, "w1", new RoutePlan(), new List { +var scenario = scenario.CreateScenario("我的想定", ""); +scenario.SaveScene(scenario.Id, new CombatScene { WindSpeed = 5, WindDirection = (int)WindDirection.E }); +scenario.SaveTarget(scenario.Id, new DroneProfile { WaveId = "w1", Quantity = 1, TypicalSpeed = 200, TypicalAltitude = 500 }); +scenario.SaveRoute(scenario.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(task.Id, new List { +scenario.SaveDeployment(scenario.Id, new List { new() { EquipmentRole = 1, PlatformType = 1, Quantity = 1, PositionX = 5000, AerosolType = 0, MunitionCount = 8 } }); -scenario.SaveCloud(task.Id, new CloudDispersal { AerosolType = 0, DisperseHeight = 500 }); -scenario.UpdateStep(task.Id, 5); +scenario.SaveCloud(scenario.Id, new CloudDispersal { AerosolType = 0, DisperseHeight = 500 }); +scenario.UpdateStep(scenario.Id, 5); ``` ### 3.3 步骤 3:运行仿真 @@ -142,7 +142,7 @@ mgr.DataService.GetAllFireUnits() / GetAllDrones() / GetAllSensors() mgr.DataService.GetAllEnvironments() / GetAllFormations() / GetAllRoutes() // 想定 CRUD -mgr.CreateTask(name, "") / mgr.DeleteTask(id) / mgr.Search(kw, from, to, page, size) +mgr.CreateScenario(name, "") / mgr.DeleteScenario(id) / mgr.Search(kw, from, to, page, size) mgr.SaveScene / SaveTarget / SaveDeployment / SaveCloud / SaveRoute / UpdateStep mgr.GetDetail(id) → ScenarioConfig ``` diff --git a/src/CounterDrone.Core/DatabaseManager.cs b/src/CounterDrone.Core/DatabaseManager.cs index bcdffed..c2022b0 100644 --- a/src/CounterDrone.Core/DatabaseManager.cs +++ b/src/CounterDrone.Core/DatabaseManager.cs @@ -117,7 +117,7 @@ namespace CounterDrone.Core db.CreateTable(); db.CreateTable(); - db.CreateIndex("Scenario", "TaskNumber"); + db.CreateIndex("Scenario", "ScenarioNumber"); db.CreateIndex("ControlZone", "ScenarioId"); db.CreateIndex("DroneProfile", "ScenarioId"); db.CreateIndex("EquipmentDeployment", "ScenarioId"); diff --git a/src/CounterDrone.Core/DefaultData.cs b/src/CounterDrone.Core/DefaultData.cs index 10c26b9..2130bf9 100644 --- a/src/CounterDrone.Core/DefaultData.cs +++ b/src/CounterDrone.Core/DefaultData.cs @@ -164,6 +164,8 @@ namespace CounterDrone.Core public string Id { get; set; } = ""; public string Name { get; set; } = ""; public int DroneType { get; set; } + public string Model { get; set; } = ""; + public string Description { get; set; } = ""; public int PowerType { get; set; } public double Wingspan { get; set; } public double TypicalSpeed { get; set; } @@ -175,6 +177,8 @@ namespace CounterDrone.Core { WaveId = waveId, DroneType = DroneType, + Model = Model, + Description = Description, PowerType = PowerType, Quantity = 1, Wingspan = Wingspan, diff --git a/src/CounterDrone.Core/DefaultScenarios.cs b/src/CounterDrone.Core/DefaultScenarios.cs index af2f0fb..55b503f 100644 --- a/src/CounterDrone.Core/DefaultScenarios.cs +++ b/src/CounterDrone.Core/DefaultScenarios.cs @@ -14,12 +14,12 @@ namespace CounterDrone.Core public static void Seed(IScenarioService scenario, DefaultData d) { // 检测旧格式任务(名称含 [Demo],但 SQL LIKE 中 [] 是通配符,搜索 "Demo") - var existing = scenario.SearchTasks("Demo", null, null, 1, 100); + var existing = scenario.SearchScenarios("Demo", null, null, 1, 100); if (existing.TotalCount > 0) { // 版本升级:删除旧 Demo 任务,重新创建 foreach (var t in existing.Items) - scenario.DeleteTask(t.Id); + scenario.DeleteScenario(t.Id); } SeedNoDefense(scenario, d); @@ -35,7 +35,7 @@ namespace CounterDrone.Core private static void SeedNoDefense(IScenarioService s, DefaultData d) { - var t = s.CreateTask("[Demo] 无防御-无人机抵达目标", ""); + var t = s.CreateScenario("[Demo] 无防御-无人机抵达目标", ""); s.SaveScene(t.Id, d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); s.SaveTarget(t.Id, d.Drones.First(p => p.Id == "shahed").ToDroneProfile()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), R("3km-h400", 600, d)); @@ -46,7 +46,7 @@ namespace CounterDrone.Core private static void SeedZoneIntrusion(IScenarioService s, DefaultData d) { - var t = s.CreateTask("[Demo] 管控区域侵入", ""); + var t = s.CreateScenario("[Demo] 管控区域侵入", ""); s.SaveScene(t.Id, d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); s.SaveTarget(t.Id, d.Drones.First(p => p.Id == "electric-scout").ToDroneProfile()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), R("3km-h300", 300, d)); @@ -66,7 +66,7 @@ namespace CounterDrone.Core private static void SeedPistonWindy(IScenarioService s, DefaultData d) { - var t = s.CreateTask("[Demo] 活塞拦截-西风5ms", ""); + var t = s.CreateScenario("[Demo] 活塞拦截-西风5ms", ""); var scene = d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene(); scene.WindSpeed = 5; scene.WindDirection = (int)WindDirection.W; @@ -87,7 +87,7 @@ namespace CounterDrone.Core private static void SeedJetActiveMaterial(IScenarioService s, DefaultData d) { - var t = s.CreateTask("[Demo] 喷气式拦截-活性材料", ""); + var t = s.CreateScenario("[Demo] 喷气式拦截-活性材料", ""); s.SaveScene(t.Id, d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); s.SaveTarget(t.Id, d.Drones.First(p => p.Id == "cruise-missile").ToDroneProfile()); s.SaveRoute(t.Id, "default", d.Formations.First(f => f.Id == "single").ToRoutePlan(), @@ -105,7 +105,7 @@ namespace CounterDrone.Core private static void SeedAirBasedWindy(IScenarioService s, DefaultData d) { - var t = s.CreateTask("[Demo] 空基拦截-东风5ms", ""); + var t = s.CreateScenario("[Demo] 空基拦截-东风5ms", ""); var scene = d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene(); scene.WindSpeed = 5; scene.WindDirection = (int)WindDirection.E; @@ -126,7 +126,7 @@ namespace CounterDrone.Core private static void Seed3DronesAirBased(IScenarioService s, DefaultData d) { - var t = s.CreateTask("[Demo] 3架空基编队拦截", ""); + var t = s.CreateScenario("[Demo] 3架空基编队拦截", ""); var scene = d.Environments.First(w => w.Id == "sunny-calm").ToCombatScene(); scene.WindSpeed = 5; scene.WindDirection = (int)WindDirection.E; diff --git a/src/CounterDrone.Core/Models/DroneProfile.cs b/src/CounterDrone.Core/Models/DroneProfile.cs index 9e36b15..8e4fdfc 100644 --- a/src/CounterDrone.Core/Models/DroneProfile.cs +++ b/src/CounterDrone.Core/Models/DroneProfile.cs @@ -17,6 +17,12 @@ namespace CounterDrone.Core.Models public int DroneType { get; set; } = (int)Models.DroneType.Rotor; + /// 型号 + public string Model { get; set; } = string.Empty; + + /// 描述/用途 + public string Description { get; set; } = string.Empty; + public int Quantity { get; set; } = 1; public int PowerType { get; set; } = (int)Models.PowerType.Electric; diff --git a/src/CounterDrone.Core/Models/Enums.cs b/src/CounterDrone.Core/Models/Enums.cs index d503fb8..3b39003 100644 --- a/src/CounterDrone.Core/Models/Enums.cs +++ b/src/CounterDrone.Core/Models/Enums.cs @@ -1,7 +1,7 @@ namespace CounterDrone.Core.Models { // === 任务 === - public enum TaskStatus + public enum ScenarioStatus { Draft = 0, Configuring = 1, diff --git a/src/CounterDrone.Core/Models/EquipmentDeployment.cs b/src/CounterDrone.Core/Models/EquipmentDeployment.cs index cff6c34..50a1ec6 100644 --- a/src/CounterDrone.Core/Models/EquipmentDeployment.cs +++ b/src/CounterDrone.Core/Models/EquipmentDeployment.cs @@ -13,6 +13,8 @@ namespace CounterDrone.Core.Models [Indexed] public string ScenarioId { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public int EquipmentRole { get; set; } = (int)Models.EquipmentRole.LaunchPlatform; public int Quantity { get; set; } = 1; diff --git a/src/CounterDrone.Core/Models/Scenario.cs b/src/CounterDrone.Core/Models/Scenario.cs index f6ee4df..0bba06b 100644 --- a/src/CounterDrone.Core/Models/Scenario.cs +++ b/src/CounterDrone.Core/Models/Scenario.cs @@ -14,9 +14,11 @@ namespace CounterDrone.Core.Models public string Name { get; set; } = string.Empty; [Unique] - public string TaskNumber { get; set; } = string.Empty; + public string ScenarioNumber { get; set; } = string.Empty; - public int Status { get; set; } = (int)TaskStatus.Draft; + public string Description { get; set; } = string.Empty; + + public int Status { get; set; } = (int)ScenarioStatus.Draft; public int CurrentStep { get; set; } = 1; diff --git a/src/CounterDrone.Core/Models/ScenarioConfig.cs b/src/CounterDrone.Core/Models/ScenarioConfig.cs index 35a0d13..8ea9275 100644 --- a/src/CounterDrone.Core/Models/ScenarioConfig.cs +++ b/src/CounterDrone.Core/Models/ScenarioConfig.cs @@ -5,7 +5,7 @@ namespace CounterDrone.Core.Models /// 想定完整配置(聚合 5 步配置) public class ScenarioConfig { - public Scenario Task { get; set; } = new(); + public Scenario Info { get; set; } = new(); public CombatScene Scene { get; set; } = new(); public List ControlZones { get; set; } = new(); public List Targets { get; set; } = new(); diff --git a/src/CounterDrone.Core/Models/SimulationReport.cs b/src/CounterDrone.Core/Models/SimulationReport.cs index d711d9a..f15ab5c 100644 --- a/src/CounterDrone.Core/Models/SimulationReport.cs +++ b/src/CounterDrone.Core/Models/SimulationReport.cs @@ -13,9 +13,9 @@ namespace CounterDrone.Core.Models [Indexed] public string ScenarioId { get; set; } = string.Empty; - public string TaskName { get; set; } = string.Empty; + public string ScenarioName { get; set; } = string.Empty; - public string TaskNumber { get; set; } = string.Empty; + public string ScenarioNumber { get; set; } = string.Empty; public string CompletedAt { get; set; } = string.Empty; diff --git a/src/CounterDrone.Core/Repository/RoutePlanRepository.cs b/src/CounterDrone.Core/Repository/RoutePlanRepository.cs index e3af68d..37bf297 100644 --- a/src/CounterDrone.Core/Repository/RoutePlanRepository.cs +++ b/src/CounterDrone.Core/Repository/RoutePlanRepository.cs @@ -14,7 +14,7 @@ namespace CounterDrone.Core.Repository return Db.Table().Where(r => r.ScenarioId == scenarioId).ToList(); } - public RoutePlan GetByTaskAndWave(string scenarioId, string waveId) + public RoutePlan GetByScenarioAndWave(string scenarioId, string waveId) { return Db.Table() .FirstOrDefault(r => r.ScenarioId == scenarioId && r.WaveId == waveId); diff --git a/src/CounterDrone.Core/Repository/ScenarioRepository.cs b/src/CounterDrone.Core/Repository/ScenarioRepository.cs index aa1c0af..e3a7ae7 100644 --- a/src/CounterDrone.Core/Repository/ScenarioRepository.cs +++ b/src/CounterDrone.Core/Repository/ScenarioRepository.cs @@ -9,9 +9,9 @@ namespace CounterDrone.Core.Repository { public ScenarioRepository(SQLiteConnection db) : base(db) { } - public Scenario GetByTaskNumber(string taskNumber) + public Scenario GetByScenarioNumber(string ScenarioNumber) { - return Db.Table().FirstOrDefault(t => t.TaskNumber == taskNumber); + return Db.Table().FirstOrDefault(t => t.ScenarioNumber == ScenarioNumber); } public List Search(string keyword, string? dateFrom, string? dateTo, int offset, int limit, out int totalCount) @@ -19,7 +19,7 @@ namespace CounterDrone.Core.Repository var query = Db.Table().AsQueryable(); if (!string.IsNullOrWhiteSpace(keyword)) - query = query.Where(t => t.Name.Contains(keyword) || t.TaskNumber.Contains(keyword)); + query = query.Where(t => t.Name.Contains(keyword) || t.ScenarioNumber.Contains(keyword)); if (!string.IsNullOrWhiteSpace(dateFrom)) query = query.Where(t => t.CreatedAt.CompareTo(dateFrom) >= 0); diff --git a/src/CounterDrone.Core/Repository/WaypointRepository.cs b/src/CounterDrone.Core/Repository/WaypointRepository.cs index aa7713b..c50f754 100644 --- a/src/CounterDrone.Core/Repository/WaypointRepository.cs +++ b/src/CounterDrone.Core/Repository/WaypointRepository.cs @@ -17,7 +17,7 @@ namespace CounterDrone.Core.Repository .ToList(); } - public List GetByTaskAndWave(string scenarioId, string waveId) + public List GetByScenarioAndWave(string scenarioId, string waveId) { return Db.Table() .Where(w => w.ScenarioId == scenarioId && w.WaveId == waveId) diff --git a/src/CounterDrone.Core/Services/IScenarioService.cs b/src/CounterDrone.Core/Services/IScenarioService.cs index 4f5f8eb..73b2156 100644 --- a/src/CounterDrone.Core/Services/IScenarioService.cs +++ b/src/CounterDrone.Core/Services/IScenarioService.cs @@ -6,10 +6,10 @@ namespace CounterDrone.Core.Services /// 想定管理服务 public interface IScenarioService { - Scenario CreateTask(string name, string taskNumber); - void DeleteTask(string id); - PagedResult SearchTasks(string keyword, string? dateFrom, string? dateTo, int page, int pageSize); - ScenarioConfig? GetTaskDetail(string id); + Scenario CreateScenario(string name, string scenarioNumber); + void DeleteScenario(string id); + PagedResult SearchScenarios(string keyword, string? dateFrom, string? dateTo, int page, int pageSize); + ScenarioConfig? GetScenarioDetail(string id); void SaveScene(string scenarioId, CombatScene scene); void SaveControlZones(string scenarioId, List zones); diff --git a/src/CounterDrone.Core/Services/ReportGenerator.cs b/src/CounterDrone.Core/Services/ReportGenerator.cs index 00851c7..1cc311d 100644 --- a/src/CounterDrone.Core/Services/ReportGenerator.cs +++ b/src/CounterDrone.Core/Services/ReportGenerator.cs @@ -26,8 +26,8 @@ namespace CounterDrone.Core.Services sb.AppendLine(); sb.AppendLine($"| 项目 | 值 |"); sb.AppendLine($"|------|-----|"); - sb.AppendLine($"| 任务名称 | {config.Task.Name} |"); - sb.AppendLine($"| 任务编号 | {config.Task.TaskNumber} |"); + sb.AppendLine($"| 任务名称 | {config.Info.Name} |"); + sb.AppendLine($"| 任务编号 | {config.Info.ScenarioNumber} |"); sb.AppendLine($"| 仿真耗时 | {simulationDuration:F1} 秒 |"); sb.AppendLine($"| 气溶胶类型 | {TranslateAerosol((AerosolType)config.Cloud.AerosolType)} |"); sb.AppendLine(); diff --git a/src/CounterDrone.Core/Services/ReportService.cs b/src/CounterDrone.Core/Services/ReportService.cs index 08aee3a..5dd73a7 100644 --- a/src/CounterDrone.Core/Services/ReportService.cs +++ b/src/CounterDrone.Core/Services/ReportService.cs @@ -32,8 +32,8 @@ namespace CounterDrone.Core.Services var report = new SimulationReport { ScenarioId = scenarioId, - TaskName = config.Task.Name, - TaskNumber = config.Task.TaskNumber, + ScenarioName = config.Info.Name, + ScenarioNumber = config.Info.ScenarioNumber, CompletedAt = DateTime.UtcNow.ToString("o"), TargetCount = total, EquipmentCount = config.Equipment.Count, @@ -63,7 +63,7 @@ namespace CounterDrone.Core.Services var query = _db.Table().AsQueryable(); if (!string.IsNullOrWhiteSpace(keyword)) - query = query.Where(r => r.TaskName.Contains(keyword) || r.TaskNumber.Contains(keyword)); + query = query.Where(r => r.ScenarioName.Contains(keyword) || r.ScenarioNumber.Contains(keyword)); if (!string.IsNullOrWhiteSpace(dateFrom)) query = query.Where(r => r.CompletedAt.CompareTo(dateFrom) >= 0); if (!string.IsNullOrWhiteSpace(dateTo)) @@ -88,7 +88,7 @@ namespace CounterDrone.Core.Services Directory.CreateDirectory(outputDir); var safeTime = DateTime.UtcNow.ToString("yyyyMMdd_HHmmss"); - var fileName = $"{report.TaskName}_{safeTime}.md"; + var fileName = $"{report.ScenarioName}_{safeTime}.md"; var filePath = Path.Combine(outputDir, fileName); File.WriteAllText(filePath, report.Content); return filePath; diff --git a/src/CounterDrone.Core/Services/ScenarioService.cs b/src/CounterDrone.Core/Services/ScenarioService.cs index 4b63198..64b95cf 100644 --- a/src/CounterDrone.Core/Services/ScenarioService.cs +++ b/src/CounterDrone.Core/Services/ScenarioService.cs @@ -9,7 +9,7 @@ namespace CounterDrone.Core.Services { public class ScenarioService : IScenarioService { - private readonly ScenarioRepository _taskRepo; + private readonly ScenarioRepository _scenarioRepo; private readonly CombatSceneRepository _sceneRepo; private readonly ControlZoneRepository _zoneRepo; private readonly DroneProfileRepository _targetRepo; @@ -19,7 +19,7 @@ namespace CounterDrone.Core.Services private readonly WaypointRepository _waypointRepo; public ScenarioService( - ScenarioRepository taskRepo, + ScenarioRepository scenarioRepo, CombatSceneRepository sceneRepo, ControlZoneRepository zoneRepo, DroneProfileRepository targetRepo, @@ -28,7 +28,7 @@ namespace CounterDrone.Core.Services RoutePlanRepository routeRepo, WaypointRepository waypointRepo) { - _taskRepo = taskRepo; + _scenarioRepo = scenarioRepo; _sceneRepo = sceneRepo; _zoneRepo = zoneRepo; _targetRepo = targetRepo; @@ -38,44 +38,44 @@ namespace CounterDrone.Core.Services _waypointRepo = waypointRepo; } - // ========== Task CRUD ========== + // ========== scenario CRUD ========== - public Scenario CreateTask(string name, string taskNumber) + public Scenario CreateScenario(string name, string ScenarioNumber) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("任务名称不能为空"); - if (string.IsNullOrWhiteSpace(taskNumber)) - taskNumber = GenerateTaskNumber(); + if (string.IsNullOrWhiteSpace(ScenarioNumber)) + ScenarioNumber = GenerateScenarioNumber(); - var existing = _taskRepo.GetByTaskNumber(taskNumber); + var existing = _scenarioRepo.GetByScenarioNumber(ScenarioNumber); if (existing != null) - throw new ArgumentException($"任务编号 {taskNumber} 已存在"); + throw new ArgumentException($"任务编号 {ScenarioNumber} 已存在"); - var task = new Scenario + var scenario = new Scenario { Name = name, - TaskNumber = taskNumber, - Status = (int)TaskStatus.Configuring, + ScenarioNumber = ScenarioNumber, + Status = (int)ScenarioStatus.Configuring, CurrentStep = 1, }; - _taskRepo.Insert(task); - return task; + _scenarioRepo.Insert(scenario); + return scenario; } - public void DeleteTask(string id) + public void DeleteScenario(string id) { - _taskRepo.Delete(id); + _scenarioRepo.Delete(id); } - public PagedResult SearchTasks(string keyword, string? dateFrom, string? dateTo, int page, int pageSize) + public PagedResult SearchScenarios(string keyword, string? dateFrom, string? dateTo, int page, int pageSize) { if (page < 1) page = 1; if (pageSize < 1) pageSize = 10; var offset = (page - 1) * pageSize; - var items = _taskRepo.Search(keyword, dateFrom, dateTo, offset, pageSize, out var total); + var items = _scenarioRepo.Search(keyword, dateFrom, dateTo, offset, pageSize, out var total); return new PagedResult { @@ -86,14 +86,14 @@ namespace CounterDrone.Core.Services }; } - public ScenarioConfig? GetTaskDetail(string id) + public ScenarioConfig? GetScenarioDetail(string id) { - var task = _taskRepo.GetById(id); - if (task == null) return null; + var scenario = _scenarioRepo.GetById(id); + if (scenario == null) return null; return new ScenarioConfig { - Task = task, + Info = scenario, Scene = _sceneRepo.GetById(id) ?? new CombatScene { ScenarioId = id }, ControlZones = _zoneRepo.GetByScenarioId(id), Targets = _targetRepo.GetByScenarioId(id), @@ -116,7 +116,7 @@ namespace CounterDrone.Core.Services _sceneRepo.Update(scene); else _sceneRepo.Insert(scene); - TouchTask(scenarioId); + TouchScenario(scenarioId); } public void SaveControlZones(string scenarioId, List zones) @@ -128,7 +128,7 @@ namespace CounterDrone.Core.Services zones[i].OrderIndex = i; } _zoneRepo.InsertAll(zones); - TouchTask(scenarioId); + TouchScenario(scenarioId); } public void SaveTarget(string scenarioId, DroneProfile target) @@ -142,7 +142,7 @@ namespace CounterDrone.Core.Services _targetRepo.Update(target); else _targetRepo.Insert(target); - TouchTask(scenarioId); + TouchScenario(scenarioId); } public void SaveDeployment(string scenarioId, List equips) @@ -155,7 +155,7 @@ namespace CounterDrone.Core.Services e.Id = Guid.NewGuid().ToString(); } _equipRepo.InsertAll(equips); - TouchTask(scenarioId); + TouchScenario(scenarioId); } public void AddDetection(string scenarioId, EquipmentDeployment detection) @@ -165,7 +165,7 @@ namespace CounterDrone.Core.Services if (string.IsNullOrEmpty(detection.Id)) detection.Id = Guid.NewGuid().ToString(); _equipRepo.Insert(detection); - TouchTask(scenarioId); + TouchScenario(scenarioId); } public void DeleteDetection(string detectionId) @@ -186,14 +186,14 @@ namespace CounterDrone.Core.Services _cloudRepo.Update(cloud); else _cloudRepo.Insert(cloud); - TouchTask(scenarioId); + TouchScenario(scenarioId); } public void SaveRoute(string scenarioId, string waveId, RoutePlan route, List waypoints) { route.ScenarioId = scenarioId; route.WaveId = waveId; - var existing = _routeRepo.GetByTaskAndWave(scenarioId, waveId); + var existing = _routeRepo.GetByScenarioAndWave(scenarioId, waveId); if (existing != null) { route.Id = existing.Id; @@ -203,7 +203,7 @@ namespace CounterDrone.Core.Services _routeRepo.Insert(route); // 删除该批次的旧航路点,插入新的 - var oldWps = _waypointRepo.GetByTaskAndWave(scenarioId, waveId); + var oldWps = _waypointRepo.GetByScenarioAndWave(scenarioId, waveId); foreach (var w in oldWps) _waypointRepo.Delete(w.Id); for (int i = 0; i < waypoints.Count; i++) { @@ -214,36 +214,36 @@ namespace CounterDrone.Core.Services waypoints[i].Id = Guid.NewGuid().ToString(); } _waypointRepo.InsertAll(waypoints); - TouchTask(scenarioId); + TouchScenario(scenarioId); } public void UpdateStep(string scenarioId, int step) { - var task = _taskRepo.GetById(scenarioId); - if (task == null) return; + var scenario = _scenarioRepo.GetById(scenarioId); + if (scenario == null) return; if (step < 1) step = 1; if (step > 5) step = 5; - task.CurrentStep = step; - _taskRepo.Update(task); + scenario.CurrentStep = step; + _scenarioRepo.Update(scenario); } // ========== Helpers ========== - private void TouchTask(string scenarioId) + private void TouchScenario(string scenarioId) { - var task = _taskRepo.GetById(scenarioId); - if (task != null) + var scenario = _scenarioRepo.GetById(scenarioId); + if (scenario != null) { - task.UpdatedAt = DateTime.UtcNow.ToString("o"); - _taskRepo.Update(task); + scenario.UpdatedAt = DateTime.UtcNow.ToString("o"); + _scenarioRepo.Update(scenario); } } private static int _counter; - public static string GenerateTaskNumber() + public static string GenerateScenarioNumber() { var now = DateTime.Now; var datePart = now.ToString("yyyyMMdd"); diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index cdedb86..2d8bb39 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -85,12 +85,12 @@ namespace CounterDrone.Core.Simulation public void Initialize(string scenarioId) { _scenarioId = scenarioId; - var config = _scenarioService.GetTaskDetail(scenarioId); - if (config == null) throw new InvalidOperationException("Task not found"); + var config = _scenarioService.GetScenarioDetail(scenarioId); + if (config == null) throw new InvalidOperationException("scenario not found"); _scene = config.Scene; _disperseHeight = (float)config.Cloud.DisperseHeight; - _tickRate = config.Task.TickRate; + _tickRate = config.Info.TickRate; _tickInterval = 1.0f / _tickRate; using (var ammoDb = new SQLiteConnection(_paths.GetMainDbPath())) diff --git a/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.deps.json b/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.deps.json index cfca9b2..5a510c9 100644 --- a/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.deps.json +++ b/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.deps.json @@ -82,7 +82,7 @@ "dependencies": { "System.Buffers": "4.5.1", "System.Memory": "4.5.5", - "System.Threading.Tasks.Extensions": "4.5.4" + "System.Threading.Scenarios.Extensions": "4.5.4" }, "runtime": { "lib/netstandard2.0/System.IO.Pipelines.dll": { @@ -141,7 +141,7 @@ "System.Memory": "4.5.5", "System.Runtime.CompilerServices.Unsafe": "6.0.0", "System.Text.Encodings.Web": "9.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" + "System.Threading.Scenarios.Extensions": "4.5.4" }, "runtime": { "lib/netstandard2.0/System.Text.Json.dll": { @@ -150,12 +150,12 @@ } } }, - "System.Threading.Tasks.Extensions/4.5.4": { + "System.Threading.Scenarios.Extensions/4.5.4": { "dependencies": { "System.Runtime.CompilerServices.Unsafe": "6.0.0" }, "runtime": { - "lib/netstandard2.0/System.Threading.Tasks.Extensions.dll": { + "lib/netstandard2.0/System.Threading.Scenarios.Extensions.dll": { "assemblyVersion": "4.2.0.1", "fileVersion": "4.6.28619.1" } @@ -260,12 +260,12 @@ "path": "system.text.json/9.0.0", "hashPath": "system.text.json.9.0.0.nupkg.sha512" }, - "System.Threading.Tasks.Extensions/4.5.4": { + "System.Threading.Scenarios.Extensions/4.5.4": { "type": "package", "serviceable": true, "sha512": "sha512-zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", - "path": "system.threading.tasks.extensions/4.5.4", - "hashPath": "system.threading.tasks.extensions.4.5.4.nupkg.sha512" + "path": "system.threading.scenarios.extensions/4.5.4", + "hashPath": "system.threading.scenarios.extensions.4.5.4.nupkg.sha512" } } } \ No newline at end of file diff --git a/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs b/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs index 6d0e5b6..7a6e740 100644 --- a/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs +++ b/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs @@ -28,9 +28,9 @@ namespace CounterDrone.Unity var scenarioMgr = gameObject.AddComponent(); scenarioMgr.Awake(); - var task = scenarioMgr.CreateTask("Verification", ""); - var scenarioId = task.Id; - Debug.Log($"2. ScenarioManager OK. Task: {scenarioId}"); + var scenario = scenarioMgr.CreateScenario("Verification", ""); + var scenarioId = scenario.Id; + Debug.Log($"2. ScenarioManager OK. scenario: {scenarioId}"); scenarioMgr.SaveScene(scenarioId, new CombatScene { WindSpeed = 0 }); scenarioMgr.SaveTarget(scenarioId, new DroneProfile diff --git a/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs b/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs index 3d946b9..93cb812 100644 --- a/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs +++ b/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs @@ -45,11 +45,11 @@ namespace CounterDrone.Unity void OnDisable() { SqliteConnectionTracker.Untrack(_db); _db?.Dispose(); _db = null; } - public Scenario CreateTask(string name, string number) => _service.CreateTask(name, number); - public void DeleteTask(string id) => _service.DeleteTask(id); - public ScenarioConfig GetDetail(string id) => _service.GetTaskDetail(id); + public Scenario CreateScenario(string name, string number) => _service.CreateScenario(name, number); + public void DeleteScenario(string id) => _service.DeleteScenario(id); + public ScenarioConfig GetDetail(string id) => _service.GetScenarioDetail(id); public PagedResult Search(string kw, string from, string to, int page, int size) - => _service.SearchTasks(kw, from, to, page, size); + => _service.SearchScenarios(kw, from, to, page, size); public void SaveScene(string scenarioId, CombatScene s) => _service.SaveScene(scenarioId, s); public void SaveTarget(string scenarioId, DroneProfile t) => _service.SaveTarget(scenarioId, t); @@ -62,8 +62,8 @@ namespace CounterDrone.Unity void Verify() { Awake(); - var task = CreateTask("验证任务", ""); - Debug.Log($"ScenarioManager OK. Created: {task.Name} ({task.TaskNumber})"); + var scenario = CreateScenario("验证任务", ""); + Debug.Log($"ScenarioManager OK. Created: {scenario.Name} ({scenario.ScenarioNumber})"); } } } diff --git a/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs b/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs index e8a8495..d3e971d 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationBootstrap.cs @@ -52,7 +52,7 @@ namespace CounterDrone.Unity if (_usePreset) { // 方式1:直接使用预设想定(最简单) - var demos = scenario.SearchTasks("Demo", null, null, 1, 1); + var demos = scenario.SearchScenarios("Demo", null, null, 1, 1); if (demos.TotalCount == 0) { Debug.LogError("无预设想定,请确认 defaults.json 已放入 StreamingAssets"); @@ -66,8 +66,8 @@ namespace CounterDrone.Unity // 方式2:用 DefaultData 预设组装自定义想定 var defaults = DefaultData.Load(paths); - var task = scenario.CreateTask("Unity Demo", ""); - scenarioId = task.Id; + var scenario = scenario.CreateScenario("Unity Demo", ""); + scenarioId = scenario.Id; scenario.SaveScene(scenarioId, defaults.Environments.First(w => w.Id == "sunny-calm").ToCombatScene()); scenario.SaveTarget(scenarioId, defaults.Drones.First(p => p.Id == "shahed").ToDroneProfile()); @@ -77,7 +77,7 @@ namespace CounterDrone.Unity .ToWaypoints(_droneSpeed)); // 从火力单元预设构建 FireUnit → Planner 自动生成方案 → 引擎执行 - var detail = scenario.GetTaskDetail(scenarioId); + var detail = scenario.GetScenarioDetail(scenarioId); var ammoCatalog = db.Table().ToList(); var planner = new DefensePlanner(ammoCatalog, PlannerConfig.Load(paths)); var threats = new List diff --git a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs index 6527d56..0991bc1 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs @@ -55,8 +55,8 @@ namespace CounterDrone.Unity public void LoadAndStart(string scenarioId) { _scenarioId = scenarioId; - var detail = _scenario.GetTaskDetail(scenarioId); - if (detail == null) { Debug.LogError("Task not found"); return; } + var detail = _scenario.GetScenarioDetail(scenarioId); + if (detail == null) { Debug.LogError("scenario not found"); return; } _engine.Initialize(scenarioId); diff --git a/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs b/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs index 45690a5..98f0210 100644 --- a/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs +++ b/test/unit/CounterDrone.Core.Tests/DatabaseManagerTests.cs @@ -53,7 +53,7 @@ namespace CounterDrone.Core.Tests [Fact] public void OpenFrameDb_CreatesFrameRecordTable() { - var db = _dbManager.OpenFrameDb("task_001"); + var db = _dbManager.OpenFrameDb("scenario_001"); var count = db.ExecuteScalar( "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='SimFrameRecord'"); @@ -65,7 +65,7 @@ namespace CounterDrone.Core.Tests [Fact] public void DeleteFrameDb_RemovesFile() { - var scenarioId = "task_del"; + var scenarioId = "scenario_del"; var db = _dbManager.OpenFrameDb(scenarioId); db.Close(); diff --git a/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs b/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs index cd0d4ba..0403865 100644 --- a/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs +++ b/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs @@ -42,8 +42,8 @@ namespace CounterDrone.Core.Tests [Fact] public void EmptyDeployment_EngineRunsWithoutCrash() { - var task = _scenario.CreateTask("空部署", ""); - _scenarioId = task.Id; + var scenario = _scenario.CreateScenario("空部署", ""); + _scenarioId = scenario.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 }); _scenario.SaveTarget(_scenarioId, new DroneProfile @@ -81,8 +81,8 @@ namespace CounterDrone.Core.Tests [Fact] public void ExtremeWind_DroneStillFlies() { - var task = _scenario.CreateTask("飓风", ""); - _scenarioId = task.Id; + var scenario = _scenario.CreateScenario("飓风", ""); + _scenarioId = scenario.Id; _scenario.SaveScene(_scenarioId, new CombatScene { @@ -124,8 +124,8 @@ namespace CounterDrone.Core.Tests [Fact] public void LongRoute_CompletesWithoutError() { - var task = _scenario.CreateTask("超长航路", ""); - _scenarioId = task.Id; + var scenario = _scenario.CreateScenario("超长航路", ""); + _scenarioId = scenario.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 }); _scenario.SaveTarget(_scenarioId, new DroneProfile diff --git a/test/unit/CounterDrone.Core.Tests/FrameDataStoreTests.cs b/test/unit/CounterDrone.Core.Tests/FrameDataStoreTests.cs index a60a601..dd50637 100644 --- a/test/unit/CounterDrone.Core.Tests/FrameDataStoreTests.cs +++ b/test/unit/CounterDrone.Core.Tests/FrameDataStoreTests.cs @@ -36,22 +36,22 @@ namespace CounterDrone.Core.Tests public void CleanupExpired_DeletesOldFiles() { _store.RetentionDays = 0; - CreateFakeDb("task_old_1"); - CreateFakeDb("task_old_2"); + CreateFakeDb("scenario_old_1"); + CreateFakeDb("scenario_old_2"); var deleted = _store.CleanupExpired(); Assert.Equal(2, deleted); - Assert.False(File.Exists(Path.Combine(_testDir, "frames", "task_old_1.db"))); - Assert.False(File.Exists(Path.Combine(_testDir, "frames", "task_old_2.db"))); + Assert.False(File.Exists(Path.Combine(_testDir, "frames", "scenario_old_1.db"))); + Assert.False(File.Exists(Path.Combine(_testDir, "frames", "scenario_old_2.db"))); } [Fact] public void CleanupExpired_KeepsRecentFiles() { _store.RetentionDays = 365; - CreateFakeDb("task_new"); + CreateFakeDb("scenario_new"); - var filePath = Path.Combine(_testDir, "frames", "task_new.db"); + var filePath = Path.Combine(_testDir, "frames", "scenario_new.db"); File.SetCreationTime(filePath, DateTime.Now); var deleted = _store.CleanupExpired(); @@ -68,7 +68,7 @@ namespace CounterDrone.Core.Tests [Fact] public void RecordAndFlush_ThenReadFrames() { - _store.BeginRecording("task_rw"); + _store.BeginRecording("scenario_rw"); var snapshots = new List { new EntitySnapshot { EntityId = "d1", EntityType = Models.EntityType.Drone, PosX = 100 }, @@ -78,7 +78,7 @@ namespace CounterDrone.Core.Tests _store.RecordFrame(2, 0.10f, snapshots); _store.Flush(); - var frames = _store.ReadFrames("task_rw", 1, 2); + var frames = _store.ReadFrames("scenario_rw", 1, 2); Assert.Equal(2, frames.Count); Assert.Equal(1, frames[0].FrameIndex); Assert.Equal(2, frames[1].FrameIndex); @@ -87,15 +87,15 @@ namespace CounterDrone.Core.Tests [Fact] public void Flush_EmptyBuffer_DoesNothing() { - _store.BeginRecording("task_empty"); + _store.BeginRecording("scenario_empty"); _store.Flush(); // no crash - Assert.False(File.Exists(Path.Combine(_testDir, "frames", "task_empty.db"))); + Assert.False(File.Exists(Path.Combine(_testDir, "frames", "scenario_empty.db"))); } [Fact] public void Discard_ClearsBuffer() { - _store.BeginRecording("task_discard"); + _store.BeginRecording("scenario_discard"); _store.RecordFrame(0, 0f, new List { new EntitySnapshot { EntityId = "d1" } }); _store.Discard(); Assert.Equal(0, _store.BufferedFrameCount); diff --git a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs index 4a8965f..98dee63 100644 --- a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs +++ b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs @@ -66,10 +66,10 @@ namespace CounterDrone.Core.Tests private void VerifyAndExportReport(SimulationEngine eng, DroneEntity drone) { - var detail = _scenario.GetTaskDetail(_scenarioId)!; + var detail = _scenario.GetScenarioDetail(_scenarioId)!; var report = new ReportGenerator().Generate(detail, eng.Events.ToList(), drone.Status, eng.SimulationTime); Assert.Contains("对抗结果", report); - Assert.Contains(detail.Task.Name, report); + Assert.Contains(detail.Info.Name, report); var svc = new ReportService(_mainDb, _paths); var r = svc.Generate(_scenarioId, detail, eng.Events.ToList(), drone.Status.ToString(), eng.SimulationTime); @@ -78,10 +78,10 @@ namespace CounterDrone.Core.Tests private ScenarioConfig LoadPreset(string name) { - var results = _scenario.SearchTasks(name, null, null, 1, 1); + var results = _scenario.SearchScenarios(name, null, null, 1, 1); Assert.True(results.TotalCount > 0, $"预设想定未找到: {name}"); _scenarioId = results.Items[0].Id; - return _scenario.GetTaskDetail(_scenarioId)!; + return _scenario.GetScenarioDetail(_scenarioId)!; } private SimulationEngine RunPreset(string name, int maxFrames = 8000) @@ -152,7 +152,7 @@ namespace CounterDrone.Core.Tests Assert.All(eng.Events.Where(e => e.Type == SimEventType.MunitionLaunched), e => Assert.Contains("空基", e.Description)); var drone = eng.Drones[0]; - var detail = _scenario.GetTaskDetail(_scenarioId)!; + var detail = _scenario.GetScenarioDetail(_scenarioId)!; var report = new ReportGenerator().Generate(detail, eng.Events.ToList(), drone.Status, eng.SimulationTime); Assert.True(drone.Hp < 0.1f, $"Hp={drone.Hp:F3} pos=({drone.PosX:F0},{drone.PosY:F0}) launched={eng.Events.Count(e => e.Type == SimEventType.MunitionLaunched)}\n{report}"); VerifyAndExportReport(eng, drone); @@ -182,8 +182,8 @@ namespace CounterDrone.Core.Tests public void Scenario_DetectionDriven_PlanningDelayedByDetectionBoundary() { // 场景A:无探测设备(上帝视角,从航路起点算) - var taskA = _scenario.CreateTask("无探测远航路", ""); - _scenarioId = taskA.Id; + var scenarioA = _scenario.CreateScenario("无探测远航路", ""); + _scenarioId = scenarioA.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0, Visibility = 10000 }); _scenario.SaveTarget(_scenarioId, new DroneProfile { @@ -207,8 +207,8 @@ namespace CounterDrone.Core.Tests // 场景B:有独立探测设备(雷达 6000m,部署在 X=10000 航路中点附近) // 探测圆边界 X=4000 和 X=16000,无人机从 X=0 飞向 20000,在 X=4000 进入探测 // planner 基于探测边界 X=4000 算到达时间(而非起点 X=0) - var taskB = _scenario.CreateTask("有探测远航路", ""); - _scenarioId = taskB.Id; + var scenarioB = _scenario.CreateScenario("有探测远航路", ""); + _scenarioId = scenarioB.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0, Visibility = 10000 }); _scenario.SaveTarget(_scenarioId, new DroneProfile { diff --git a/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs b/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs index 263b12d..14bf667 100644 --- a/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs +++ b/test/unit/CounterDrone.Core.Tests/ReportGeneratorTests.cs @@ -35,7 +35,7 @@ namespace CounterDrone.Core.Tests var gen = new ReportGenerator(); var config = new ScenarioConfig { - Task = new Scenario { Name = "测试任务", TaskNumber = "SIM-001" }, + Info = new Scenario { Name = "测试任务", ScenarioNumber = "SIM-001" }, Targets = new List { new DroneProfile { Quantity = 1 } }, Equipment = new List { diff --git a/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs b/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs index e3f9656..5915532 100644 --- a/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs +++ b/test/unit/CounterDrone.Core.Tests/ReportServiceTests.cs @@ -36,17 +36,17 @@ namespace CounterDrone.Core.Tests { var config = new ScenarioConfig { - Task = new Scenario { Name = "Test", TaskNumber = "SIM-001" }, + Info = new Scenario { Name = "Test", ScenarioNumber = "SIM-001" }, Targets = new List { new DroneProfile { Quantity = 1 } }, Equipment = new List(), Cloud = new CloudDispersal(), }; - var report = _service.Generate("task1", config, new List(), "Destroyed", 45f); + var report = _service.Generate("scenario1", config, new List(), "Destroyed", 45f); Assert.NotNull(report); Assert.NotEmpty(report.Id); - Assert.Equal("Test", report.TaskName); + Assert.Equal("Test", report.ScenarioName); Assert.Contains("仿真评估报告", report.Content); var fetched = _service.GetReport(report.Id); @@ -58,13 +58,13 @@ namespace CounterDrone.Core.Tests { var config = new ScenarioConfig { - Task = new Scenario { Name = "Del", TaskNumber = "SIM-DEL" }, + Info = new Scenario { Name = "Del", ScenarioNumber = "SIM-DEL" }, Targets = new List { new DroneProfile { Quantity = 1 } }, Equipment = new List(), Cloud = new CloudDispersal(), }; - var report = _service.Generate("task1", config, new List(), "Destroyed", 10f); + var report = _service.Generate("scenario1", config, new List(), "Destroyed", 10f); _service.DeleteReport(report.Id); Assert.Null(_service.GetReport(report.Id)); } @@ -74,15 +74,15 @@ namespace CounterDrone.Core.Tests { var cfg = new ScenarioConfig { - Task = new Scenario { Name = "城市防御", TaskNumber = "SIM-A" }, + Info = new Scenario { Name = "城市防御", ScenarioNumber = "SIM-A" }, Targets = new List { new DroneProfile { Quantity = 1 } }, Equipment = new List(), Cloud = new CloudDispersal(), }; _service.Generate("t1", cfg, new List(), "Destroyed", 10f); - cfg.Task.Name = "平原拦截"; - cfg.Task.TaskNumber = "SIM-B"; + cfg.Info.Name = "平原拦截"; + cfg.Info.ScenarioNumber = "SIM-B"; _service.Generate("t2", cfg, new List(), "Destroyed", 20f); var result = _service.SearchReports("城市", null, null, 1, 10); diff --git a/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs b/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs index 3c98e49..b5f01a9 100644 --- a/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs +++ b/test/unit/CounterDrone.Core.Tests/RepositoryEdgeTests.cs @@ -25,14 +25,14 @@ namespace CounterDrone.Core.Tests public void DroneProfile_DeleteByScenarioId_RemovesAll() { var repo = new DroneProfileRepository(_db); - repo.Insert(new DroneProfile { Id = "t1", ScenarioId = "taskA", Quantity = 1 }); - repo.Insert(new DroneProfile { Id = "t2", ScenarioId = "taskA", Quantity = 2 }); - repo.Insert(new DroneProfile { Id = "t3", ScenarioId = "taskB", Quantity = 1 }); + 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 }); - repo.DeleteByScenarioId("taskA"); + repo.DeleteByScenarioId("scenarioA"); - Assert.Empty(repo.GetByScenarioId("taskA")); - Assert.Single(repo.GetByScenarioId("taskB")); + Assert.Empty(repo.GetByScenarioId("scenarioA")); + Assert.Single(repo.GetByScenarioId("scenarioB")); } [Fact] diff --git a/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs b/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs index 07cf620..0b786d9 100644 --- a/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs +++ b/test/unit/CounterDrone.Core.Tests/ScenarioServiceTests.cs @@ -7,7 +7,7 @@ using CounterDrone.Core.Repository; using CounterDrone.Core.Services; using SQLite; using Xunit; -using TaskStatus = CounterDrone.Core.Models.TaskStatus; +using ScenarioStatus = CounterDrone.Core.Models.ScenarioStatus; namespace CounterDrone.Core.Tests { @@ -41,86 +41,86 @@ namespace CounterDrone.Core.Tests Directory.Delete(_testDir, true); } - // ========== Task CRUD ========== + // ========== scenario CRUD ========== [Fact] - public void CreateTask_Valid_ReturnsTask() + public void CreateScenario_Valid_ReturnsScenario() { - var task = _service.CreateTask("测试任务", "SIM-20260611-001"); + var scenario = _service.CreateScenario("测试任务", "SIM-20260611-001"); - Assert.NotNull(task); - Assert.Equal("测试任务", task.Name); - Assert.Equal("SIM-20260611-001", task.TaskNumber); - Assert.Equal((int)TaskStatus.Configuring, task.Status); - Assert.Equal(1, task.CurrentStep); - Assert.NotEmpty(task.Id); + Assert.NotNull(scenario); + Assert.Equal("测试任务", scenario.Name); + Assert.Equal("SIM-20260611-001", scenario.ScenarioNumber); + Assert.Equal((int)ScenarioStatus.Configuring, scenario.Status); + Assert.Equal(1, scenario.CurrentStep); + Assert.NotEmpty(scenario.Id); } [Fact] - public void CreateTask_AutoGeneratesTaskNumber() + public void CreateScenario_AutoGeneratesScenarioNumber() { - var task = _service.CreateTask("自动编号", ""); - Assert.StartsWith("SIM-", task.TaskNumber); + var scenario = _service.CreateScenario("自动编号", ""); + Assert.StartsWith("SIM-", scenario.ScenarioNumber); } [Fact] - public void CreateTask_EmptyName_Throws() + public void CreateScenario_EmptyName_Throws() { Assert.Throws(() => - _service.CreateTask("", "SIM-001")); + _service.CreateScenario("", "SIM-001")); } [Fact] - public void CreateTask_DuplicateNumber_Throws() + public void CreateScenario_DuplicateNumber_Throws() { - _service.CreateTask("Task A", "SIM-001"); + _service.CreateScenario("scenario A", "SIM-001"); Assert.Throws(() => - _service.CreateTask("Task B", "SIM-001")); + _service.CreateScenario("scenario B", "SIM-001")); } [Fact] - public void DeleteTask_RemovesTask() + public void DeleteScenario_RemovesScenario() { - var task = _service.CreateTask("ToDelete", ""); - _service.DeleteTask(task.Id); + var scenario = _service.CreateScenario("ToDelete", ""); + _service.DeleteScenario(scenario.Id); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); Assert.Null(detail); } [Fact] - public void GetTaskDetail_ReturnsFullConfig() + public void GetScenarioDetail_ReturnsFullConfig() { - var task = _service.CreateTask("Full Config", ""); + var scenario = _service.CreateScenario("Full Config", ""); // 保存各步骤配置 - _service.SaveScene(task.Id, new CombatScene + _service.SaveScene(scenario.Id, new CombatScene { SceneType = (int)SceneType.Mountain, WindSpeed = 10.0, Temperature = 25.0, }); - _service.SaveTarget(task.Id, new DroneProfile + _service.SaveTarget(scenario.Id, new DroneProfile { WaveId = "default", DroneType = (int)DroneType.FixedWing, Quantity = 3, }); - _service.SaveCloudDispersal(task.Id, new CloudDispersal + _service.SaveCloudDispersal(scenario.Id, new CloudDispersal { AerosolType = (int)AerosolType.ActiveMaterial, Duration = 45.0, }); - _service.UpdateStep(task.Id, 4); + _service.UpdateStep(scenario.Id, 4); // 读取完整配置 - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); - Assert.Equal("Full Config", detail.Task.Name); - Assert.Equal(4, detail.Task.CurrentStep); + Assert.Equal("Full Config", detail.Info.Name); + Assert.Equal(4, detail.Info.CurrentStep); Assert.Equal((int)SceneType.Mountain, detail.Scene.SceneType); Assert.Equal(10.0, detail.Scene.WindSpeed); Assert.Equal(3, detail.Targets[0].Quantity); @@ -132,15 +132,15 @@ namespace CounterDrone.Core.Tests [Fact] public void SaveScene_FirstTime_Inserts() { - var task = _service.CreateTask("Scene Test", ""); - _service.SaveScene(task.Id, new CombatScene + var scenario = _service.CreateScenario("Scene Test", ""); + _service.SaveScene(scenario.Id, new CombatScene { WeatherType = (int)WeatherType.Fog, Visibility = 2000.0, TimeOfDay = "03:00", }); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); Assert.Equal((int)WeatherType.Fog, detail.Scene.WeatherType); Assert.Equal(2000.0, detail.Scene.Visibility); Assert.Equal("03:00", detail.Scene.TimeOfDay); @@ -149,27 +149,27 @@ namespace CounterDrone.Core.Tests [Fact] public void SaveScene_SecondTime_Updates() { - var task = _service.CreateTask("Update Scene", ""); - _service.SaveScene(task.Id, new CombatScene { WindSpeed = 5.0 }); - _service.SaveScene(task.Id, new CombatScene { WindSpeed = 15.0 }); + var scenario = _service.CreateScenario("Update Scene", ""); + _service.SaveScene(scenario.Id, new CombatScene { WindSpeed = 5.0 }); + _service.SaveScene(scenario.Id, new CombatScene { WindSpeed = 15.0 }); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); Assert.Equal(15.0, detail.Scene.WindSpeed); } [Fact] public void SaveControlZones_SavesAndRetrieves() { - var task = _service.CreateTask("Zone Test", ""); + var scenario = _service.CreateScenario("Zone Test", ""); var zones = new List { new ControlZone { Name = "禁区A", VerticesJson = "[{\"x\":0,\"y\":0,\"z\":0},{\"x\":100,\"y\":0,\"z\":0},{\"x\":100,\"y\":100,\"z\":0}]", MinAltitude = 0, MaxAltitude = 500 }, new ControlZone { Name = "禁区B", VerticesJson = "[{\"x\":200,\"y\":200,\"z\":0}]", MinAltitude = 100, MaxAltitude = 300 }, }; - _service.SaveControlZones(task.Id, zones); + _service.SaveControlZones(scenario.Id, zones); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); Assert.Equal(2, detail.ControlZones.Count); Assert.Equal("禁区A", detail.ControlZones[0].Name); Assert.Equal(0, detail.ControlZones[0].OrderIndex); @@ -180,26 +180,26 @@ namespace CounterDrone.Core.Tests [Fact] public void SaveControlZones_ReplaceExisting() { - var task = _service.CreateTask("Zone Replace", ""); - _service.SaveControlZones(task.Id, new List + var scenario = _service.CreateScenario("Zone Replace", ""); + _service.SaveControlZones(scenario.Id, new List { new ControlZone { Name = "Old" } }); - _service.SaveControlZones(task.Id, new List + _service.SaveControlZones(scenario.Id, new List { new ControlZone { Name = "New1" }, new ControlZone { Name = "New2" }, }); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); Assert.Equal(2, detail.ControlZones.Count); } [Fact] public void SaveTarget_SavesCorrectly() { - var task = _service.CreateTask("Target Test", ""); - _service.SaveTarget(task.Id, new DroneProfile + var scenario = _service.CreateScenario("Target Test", ""); + _service.SaveTarget(scenario.Id, new DroneProfile { WaveId = "default", DroneType = (int)DroneType.FixedWing, @@ -210,7 +210,7 @@ namespace CounterDrone.Core.Tests TypicalAltitude = 800.0, }); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); var target = detail.Targets[0]; Assert.Equal((int)DroneType.FixedWing, target.DroneType); Assert.Equal(5, target.Quantity); @@ -220,7 +220,7 @@ namespace CounterDrone.Core.Tests [Fact] public void SaveDeployment_SavesMultiple() { - var task = _service.CreateTask("Equip Test", ""); + var scenario = _service.CreateScenario("Equip Test", ""); var equips = new List { new EquipmentDeployment @@ -240,9 +240,9 @@ namespace CounterDrone.Core.Tests }, }; - _service.SaveDeployment(task.Id, equips); + _service.SaveDeployment(scenario.Id, equips); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); Assert.Equal(2, detail.Equipment.Count); var platform = detail.Equipment.Find(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform); @@ -254,7 +254,7 @@ namespace CounterDrone.Core.Tests [Fact] public void SaveRoute_SavesWaypoints() { - var task = _service.CreateTask("Route Test", ""); + var scenario = _service.CreateScenario("Route Test", ""); var route = new RoutePlan { FormationMode = (int)FormationMode.Formation, @@ -267,9 +267,9 @@ namespace CounterDrone.Core.Tests new Waypoint { PosX = 10000, PosY = 0, PosZ = 100, Altitude = 300, Speed = 80 }, }; - _service.SaveRoute(task.Id, "default", route, waypoints); + _service.SaveRoute(scenario.Id, "default", route, waypoints); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); Assert.Equal((int)FormationMode.Formation, detail.Routes[0].FormationMode); Assert.Equal(3, detail.WaypointGroups["default"].Count); Assert.Equal(0, detail.WaypointGroups["default"][0].OrderIndex); @@ -280,53 +280,53 @@ namespace CounterDrone.Core.Tests // ========== Search & Pagination ========== [Fact] - public void SearchTasks_KeywordFilter() + public void SearchScenarios_KeywordFilter() { - _service.CreateTask("城市防御演习", ""); - _service.CreateTask("平原拦截测试", ""); - _service.CreateTask("海岸边防演练", ""); + _service.CreateScenario("城市防御演习", ""); + _service.CreateScenario("平原拦截测试", ""); + _service.CreateScenario("海岸边防演练", ""); - var result = _service.SearchTasks("城市", null, null, 1, 10); + var result = _service.SearchScenarios("城市", null, null, 1, 10); Assert.Equal(1, result.TotalCount); Assert.Equal("城市防御演习", result.Items[0].Name); } [Fact] - public void SearchTasks_NoResults() + public void SearchScenarios_NoResults() { - _service.CreateTask("Task A", ""); - var result = _service.SearchTasks("不存在的任务", null, null, 1, 10); + _service.CreateScenario("scenario A", ""); + var result = _service.SearchScenarios("不存在的任务", null, null, 1, 10); Assert.Equal(0, result.TotalCount); } [Fact] - public void SearchTasks_Pagination() + public void SearchScenarios_Pagination() { for (int i = 0; i < 15; i++) - _service.CreateTask($"Task {i:D2}", ""); + _service.CreateScenario($"scenario {i:D2}", ""); - var page1 = _service.SearchTasks(null, null, null, 1, 5); + var page1 = _service.SearchScenarios(null, null, null, 1, 5); Assert.Equal(21, page1.TotalCount); // 15 + 6 预设想定 Assert.Equal(5, page1.Items.Count); Assert.Equal(5, page1.TotalPages); // 21 ÷ 5 = 5 页 - var page3 = _service.SearchTasks(null, null, null, 3, 5); + var page3 = _service.SearchScenarios(null, null, null, 3, 5); Assert.Equal(5, page3.Items.Count); } [Fact] - public void SearchTasks_DateRangeFilter() + public void SearchScenarios_DateRangeFilter() { - // All tasks created today, so date filter should include them - _service.CreateTask("Recent Task", ""); + // All scenarios created today, so date filter should include them + _service.CreateScenario("Recent scenario", ""); var yesterday = DateTime.UtcNow.AddDays(-1).ToString("yyyy-MM-dd"); var tomorrow = DateTime.UtcNow.AddDays(1).ToString("yyyy-MM-dd"); - var result = _service.SearchTasks(null, yesterday, tomorrow, 1, 10); + var result = _service.SearchScenarios(null, yesterday, tomorrow, 1, 10); Assert.Equal(7, result.TotalCount); // 1 + 6 预设想定 - var oldResult = _service.SearchTasks(null, "2020-01-01", "2020-12-31", 1, 10); + var oldResult = _service.SearchScenarios(null, "2020-01-01", "2020-12-31", 1, 10); Assert.Equal(0, oldResult.TotalCount); } @@ -335,28 +335,28 @@ namespace CounterDrone.Core.Tests [Fact] public void UpdateStep_ValidSteps() { - var task = _service.CreateTask("Step Test", ""); - Assert.Equal(1, task.CurrentStep); + var scenario = _service.CreateScenario("Step Test", ""); + Assert.Equal(1, scenario.CurrentStep); - _service.UpdateStep(task.Id, 3); - var detail = _service.GetTaskDetail(task.Id); - Assert.Equal(3, detail.Task.CurrentStep); + _service.UpdateStep(scenario.Id, 3); + var detail = _service.GetScenarioDetail(scenario.Id); + Assert.Equal(3, detail.Info.CurrentStep); - _service.UpdateStep(task.Id, 5); - detail = _service.GetTaskDetail(task.Id); - Assert.Equal(5, detail.Task.CurrentStep); + _service.UpdateStep(scenario.Id, 5); + detail = _service.GetScenarioDetail(scenario.Id); + Assert.Equal(5, detail.Info.CurrentStep); } [Fact] public void UpdateStep_ClampedToRange() { - var task = _service.CreateTask("Clamp Test", ""); + var scenario = _service.CreateScenario("Clamp Test", ""); - _service.UpdateStep(task.Id, 0); - Assert.Equal(1, _service.GetTaskDetail(task.Id).Task.CurrentStep); + _service.UpdateStep(scenario.Id, 0); + Assert.Equal(1, _service.GetScenarioDetail(scenario.Id).Info.CurrentStep); - _service.UpdateStep(task.Id, 10); - Assert.Equal(5, _service.GetTaskDetail(task.Id).Task.CurrentStep); + _service.UpdateStep(scenario.Id, 10); + Assert.Equal(5, _service.GetScenarioDetail(scenario.Id).Info.CurrentStep); } // ========== Full Workflow ========== @@ -365,11 +365,11 @@ namespace CounterDrone.Core.Tests public void FullWorkflow_CreateConfigureSearch() { // 1. 创建任务 - var task = _service.CreateTask("完整流程测试", ""); - Assert.NotNull(task); + var scenario = _service.CreateScenario("完整流程测试", ""); + Assert.NotNull(scenario); // 2. 步骤1:作战场景 - _service.SaveScene(task.Id, new CombatScene + _service.SaveScene(scenario.Id, new CombatScene { SceneType = (int)SceneType.Urban, WeatherType = (int)WeatherType.Rain, @@ -378,10 +378,10 @@ namespace CounterDrone.Core.Tests Temperature = 18.0, TimeOfDay = "14:00", }); - _service.UpdateStep(task.Id, 1); + _service.UpdateStep(scenario.Id, 1); // 3. 步骤1扩展:管控区域 - _service.SaveControlZones(task.Id, new List + _service.SaveControlZones(scenario.Id, new List { new ControlZone { @@ -392,7 +392,7 @@ namespace CounterDrone.Core.Tests }); // 4. 步骤2:目标配置 - _service.SaveTarget(task.Id, new DroneProfile + _service.SaveTarget(scenario.Id, new DroneProfile { WaveId = "default", DroneType = (int)DroneType.HighSpeed, @@ -400,10 +400,10 @@ namespace CounterDrone.Core.Tests PowerType = (int)PowerType.Jet, TypicalSpeed = 300.0, }); - _service.UpdateStep(task.Id, 2); + _service.UpdateStep(scenario.Id, 2); // 5. 步骤3:装备部署 - _service.SaveDeployment(task.Id, new List + _service.SaveDeployment(scenario.Id, new List { new EquipmentDeployment { @@ -421,10 +421,10 @@ namespace CounterDrone.Core.Tests MunitionCount = 2, }, }); - _service.UpdateStep(task.Id, 3); + _service.UpdateStep(scenario.Id, 3); // 6. 步骤4:云团抛撒 - _service.SaveCloudDispersal(task.Id, new CloudDispersal + _service.SaveCloudDispersal(scenario.Id, new CloudDispersal { AerosolType = (int)AerosolType.ActiveMaterial, TriggerMode = (int)TriggerMode.Area, @@ -433,10 +433,10 @@ namespace CounterDrone.Core.Tests PositionY = 0, PositionZ = 300, }); - _service.UpdateStep(task.Id, 4); + _service.UpdateStep(scenario.Id, 4); // 7. 步骤5:航路规划 - _service.SaveRoute(task.Id, "default", new RoutePlan + _service.SaveRoute(scenario.Id, "default", new RoutePlan { FormationMode = (int)FormationMode.Swarm, LateralSpacing = 30.0, @@ -445,14 +445,14 @@ namespace CounterDrone.Core.Tests new Waypoint { PosX = 0, PosY = 100, PosZ = 200, Altitude = 600, Speed = 250 }, new Waypoint { PosX = 10000, PosY = 100, PosZ = 200, Altitude = 600, Speed = 250 }, }); - _service.UpdateStep(task.Id, 5); + _service.UpdateStep(scenario.Id, 5); // 8. 验证完整配置 - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); - Assert.Equal("完整流程测试", detail.Task.Name); - Assert.Equal(5, detail.Task.CurrentStep); - Assert.Equal((int)TaskStatus.Configuring, detail.Task.Status); + Assert.Equal("完整流程测试", detail.Info.Name); + Assert.Equal(5, detail.Info.CurrentStep); + Assert.Equal((int)ScenarioStatus.Configuring, detail.Info.Status); // 场景 Assert.Equal((int)SceneType.Urban, detail.Scene.SceneType); @@ -481,7 +481,7 @@ namespace CounterDrone.Core.Tests Assert.Equal(250.0, detail.WaypointGroups["default"][0].Speed); // 9. 搜索验证 - var searchResult = _service.SearchTasks("完整流程", null, null, 1, 10); + var searchResult = _service.SearchScenarios("完整流程", null, null, 1, 10); Assert.Equal(1, searchResult.TotalCount); } @@ -492,8 +492,8 @@ namespace CounterDrone.Core.Tests [Fact] public void AddDetection_PersistsAndQueryable() { - var task = _service.CreateTask("探测设备测试", ""); - _service.AddDetection(task.Id, new EquipmentDeployment + var scenario = _service.CreateScenario("探测设备测试", ""); + _service.AddDetection(scenario.Id, new EquipmentDeployment { Quantity = 1, PositionX = 5000, PositionY = 0, PositionZ = 0, @@ -501,7 +501,7 @@ namespace CounterDrone.Core.Tests DetectionAccuracy = 50, }); - var detections = _service.GetDetections(task.Id); + var detections = _service.GetDetections(scenario.Id); Assert.Single(detections); Assert.Equal((int)EquipmentRole.Detection, detections[0].EquipmentRole); Assert.Equal(8000.0, detections[0].RadarRange); @@ -511,9 +511,9 @@ namespace CounterDrone.Core.Tests [Fact] public void GetDetections_FiltersOutLaunchPlatforms() { - var task = _service.CreateTask("探测过滤测试", ""); + var scenario = _service.CreateScenario("探测过滤测试", ""); // 一个火力单元 - _service.SaveDeployment(task.Id, new List + _service.SaveDeployment(scenario.Id, new List { new EquipmentDeployment { @@ -522,39 +522,39 @@ namespace CounterDrone.Core.Tests }, }); // 两个探测设备(独立添加) - _service.AddDetection(task.Id, new EquipmentDeployment { RadarRange = 5000 }); - _service.AddDetection(task.Id, new EquipmentDeployment { EORange = 3000 }); + _service.AddDetection(scenario.Id, new EquipmentDeployment { RadarRange = 5000 }); + _service.AddDetection(scenario.Id, new EquipmentDeployment { EORange = 3000 }); - var detections = _service.GetDetections(task.Id); + var detections = _service.GetDetections(scenario.Id); Assert.Equal(2, detections.Count); // 只有探测设备,不含火力单元 } [Fact] public void DeleteDetection_RemovesOnlyOne() { - var task = _service.CreateTask("探测删除测试", ""); - _service.AddDetection(task.Id, new EquipmentDeployment { RadarRange = 5000 }); + var scenario = _service.CreateScenario("探测删除测试", ""); + _service.AddDetection(scenario.Id, new EquipmentDeployment { RadarRange = 5000 }); var det2 = new EquipmentDeployment { EORange = 3000 }; - _service.AddDetection(task.Id, det2); + _service.AddDetection(scenario.Id, det2); _service.DeleteDetection(det2.Id); - var detections = _service.GetDetections(task.Id); + var detections = _service.GetDetections(scenario.Id); Assert.Single(detections); Assert.Equal(5000.0, detections[0].RadarRange); } [Fact] - public void GetTaskDetail_IncludesDetections() + public void GetScenarioDetail_IncludesDetections() { - var task = _service.CreateTask("想定含探测", ""); - _service.SaveDeployment(task.Id, new List + var scenario = _service.CreateScenario("想定含探测", ""); + _service.SaveDeployment(scenario.Id, new List { new EquipmentDeployment { EquipmentRole = (int)EquipmentRole.LaunchPlatform, Quantity = 1 }, }); - _service.AddDetection(task.Id, new EquipmentDeployment { RadarRange = 10000 }); + _service.AddDetection(scenario.Id, new EquipmentDeployment { RadarRange = 10000 }); - var detail = _service.GetTaskDetail(task.Id); + var detail = _service.GetScenarioDetail(scenario.Id); // Equipment 包含火力单元 + 探测设备 Assert.Equal(2, detail.Equipment.Count); Assert.Contains(detail.Equipment, e => e.EquipmentRole == (int)EquipmentRole.Detection); diff --git a/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs b/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs index bfe10a1..8e8f5be 100644 --- a/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs +++ b/test/unit/CounterDrone.Core.Tests/SimulationEngineTests.cs @@ -47,8 +47,8 @@ namespace CounterDrone.Core.Tests private void SetupScenario() { - var task = _scenarioService.CreateTask("Test", ""); - _scenarioId = task.Id; + var scenario = _scenarioService.CreateScenario("Test", ""); + _scenarioId = scenario.Id; _scenarioService.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 }); _scenarioService.SaveTarget(_scenarioId, new DroneProfile { @@ -148,8 +148,8 @@ namespace CounterDrone.Core.Tests private void SetupScenarioWithDetection() { - var task = _scenarioService.CreateTask("Detect", ""); - _scenarioId = task.Id; + var scenario = _scenarioService.CreateScenario("Detect", ""); + _scenarioId = scenario.Id; _scenarioService.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0, Visibility = 10000 }); _scenarioService.SaveTarget(_scenarioId, new DroneProfile { @@ -222,24 +222,24 @@ namespace CounterDrone.Core.Tests public void TargetDetected_FiresAgainAfterLeaveAndReenter() { // 探测设备在 X=5000 半径 1000 → 入口 X=4000,出口 X=6000 - var task = _scenarioService.CreateTask("Reenter", ""); - _scenarioService.SaveScene(task.Id, new CombatScene { WindSpeed = 0, Visibility = 10000 }); - _scenarioService.SaveTarget(task.Id, new DroneProfile + var scenario = _scenarioService.CreateScenario("Reenter", ""); + _scenarioService.SaveScene(scenario.Id, new CombatScene { WindSpeed = 0, Visibility = 10000 }); + _scenarioService.SaveTarget(scenario.Id, new DroneProfile { WaveId = "w1", Quantity = 1, TypicalSpeed = 120, PowerType = (int)PowerType.Piston, TypicalAltitude = 300, }); - _scenarioService.SaveDeployment(task.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, Quantity = 1, PositionX = 0, PositionY = 0, PositionZ = 0, AerosolType = (int)AerosolType.InertGas, MunitionCount = 1 }, }); - _scenarioService.SaveCloudDispersal(task.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 300, Duration = 60 }); - _scenarioService.SaveRoute(task.Id, "w1", new RoutePlan(), + _scenarioService.SaveCloudDispersal(scenario.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 300, Duration = 60 }); + _scenarioService.SaveRoute(scenario.Id, "w1", new RoutePlan(), new() { new() { PosX = 0, PosY = 300, PosZ = 0, Speed = 120 }, new() { PosX = 10000, PosY = 300, PosZ = 0, Speed = 120 } }); _engine.SetFireSchedule(new List()); - _engine.Initialize(task.Id); + _engine.Initialize(scenario.Id); int detectCount = 0; for (int i = 0; i < 3000; i++) @@ -273,25 +273,25 @@ namespace CounterDrone.Core.Tests { // 两个探测设备:D1在 X=3000 半径 2000、D2在 X=7000 半径 4000 // D1 边界 X=1000,D2 边界 X=3000 → D1 更早发现 - var task = _scenarioService.CreateTask("Fuse", ""); - _scenarioService.SaveScene(task.Id, new CombatScene { WindSpeed = 0, Visibility = 10000 }); - _scenarioService.SaveTarget(task.Id, new DroneProfile + var scenario = _scenarioService.CreateScenario("Fuse", ""); + _scenarioService.SaveScene(scenario.Id, new CombatScene { WindSpeed = 0, Visibility = 10000 }); + _scenarioService.SaveTarget(scenario.Id, new DroneProfile { WaveId = "w1", Quantity = 1, TypicalSpeed = 60, PowerType = (int)PowerType.Piston, TypicalAltitude = 300, }); - _scenarioService.SaveDeployment(task.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 }, new() { EquipmentRole = (int)EquipmentRole.LaunchPlatform, PlatformType = (int)PlatformType.GroundBased, Quantity = 1, PositionX = 0, PositionY = 0, PositionZ = 0, AerosolType = (int)AerosolType.InertGas, MunitionCount = 1 }, }); - _scenarioService.SaveCloudDispersal(task.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 300, Duration = 60 }); - _scenarioService.SaveRoute(task.Id, "w1", new RoutePlan(), + _scenarioService.SaveCloudDispersal(scenario.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 300, Duration = 60 }); + _scenarioService.SaveRoute(scenario.Id, "w1", new RoutePlan(), new() { new() { PosX = 0, PosY = 300, PosZ = 0, Speed = 60 }, new() { PosX = 10000, PosY = 300, PosZ = 0, Speed = 60 } }); _engine.SetFireSchedule(new List()); - _engine.Initialize(task.Id); + _engine.Initialize(scenario.Id); SimEvent? detected = null; for (int i = 0; i < 6000 && detected == null; i++)