增加了单元测试框架,重构了告警器模型,增加了告警器配置,编写了新增告警器的单元测试
This commit is contained in:
parent
3f02f52074
commit
af702cbbda
@ -4,8 +4,19 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
</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>
|
||||
|
||||
@ -1,29 +1,33 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.002.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActiveProtect", "ActiveProtect.csproj", "{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {73773200-50D4-40ED-803B-FC16B131FFD2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActiveProtect", "ActiveProtect.csproj", "{7138CDD4-EC75-4803-8050-D72A32B381CA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{88B204F0-6636-4265-ACFB-52D889A56413}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActiveProtect.Tests", "src\Tests\ActiveProtect.Tests.csproj", "{55F5BDBE-025D-465B-BB34-2262369715BB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7138CDD4-EC75-4803-8050-D72A32B381CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{55F5BDBE-025D-465B-BB34-2262369715BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{55F5BDBE-025D-465B-BB34-2262369715BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55F5BDBE-025D-465B-BB34-2262369715BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55F5BDBE-025D-465B-BB34-2262369715BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
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.Utility;
|
||||
|
||||
@ -8,22 +9,24 @@ namespace ActiveProtect.Models
|
||||
/// </summary>
|
||||
public class UltravioletWarner : WarnerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 紫外告警器灵敏度阈值
|
||||
/// </summary>
|
||||
private readonly double sensitivityThreshold;
|
||||
private readonly double _sensitivityThreshold;
|
||||
private readonly double _wavelengthMin;
|
||||
private readonly double _wavelengthMax;
|
||||
|
||||
public UltravioletWarner(string id, Vector3D position, Orientation orientation,
|
||||
ISimulationManager manager, string tankId, double warningDuration, double sensitivityThreshold)
|
||||
: base(id, position, orientation, manager, tankId, warningDuration)
|
||||
ISimulationManager manager, string tankId, UltravioletWarnerConfig config)
|
||||
: 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);
|
||||
}
|
||||
|
||||
private void OnUltravioletDetection(UltravioletDetectionEvent evt)
|
||||
{
|
||||
if (evt?.TargetId == TankId && evt.Intensity >= sensitivityThreshold)
|
||||
if (evt?.TargetId == TankId && evt.Intensity >= _sensitivityThreshold)
|
||||
{
|
||||
StartWarning();
|
||||
}
|
||||
@ -33,7 +36,24 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
return $"紫外告警器 {Id}:\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()
|
||||
@ -14,6 +14,16 @@ namespace ActiveProtect.Models
|
||||
/// </summary>
|
||||
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>
|
||||
@ -30,10 +40,12 @@ namespace ActiveProtect.Models
|
||||
protected string TankId { get; set; }
|
||||
|
||||
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)
|
||||
{
|
||||
TankId = tankId;
|
||||
SensitivityThreshold = sensitivityThreshold;
|
||||
FrequencyRange = frequencyRange;
|
||||
WarningDuration = warningDuration;
|
||||
CurrentWarningTime = 0;
|
||||
IsWarning = false;
|
||||
@ -165,18 +165,165 @@ namespace ActiveProtect.Simulation
|
||||
/// </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 LaserWarnerConfig()
|
||||
{
|
||||
Id = "";
|
||||
SensitivityThreshold = 0;
|
||||
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