增加了单元测试框架,重构了告警器模型,增加了告警器配置,编写了新增告警器的单元测试
This commit is contained in:
parent
3f02f52074
commit
af702cbbda
@ -4,8 +4,19 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<LangVersion>9.0</LangVersion>
|
<LangVersion>9.0</LangVersion>
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
<ImplicitUsings>disable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="obj\**" />
|
||||||
|
<Compile Remove="src\Tests\**" />
|
||||||
|
<EmbeddedResource Remove="obj\**" />
|
||||||
|
<EmbeddedResource Remove="src\Tests\**" />
|
||||||
|
<None Remove="obj\**" />
|
||||||
|
<None Remove="src\Tests\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,29 +1,33 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.5.002.0
|
VisualStudioVersion = 17.0.31903.59
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActiveProtect", "ActiveProtect.csproj", "{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActiveProtect", "ActiveProtect.csproj", "{7138CDD4-EC75-4803-8050-D72A32B381CA}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{88B204F0-6636-4265-ACFB-52D889A56413}"
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
EndProject
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActiveProtect.Tests", "src\Tests\ActiveProtect.Tests.csproj", "{55F5BDBE-025D-465B-BB34-2262369715BB}"
|
||||||
Release|Any CPU = Release|Any CPU
|
EndProject
|
||||||
EndGlobalSection
|
Global
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
EndGlobalSection
|
||||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.Build.0 = Release|Any CPU
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
HideSolutionNode = FALSE
|
||||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
EndGlobalSection
|
||||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
EndGlobalSection
|
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
HideSolutionNode = FALSE
|
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
{55F5BDBE-025D-465B-BB34-2262369715BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
{55F5BDBE-025D-465B-BB34-2262369715BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
SolutionGuid = {73773200-50D4-40ED-803B-FC16B131FFD2}
|
{55F5BDBE-025D-465B-BB34-2262369715BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
EndGlobalSection
|
{55F5BDBE-025D-465B-BB34-2262369715BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobal
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{55F5BDBE-025D-465B-BB34-2262369715BB} = {88B204F0-6636-4265-ACFB-52D889A56413}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
|
|||||||
@ -1,51 +0,0 @@
|
|||||||
using ActiveProtect.Simulation;
|
|
||||||
using ActiveProtect.Utility;
|
|
||||||
|
|
||||||
namespace ActiveProtect.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 红外告警器类,用于检测红外辐射并发出警报
|
|
||||||
/// </summary>
|
|
||||||
public class InfraredWarner : WarnerBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 红外告警器灵敏度阈值
|
|
||||||
/// </summary>
|
|
||||||
private readonly double sensitivityThreshold;
|
|
||||||
|
|
||||||
public InfraredWarner(string id, Vector3D position, Orientation orientation,
|
|
||||||
ISimulationManager manager, string tankId, double warningDuration, double sensitivityThreshold)
|
|
||||||
: base(id, position, orientation, manager, tankId, warningDuration)
|
|
||||||
{
|
|
||||||
this.sensitivityThreshold = sensitivityThreshold;
|
|
||||||
SimulationManager.SubscribeToEvent<InfraredDetectionEvent>(OnInfraredDetection);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnInfraredDetection(InfraredDetectionEvent evt)
|
|
||||||
{
|
|
||||||
if (evt?.TargetId == TankId && evt.Intensity >= sensitivityThreshold)
|
|
||||||
{
|
|
||||||
StartWarning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetWarningStatus()
|
|
||||||
{
|
|
||||||
return $"红外告警器 {Id}:\n" +
|
|
||||||
$" 告警状态: {(IsWarning ? "告警中" : "正常")}\n" +
|
|
||||||
$" 告警持续时间: {CurrentWarningTime:F2}/{WarningDuration:F2}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Activate()
|
|
||||||
{
|
|
||||||
base.Activate();
|
|
||||||
SimulationManager.SubscribeToEvent<InfraredDetectionEvent>(OnInfraredDetection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Deactivate()
|
|
||||||
{
|
|
||||||
base.Deactivate();
|
|
||||||
SimulationManager.UnsubscribeFromEvent<InfraredDetectionEvent>(OnInfraredDetection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,160 +0,0 @@
|
|||||||
using ActiveProtect.Simulation;
|
|
||||||
using System;
|
|
||||||
using ActiveProtect.Utility;
|
|
||||||
|
|
||||||
namespace ActiveProtect.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 激光告警器类,用于检测激光照射并发出警报
|
|
||||||
/// </summary>
|
|
||||||
public class LaserWarner : SimulationElement
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 是否正在发出警报
|
|
||||||
/// </summary>
|
|
||||||
public bool IsAlarming { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 警报持续时间(秒)
|
|
||||||
/// </summary>
|
|
||||||
private readonly double alarmDuration;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 当前警报计时器
|
|
||||||
/// </summary>
|
|
||||||
private double alarmTimer = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 被监视实体的ID
|
|
||||||
/// </summary>
|
|
||||||
public string MonitoredEntityId { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造函数
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">激光告警器ID</param>
|
|
||||||
/// <param name="position">初始位置</param>
|
|
||||||
/// <param name="orientation">初始朝向</param>
|
|
||||||
/// <param name="simulationManager">仿真管理器</param>
|
|
||||||
/// <param name="monitoredEntityId">被监视实体的ID</param>
|
|
||||||
/// <param name="config">激光告警器配置</param>
|
|
||||||
public LaserWarner(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserWarnerConfig config)
|
|
||||||
: base(id, position, orientation, 0, simulationManager)
|
|
||||||
{
|
|
||||||
MonitoredEntityId = monitoredEntityId;
|
|
||||||
IsAlarming = false;
|
|
||||||
alarmDuration = config.AlarmDuration;
|
|
||||||
base.SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
|
||||||
base.SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 更新激光告警器状态
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deltaTime">时间步长</param>
|
|
||||||
public override void Update(double deltaTime)
|
|
||||||
{
|
|
||||||
if (!IsActive) return;
|
|
||||||
|
|
||||||
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
|
|
||||||
if (tank != null)
|
|
||||||
{
|
|
||||||
Position = tank.Position;
|
|
||||||
Orientation = tank.Orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsAlarming)
|
|
||||||
{
|
|
||||||
alarmTimer += deltaTime;
|
|
||||||
if (alarmTimer >= alarmDuration)
|
|
||||||
{
|
|
||||||
StopAlarm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 处理激光照射事件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="evt">激光照射事件</param>
|
|
||||||
private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt)
|
|
||||||
{
|
|
||||||
if (evt?.Target != null && evt.Target.Id == MonitoredEntityId)
|
|
||||||
{
|
|
||||||
TriggerAlarm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 处理激光照射停止事件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="evt">激光照射停止事件</param>
|
|
||||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
|
||||||
{
|
|
||||||
if (evt?.Target != null && evt.Target.Id == MonitoredEntityId)
|
|
||||||
{
|
|
||||||
StopAlarm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 触发警报
|
|
||||||
/// </summary>
|
|
||||||
public void TriggerAlarm()
|
|
||||||
{
|
|
||||||
if (!IsAlarming)
|
|
||||||
{
|
|
||||||
IsAlarming = true;
|
|
||||||
alarmTimer = 0;
|
|
||||||
PublishEvent(new LaserWarnerAlarmEvent() { TargetId = MonitoredEntityId });
|
|
||||||
Console.WriteLine($"激光告警器 {Id} 发出警报!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 停止警报
|
|
||||||
/// </summary>
|
|
||||||
public void StopAlarm()
|
|
||||||
{
|
|
||||||
if (IsAlarming)
|
|
||||||
{
|
|
||||||
IsAlarming = false;
|
|
||||||
alarmTimer = 0;
|
|
||||||
PublishEvent(new LaserWarnerAlarmStopEvent() { TargetId = MonitoredEntityId });
|
|
||||||
Console.WriteLine($"激光告警器 {Id} 停止警报");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取激光告警器状态信息
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>状态信息字符串</returns>
|
|
||||||
public override string GetStatus()
|
|
||||||
{
|
|
||||||
return $"激光告警器 {Id}:\n" +
|
|
||||||
$" 监视实体: {MonitoredEntityId}\n" +
|
|
||||||
$" 警报状态: {(IsAlarming ? "警报中" : "正常")}\n" +
|
|
||||||
$" 警报持续时间: {(IsAlarming ? alarmTimer : 0):F2}/{alarmDuration:F2}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 激活激光告警器
|
|
||||||
/// </summary>
|
|
||||||
public override void Activate()
|
|
||||||
{
|
|
||||||
base.Activate();
|
|
||||||
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
|
||||||
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 停用激光告警器
|
|
||||||
/// </summary>
|
|
||||||
public override void Deactivate()
|
|
||||||
{
|
|
||||||
base.Deactivate();
|
|
||||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
|
||||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
using ActiveProtect.Simulation;
|
|
||||||
using ActiveProtect.Utility;
|
|
||||||
|
|
||||||
namespace ActiveProtect.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 毫米波告警器类,用于检测毫米波辐射并发出警报
|
|
||||||
/// </summary>
|
|
||||||
public class MillimeterWaveWarner : WarnerBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 毫米波告警器灵敏度阈值
|
|
||||||
/// </summary>
|
|
||||||
private readonly double sensitivityThreshold;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 频率范围(GHz)
|
|
||||||
/// </summary>
|
|
||||||
private readonly (double Min, double Max) frequencyRange;
|
|
||||||
|
|
||||||
public MillimeterWaveWarner(string id, Vector3D position, Orientation orientation,
|
|
||||||
ISimulationManager manager, string tankId, double warningDuration,
|
|
||||||
double sensitivityThreshold, (double Min, double Max) frequencyRange)
|
|
||||||
: base(id, position, orientation, manager, tankId, warningDuration)
|
|
||||||
{
|
|
||||||
this.sensitivityThreshold = sensitivityThreshold;
|
|
||||||
this.frequencyRange = frequencyRange;
|
|
||||||
SimulationManager.SubscribeToEvent<MillimeterWaveDetectionEvent>(OnMillimeterWaveDetection);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMillimeterWaveDetection(MillimeterWaveDetectionEvent evt)
|
|
||||||
{
|
|
||||||
if (evt?.TargetId == TankId &&
|
|
||||||
evt.Intensity >= sensitivityThreshold &&
|
|
||||||
evt.Frequency >= frequencyRange.Min &&
|
|
||||||
evt.Frequency <= frequencyRange.Max)
|
|
||||||
{
|
|
||||||
StartWarning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetWarningStatus()
|
|
||||||
{
|
|
||||||
return $"毫米波告警器 {Id}:\n" +
|
|
||||||
$" 告警状态: {(IsWarning ? "告警中" : "正常")}\n" +
|
|
||||||
$" 告警持续时间: {CurrentWarningTime:F2}/{WarningDuration:F2}\n" +
|
|
||||||
$" 频率范围: {frequencyRange.Min}-{frequencyRange.Max} GHz";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Activate()
|
|
||||||
{
|
|
||||||
base.Activate();
|
|
||||||
SimulationManager.SubscribeToEvent<MillimeterWaveDetectionEvent>(OnMillimeterWaveDetection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Deactivate()
|
|
||||||
{
|
|
||||||
base.Deactivate();
|
|
||||||
SimulationManager.UnsubscribeFromEvent<MillimeterWaveDetectionEvent>(OnMillimeterWaveDetection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
71
src/Models/Warner/InfraredWarner.cs
Normal file
71
src/Models/Warner/InfraredWarner.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 红外告警器类,用于检测红外辐射并发出警报
|
||||||
|
/// </summary>
|
||||||
|
public class InfraredWarner : WarnerBase
|
||||||
|
{
|
||||||
|
private readonly double _sensitivityThreshold;
|
||||||
|
private readonly double _wavelengthMin;
|
||||||
|
private readonly double _wavelengthMax;
|
||||||
|
|
||||||
|
public InfraredWarner(string id, Vector3D position, Orientation orientation,
|
||||||
|
ISimulationManager manager, string tankId, InfraredWarnerConfig config)
|
||||||
|
: base(id, position, orientation, manager, tankId, config.SensitivityThreshold,
|
||||||
|
(config.WavelengthMin, config.WavelengthMax), config.AlarmDuration)
|
||||||
|
{
|
||||||
|
_sensitivityThreshold = config.SensitivityThreshold;
|
||||||
|
_wavelengthMin = config.WavelengthMin;
|
||||||
|
_wavelengthMax = config.WavelengthMax;
|
||||||
|
SimulationManager.SubscribeToEvent<InfraredDetectionEvent>(OnInfraredDetection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInfraredDetection(InfraredDetectionEvent evt)
|
||||||
|
{
|
||||||
|
if (evt?.TargetId == TankId && evt.Intensity >= _sensitivityThreshold)
|
||||||
|
{
|
||||||
|
StartWarning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetWarningStatus()
|
||||||
|
{
|
||||||
|
return $"红外告警器 {Id}:\n" +
|
||||||
|
$" 告警状态: {(IsWarning ? "告警中" : "正常")}\n" +
|
||||||
|
$" 告警持续时间: {CurrentWarningTime:F2}/{WarningDuration:F2}\n" +
|
||||||
|
$" 波长范围: {_wavelengthMin:F2}-{_wavelengthMax:F2}微米";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (IsWarning && IsActive)
|
||||||
|
{
|
||||||
|
// 发布告警事件
|
||||||
|
SimulationManager.PublishEvent(new InfraredWarnerAlarmEvent
|
||||||
|
{
|
||||||
|
SenderId = Id,
|
||||||
|
Timestamp = SimulationManager.CurrentTime,
|
||||||
|
TargetId = TankId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Activate()
|
||||||
|
{
|
||||||
|
base.Activate();
|
||||||
|
SimulationManager.SubscribeToEvent<InfraredDetectionEvent>(OnInfraredDetection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deactivate()
|
||||||
|
{
|
||||||
|
base.Deactivate();
|
||||||
|
SimulationManager.UnsubscribeFromEvent<InfraredDetectionEvent>(OnInfraredDetection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
src/Models/Warner/LaserWarner.cs
Normal file
94
src/Models/Warner/LaserWarner.cs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
using System;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 激光告警器类,用于检测激光照射并发出警报
|
||||||
|
/// </summary>
|
||||||
|
public class LaserWarner : WarnerBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
public LaserWarner(string id, Vector3D position, Orientation orientation,
|
||||||
|
ISimulationManager manager, string tankId, LaserWarnerConfig config)
|
||||||
|
: base(id, position, orientation, manager, tankId, config.SensitivityThreshold,
|
||||||
|
(config.WavelengthMin, config.WavelengthMax), config.AlarmDuration)
|
||||||
|
{
|
||||||
|
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||||
|
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理激光照射事件
|
||||||
|
/// </summary>
|
||||||
|
private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt)
|
||||||
|
{
|
||||||
|
// 添加日志以帮助调试
|
||||||
|
Console.WriteLine($"收到激光照射事件: TargetId={evt?.Target?.Id}, ExpectedId={TankId}");
|
||||||
|
|
||||||
|
if (evt?.Target != null && evt.Target.Id == TankId)
|
||||||
|
{
|
||||||
|
Console.WriteLine("开始告警");
|
||||||
|
StartWarning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理激光照射停止事件
|
||||||
|
/// </summary>
|
||||||
|
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||||
|
{
|
||||||
|
// 添加日志以帮助调试
|
||||||
|
Console.WriteLine($"收到激光照射停止事件: TargetId={evt?.Target?.Id}, ExpectedId={TankId}");
|
||||||
|
|
||||||
|
if (evt?.Target != null && evt.Target.Id == TankId)
|
||||||
|
{
|
||||||
|
Console.WriteLine("停止告警");
|
||||||
|
StopWarning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取告警状态信息
|
||||||
|
/// </summary>
|
||||||
|
public override string GetWarningStatus()
|
||||||
|
{
|
||||||
|
return $"激光告警器 {Id}:\n" +
|
||||||
|
$" 告警状态: {(IsWarning ? "告警中" : "正常")}\n" +
|
||||||
|
$" 告警持续时间: {CurrentWarningTime:F2}/{WarningDuration:F2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Activate()
|
||||||
|
{
|
||||||
|
base.Activate();
|
||||||
|
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||||
|
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deactivate()
|
||||||
|
{
|
||||||
|
base.Deactivate();
|
||||||
|
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||||
|
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (IsWarning)
|
||||||
|
{
|
||||||
|
// 发布告警事件
|
||||||
|
SimulationManager.PublishEvent(new LaserWarnerAlarmEvent
|
||||||
|
{
|
||||||
|
SenderId = Id,
|
||||||
|
Timestamp = SimulationManager.CurrentTime,
|
||||||
|
TargetId = TankId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
src/Models/Warner/MillimeterWaveWarner.cs
Normal file
75
src/Models/Warner/MillimeterWaveWarner.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 毫米波告警器类,用于检测毫米波辐射并发出警报
|
||||||
|
/// </summary>
|
||||||
|
public class MillimeterWaveWarner : WarnerBase
|
||||||
|
{
|
||||||
|
private readonly double _sensitivityThreshold;
|
||||||
|
private readonly double _wavelengthMin;
|
||||||
|
private readonly double _wavelengthMax;
|
||||||
|
|
||||||
|
public MillimeterWaveWarner(string id, Vector3D position, Orientation orientation,
|
||||||
|
ISimulationManager manager, string tankId, MillimeterWaveWarnerConfig config)
|
||||||
|
: base(id, position, orientation, manager, tankId, config.SensitivityThreshold,
|
||||||
|
(config.WavelengthMin, config.WavelengthMax), config.AlarmDuration)
|
||||||
|
{
|
||||||
|
_sensitivityThreshold = config.SensitivityThreshold;
|
||||||
|
_wavelengthMin = config.WavelengthMin;
|
||||||
|
_wavelengthMax = config.WavelengthMax;
|
||||||
|
SimulationManager.SubscribeToEvent<MillimeterWaveDetectionEvent>(OnMillimeterWaveDetection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMillimeterWaveDetection(MillimeterWaveDetectionEvent evt)
|
||||||
|
{
|
||||||
|
if (evt?.TargetId == TankId &&
|
||||||
|
evt.Intensity >= _sensitivityThreshold &&
|
||||||
|
evt.Frequency >= _wavelengthMin &&
|
||||||
|
evt.Frequency <= _wavelengthMax)
|
||||||
|
{
|
||||||
|
StartWarning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetWarningStatus()
|
||||||
|
{
|
||||||
|
return $"毫米波告警器 {Id}:\n" +
|
||||||
|
$" 告警状态: {(IsWarning ? "告警中" : "正常")}\n" +
|
||||||
|
$" 告警持续时间: {CurrentWarningTime:F2}/{WarningDuration:F2}\n" +
|
||||||
|
$" 频率范围: {_wavelengthMin:F2}-{_wavelengthMax:F2}GHz";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (IsWarning && IsActive)
|
||||||
|
{
|
||||||
|
// 发布告警事件
|
||||||
|
SimulationManager.PublishEvent(new MillimeterWaveWarnerAlarmEvent
|
||||||
|
{
|
||||||
|
SenderId = Id,
|
||||||
|
Timestamp = SimulationManager.CurrentTime,
|
||||||
|
TargetId = TankId,
|
||||||
|
DetectedFrequency = (_wavelengthMin + _wavelengthMax) / 2 // 使用中心频率
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Activate()
|
||||||
|
{
|
||||||
|
base.Activate();
|
||||||
|
SimulationManager.SubscribeToEvent<MillimeterWaveDetectionEvent>(OnMillimeterWaveDetection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deactivate()
|
||||||
|
{
|
||||||
|
base.Deactivate();
|
||||||
|
SimulationManager.UnsubscribeFromEvent<MillimeterWaveDetectionEvent>(OnMillimeterWaveDetection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using ActiveProtect.Simulation;
|
using ActiveProtect.Simulation;
|
||||||
using ActiveProtect.Utility;
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
@ -8,22 +9,24 @@ namespace ActiveProtect.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class UltravioletWarner : WarnerBase
|
public class UltravioletWarner : WarnerBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly double _sensitivityThreshold;
|
||||||
/// 紫外告警器灵敏度阈值
|
private readonly double _wavelengthMin;
|
||||||
/// </summary>
|
private readonly double _wavelengthMax;
|
||||||
private readonly double sensitivityThreshold;
|
|
||||||
|
|
||||||
public UltravioletWarner(string id, Vector3D position, Orientation orientation,
|
public UltravioletWarner(string id, Vector3D position, Orientation orientation,
|
||||||
ISimulationManager manager, string tankId, double warningDuration, double sensitivityThreshold)
|
ISimulationManager manager, string tankId, UltravioletWarnerConfig config)
|
||||||
: base(id, position, orientation, manager, tankId, warningDuration)
|
: base(id, position, orientation, manager, tankId, config.SensitivityThreshold,
|
||||||
|
(config.WavelengthMin, config.WavelengthMax), config.AlarmDuration)
|
||||||
{
|
{
|
||||||
this.sensitivityThreshold = sensitivityThreshold;
|
_sensitivityThreshold = config.SensitivityThreshold;
|
||||||
|
_wavelengthMin = config.WavelengthMin;
|
||||||
|
_wavelengthMax = config.WavelengthMax;
|
||||||
SimulationManager.SubscribeToEvent<UltravioletDetectionEvent>(OnUltravioletDetection);
|
SimulationManager.SubscribeToEvent<UltravioletDetectionEvent>(OnUltravioletDetection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUltravioletDetection(UltravioletDetectionEvent evt)
|
private void OnUltravioletDetection(UltravioletDetectionEvent evt)
|
||||||
{
|
{
|
||||||
if (evt?.TargetId == TankId && evt.Intensity >= sensitivityThreshold)
|
if (evt?.TargetId == TankId && evt.Intensity >= _sensitivityThreshold)
|
||||||
{
|
{
|
||||||
StartWarning();
|
StartWarning();
|
||||||
}
|
}
|
||||||
@ -33,7 +36,24 @@ namespace ActiveProtect.Models
|
|||||||
{
|
{
|
||||||
return $"紫外告警器 {Id}:\n" +
|
return $"紫外告警器 {Id}:\n" +
|
||||||
$" 告警状态: {(IsWarning ? "告警中" : "正常")}\n" +
|
$" 告警状态: {(IsWarning ? "告警中" : "正常")}\n" +
|
||||||
$" 告警持续时间: {CurrentWarningTime:F2}/{WarningDuration:F2}";
|
$" 告警持续时间: {CurrentWarningTime:F2}/{WarningDuration:F2}\n" +
|
||||||
|
$" 波长范围: {_wavelengthMin:F2}-{_wavelengthMax:F2}纳米";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
base.Update(deltaTime);
|
||||||
|
|
||||||
|
if (IsWarning && IsActive)
|
||||||
|
{
|
||||||
|
// 发布告警事件
|
||||||
|
SimulationManager.PublishEvent(new UltravioletWarnerAlarmEvent
|
||||||
|
{
|
||||||
|
SenderId = Id,
|
||||||
|
Timestamp = SimulationManager.CurrentTime,
|
||||||
|
TargetId = TankId
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Activate()
|
public override void Activate()
|
||||||
@ -14,6 +14,16 @@ namespace ActiveProtect.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsWarning { get; protected set; }
|
public bool IsWarning { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 告警灵敏度阈值
|
||||||
|
/// </summary>
|
||||||
|
protected double SensitivityThreshold { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 告警频率范围
|
||||||
|
/// </summary>
|
||||||
|
protected (double Min, double Max) FrequencyRange { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 告警持续时间(秒)
|
/// 告警持续时间(秒)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -30,10 +40,12 @@ namespace ActiveProtect.Models
|
|||||||
protected string TankId { get; set; }
|
protected string TankId { get; set; }
|
||||||
|
|
||||||
protected WarnerBase(string id, Vector3D position, Orientation orientation,
|
protected WarnerBase(string id, Vector3D position, Orientation orientation,
|
||||||
ISimulationManager manager, string tankId, double warningDuration)
|
ISimulationManager manager, string tankId, double sensitivityThreshold, (double Min, double Max) frequencyRange, double warningDuration)
|
||||||
: base(id, position, orientation, 0, manager)
|
: base(id, position, orientation, 0, manager)
|
||||||
{
|
{
|
||||||
TankId = tankId;
|
TankId = tankId;
|
||||||
|
SensitivityThreshold = sensitivityThreshold;
|
||||||
|
FrequencyRange = frequencyRange;
|
||||||
WarningDuration = warningDuration;
|
WarningDuration = warningDuration;
|
||||||
CurrentWarningTime = 0;
|
CurrentWarningTime = 0;
|
||||||
IsWarning = false;
|
IsWarning = false;
|
||||||
@ -165,18 +165,165 @@ namespace ActiveProtect.Simulation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 告警灵敏度阈值
|
||||||
|
/// </summary>
|
||||||
|
public double SensitivityThreshold { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 警报持续时间(秒)
|
/// 警报持续时间(秒)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double AlarmDuration { get; set; }
|
public double AlarmDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最小波长(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大波长(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMax { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数,设置默认值
|
/// 构造函数,设置默认值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LaserWarnerConfig()
|
public LaserWarnerConfig()
|
||||||
{
|
{
|
||||||
Id = "";
|
Id = "";
|
||||||
|
SensitivityThreshold = 0;
|
||||||
AlarmDuration = 5.0; // 默认警报持续5秒
|
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||||
|
WavelengthMin = 0;
|
||||||
|
WavelengthMax = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 紫外线告警器配置类
|
||||||
|
/// </summary>
|
||||||
|
public class UltravioletWarnerConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 紫外线告警器ID
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 告警灵敏度阈值
|
||||||
|
/// </summary>
|
||||||
|
public double SensitivityThreshold { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 警报持续时间(秒)
|
||||||
|
/// </summary>
|
||||||
|
public double AlarmDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 波长范围(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大波长(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMax { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数,设置默认值
|
||||||
|
/// </summary>
|
||||||
|
public UltravioletWarnerConfig()
|
||||||
|
{
|
||||||
|
Id = "";
|
||||||
|
SensitivityThreshold = 0;
|
||||||
|
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||||
|
WavelengthMin = 0;
|
||||||
|
WavelengthMax = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 红外告警器配置类
|
||||||
|
/// </summary>
|
||||||
|
public class InfraredWarnerConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 红外告警器ID
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 告警灵敏度阈值
|
||||||
|
/// </summary>
|
||||||
|
public double SensitivityThreshold { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 警报持续时间(秒)
|
||||||
|
/// </summary>
|
||||||
|
public double AlarmDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最小波长(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大波长(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMax { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数,设置默认值
|
||||||
|
/// </summary>
|
||||||
|
public InfraredWarnerConfig()
|
||||||
|
{
|
||||||
|
Id = "";
|
||||||
|
SensitivityThreshold = 0;
|
||||||
|
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||||
|
WavelengthMin = 0;
|
||||||
|
WavelengthMax = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 毫米波告警器配置类
|
||||||
|
/// </summary>
|
||||||
|
public class MillimeterWaveWarnerConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 毫米波告警器ID
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 告警灵敏度阈值
|
||||||
|
/// </summary>
|
||||||
|
public double SensitivityThreshold { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 警报持续时间(秒)
|
||||||
|
/// </summary>
|
||||||
|
public double AlarmDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 波长范围(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大波长(纳米)
|
||||||
|
/// </summary>
|
||||||
|
public double WavelengthMax { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数,设置默认值
|
||||||
|
/// </summary>
|
||||||
|
public MillimeterWaveWarnerConfig()
|
||||||
|
{
|
||||||
|
Id = "";
|
||||||
|
SensitivityThreshold = 0;
|
||||||
|
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||||
|
WavelengthMin = 0;
|
||||||
|
WavelengthMax = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
src/Tests/ActiveProtect.Tests.csproj
Normal file
37
src/Tests/ActiveProtect.Tests.csproj
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<LangVersion>9.0</LangVersion>
|
||||||
|
<ImplicitUsings>disable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.4.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="3.2.0">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Moq" Version="4.18.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\ActiveProtect.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="obj\**" />
|
||||||
|
<EmbeddedResource Remove="obj\**" />
|
||||||
|
<None Remove="obj\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
167
src/Tests/Unit/Models/Jammer/InfraredJammerTests.cs
Normal file
167
src/Tests/Unit/Models/Jammer/InfraredJammerTests.cs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using ActiveProtect.Models;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Tests.Unit.Models.Jammer
|
||||||
|
{
|
||||||
|
public class InfraredJammerTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Mock<ISimulationManager> _mockSimManager;
|
||||||
|
private readonly InfraredJammer _jammer;
|
||||||
|
private readonly string _jammerId = "TestJammer";
|
||||||
|
private readonly string _tankId = "TestTank";
|
||||||
|
|
||||||
|
public InfraredJammerTests()
|
||||||
|
{
|
||||||
|
// 设置测试环境
|
||||||
|
_mockSimManager = new Mock<ISimulationManager>();
|
||||||
|
_mockSimManager.Setup(m => m.CurrentTime).Returns(0.0);
|
||||||
|
|
||||||
|
// 设置事件发布
|
||||||
|
_mockSimManager.Setup(m => m.PublishEvent(It.IsAny<SimulationEvent>()));
|
||||||
|
|
||||||
|
_jammer = new InfraredJammer(
|
||||||
|
_jammerId,
|
||||||
|
new Vector3D(0, 0, 0),
|
||||||
|
new Orientation(),
|
||||||
|
_mockSimManager.Object,
|
||||||
|
_tankId,
|
||||||
|
maxJammingPower: 1000.0,
|
||||||
|
initialJammingPower: 400.0,
|
||||||
|
powerIncreaseRate: 100.0,
|
||||||
|
maxCooldownTime: 5.0,
|
||||||
|
wavelengthRange: (3.0, 5.0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// 清理资源
|
||||||
|
_jammer.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_InitializesCorrectly()
|
||||||
|
{
|
||||||
|
Assert.Equal(_jammerId, _jammer.Id);
|
||||||
|
Assert.False(_jammer.IsJamming);
|
||||||
|
Assert.Equal(400.0, _jammer.CurrentJammingPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StartJamming_WhenNotJamming_StartsJamming()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_jammer.StartJamming();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(_jammer.IsJamming);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StopJamming_WhenJamming_StopsAndEntersCooldown()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_jammer.StartJamming();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_jammer.StopJamming();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_jammer.IsJamming);
|
||||||
|
Assert.Equal(400.0, _jammer.CurrentJammingPower); // 重置为初始功率
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(1.0, 500.0)] // 1秒后功率增加100
|
||||||
|
[InlineData(2.0, 600.0)] // 2秒后功率增加200
|
||||||
|
[InlineData(10.0, 1000.0)] // 10秒后达到最大功率1000
|
||||||
|
public void Update_WhenJamming_IncreasesPowerCorrectly(double deltaTime, double expectedPower)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_jammer.StartJamming();
|
||||||
|
_jammer.Activate(); // 确保激活状态
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_jammer.Update(deltaTime);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedPower, _jammer.CurrentJammingPower, 1); // 允许1瓦特的误差
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OnInfraredWarnerAlarm_StartsJamming()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Action<InfraredWarnerAlarmEvent>? eventHandler = null;
|
||||||
|
_mockSimManager.Setup(m => m.SubscribeToEvent(It.IsAny<Action<InfraredWarnerAlarmEvent>>()))
|
||||||
|
.Callback<Action<InfraredWarnerAlarmEvent>>(handler => eventHandler = handler);
|
||||||
|
|
||||||
|
// 激活干扰器以触发事件订阅
|
||||||
|
_jammer.Activate();
|
||||||
|
|
||||||
|
// 确保事件处理程序被设置
|
||||||
|
Assert.NotNull(eventHandler);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
eventHandler?.Invoke(new InfraredWarnerAlarmEvent { TargetId = _tankId });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(_jammer.IsJamming);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_PublishesJammingEvent()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_jammer.StartJamming();
|
||||||
|
_jammer.Activate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_jammer.Update(1.0);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(m => m.PublishEvent(It.Is<InfraredJammingEvent>(e =>
|
||||||
|
e.TargetId == _tankId &&
|
||||||
|
Math.Abs(e.JammingPower - 500.0) < 1 &&
|
||||||
|
e.WavelengthMin == 3.0 &&
|
||||||
|
e.WavelengthMax == 5.0
|
||||||
|
)), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetJammingStatus_ReturnsCorrectFormat()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_jammer.StartJamming();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string status = _jammer.GetJammingStatus();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Contains("红外干扰器", status);
|
||||||
|
Assert.Contains("干扰中", status);
|
||||||
|
Assert.Contains("400.00/1000.00", status);
|
||||||
|
Assert.Contains("3.00-5.00微米", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Deactivate_UnsubscribesFromEvents()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_jammer.Deactivate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(
|
||||||
|
m => m.UnsubscribeFromEvent<InfraredWarnerAlarmEvent>(It.IsAny<Action<InfraredWarnerAlarmEvent>>()),
|
||||||
|
Times.Once);
|
||||||
|
_mockSimManager.Verify(
|
||||||
|
m => m.UnsubscribeFromEvent<InfraredWarnerAlarmStopEvent>(It.IsAny<Action<InfraredWarnerAlarmStopEvent>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
161
src/Tests/Unit/Models/Warner/InfraredWarnerTests.cs
Normal file
161
src/Tests/Unit/Models/Warner/InfraredWarnerTests.cs
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
using System;
|
||||||
|
using ActiveProtect.Models;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Tests.Unit.Models.Warner
|
||||||
|
{
|
||||||
|
public class InfraredWarnerTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Mock<ISimulationManager> _mockSimManager;
|
||||||
|
private readonly InfraredWarner _warner;
|
||||||
|
private readonly string _warnerId = "TestInfraredWarner";
|
||||||
|
private readonly string _tankId = "TestTank";
|
||||||
|
private readonly InfraredWarnerConfig _config;
|
||||||
|
|
||||||
|
public InfraredWarnerTests()
|
||||||
|
{
|
||||||
|
_mockSimManager = new Mock<ISimulationManager>();
|
||||||
|
_mockSimManager.Setup(m => m.CurrentTime).Returns(0.0);
|
||||||
|
_mockSimManager.Setup(m => m.PublishEvent(It.IsAny<SimulationEvent>()));
|
||||||
|
|
||||||
|
_config = new InfraredWarnerConfig
|
||||||
|
{
|
||||||
|
AlarmDuration = 5.0,
|
||||||
|
SensitivityThreshold = 0.1,
|
||||||
|
WavelengthMin = 3.0,
|
||||||
|
WavelengthMax = 5.0
|
||||||
|
};
|
||||||
|
|
||||||
|
_warner = new InfraredWarner(
|
||||||
|
_warnerId,
|
||||||
|
new Vector3D(0, 0, 0),
|
||||||
|
new Orientation(0, 0, 0),
|
||||||
|
_mockSimManager.Object,
|
||||||
|
_tankId,
|
||||||
|
_config
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_warner.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_InitializesCorrectly()
|
||||||
|
{
|
||||||
|
Assert.Equal(_warnerId, _warner.Id);
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StartWarning_WhenNotWarning_StartsWarning()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StopWarning_WhenWarning_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.StopWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_WhenWarningTimeExceeded_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.Activate();
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.Update(6.0); // 超过警报持续时间
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.2, true)] // 高于阈值,应该触发
|
||||||
|
[InlineData(0.05, false)] // 低于阈值,不应该触发
|
||||||
|
public void OnInfraredDetection_RespondsToIntensityThreshold(double intensity, bool shouldTrigger)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Action<InfraredDetectionEvent>? eventHandler = null;
|
||||||
|
_mockSimManager.Setup(m => m.SubscribeToEvent(It.IsAny<Action<InfraredDetectionEvent>>()))
|
||||||
|
.Callback<Action<InfraredDetectionEvent>>(handler => eventHandler = handler);
|
||||||
|
|
||||||
|
_warner.Activate();
|
||||||
|
Assert.NotNull(eventHandler);
|
||||||
|
|
||||||
|
var detectionEvent = new InfraredDetectionEvent
|
||||||
|
{
|
||||||
|
TargetId = _tankId,
|
||||||
|
Intensity = intensity
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
eventHandler?.Invoke(detectionEvent);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(shouldTrigger, _warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetWarningStatus_ReturnsCorrectFormat()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string status = _warner.GetWarningStatus();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Contains("红外告警器", status);
|
||||||
|
Assert.Contains("告警中", status);
|
||||||
|
Assert.Contains("3.00-5.00微米", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_PublishesWarningEvent_WhenWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
_warner.Activate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.Update(1.0);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(m => m.PublishEvent(It.Is<InfraredWarnerAlarmEvent>(e =>
|
||||||
|
e.TargetId == _tankId
|
||||||
|
)), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Deactivate_UnsubscribesFromEvents()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.Deactivate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(
|
||||||
|
m => m.UnsubscribeFromEvent<InfraredDetectionEvent>(
|
||||||
|
It.IsAny<Action<InfraredDetectionEvent>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
204
src/Tests/Unit/Models/Warner/LaserWarnerTests.cs
Normal file
204
src/Tests/Unit/Models/Warner/LaserWarnerTests.cs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
using System;
|
||||||
|
using ActiveProtect.Models;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Tests.Unit.Models.Warner
|
||||||
|
{
|
||||||
|
public class LaserWarnerTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Mock<ISimulationManager> _mockSimManager;
|
||||||
|
private readonly LaserWarner _warner;
|
||||||
|
private readonly string _warnerId = "TestLaserWarner";
|
||||||
|
private readonly string _tankId = "TestTank";
|
||||||
|
private readonly LaserWarnerConfig _config;
|
||||||
|
|
||||||
|
public LaserWarnerTests()
|
||||||
|
{
|
||||||
|
_mockSimManager = new Mock<ISimulationManager>();
|
||||||
|
_mockSimManager.Setup(m => m.CurrentTime).Returns(0.0);
|
||||||
|
_mockSimManager.Setup(m => m.PublishEvent(It.IsAny<SimulationEvent>()));
|
||||||
|
|
||||||
|
_config = new LaserWarnerConfig
|
||||||
|
{
|
||||||
|
AlarmDuration = 5.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
_warner = new LaserWarner(
|
||||||
|
_warnerId,
|
||||||
|
new Vector3D(0, 0, 0),
|
||||||
|
new Orientation(0, 0, 0),
|
||||||
|
_mockSimManager.Object,
|
||||||
|
_tankId,
|
||||||
|
_config
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_warner.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_InitializesCorrectly()
|
||||||
|
{
|
||||||
|
Assert.Equal(_warnerId, _warner.Id);
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StartWarning_WhenNotWarning_StartsWarning()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StopWarning_WhenWarning_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.StopWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_WhenWarningTimeExceeded_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.Activate();
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.Update(6.0); // 超过警报持续时间
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OnLaserIllumination_StartsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Action<LaserIlluminationStartEvent>? eventHandler = null;
|
||||||
|
_mockSimManager.Setup(m => m.SubscribeToEvent(It.IsAny<Action<LaserIlluminationStartEvent>>()))
|
||||||
|
.Callback<Action<LaserIlluminationStartEvent>>(handler => eventHandler = handler);
|
||||||
|
|
||||||
|
_warner.Activate();
|
||||||
|
Assert.NotNull(eventHandler);
|
||||||
|
|
||||||
|
// 创建一个模拟的目标
|
||||||
|
var mockTarget = new Mock<SimulationElement>(_tankId,
|
||||||
|
new Vector3D(0, 0, 0),
|
||||||
|
new Orientation(0, 0, 0),
|
||||||
|
0,
|
||||||
|
_mockSimManager.Object);
|
||||||
|
|
||||||
|
// 设置模拟对象的 Id 属性
|
||||||
|
mockTarget.Setup(t => t.Id).Returns(_tankId);
|
||||||
|
|
||||||
|
var illuminationEvent = new LaserIlluminationStartEvent
|
||||||
|
{
|
||||||
|
Target = mockTarget.Object,
|
||||||
|
SenderId = "TestLaser" // 添加发送者ID
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
eventHandler?.Invoke(illuminationEvent);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OnLaserIlluminationStop_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Action<LaserIlluminationStopEvent>? eventHandler = null;
|
||||||
|
_mockSimManager.Setup(m => m.SubscribeToEvent(It.IsAny<Action<LaserIlluminationStopEvent>>()))
|
||||||
|
.Callback<Action<LaserIlluminationStopEvent>>(handler => eventHandler = handler);
|
||||||
|
|
||||||
|
_warner.Activate();
|
||||||
|
_warner.StartWarning();
|
||||||
|
Assert.NotNull(eventHandler);
|
||||||
|
|
||||||
|
// 创建一个模拟的目标
|
||||||
|
var mockTarget = new Mock<SimulationElement>(_tankId,
|
||||||
|
new Vector3D(0, 0, 0),
|
||||||
|
new Orientation(0, 0, 0),
|
||||||
|
0,
|
||||||
|
_mockSimManager.Object);
|
||||||
|
|
||||||
|
// 设置模拟对象的 Id 属性
|
||||||
|
mockTarget.Setup(t => t.Id).Returns(_tankId);
|
||||||
|
|
||||||
|
var illuminationStopEvent = new LaserIlluminationStopEvent
|
||||||
|
{
|
||||||
|
Target = mockTarget.Object,
|
||||||
|
SenderId = "TestLaser" // 添加发送者ID
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
eventHandler?.Invoke(illuminationStopEvent);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetWarningStatus_ReturnsCorrectFormat()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string status = _warner.GetWarningStatus();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Contains("激光告警器", status);
|
||||||
|
Assert.Contains("告警中", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_PublishesWarningEvent_WhenWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
_warner.Activate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.Update(1.0);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(m => m.PublishEvent(It.Is<LaserWarnerAlarmEvent>(e =>
|
||||||
|
e.TargetId == _tankId
|
||||||
|
)), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Deactivate_UnsubscribesFromEvents()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.Deactivate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(
|
||||||
|
m => m.UnsubscribeFromEvent<LaserIlluminationStartEvent>(
|
||||||
|
It.IsAny<Action<LaserIlluminationStartEvent>>()),
|
||||||
|
Times.Once);
|
||||||
|
_mockSimManager.Verify(
|
||||||
|
m => m.UnsubscribeFromEvent<LaserIlluminationStopEvent>(
|
||||||
|
It.IsAny<Action<LaserIlluminationStopEvent>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
150
src/Tests/Unit/Models/Warner/MillimeterWaveWarnerTests.cs
Normal file
150
src/Tests/Unit/Models/Warner/MillimeterWaveWarnerTests.cs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
using System;
|
||||||
|
using ActiveProtect.Models;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Tests.Unit.Models.Warner
|
||||||
|
{
|
||||||
|
public class MillimeterWaveWarnerTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Mock<ISimulationManager> _mockSimManager;
|
||||||
|
private readonly MillimeterWaveWarner _warner;
|
||||||
|
private readonly string _warnerId = "TestMMWWarner";
|
||||||
|
private readonly string _tankId = "TestTank";
|
||||||
|
private readonly MillimeterWaveWarnerConfig _config;
|
||||||
|
|
||||||
|
public MillimeterWaveWarnerTests()
|
||||||
|
{
|
||||||
|
_mockSimManager = new Mock<ISimulationManager>();
|
||||||
|
_mockSimManager.Setup(m => m.CurrentTime).Returns(0.0);
|
||||||
|
_mockSimManager.Setup(m => m.PublishEvent(It.IsAny<SimulationEvent>()));
|
||||||
|
|
||||||
|
_config = new MillimeterWaveWarnerConfig
|
||||||
|
{
|
||||||
|
AlarmDuration = 5.0,
|
||||||
|
SensitivityThreshold = 0.1,
|
||||||
|
WavelengthMin = 30.0, // 30 GHz
|
||||||
|
WavelengthMax = 300.0 // 300 GHz
|
||||||
|
};
|
||||||
|
|
||||||
|
_warner = new MillimeterWaveWarner(
|
||||||
|
_warnerId,
|
||||||
|
new Vector3D(0, 0, 0),
|
||||||
|
new Orientation(0, 0, 0),
|
||||||
|
_mockSimManager.Object,
|
||||||
|
_tankId,
|
||||||
|
_config
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_warner.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_InitializesCorrectly()
|
||||||
|
{
|
||||||
|
Assert.Equal(_warnerId, _warner.Id);
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StartWarning_WhenNotWarning_StartsWarning()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StopWarning_WhenWarning_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.StopWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.2, 100.0, true)] // 高于阈值,频率在范围内
|
||||||
|
[InlineData(0.05, 100.0, false)] // 低于阈值,频率在范围内
|
||||||
|
[InlineData(0.2, 400.0, false)] // 高于阈值,频率超出范围
|
||||||
|
public void OnMillimeterWaveDetection_RespondsToThresholds(
|
||||||
|
double intensity, double frequency, bool shouldTrigger)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Action<MillimeterWaveDetectionEvent>? eventHandler = null;
|
||||||
|
_mockSimManager.Setup(m => m.SubscribeToEvent(It.IsAny<Action<MillimeterWaveDetectionEvent>>()))
|
||||||
|
.Callback<Action<MillimeterWaveDetectionEvent>>(handler => eventHandler = handler);
|
||||||
|
|
||||||
|
_warner.Activate();
|
||||||
|
Assert.NotNull(eventHandler);
|
||||||
|
|
||||||
|
var detectionEvent = new MillimeterWaveDetectionEvent
|
||||||
|
{
|
||||||
|
TargetId = _tankId,
|
||||||
|
Intensity = intensity,
|
||||||
|
Frequency = frequency
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
eventHandler?.Invoke(detectionEvent);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(shouldTrigger, _warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetWarningStatus_ReturnsCorrectFormat()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string status = _warner.GetWarningStatus();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Contains("毫米波告警器", status);
|
||||||
|
Assert.Contains("告警中", status);
|
||||||
|
Assert.Contains("30.00-300.00GHz", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_PublishesWarningEvent_WhenWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
_warner.Activate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.Update(1.0);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(m => m.PublishEvent(It.Is<MillimeterWaveWarnerAlarmEvent>(e =>
|
||||||
|
e.TargetId == _tankId
|
||||||
|
)), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Deactivate_UnsubscribesFromEvents()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.Deactivate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(
|
||||||
|
m => m.UnsubscribeFromEvent<MillimeterWaveDetectionEvent>(
|
||||||
|
It.IsAny<Action<MillimeterWaveDetectionEvent>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
161
src/Tests/Unit/Models/Warner/UltravioletWarnerTests.cs
Normal file
161
src/Tests/Unit/Models/Warner/UltravioletWarnerTests.cs
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
using System;
|
||||||
|
using ActiveProtect.Models;
|
||||||
|
using ActiveProtect.Simulation;
|
||||||
|
using ActiveProtect.Utility;
|
||||||
|
|
||||||
|
namespace ActiveProtect.Tests.Unit.Models.Warner
|
||||||
|
{
|
||||||
|
public class UltravioletWarnerTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Mock<ISimulationManager> _mockSimManager;
|
||||||
|
private readonly UltravioletWarner _warner;
|
||||||
|
private readonly string _warnerId = "TestUVWarner";
|
||||||
|
private readonly string _tankId = "TestTank";
|
||||||
|
private readonly UltravioletWarnerConfig _config;
|
||||||
|
|
||||||
|
public UltravioletWarnerTests()
|
||||||
|
{
|
||||||
|
_mockSimManager = new Mock<ISimulationManager>();
|
||||||
|
_mockSimManager.Setup(m => m.CurrentTime).Returns(0.0);
|
||||||
|
_mockSimManager.Setup(m => m.PublishEvent(It.IsAny<SimulationEvent>()));
|
||||||
|
|
||||||
|
_config = new UltravioletWarnerConfig
|
||||||
|
{
|
||||||
|
AlarmDuration = 5.0,
|
||||||
|
SensitivityThreshold = 0.1,
|
||||||
|
WavelengthMin = 200.0,
|
||||||
|
WavelengthMax = 280.0
|
||||||
|
};
|
||||||
|
|
||||||
|
_warner = new UltravioletWarner(
|
||||||
|
_warnerId,
|
||||||
|
new Vector3D(0, 0, 0),
|
||||||
|
new Orientation(0, 0, 0),
|
||||||
|
_mockSimManager.Object,
|
||||||
|
_tankId,
|
||||||
|
_config
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_warner.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_InitializesCorrectly()
|
||||||
|
{
|
||||||
|
Assert.Equal(_warnerId, _warner.Id);
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StartWarning_WhenNotWarning_StartsWarning()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StopWarning_WhenWarning_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.StopWarning();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_WhenWarningTimeExceeded_StopsWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.Activate();
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.Update(6.0); // 超过警报持续时间
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(_warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.2, true)] // 高于阈值,应该触发
|
||||||
|
[InlineData(0.05, false)] // 低于阈值,不应该触发
|
||||||
|
public void OnUltravioletDetection_RespondsToIntensityThreshold(double intensity, bool shouldTrigger)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
Action<UltravioletDetectionEvent>? eventHandler = null;
|
||||||
|
_mockSimManager.Setup(m => m.SubscribeToEvent(It.IsAny<Action<UltravioletDetectionEvent>>()))
|
||||||
|
.Callback<Action<UltravioletDetectionEvent>>(handler => eventHandler = handler);
|
||||||
|
|
||||||
|
_warner.Activate();
|
||||||
|
Assert.NotNull(eventHandler);
|
||||||
|
|
||||||
|
var detectionEvent = new UltravioletDetectionEvent
|
||||||
|
{
|
||||||
|
TargetId = _tankId,
|
||||||
|
Intensity = intensity
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
eventHandler?.Invoke(detectionEvent);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(shouldTrigger, _warner.IsWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetWarningStatus_ReturnsCorrectFormat()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string status = _warner.GetWarningStatus();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Contains("紫外告警器", status);
|
||||||
|
Assert.Contains("告警中", status);
|
||||||
|
Assert.Contains("200.00-280.00纳米", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Update_PublishesWarningEvent_WhenWarning()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_warner.StartWarning();
|
||||||
|
_warner.Activate();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
_warner.Update(1.0);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(m => m.PublishEvent(It.Is<UltravioletWarnerAlarmEvent>(e =>
|
||||||
|
e.TargetId == _tankId
|
||||||
|
)), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Deactivate_UnsubscribesFromEvents()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
_warner.Deactivate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_mockSimManager.Verify(
|
||||||
|
m => m.UnsubscribeFromEvent<UltravioletDetectionEvent>(
|
||||||
|
It.IsAny<Action<UltravioletDetectionEvent>>()),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user