| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- using System.Globalization;
- namespace Admin.NET.Plugin.AiDOP.Manufacturing;
- /// <summary>录入类型(快照冻结值)。</summary>
- public static class S6ResultType
- {
- public const string Numeric = "NUMERIC";
- public const string NonNumeric = "NON_NUMERIC";
- }
- /// <summary>逐样本 / 单项 / 整单判定值。</summary>
- public static class S6Judgement
- {
- public const string Pass = "PASS";
- public const string Fail = "FAIL";
- public const string Invalid = "INVALID"; // 配置无法判定 / 值非法
- public const string Pending = "PENDING"; // 样本不足,未完成
- }
- /// <summary>单项完成状态。</summary>
- public static class S6ItemStatus
- {
- public const string NotStarted = "NOT_STARTED";
- public const string InProgress = "IN_PROGRESS";
- public const string Completed = "COMPLETED";
- }
- /// <summary>
- /// S6 过程检验 自动判定引擎(Phase 1C,纯函数,后端唯一判定真源)。
- /// 只依据"快照冻结的规格"(ResultType/上下限/要求样本量)+ 实录样本值判定;绝不回查 S0 检规。
- /// FQC 未做的两处在此补齐:① NON_NUMERIC 自动 OK→PASS/NG→FAIL;② 单项完成度 + 整单聚合后端计算。
- /// </summary>
- public static class S6ProcessInspectionJudge
- {
- /// <summary>解析上/下限字符串为 decimal;空/非法 → null(该边界不生效)。</summary>
- public static decimal? ParseLimit(string? raw)
- {
- if (string.IsNullOrWhiteSpace(raw)) return null;
- return decimal.TryParse(raw.Trim(), NumberStyles.Any, CultureInfo.InvariantCulture, out var d) ? d : null;
- }
- /// <summary>解析数值样本;空/非法 → null。</summary>
- public static decimal? ParseNumeric(string? raw)
- {
- if (string.IsNullOrWhiteSpace(raw)) return null;
- return decimal.TryParse(raw.Trim(), NumberStyles.Any, CultureInfo.InvariantCulture, out var d) ? d : null;
- }
- /// <summary>
- /// 逐样本判定。NUMERIC:闭区间(上下限可各自缺省,均缺=INVALID 不可判);值非法=INVALID。
- /// NON_NUMERIC:OK→PASS / NG→FAIL / 其他=INVALID。
- /// </summary>
- public static string JudgeSample(string? resultType, string? actualRaw, string? lowerRaw, string? upperRaw)
- {
- var rt = (resultType ?? string.Empty).Trim().ToUpperInvariant();
- if (rt == S6ResultType.NonNumeric)
- {
- var v = (actualRaw ?? string.Empty).Trim().ToUpperInvariant();
- return v switch { "OK" => S6Judgement.Pass, "NG" => S6Judgement.Fail, _ => S6Judgement.Invalid };
- }
- if (rt == S6ResultType.Numeric)
- {
- var lo = ParseLimit(lowerRaw);
- var up = ParseLimit(upperRaw);
- if (lo == null && up == null) return S6Judgement.Invalid; // 无任何界限 → 无法判定
- var actual = ParseNumeric(actualRaw);
- if (actual == null) return S6Judgement.Invalid; // 非法/空数值 → 不可默认 PASS
- var ok = (lo == null || actual.Value >= lo.Value) && (up == null || actual.Value <= up.Value);
- return ok ? S6Judgement.Pass : S6Judgement.Fail;
- }
- return S6Judgement.Invalid; // 未知录入类型
- }
- /// <summary>
- /// 单项聚合:由该项已录样本的判定 + 要求样本量 → (完成状态, 单项结果)。
- /// 任一 INVALID→INVALID;任一 FAIL→FAIL;已录满且全 PASS→PASS;否则 PENDING。
- /// </summary>
- public static (string Status, string Result) AggregateItem(int requiredCount, IReadOnlyList<string> sampleJudgements)
- {
- var recorded = sampleJudgements?.Count ?? 0;
- var required = requiredCount <= 0 ? 1 : requiredCount;
- if (recorded == 0) return (S6ItemStatus.NotStarted, S6Judgement.Pending);
- var status = recorded >= required ? S6ItemStatus.Completed : S6ItemStatus.InProgress;
- if (sampleJudgements!.Any(j => j == S6Judgement.Invalid)) return (status, S6Judgement.Invalid);
- if (sampleJudgements.Any(j => j == S6Judgement.Fail)) return (status, S6Judgement.Fail);
- if (status == S6ItemStatus.Completed && sampleJudgements.All(j => j == S6Judgement.Pass))
- return (status, S6Judgement.Pass);
- return (status, S6Judgement.Pending); // 已录未满
- }
- /// <summary>
- /// 整单聚合:由各项 (完成状态, 单项结果) → 整单结果。
- /// 任一 INVALID→INVALID;任一 FAIL→FAIL;全部 COMPLETED 且 PASS→PASS;否则 PENDING。
- /// </summary>
- public static string AggregateOverall(IReadOnlyList<(string Status, string Result)> items)
- {
- if (items == null || items.Count == 0) return S6Judgement.Pending;
- if (items.Any(i => i.Result == S6Judgement.Invalid)) return S6Judgement.Invalid;
- if (items.Any(i => i.Result == S6Judgement.Fail)) return S6Judgement.Fail;
- if (items.All(i => i.Status == S6ItemStatus.Completed && i.Result == S6Judgement.Pass)) return S6Judgement.Pass;
- return S6Judgement.Pending;
- }
- /// <summary>是否全部项目均已完成(可完成检验的前置)。</summary>
- public static bool AllItemsCompleted(IReadOnlyList<(string Status, string Result)> items)
- => items != null && items.Count > 0 && items.All(i => i.Status == S6ItemStatus.Completed);
- }
|