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; } }