| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- using System.Text.Json;
- namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules;
- /// <summary>
- /// R3 OUT_OF_RANGE 类规则 params_json 解析结果。internal 可见,供测试覆盖。
- /// 兼容两种协议形态:
- /// 1. 新协议:measuredValueField / lowerBound / upperBound / lowerBoundField / upperBoundField / objectCodeField / objectIdField / toleranceAbs / toleranceRatio / exceptionTypeCode
- /// 2. 旧 G01 兼容:mode=single_threshold / operator=">"|">="|"<"|"<=" / threshold / valueField / objectCodeField / compatAlertRuleCode
- /// 字段缺失或非法 JSON:调用方负责降级(evaluator 静默返空命中),不在此抛出业务异常。
- /// </summary>
- internal sealed class S8OutOfRangeParams
- {
- public string? MeasuredValueField { get; set; }
- public string? ObjectCodeField { get; set; }
- public string? ObjectIdField { get; set; }
- public string? LowerBoundField { get; set; }
- public string? UpperBoundField { get; set; }
- public decimal? LowerBound { get; set; }
- public decimal? UpperBound { get; set; }
- public decimal ToleranceAbs { get; set; }
- public decimal ToleranceRatio { get; set; }
- public string? ExceptionTypeCode { get; set; }
- /// <summary>解析 params_json;非法 JSON 抛 <see cref="JsonException"/>,由上游捕获。</summary>
- public static S8OutOfRangeParams Parse(string json)
- {
- using var doc = JsonDocument.Parse(json);
- var root = doc.RootElement;
- var p = new S8OutOfRangeParams();
- // 新协议字段
- if (root.TryGetProperty("measuredValueField", out var v1)) p.MeasuredValueField = v1.GetString();
- if (root.TryGetProperty("objectCodeField", out var v2)) p.ObjectCodeField = v2.GetString();
- if (root.TryGetProperty("objectIdField", out var v3)) p.ObjectIdField = v3.GetString();
- if (root.TryGetProperty("lowerBoundField", out var v4)) p.LowerBoundField = v4.GetString();
- if (root.TryGetProperty("upperBoundField", out var v5)) p.UpperBoundField = v5.GetString();
- if (root.TryGetProperty("lowerBound", out var v6) && v6.ValueKind == JsonValueKind.Number) p.LowerBound = v6.GetDecimal();
- if (root.TryGetProperty("upperBound", out var v7) && v7.ValueKind == JsonValueKind.Number) p.UpperBound = v7.GetDecimal();
- if (root.TryGetProperty("toleranceAbs", out var v8) && v8.ValueKind == JsonValueKind.Number) p.ToleranceAbs = v8.GetDecimal();
- if (root.TryGetProperty("toleranceRatio", out var v9) && v9.ValueKind == JsonValueKind.Number) p.ToleranceRatio = v9.GetDecimal();
- if (root.TryGetProperty("exceptionTypeCode", out var v10)) p.ExceptionTypeCode = v10.GetString();
- // G01 兼容:valueField → measuredValueField
- if (string.IsNullOrWhiteSpace(p.MeasuredValueField)
- && root.TryGetProperty("valueField", out var legacyVal))
- p.MeasuredValueField = legacyVal.GetString();
- // G01 兼容:mode=single_threshold + operator + threshold → upperBound 或 lowerBound
- if (root.TryGetProperty("mode", out var modeEl)
- && string.Equals(modeEl.GetString(), "single_threshold", StringComparison.OrdinalIgnoreCase)
- && root.TryGetProperty("operator", out var opEl)
- && root.TryGetProperty("threshold", out var thrEl)
- && thrEl.ValueKind == JsonValueKind.Number)
- {
- var op = opEl.GetString()?.Trim();
- var thr = thrEl.GetDecimal();
- // operator '>' 或 '>=' → measured 超过 threshold 命中 → 等价 upperBound=threshold
- // operator '<' 或 '<=' → measured 低于 threshold 命中 → 等价 lowerBound=threshold
- if (op == ">" || op == ">=") p.UpperBound ??= thr;
- else if (op == "<" || op == "<=") p.LowerBound ??= thr;
- }
- return p;
- }
- }
|