using System.Text.Json;
namespace Server.WatchBody.Core.Metrics;
///
/// Пороги красных флагов (секция Safety, Р3-А); умолчания — документ
/// метрик (п. 2.1–2.3, правила 1 и 6). 🛡 В расчётном коде пороги не
/// хардкодятся — только эти значения.
///
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;
/// Чтение секции Safety (отсутствует/частичная — умолчания).
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;
}
/// Ошибки конфигурации (фатальны при старте).
public List Validate()
{
var errors = new List();
// по документу метрик коридоры АД перекрываются
// (отмена: >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;
}
}