53 lines
2.9 KiB
C#
53 lines
2.9 KiB
C#
using System.Text.Json;
|
||
|
||
namespace Server.WatchBody.Core.Programs;
|
||
|
||
/// <summary>
|
||
/// Пороги правил прогрессии/делоада/перерывов (секция Progression);
|
||
/// умолчания — requirements разд. 3 и Ф-14.1. 🛡 В расчётном коде
|
||
/// пороги не хардкодятся — только эти значения (Р3-А).
|
||
/// </summary>
|
||
public class ProgressionConfig
|
||
{
|
||
public decimal BaseStepKg { get; set; } = 2.5m;
|
||
public decimal IsoStepKg { get; set; } = 1.0m;
|
||
public int BackoffPercent { get; set; } = 5;
|
||
public int DeloadMaxWeeks { get; set; } = 6;
|
||
public int MissDaysForBreak { get; set; } = 4;
|
||
public decimal ReturnMinFactor { get; set; } = 0.6m;
|
||
public decimal ReturnMaxFactor { get; set; } = 0.9m;
|
||
|
||
/// <summary>Чтение секции Progression (отсутствует/частичная — умолчания).</summary>
|
||
public static ProgressionConfig Load(JsonElement root)
|
||
{
|
||
var config = new ProgressionConfig();
|
||
if (!root.TryGetProperty("Progression", out var section) || section.ValueKind != JsonValueKind.Object)
|
||
return config;
|
||
foreach (var property in typeof(ProgressionConfig).GetProperties())
|
||
{
|
||
var name = char.ToLowerInvariant(property.Name[0]) + property.Name[1..];
|
||
if (!section.TryGetProperty(name, out var value)) continue;
|
||
if (value.ValueKind != JsonValueKind.Number || !value.TryGetDecimal(out var number))
|
||
throw new InvalidOperationException($"Progression.{name}: ожидалось число");
|
||
property.SetValue(config, Convert.ChangeType(number, property.PropertyType));
|
||
}
|
||
return config;
|
||
}
|
||
|
||
/// <summary>Ошибки конфигурации (фатальны при старте).</summary>
|
||
public List<string> Validate()
|
||
{
|
||
var errors = new List<string>();
|
||
// IsoStepKg — коридор метрик «+0,5–1 кг» (О-3-А): 0.25–5
|
||
if (IsoStepKg < 0.25m || IsoStepKg > 5m) errors.Add("Progression: isoStepKg вне [0.25; 5]");
|
||
if (BaseStepKg < 0.5m || BaseStepKg > 10m) errors.Add("Progression: baseStepKg вне [0.5; 10]");
|
||
if (BackoffPercent < 1 || BackoffPercent > 20) errors.Add("Progression: backoffPercent вне [1; 20]");
|
||
if (DeloadMaxWeeks < 3 || DeloadMaxWeeks > 12) errors.Add("Progression: deloadMaxWeeks вне [3; 12]");
|
||
if (MissDaysForBreak < 2) errors.Add("Progression: missDaysForBreak < 2");
|
||
if (ReturnMinFactor < 0.3m || ReturnMinFactor > 0.9m) errors.Add("Progression: returnMinFactor вне [0.3; 0.9]");
|
||
if (ReturnMaxFactor <= 0.5m || ReturnMaxFactor > 1m) errors.Add("Progression: returnMaxFactor вне (0.5; 1]");
|
||
if (ReturnMinFactor > ReturnMaxFactor) errors.Add("Progression: returnMinFactor > returnMaxFactor");
|
||
return errors;
|
||
}
|
||
}
|