59 lines
2.7 KiB
C#
59 lines
2.7 KiB
C#
using System.Text.Json;
|
||
|
||
namespace Server.WatchBody.Core.Metrics;
|
||
|
||
/// <summary>
|
||
/// Пороги красных флагов (секция Safety, Р3-А); умолчания — документ
|
||
/// метрик (п. 2.1–2.3, правила 1 и 6). 🛡 В расчётном коде пороги не
|
||
/// хардкодятся — только эти значения.
|
||
/// </summary>
|
||
public class MetricsConfig
|
||
{
|
||
public int BpCancelSys { get; set; } = 150;
|
||
public int BpCancelDias { get; set; } = 90;
|
||
public int BpElevatedSys { get; set; } = 140;
|
||
public int BpElevatedDias { get; set; } = 95;
|
||
public int HrRestingRise { get; set; } = 8;
|
||
public int HrRestingDays { get; set; } = 2;
|
||
public int WellbeingLow { get; set; } = 2;
|
||
public int WellbeingDays { get; set; } = 2;
|
||
public int LightDayCount { get; set; } = 3;
|
||
public int KneePainMin { get; set; } = 1;
|
||
public int KneeRepeatSessions { get; set; } = 2;
|
||
public int HrBaselineDays { get; set; } = 14;
|
||
public int HrBaselineMin { get; set; } = 3;
|
||
|
||
/// <summary>Чтение секции Safety (отсутствует/частичная — умолчания).</summary>
|
||
public static MetricsConfig Load(JsonElement root)
|
||
{
|
||
var config = new MetricsConfig();
|
||
if (!root.TryGetProperty("Safety", out var safety) || safety.ValueKind != JsonValueKind.Object)
|
||
return config;
|
||
foreach (var property in typeof(MetricsConfig).GetProperties())
|
||
{
|
||
var name = char.ToLowerInvariant(property.Name[0]) + property.Name[1..];
|
||
if (!safety.TryGetProperty(name, out var value)) continue;
|
||
if (value.ValueKind != JsonValueKind.Number || !value.TryGetInt32(out var number))
|
||
throw new InvalidOperationException($"Safety.{name}: ожидалось целое число");
|
||
property.SetValue(config, number);
|
||
}
|
||
return config;
|
||
}
|
||
|
||
/// <summary>Ошибки конфигурации (фатальны при старте).</summary>
|
||
public List<string> Validate()
|
||
{
|
||
var errors = new List<string>();
|
||
// по документу метрик коридоры АД перекрываются
|
||
// (отмена: >150/90; «только кардио»: 140–150/90–95), поэтому
|
||
// bpElevatedDias (95) может быть больше bpCancelDias (90)
|
||
if (BpElevatedSys > BpCancelSys) errors.Add("Safety: bpElevatedSys > bpCancelSys");
|
||
foreach (var property in typeof(MetricsConfig).GetProperties())
|
||
{
|
||
var name = char.ToLowerInvariant(property.Name[0]) + property.Name[1..];
|
||
if ((int)property.GetValue(this)! <= 0) errors.Add($"Safety: {name} <= 0");
|
||
}
|
||
return errors;
|
||
}
|
||
}
|