378 lines
16 KiB
C#
378 lines
16 KiB
C#
using System.Diagnostics;
|
||
|
||
namespace ThreatSource.Tools.MissileSimulation
|
||
{
|
||
class Program
|
||
{
|
||
static void Main(string[] args)
|
||
{
|
||
Console.WriteLine("综合导弹模拟程序启动...");
|
||
var simulator = new ComprehensiveMissileSimulator();
|
||
// 如果需要,可以在启动时设置默认日志级别,或依赖Simulator的默认值
|
||
simulator.SetLogLevel(SourceLevels.Verbose);
|
||
ApplicationHostLoop(simulator);
|
||
Console.WriteLine("\n程序已退出。");
|
||
}
|
||
|
||
static void ApplicationHostLoop(ComprehensiveMissileSimulator simulator)
|
||
{
|
||
bool exitProgram = false;
|
||
while (!exitProgram)
|
||
{
|
||
Console.WriteLine("\n=== 导弹仿真系统主菜单 ===");
|
||
string missileStatus = string.IsNullOrEmpty(simulator.SelectedMissileId) ? "未选择" : $"已选: {simulator.SelectedMissileDisplayName}";
|
||
|
||
string sensorStatusString = "";
|
||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||
{
|
||
var indicators = simulator.GetActiveIndicators();
|
||
var firstActiveIndicator = indicators.FirstOrDefault(ind => ind.IsActive);
|
||
if (firstActiveIndicator.Name != null)
|
||
{
|
||
sensorStatusString = $"(已激活: {firstActiveIndicator.Name})";
|
||
}
|
||
else
|
||
{
|
||
sensorStatusString = "(无默认激活指示器)";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
sensorStatusString = "(需先选导弹)";
|
||
}
|
||
|
||
Console.WriteLine($"1. 选择导弹 ({missileStatus})");
|
||
Console.WriteLine($"2. 配置传感器 {sensorStatusString}");
|
||
Console.WriteLine($"3. 配置干扰 {simulator.GetActiveJammingDescription()} {(string.IsNullOrEmpty(simulator.SelectedMissileId) ? "(需先选导弹)" : "")}");
|
||
Console.WriteLine($"4. 设置日志级别 (当前级别: {simulator.CurrentLogLevel})");
|
||
Console.WriteLine($"5. 开始仿真 {(string.IsNullOrEmpty(simulator.SelectedMissileId) ? "(需先选导弹)" : "")}");
|
||
Console.WriteLine($"6. 设置仿真步长 (当前: {simulator.TimeStep}s)");
|
||
Console.WriteLine("0. 退出程序");
|
||
Console.Write("\n请选择: ");
|
||
string choice = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||
|
||
switch (choice)
|
||
{
|
||
case "1":
|
||
SelectMissile(simulator);
|
||
break;
|
||
case "2":
|
||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||
ConfigureSensors(simulator);
|
||
else
|
||
Console.WriteLine("请先选择导弹。");
|
||
break;
|
||
case "3":
|
||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||
ConfigureJamming(simulator);
|
||
else
|
||
Console.WriteLine("请先选择导弹。");
|
||
break;
|
||
case "4":
|
||
ShowLogLevelMenu(simulator);
|
||
break;
|
||
case "5":
|
||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||
{
|
||
RunSimulationInstance(simulator);
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("请先选择导弹并完成基本配置 (选择导弹是启动仿真的最低要求)。");
|
||
}
|
||
break;
|
||
case "6":
|
||
ConfigureTimeStep(simulator);
|
||
break;
|
||
case "0":
|
||
exitProgram = true;
|
||
break;
|
||
default:
|
||
Console.WriteLine("无效选择,请重试。");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
static void ShowLogLevelMenu(ComprehensiveMissileSimulator simulator)
|
||
{
|
||
bool backToMainMenu = false;
|
||
while (!backToMainMenu)
|
||
{
|
||
Console.WriteLine("\n--- 设置日志级别 ---");
|
||
Console.WriteLine("1. Off (关闭所有Trace/Debug输出)");
|
||
Console.WriteLine("2. Error (仅错误信息)");
|
||
Console.WriteLine("3. Warning (警告及错误)");
|
||
Console.WriteLine("4. Information (普通信息、警告、错误)");
|
||
Console.WriteLine("5. Verbose (所有信息,包括Debug.WriteLine)");
|
||
Console.WriteLine("0. 返回主菜单");
|
||
Console.Write("请选择日志级别: ");
|
||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||
|
||
SourceLevels currentLevel = simulator.CurrentLogLevel;
|
||
SourceLevels selectedLevel = currentLevel; // 默认使用当前级别
|
||
bool levelSet = false;
|
||
|
||
switch (input)
|
||
{
|
||
case "1": selectedLevel = SourceLevels.Off; levelSet = true; break;
|
||
case "2": selectedLevel = SourceLevels.Error; levelSet = true; break;
|
||
case "3": selectedLevel = SourceLevels.Warning; levelSet = true; break;
|
||
case "4": selectedLevel = SourceLevels.Information; levelSet = true; break;
|
||
case "5": selectedLevel = SourceLevels.Verbose; levelSet = true; break;
|
||
case "0": backToMainMenu = true; break;
|
||
default: Console.WriteLine("无效选择,请重试。"); break;
|
||
}
|
||
|
||
if (levelSet)
|
||
{
|
||
simulator.SetLogLevel(selectedLevel);
|
||
// 设置日志级别后,会由simulator打印确认
|
||
return; // 设置后返回主菜单
|
||
}
|
||
}
|
||
}
|
||
|
||
static void RunSimulationInstance(ComprehensiveMissileSimulator simulator)
|
||
{
|
||
Console.WriteLine("\n--- 开始仿真 --- ");
|
||
var simulationEndedEvent = new ManualResetEvent(false);
|
||
simulator.SimulationEnded += (sender, e) => {
|
||
simulationEndedEvent.Set();
|
||
// 防止多次调用RunSimulationInstance时出现的问题
|
||
if (sender is ComprehensiveMissileSimulator sim)
|
||
{
|
||
sim.SimulationEnded -= (s, args) => simulationEndedEvent.Set(); // 尝试取消订阅,精确的lambda匹配比较困难
|
||
}
|
||
};
|
||
|
||
var simulationThread = new Thread(simulator.Start);
|
||
simulationThread.Start();
|
||
|
||
Console.WriteLine("仿真已开始运行。在主菜单输入 '0' 可在下次返回主菜单时退出程序。");
|
||
Console.WriteLine("仿真过程中,您可以随时按 Enter 键尝试提前中止当前仿真实例并返回主菜单。");
|
||
|
||
bool simulationForceStopped = false;
|
||
while (!simulationEndedEvent.WaitOne(100)) // 每100ms检查一次仿真是否结束
|
||
{
|
||
if (Console.KeyAvailable)
|
||
{
|
||
var keyInfo = Console.ReadKey(intercept: true);
|
||
if (keyInfo.Key == ConsoleKey.Enter)
|
||
{
|
||
Console.WriteLine("\n用户请求中止当前仿真实例...");
|
||
simulator.Stop();
|
||
simulationForceStopped = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 等待仿真线程实际完成,特别是如果被强制停止。
|
||
simulationThread.Join();
|
||
|
||
if (simulationForceStopped)
|
||
{
|
||
Console.WriteLine("当前仿真实例已被用户中止。");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("当前导弹仿真自然结束。");
|
||
}
|
||
|
||
Console.WriteLine("按任意键返回主菜单...");
|
||
Console.ReadKey(); // 等待用户确认后返回主菜单
|
||
}
|
||
|
||
static void SelectMissile(ComprehensiveMissileSimulator simulator)
|
||
{
|
||
var missiles = new[]
|
||
{
|
||
("LSGM_1", "激光半主动制导导弹"),
|
||
("LBRM_1", "激光驾束制导导弹"),
|
||
("TSM_1", "末敏弹"),
|
||
("ICGM_1", "红外指令制导导弹"),
|
||
("ITGM_1", "红外成像末制导导弹"),
|
||
("MMWG_1", "毫米波末制导导弹"),
|
||
("CGGM_1", "复合制导导弹")
|
||
};
|
||
|
||
while (true)
|
||
{
|
||
Console.WriteLine("\n--- 选择导弹类型 ---");
|
||
for (int i = 0; i < missiles.Length; i++)
|
||
{
|
||
Console.WriteLine($" {i + 1}. {missiles[i].Item2}");
|
||
}
|
||
Console.WriteLine(" 0. 返回主菜单");
|
||
Console.Write("请选择: ");
|
||
|
||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||
if (input == "0")
|
||
return;
|
||
|
||
if (int.TryParse(input, out int choice) &&
|
||
choice >= 1 && choice <= missiles.Length)
|
||
{
|
||
simulator.SelectMissile(missiles[choice - 1].Item1);
|
||
Console.WriteLine($"已选择: {simulator.SelectedMissileDisplayName}");
|
||
return;
|
||
}
|
||
Console.WriteLine("无效选择,请重试。");
|
||
}
|
||
}
|
||
|
||
static void ConfigureSensors(ComprehensiveMissileSimulator simulator)
|
||
{
|
||
while (true)
|
||
{
|
||
Console.WriteLine("\n--- 配置传感器和指示器 ---");
|
||
Console.WriteLine("当前传感器状态:");
|
||
var indicators = simulator.GetActiveIndicators();
|
||
if (indicators.Length == 0)
|
||
{
|
||
Console.WriteLine("当前导弹类型没有可配置的独立传感器/指示器,或未实现获取接口。");
|
||
}
|
||
else
|
||
{
|
||
for (int i = 0; i < indicators.Length; i++)
|
||
{
|
||
Console.WriteLine($" {i + 1}. {indicators[i].Name} [{(indicators[i].IsActive ? "激活" : "未激活")}]");
|
||
}
|
||
}
|
||
Console.WriteLine(" 0. 返回主菜单");
|
||
Console.Write("请选择切换状态的传感器,或返回: ");
|
||
|
||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||
if (input == "0")
|
||
return;
|
||
|
||
if (int.TryParse(input, out int choice))
|
||
{
|
||
if (choice >= 1 && choice <= indicators.Length)
|
||
{
|
||
simulator.ToggleIndicator(indicators[choice - 1].Id);
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("无效选择,请重试。");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("无效输入,请输入数字。");
|
||
}
|
||
}
|
||
}
|
||
|
||
static void ConfigureJamming(ComprehensiveMissileSimulator simulator)
|
||
{
|
||
var availableJammingOptions = simulator.GetAvailableJammingOptions();
|
||
var currentlyActiveJammingsFromSimulator = simulator.GetCurrentlyActiveJammings();
|
||
var jammingStatus = new bool[availableJammingOptions.Length];
|
||
|
||
for (int i = 0; i < availableJammingOptions.Length; i++)
|
||
{
|
||
var currentOptionForLoop = availableJammingOptions[i]; // Renamed to avoid conflict
|
||
if (currentlyActiveJammingsFromSimulator.Any(activeJam => activeJam.JammerId == currentOptionForLoop.JammerId && activeJam.Type == currentOptionForLoop.Type))
|
||
{
|
||
jammingStatus[i] = true;
|
||
}
|
||
else
|
||
{
|
||
jammingStatus[i] = false;
|
||
}
|
||
}
|
||
|
||
while (true)
|
||
{
|
||
Console.WriteLine("\n--- 配置干扰方式 ---");
|
||
Console.WriteLine($"当前导弹: {simulator.SelectedMissileDisplayName}");
|
||
|
||
if (availableJammingOptions.Length == 0)
|
||
{
|
||
Console.WriteLine("当前导弹类型没有可配置的干扰选项。");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("可用干扰方式:");
|
||
for (int i = 0; i < availableJammingOptions.Length; i++)
|
||
{
|
||
var option = availableJammingOptions[i];
|
||
Console.WriteLine($" {i + 1}. {option.DisplayName} [{(jammingStatus[i] ? "激活" : "未激活")}] " +
|
||
$"(干扰模式: {option.Mode}, 作用对象: {option.Target})");
|
||
}
|
||
}
|
||
|
||
Console.WriteLine(" 0. 返回主菜单");
|
||
Console.Write("请选择切换状态的干扰项,或返回: ");
|
||
|
||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||
if (input == "0")
|
||
return;
|
||
|
||
if (int.TryParse(input, out int choice))
|
||
{
|
||
if (choice >= 1 && choice <= availableJammingOptions.Length)
|
||
{
|
||
var option = availableJammingOptions[choice - 1];
|
||
jammingStatus[choice - 1] = !jammingStatus[choice - 1]; // Toggle local status for display
|
||
|
||
if (jammingStatus[choice - 1])
|
||
simulator.ApplyJamming(option.Type, option.DisplayName, option.JammerId, option.Mode, option.Target);
|
||
else
|
||
simulator.ClearJamming(option.Type, option.DisplayName, option.JammerId);
|
||
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("无效选择,请重试。");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("无效输入,请输入数字。");
|
||
}
|
||
}
|
||
}
|
||
|
||
static void ConfigureTimeStep(ComprehensiveMissileSimulator simulator)
|
||
{
|
||
bool backToMainMenu = false;
|
||
while (!backToMainMenu)
|
||
{
|
||
Console.WriteLine("\n--- 设置仿真步长 ---");
|
||
Console.WriteLine($"当前步长: {simulator.TimeStep}s");
|
||
Console.WriteLine("1. 低精度 (0.02s)");
|
||
Console.WriteLine("2. 中精度 (0.01s)");
|
||
Console.WriteLine("3. 高精度 (0.005s)");
|
||
Console.WriteLine("0. 返回主菜单");
|
||
Console.Write("请选择步长: ");
|
||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||
|
||
switch (input)
|
||
{
|
||
case "1":
|
||
simulator.TimeStep = 0.02;
|
||
Console.WriteLine($"仿真步长已设置为: {simulator.TimeStep}s (低精度)");
|
||
return; // 设置后返回主菜单
|
||
case "2":
|
||
simulator.TimeStep = 0.01;
|
||
Console.WriteLine($"仿真步长已设置为: {simulator.TimeStep}s (中精度)");
|
||
return; // 设置后返回主菜单
|
||
case "3":
|
||
simulator.TimeStep = 0.005;
|
||
Console.WriteLine($"仿真步长已设置为: {simulator.TimeStep}s (高精度)");
|
||
return; // 设置后返回主菜单
|
||
case "0":
|
||
backToMainMenu = true;
|
||
break;
|
||
default:
|
||
Console.WriteLine("无效选择,请重试。");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |