SSPC-Tester/SSPCTester.Logic/Models/Results.cs
2026-07-03 14:16:15 +08:00

179 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
[ObservableProperty] private int _index;
[ObservableProperty] private string _protectType = "";
[ObservableProperty] private string _trigger = "";
[ObservableProperty] private string _measuredValue = "----";
[ObservableProperty] private string _judgeMode = "人工判别";
[ObservableProperty] private double _tripTimeMs;
[ObservableProperty] private TestStatus _status = TestStatus.Untested;
public bool CanMeasureFromPower =>
ProtectType is "跳闸" or "过压" or "欠压" or "限流";
partial void OnProtectTypeChanged(string value) =>
OnPropertyChanged(nameof(CanMeasureFromPower));
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",
_ => "----"
};
}
/// <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;
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);
}
}
}