SSPC-Tester/SSPCTester.Logic/Models/Results.cs

179 lines
7.2 KiB
C#
Raw Normal View History

using CommunityToolkit.Mvvm.ComponentModel;
namespace SSPCTester.Logic.Models;
/// <summary>基础测试单通道结果。</summary>
public partial class ChannelResult : ObservableObject
{
[ObservableProperty] private int _channel;
[ObservableProperty] private double _voltageOn;
[ObservableProperty] private double _currentOn;
[ObservableProperty] private double _voltageOff;
[ObservableProperty] private double _currentOff;
[ObservableProperty] private double _displayVoltage;
[ObservableProperty] private double _displayCurrent;
[ObservableProperty] private TestStatus _status = TestStatus.Untested;
}
/// <summary>曲线测试单通道结果(覆盖指标 1.1-1.6)。</summary>
public partial class CurveResultRow : ObservableObject
{
[ObservableProperty] private int _channel;
/// <summary>开启时间ms。</summary>
[ObservableProperty] private double _onTimeMs;
/// <summary>上升时间ms。</summary>
[ObservableProperty] private double _riseTimeMs;
/// <summary>关闭时间ms。</summary>
[ObservableProperty] private double _offTimeMs;
/// <summary>下降时间ms。</summary>
[ObservableProperty] private double _fallTimeMs;
[ObservableProperty] private string? _risingWaveformPath;
[ObservableProperty] private string? _fallingWaveformPath;
/// <summary>曲线显示起点msnull 表示全曲线)。</summary>
[ObservableProperty] private double? _viewStartMs;
/// <summary>曲线显示终点msnull 表示全曲线)。</summary>
[ObservableProperty] private double? _viewEndMs;
[ObservableProperty] private double? _risingViewStartMs;
[ObservableProperty] private double? _risingViewEndMs;
[ObservableProperty] private double? _fallingViewStartMs;
[ObservableProperty] private double? _fallingViewEndMs;
[ObservableProperty] private TestStatus _status = TestStatus.Untested;
}
/// <summary>曲线测试阈值(合格判定)。</summary>
public sealed class CurveThresholds
{
public double MaxOnTimeMs { get; set; } = 5.0;
public double MaxRiseTimeMs { get; set; } = 3.0;
public double MaxOffTimeMs { get; set; } = 5.0;
public double MaxFallTimeMs { get; set; } = 3.0;
}
/// <summary>功率损耗单通道结果(覆盖指标 1.7-1.10)。</summary>
public partial class PowerLossRow : ObservableObject
{
[ObservableProperty] private int _channel;
[ObservableProperty] private double _vin;
[ObservableProperty] private double _iin;
[ObservableProperty] private double _vout;
[ObservableProperty] private double _iout;
[ObservableProperty] private double? _measuredPowerOut;
[ObservableProperty] private TestStatus _status = TestStatus.Untested;
public double VoltageDrop => Vin - Vout;
public double PowerIn => Vin * Iin;
public double CalculatedPowerOut => Vout * Iout;
public double PowerOut => CalculatedPowerOut;
public double PowerLossW => PowerIn - PowerOut;
public double PowerLossPct => PowerIn > 0 ? (PowerIn - CalculatedPowerOut) / PowerIn * 100.0 : 0;
public double EfficiencyRatio => PowerIn > 0 ? CalculatedPowerOut / PowerIn : 0;
public double EfficiencyPct => PowerIn > 0 ? PowerOut / PowerIn * 100.0 : 0;
public double OutputPower => PowerOut;
partial void OnVinChanged(double value) => RaiseDerived();
partial void OnIinChanged(double value) => RaiseDerived();
partial void OnVoutChanged(double value) => RaiseDerived();
partial void OnIoutChanged(double value) => RaiseDerived();
partial void OnMeasuredPowerOutChanged(double? value) => RaiseDerived();
private void RaiseDerived()
{
OnPropertyChanged(nameof(VoltageDrop));
OnPropertyChanged(nameof(PowerIn));
OnPropertyChanged(nameof(PowerOut));
OnPropertyChanged(nameof(CalculatedPowerOut));
OnPropertyChanged(nameof(PowerLossW));
OnPropertyChanged(nameof(PowerLossPct));
OnPropertyChanged(nameof(EfficiencyRatio));
OnPropertyChanged(nameof(EfficiencyPct));
OnPropertyChanged(nameof(OutputPower));
}
}
/// <summary>保护功能单项结果。</summary>
public partial class ProtectRow : ObservableObject
{
2026-07-02 17:43:32 +08:00
[ObservableProperty] private int _index;
[ObservableProperty] private string _protectType = "";
[ObservableProperty] private string _trigger = "";
2026-07-02 17:43:32 +08:00
[ObservableProperty] private string _measuredValue = "----";
[ObservableProperty] private string _judgeMode = "人工判别";
[ObservableProperty] private double _tripTimeMs;
[ObservableProperty] private TestStatus _status = TestStatus.Untested;
2026-07-02 17:43:32 +08:00
2026-07-02 21:38:25 +08:00
public bool CanMeasureFromPower =>
ProtectType is "跳闸" or "过压" or "欠压" or "限流";
partial void OnProtectTypeChanged(string value) =>
OnPropertyChanged(nameof(CanMeasureFromPower));
2026-07-02 17:43:32 +08:00
public static string BuildMeasuredValue(string protectType, double? inputVoltage, double? inputCurrent) => protectType switch
{
"跳闸" when inputCurrent.HasValue => $"{inputCurrent.Value:F3} A",
"过压" or "欠压" when inputVoltage.HasValue => $"{inputVoltage.Value:F3} V",
"限流" when inputCurrent.HasValue => $"{inputCurrent.Value:F3} A",
_ => "----"
};
}
2026-07-02 21:38:25 +08:00
/// <summary>保护功能固定测试项与结果初始化逻辑。</summary>
public static class ProtectTestPlan
{
public const string ManualJudgeMode = "人工判别";
public static readonly IReadOnlyList<(string ProtectType, string Trigger)> Items = new[]
{
("跳闸", "1.5×额定电流"),
("短路", "输出短路"),
("过温", "≥85℃"),
("过压", "≥32V"),
("欠压", "≤22V"),
("限流", "≥1.2A"),
};
public static void EnsureRows(Project project)
{
var existing = project.ProtectResults
.GroupBy(x => x.ProtectType)
.ToDictionary(x => x.Key, x => x.First());
project.ProtectResults.Clear();
for (int i = 0; i < Items.Count; i++)
{
var item = Items[i];
if (!existing.TryGetValue(item.ProtectType, out var row))
{
row = new ProtectRow
{
ProtectType = item.ProtectType,
Status = TestStatus.Untested
};
}
row.Index = i + 1;
row.ProtectType = item.ProtectType;
if (string.IsNullOrWhiteSpace(row.Trigger))
row.Trigger = item.Trigger;
if (string.IsNullOrWhiteSpace(row.JudgeMode))
row.JudgeMode = ManualJudgeMode;
if (row.Status == TestStatus.Measured)
row.Status = TestStatus.Untested;
2026-07-02 21:38:25 +08:00
project.ProtectResults.Add(row);
}
RefreshMeasuredValues(project, overwriteExisting: false);
}
public static void RefreshMeasuredValues(Project project, bool overwriteExisting = true)
{
var latestPower = project.PowerResults.LastOrDefault();
foreach (var row in project.ProtectResults)
{
if (!overwriteExisting && !string.IsNullOrWhiteSpace(row.MeasuredValue) && row.MeasuredValue != "----")
continue;
row.MeasuredValue = ProtectRow.BuildMeasuredValue(row.ProtectType, latestPower?.Vin, latestPower?.Iin);
}
}
}