CounterDroneBackend/src/CounterDrone.Core/DefaultData.cs
tian 69ec9ed0e2 ScenarioDrone/ScenarioUnit 表精简:外键引用基础数据,去冗余字段
- ScenarioDrone: 仅保留 Id/ScenarioId/DroneSpecId/WaveId/Quantity
- ScenarioUnit: 仅保留 Id/ScenarioId/FireUnitSpecId/SensorSpecId/Position 等想定字段
- DroneEntity/PlatformEntity 构造函数改为接收 DroneSpec/FireUnitSpec
- SimulationEngine 加载 spec 字典,build 方法通过 FK 查 spec
- ReportGenerator/ReportService 通过 spec 字典取值
- DefaultLaneDivider.Divide 从 DroneWave.Quantity 取值
- Core 编译通过,测试待修复
2026-06-18 16:47:30 +08:00

264 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using CounterDrone.Core.Models;
namespace CounterDrone.Core
{
/// <summary>
/// 统一默认数据 — 弹药、编队、火力单元、无人机、探测设备、天气的预设库。
/// 所有默认数据集中在 data/defaults.json通过本类统一加载。
/// </summary>
public class DefaultData
{
public string Version { get; set; } = "0";
public List<AmmunitionSpec> Ammunition { get; set; } = new();
public List<FormationTemplate> Formations { get; set; } = new();
public List<RouteTemplate> Routes { get; set; } = new();
[System.Text.Json.Serialization.JsonPropertyName("fireUnits")]
public List<FireUnitSpec> FireUnits { get; set; } = new();
[System.Text.Json.Serialization.JsonPropertyName("drones")]
public List<DroneSpec> Drones { get; set; } = new();
[System.Text.Json.Serialization.JsonPropertyName("detectionEquipment")]
public List<SensorSpec> Sensors { get; set; } = new();
[System.Text.Json.Serialization.JsonPropertyName("weather")]
public List<EnvironmentSpec> Environments { get; set; } = new();
/// <summary>从 data/defaults.json 加载。文件缺失或解析失败即抛异常。</summary>
public static DefaultData Load(IPathProvider paths)
{
var jsonPath = Path.Combine(paths.GetDataRoot(), "defaults.json");
if (!File.Exists(jsonPath))
throw new FileNotFoundException($"默认数据文件未找到: {jsonPath}");
var opts = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var data = JsonSerializer.Deserialize<DefaultData>(File.ReadAllText(jsonPath), opts)
?? throw new InvalidOperationException($"默认数据文件解析失败: {jsonPath}");
Validate(data, jsonPath);
return data;
}
/// <summary>从 JSON 字符串解析(测试用)</summary>
public static DefaultData FromJson(string json)
{
var opts = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var data = JsonSerializer.Deserialize<DefaultData>(json, opts)
?? throw new InvalidOperationException("默认数据 JSON 解析失败");
Validate(data, "<string>");
return data;
}
private static void Validate(DefaultData data, string source)
{
if (data.Ammunition == null || data.Ammunition.Count == 0)
throw new InvalidOperationException($"默认数据缺少 ammunition: {source}");
if (data.Formations == null || data.Formations.Count == 0)
throw new InvalidOperationException($"默认数据缺少 formations: {source}");
if (data.Routes == null || data.Routes.Count == 0)
throw new InvalidOperationException($"默认数据缺少 routes: {source}");
if (data.FireUnits == null || data.FireUnits.Count == 0)
throw new InvalidOperationException($"默认数据缺少 fireUnits: {source}");
if (data.Drones == null || data.Drones.Count == 0)
throw new InvalidOperationException($"默认数据缺少 drones: {source}");
if (data.Environments == null || data.Environments.Count == 0)
throw new InvalidOperationException($"默认数据缺少 environments: {source}");
if (data.Sensors == null)
data.Sensors = new();
}
}
/// <summary>编队模板</summary>
public class FormationTemplate
{
public string Id { get; set; } = "";
public string Name { get; set; } = "";
public int FormationMode { get; set; }
public int LateralCount { get; set; } = 1;
public int LongitudinalCount { get; set; } = 1;
public double LateralSpacing { get; set; }
public double LongitudinalSpacing { get; set; }
public int LateralAxis { get; set; } = 2; // 0=X, 1=Y, 2=Z
public int LongitudinalAxis { get; set; } = 0; // 0=X, 1=Y, 2=Z
public RoutePlan ToRoutePlan()
{
return new RoutePlan
{
FormationMode = FormationMode,
LateralCount = LateralCount,
LongitudinalCount = LongitudinalCount,
LateralSpacing = LateralSpacing,
LongitudinalSpacing = LongitudinalSpacing,
LateralAxis = LateralAxis,
LongitudinalAxis = LongitudinalAxis,
};
}
}
/// <summary>火力单元规格(基础数据模板)</summary>
[SQLite.Table("FireUnitSpec")]
public class FireUnitSpec
{
[SQLite.PrimaryKey]
public string Id { get; set; } = "";
public string Name { get; set; } = "";
public int PlatformType { get; set; }
public int GunCount { get; set; } = 1;
public int ChannelsPerGun { get; set; } = 1;
public double ChannelInterval { get; set; } = 1.0;
public double Cooldown { get; set; } = 5.0;
public double AmmoChangeTime { get; set; } = 30.0;
public double MuzzleVelocity { get; set; }
public double CruiseSpeed { get; set; }
public double ReleaseAltitude { get; set; }
[SQLite.Ignore]
public List<int> AmmoTypes { get; set; } = new();
public double RadarRange { get; set; }
public double EORange { get; set; }
public double IRRange { get; set; }
// 3D 球冠几何(缺失时退化 2D
public double? MinElevation { get; set; }
public double? MaxElevation { get; set; }
public double? MinDetectAlt { get; set; }
public double? MaxDetectAlt { get; set; }
public ScenarioUnit ToScenarioUnit(AerosolType ammoType, int quantity,
double posX, double posY, double posZ)
{
return new ScenarioUnit
{
FireUnitSpecId = Id,
EquipmentRole = (int)Models.EquipmentRole.LaunchPlatform,
Quantity = quantity,
PositionX = posX,
PositionY = posY,
PositionZ = posZ,
AerosolType = (int)ammoType,
MunitionCount = GunCount * ChannelsPerGun * quantity,
};
}
}
/// <summary>无人机规格(基础数据模板)</summary>
[SQLite.Table("DroneSpec")]
public class DroneSpec
{
[SQLite.PrimaryKey]
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; }
public double TypicalAltitude { get; set; }
public ScenarioDrone ToScenarioDrone(string waveId = "default")
{
return new ScenarioDrone
{
DroneSpecId = Id,
WaveId = waveId,
Quantity = 1,
};
}
}
/// <summary>传感器规格(基础数据模板)</summary>
[SQLite.Table("SensorSpec")]
public class SensorSpec
{
[SQLite.PrimaryKey]
public string Id { get; set; } = "";
public string Name { get; set; } = "";
public double RadarRange { get; set; }
public double EORange { get; set; }
public double IRRange { get; set; }
public double Accuracy { get; set; } = 50.0;
// 3D 球冠几何(缺失时退化 2D
public double? MinElevation { get; set; }
public double? MaxElevation { get; set; }
public double? MinDetectAlt { get; set; }
public double? MaxDetectAlt { get; set; }
public ScenarioUnit ToScenarioUnit(double posX, double posY, double posZ)
{
return new ScenarioUnit
{
SensorSpecId = Id,
EquipmentRole = (int)Models.EquipmentRole.Detection,
Quantity = 1,
PositionX = posX,
PositionY = posY,
PositionZ = posZ,
};
}
}
/// <summary>环境规格(基础数据模板)</summary>
[SQLite.Table("EnvironmentSpec")]
public class EnvironmentSpec
{
[SQLite.PrimaryKey]
public string Id { get; set; } = "";
public string Name { get; set; } = "";
public int WeatherType { get; set; }
public double WindSpeed { get; set; }
public int WindDirection { get; set; }
public double Temperature { get; set; } = 20.0;
public double Humidity { get; set; } = 60.0;
public double Pressure { get; set; } = 1013.0;
public double Visibility { get; set; } = 5000.0;
public CombatScene ToCombatScene()
{
return new CombatScene
{
WeatherType = WeatherType,
WindSpeed = WindSpeed,
WindDirection = WindDirection,
Temperature = Temperature,
Humidity = Humidity,
Pressure = Pressure,
Visibility = Visibility,
};
}
}
/// <summary>航线模板(基础数据模板)</summary>
[SQLite.Table("RouteTemplate")]
public class RouteTemplate
{
[SQLite.PrimaryKey]
public string Id { get; set; } = "";
public string Name { get; set; } = "";
/// <summary>航路点 JSONWaypointCoord 序列化SQLite 存储用</summary>
public string WaypointsJson { get; set; } = "[]";
[SQLite.Ignore]
public List<WaypointCoord> Waypoints { get; set; } = new();
public List<Waypoint> ToWaypoints(double speed)
{
var list = new List<Waypoint>();
foreach (var w in Waypoints)
list.Add(new Waypoint
{
PosX = w.X, PosY = w.Y, PosZ = w.Z,
Altitude = w.Y, Speed = speed,
});
return list;
}
}
public class WaypointCoord
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
}