using System;
using System.Collections.Generic;
using System.Linq;
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
{
///
/// 仿真管理器接口,定义了仿真管理器的基本功能
///
public interface ISimulationManager
{
///
/// 当前仿真时间
///
double CurrentTime { get; }
///
/// 添加仿真元素
///
void AddElement(SimulationElement element);
///
/// 根据ID获取仿真实体
///
SimulationElement GetEntityById(string id);
///
/// 处理目标被击中事件
///
void HandleTargetHit(string targetId, string missileId);
///
/// 发布仿真事件
///
void PublishEvent(SimulationEvent evt);
///
/// 订阅仿真事件
///
void SubscribeToEvent(Action handler) where T : SimulationEvent;
///
/// 取消订阅仿真事件
///
void UnsubscribeFromEvent(Action handler) where T : SimulationEvent;
///
/// 取消所有事件订阅
///
void UnsubscribeAllEvents(SimulationElement element);
}
///
/// 仿真管理器类,负责管理整个仿真过程
///
public class SimulationManager : ISimulationManager
{
///
/// 仿真元素列表
///
public List Elements { get; private set; }
///
/// 当前仿真时间
///
public double CurrentTime { get; private set; }
///
/// 仿真是否结束
///
public bool IsSimulationEnded { get; private set; }
private readonly SimulationConfig config;
private Dictionary> eventHandlers = new Dictionary>();
private Dictionary> elementSubscriptions = new Dictionary>();
///
/// 构造函数
///
public SimulationManager(SimulationConfig config)
{
this.config = config;
Elements = [];
CurrentTime = 0;
IsSimulationEnded = false;
InitializeSimulation();
}
///
/// 初始化仿真
///
private void InitializeSimulation()
{
// 创建坦克
for (int i = 0; i < config.TankConfigs.Count; i++)
{
var tankConfig = config.TankConfigs[i];
var tank = new Tank($"Tank_{i + 1}", tankConfig, this);
Elements.Add(tank);
// 为坦克创建激光告警器
if (tankConfig.HasLaserWarner)
{
var laserWarner = new LaserWarner(
$"LaserWarner_{tank.Id}",
tank.Position,
tank.Orientation,
this,
tank.Id,
config.LaserWarnerConfig
);
Elements.Add(laserWarner);
}
// 为坦克创建激光干扰机
if (tankConfig.HasLaserJammer)
{
var laserJammer = new LaserJammer(
$"LaserJammer_{tank.Id}",
tank.Position,
tank.Orientation,
this,
tank.Id,
config.LaserJammerConfig
);
Elements.Add(laserJammer);
}
}
// 创建导弹
for (int i = 0; i < config.MissileConfigs.Count; i++)
{
var missileConfig = config.MissileConfigs[i];
// 确保 MaxFlightTime 设置合理
if (missileConfig.MaxFlightTime <= 0)
{
missileConfig.MaxFlightTime = 300; // 设置一个默认值,比如 300 秒
Console.WriteLine($"警告:导弹配置 {i} 的 MaxFlightTime 无效,已设置为默认值 300 秒");
}
Missile missile = missileConfig.Type switch
{
MissileType.LaserSemiActiveGuidance => new LaserSemiActiveGuidedMissile(
$"LSGM_{i + 1}",
missileConfig,
this
),
_ => new Missile(
$"NM_{i + 1}",
missileConfig,
this
),
};
Elements.Add(missile);
}
// 创建激光目标指示器
for (int i = 0; i < config.LaserDesignatorConfigs.Count; i++)
{
var laserDesignatorConfig = config.LaserDesignatorConfigs[i];
var laserDesignator = new LaserDesignator($"LD_{i + 1}", "Tank_1", "LSGM_4",laserDesignatorConfig, this);
Elements.Add(laserDesignator);
laserDesignator.ActivateLaser(); // 激活激光目标指示器
}
}
///
/// 发布仿真事件
///
public void PublishEvent(SimulationEvent evt)
{
var eventType = evt.GetType();
if (eventHandlers.TryGetValue(eventType, out var handlers))
{
foreach (var handler in handlers)
{
handler.DynamicInvoke(evt);
}
}
}
///
/// 订阅仿真事件
///
public void SubscribeToEvent(Action handler) where T : SimulationEvent
{
var eventType = typeof(T);
if (!eventHandlers.TryGetValue(eventType, out List? value))
{
value = [];
eventHandlers[eventType] = value;
}
value.Add(handler);
// 记录订阅关系
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null)
{
if (!elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
{
subscriptions = [];
elementSubscriptions[element] = subscriptions;
}
subscriptions.Add((eventType, handler as Delegate));
}
}
///
/// 取消订阅仿真事件
///
public void UnsubscribeFromEvent(Action handler) where T : SimulationEvent
{
var eventType = typeof(T);
if (eventHandlers.TryGetValue(eventType, out List? value))
{
value.Remove(handler);
}
// 移除订阅关系记录
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null && elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
{
subscriptions.RemoveAll(s => Delegate.Equals(s.Item2, handler));
}
}
///
/// 取消所有事件订阅
///
public void UnsubscribeAllEvents(SimulationElement element)
{
if (elementSubscriptions.ContainsKey(element))
{
foreach (var subscription in elementSubscriptions[element])
{
if (eventHandlers.TryGetValue(subscription.Item1, out List? value))
{
value.Remove(subscription.Item2);
}
}
elementSubscriptions.Remove(element);
}
}
///
/// 更新仿真状态
///
public void Update()
{
if (IsSimulationEnded) return;
CurrentTime += config.SimulationTimeStep;
foreach (var element in Elements.ToList())
{
if (element.IsActive)
{
element.Update(config.SimulationTimeStep);
}
else
{
UnsubscribeAllEvents(element);
}
}
// 移除不活跃的元素
Elements.RemoveAll(e => !e.IsActive);
// 检查是否所有导弹都结束飞行
if (!Elements.Any(e => e is Missile && e.IsActive))
{
EndSimulation();
}
}
///
/// 打印仿真状态
///
public void PrintStatus()
{
Console.WriteLine($"仿真时间: {CurrentTime:F2}");
foreach (var element in Elements)
{
Console.WriteLine(element.GetStatus());
}
Console.WriteLine();
}
///
/// 结束仿真
///
private void EndSimulation()
{
IsSimulationEnded = true;
Console.WriteLine("仿真结束");
Console.WriteLine($"总仿真时间: {CurrentTime:F2} 秒");
Console.WriteLine($"剩余坦克数量: {Elements.Count(e => e is Tank)}");
}
///
/// 根据ID获取仿真实体
///
public SimulationElement GetEntityById(string id)
{
return Elements.FirstOrDefault(e => e.Id == id) ?? throw new InvalidOperationException($"Entity with id {id} not found");
}
///
/// 处理目标被击中事件
///
public void HandleTargetHit(string targetId, string missileId)
{
if (GetEntityById(targetId) is Tank tank && GetEntityById(missileId) is Missile missile)
{
// 计算导弹造成的伤害
double damage = CalculateMissileDamage(missile);
// 对坦克造成伤害
tank.TakeDamage(damage, true);
// 记录击中事件
LogHitEvent(targetId, missileId, damage);
}
}
///
/// 计算导弹造成的伤害
///
private double CalculateMissileDamage(Missile missile)
{
// 这里可以根据导弹类型、速度等因素计算伤害
// 现在我们简单地返回一个固定值
return 50;
}
///
/// 记录击中事件
///
private static void LogHitEvent(string targetId, string missileId, double damage)
{
Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害");
}
///
/// 添加仿真元素
///
public void AddElement(SimulationElement element)
{
Elements.Add(element);
}
}
}