using System; using System.Collections.Generic; using System.IO; using System.Linq; using CounterDrone.Core; using CounterDrone.Core.Algorithms; using CounterDrone.Core.Models; using CounterDrone.Core.Repository; using CounterDrone.Core.Services; using SQLite; using Xunit; namespace CounterDrone.Core.Tests { public class DefenseRecommendationTests : IDisposable { private readonly string _testDir; private readonly IPathProvider _paths; private readonly SQLiteConnection _db; private readonly ScenarioService _scenario; private string _scenarioId = string.Empty; public DefenseRecommendationTests() { _testDir = Path.Combine(Path.GetTempPath(), $"cd_rec_{Guid.NewGuid():N}"); _paths = new TestPathProvider(_testDir); var dbm = new DatabaseManager(_paths); _db = dbm.OpenMainDb(); var planner = new DefensePlanner( DefaultData.Load(_paths).Ammunition, PlannerConfig.Load(_paths)); _scenario = new ScenarioService( new ScenarioRepository(_db), new CombatSceneRepository(_db), new ControlZoneRepository(_db), new ScenarioDroneRepository(_db), new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db), new RoutePlanRepository(_db), new WaypointRepository(_db), _paths, planner); } public void Dispose() { _db?.Close(); if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true); } [Fact] public void GetDefenseRecommendation_PresetScenario_ReturnsBest() { // 用预设想定 var results = _scenario.SearchScenarios("活塞", null, null, 1, 10); Assert.True(results.TotalCount > 0, "预设想定未找到"); _scenarioId = results.Items[0].Id; var rec = _scenario.GetDefenseRecommendation(_scenarioId); Assert.True(rec.Success, $"推荐失败: {rec.Summary}"); Assert.True(rec.Best.SalvoRounds > 0, "最佳方案弹药数应 > 0"); Assert.True(rec.Best.EstimatedProbability > 0, "最佳方案概率应 > 0"); Assert.NotEmpty(rec.Summary); } [Fact] public void GetDefenseRecommendation_NoFireUnits_ReturnsFailure() { // 创建无火力单元的想定 var sc = _scenario.CreateScenario("无防御测试", ""); _scenarioId = sc.Id; _scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0, Visibility = 10000 }); _scenario.SaveScenarioDrone(_scenarioId, TestData.CreateScenarioDrone("default", 1)); _scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single }, new List { new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 }, new() { PosX = 10000, PosY = 500, PosZ = 0, Speed = 200 }, }); _scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal { AerosolType = (int)AerosolType.InertGas }); var rec = _scenario.GetDefenseRecommendation(_scenarioId); Assert.False(rec.Success); Assert.Contains("火力单元", rec.Summary); } [Fact] public void GetDefenseRecommendation_NoPlanner_Throws() { // 不传 planner 的 ScenarioService var svcNoPlanner = new ScenarioService( new ScenarioRepository(_db), new CombatSceneRepository(_db), new ControlZoneRepository(_db), new ScenarioDroneRepository(_db), new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db), new RoutePlanRepository(_db), new WaypointRepository(_db)); Assert.Throws(() => svcNoPlanner.GetDefenseRecommendation("any")); } } }