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 = "(需先选导弹)"; } // 获取当前坦克移动模式状态 var currentTankMode = simulator.GetCurrentMovementMode(); 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. 设置坦克移动模式 (当前: {currentTankMode.DisplayName})"); Console.WriteLine($"7. 设置仿真步长 (当前: {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": ConfigureTankMovement(simulator); break; case "7": 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", "毫米波/红外复合制导导弹"), ("CGGM_2", "激光/红外复合制导导弹") }; 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; } } bool backToMainMenu = false; while (!backToMainMenu) { Console.WriteLine("\n--- 选择干扰方式 ---"); Console.WriteLine($"当前导弹: {simulator.SelectedMissileDisplayName}"); if (availableJammingOptions.Length == 0) { Console.WriteLine("当前导弹类型没有可选择的干扰方式。"); return; } 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("请选择干扰方式,或输入0确认并返回: "); string input = Console.ReadLine()?.ToLower() ?? string.Empty; if (input == "0") { Console.WriteLine("干扰配置已确认,返回主菜单。"); backToMainMenu = true; } else 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); Console.WriteLine($"已激活: {option.DisplayName}"); } else { simulator.ClearJamming(option.Type, option.DisplayName, option.JammerId); Console.WriteLine($"已停用: {option.DisplayName}"); } // 更新当前状态显示(获取最新激活状态) currentlyActiveJammingsFromSimulator = simulator.GetCurrentlyActiveJammings(); } else { Console.WriteLine("无效选择,请重试。"); } } else { Console.WriteLine("无效输入,请输入数字或'0'返回。"); } } } 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("4. 超高精度 (0.001s)"); 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 "4": simulator.TimeStep = 0.001; Console.WriteLine($"仿真步长已设置为: {simulator.TimeStep}s (超高精度)"); return; // 设置后返回主菜单 case "0": backToMainMenu = true; break; default: Console.WriteLine("无效选择,请重试。"); break; } } } static void ConfigureTankMovement(ComprehensiveMissileSimulator simulator) { bool backToMainMenu = false; while (!backToMainMenu) { var currentMode = simulator.GetCurrentMovementMode(); var availableModes = simulator.GetAvailableMovementModes(); Console.WriteLine("\n--- 设置坦克移动模式 ---"); Console.WriteLine($"当前坦克移动模式: {currentMode.DisplayName}"); Console.WriteLine("\n可选移动模式:"); for (int i = 0; i < availableModes.Length; i++) { string indicator = availableModes[i].Mode == currentMode.Mode ? " [当前]" : ""; Console.WriteLine($" {i + 1}. {availableModes[i].DisplayName}{indicator}"); } Console.WriteLine(" 0. 返回主菜单"); Console.Write("请选择坦克移动模式: "); string input = Console.ReadLine()?.ToLower() ?? string.Empty; if (input == "0") { backToMainMenu = true; } else if (int.TryParse(input, out int choice)) { if (choice >= 1 && choice <= availableModes.Length) { var selectedMode = availableModes[choice - 1]; simulator.SetTankMovementMode(selectedMode.Mode); Console.WriteLine($"坦克移动模式已设置为: {selectedMode.DisplayName}"); return; // 设置后返回主菜单 } else { Console.WriteLine("无效选择,请重试。"); } } else { Console.WriteLine("无效输入,请输入数字。"); } } } } }