using System;
using System.Collections.Generic;
using System.IO;
using CounterDrone.Core;
using CounterDrone.Core.Algorithms;
using CounterDrone.Core.Models;
using CounterDrone.Core.Repository;
using CounterDrone.Core.Services;
using CounterDrone.Core.Simulation;
using Xunit;
namespace CounterDrone.Core.Tests
{
/// 边界场景测试
public class EdgeCaseTests : IDisposable
{
private readonly string _testDir;
private readonly IScenarioService _scenario;
private readonly SQLite.SQLiteConnection _db;
private string _scenarioId = string.Empty;
public EdgeCaseTests()
{
_testDir = Path.Combine(Path.GetTempPath(), $"cd_edge_{Guid.NewGuid():N}");
var paths = new TestPathProvider(_testDir);
var dbm = new DatabaseManager(paths);
_db = dbm.OpenMainDb();
_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));
}
public void Dispose()
{
_db?.Close();
if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true);
}
[Fact]
public void EmptyDeployment_EngineRunsWithoutCrash()
{
var scenario = _scenario.CreateScenario("空部署", "");
_scenarioId = scenario.Id;
_scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 });
_scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone
{
WaveId = "default",
DroneType = (int)DroneType.FixedWing,
Quantity = 1,
TypicalSpeed = 100,
TypicalAltitude = 300,
});
_scenario.SaveDeployment(_scenarioId, new List());
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List
{
new Waypoint { PosX = 0, PosY = 300, PosZ = 0, Speed = 100 },
new Waypoint { PosX = 1000, PosY = 300, PosZ = 0, Speed = 100 },
});
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Ammo, TestPlannerConfig.Instance));
engine.Initialize(_scenarioId);
engine.TimeScale = 4f;
for (int i = 0; i < 500; i++)
{
var r = engine.Tick(1f / 20f);
if (r.State == SimulationState.Completed) break;
}
engine.Stop();
Assert.Equal(DroneStatus.ReachedTarget, engine.Drones[0].Status);
}
[Fact]
public void ExtremeWind_DroneStillFlies()
{
var scenario = _scenario.CreateScenario("飓风", "");
_scenarioId = scenario.Id;
_scenario.SaveScene(_scenarioId, new CombatScene
{
WindSpeed = 30, // 最大风速
WindDirection = (int)WindDirection.E,
});
_scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone
{
WaveId = "default",
DroneType = (int)DroneType.FixedWing,
Quantity = 1,
TypicalSpeed = 600, // 高速对抗强风
});
_scenario.SaveDeployment(_scenarioId, new List());
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List
{
new Waypoint { PosX = 0, PosY = 300, PosZ = 0, Speed = 600 },
new Waypoint { PosX = 5000, PosY = 300, PosZ = 0, Speed = 600 },
});
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Ammo, TestPlannerConfig.Instance));
engine.Initialize(_scenarioId);
engine.TimeScale = 4f;
for (int i = 0; i < 500; i++)
{
var r = engine.Tick(1f / 20f);
if (r.State == SimulationState.Completed) break;
}
engine.Stop();
// 强风下应偏移到东方(+X)
Assert.True(engine.Drones[0].PosX > 0);
}
[Fact]
public void LongRoute_CompletesWithoutError()
{
var scenario = _scenario.CreateScenario("超长航路", "");
_scenarioId = scenario.Id;
_scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 });
_scenario.SaveScenarioDrone(_scenarioId, new ScenarioDrone
{
WaveId = "default",
DroneType = (int)DroneType.HighSpeed,
Quantity = 1,
TypicalSpeed = 500,
});
_scenario.SaveDeployment(_scenarioId, new List());
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
// 500 km/h, 100km 航程
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List
{
new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 500 },
new Waypoint { PosX = 100000, PosY = 500, PosZ = 0, Speed = 500 },
});
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Ammo, TestPlannerConfig.Instance));
engine.Initialize(_scenarioId);
engine.TimeScale = 4f;
for (int i = 0; i < 5000; i++)
{
var r = engine.Tick(1f / 20f);
if (r.State == SimulationState.Completed) break;
}
engine.Stop();
Assert.Equal(DroneStatus.ReachedTarget, engine.Drones[0].Status);
}
}
}