# 判定逻辑补全设计(二期) > 关联文档:一期设计 `2026-05-15-rust-tauri-mvp-design.md`;需求来源 `docs/建材放射性检测结果分析软件开发计算逻辑(1).pdf`。 ## 1. 目标 一期已完成算法骨架(IRa/Ir、A/B 类不确定度、GUM 合成、MCM 仿真)。本期补齐 PDF 第 3、6 节缺失的**判定层与输出层**,使软件能给出最终交付给用户的"有效性 + 合格/不合格 + 材料分级"结论,而不只是中间量。 补齐范围: - 1.3 样品信息:材料类型选择与对应限值集。 - 2.2.4–2.2.6:扩展不确定度 U、k=1/k=2 相对扩展不确定度、GUM 解析真值区间 P2.5/P97.5。 - 3.1 有效性判定(37 Bq/kg 低活度豁免 + Ur(IRa) 阈值)。 - 3.2 临界值判定(真值区间是否跨越极限值 → 合格/不合格/建议增加次数)。 - 3.2.3 装饰装修材料 A/B/C 三级分类。 - 单次测量(n=1)主流程支持。 - 6.1 输出元信息(样品编号、计算日期)。 - 修正合成不确定度中 A 类项缺少校准因子 `a` 的问题。 非目标(仍延后):SQLite 历史、Excel/PDF 报告导出。本期只在内存结构和界面上给出完整结论,导出留三期。 ## 2. 与现状的差距映射 | PDF 节 | 现状 | 本期动作 | |---|---|---| | 1.3 材料类型 | 无,仅手填 limit | 新增 `MaterialType`,按类型派生限值 | | 2.2.4 扩展不确定度 | 无 | `IndexResult` 增 `expanded_uncertainty` | | 2.2.5 k=1/k=2 相对 | 仅一套(k=1) | 增 `relative_expanded_uncertainty_percent` | | 2.2.6 GUM 真值区间 | 仅 MCM 百分位 | `IndexResult` 增 `p2_5/p97_5 = value ± U` | | 3.1 有效性 | 仅 Ur≤20% 双指数 | 实现 37 Bq/kg 豁免,仅看 Ur(IRa) | | 3.2 临界值判定 | 无 | 新增 `Verdict` 判定函数 | | 3.2.3 A/B/C | 无 | 装饰材料级联分类 | | 单次测量 | `count<2` 报错 | n=1 时 uA=0 放行 | | 6.1 元信息 | 无 | 输入/输出增 `sample_id`、`calculation_date` | | 合成不确定度 A 类项 | 漏 `a` 因子 | 修正为 `a·uA` | ## 3. 领域模型变更(`domain.rs`) ### 3.1 输入 ```rust pub struct SampleInput { pub ra: NuclideMeasurements, pub th: NuclideMeasurements, pub k: NuclideMeasurements, #[serde(default)] pub material_type: MaterialType, // 新增,默认 BuildingMainBody #[serde(default)] pub sample_id: Option, // 新增 6.1 #[serde(default)] pub calculation_date: Option, // 新增 6.1,前端传 ISO 字符串 } #[derive(Default)] pub enum MaterialType { #[default] BuildingMainBody, // 建筑主体材料 IRa≤1.0, Ir≤1.0 HollowBuildingMainBody, // 空心率>25%主体材料 IRa≤1.0, Ir≤1.3 DecorativeMaterial, // 装饰装修材料 A/B/C 分级 } ``` `AcceptanceLimits` 不再由前端手填,改为由 `MaterialType` 派生(保留结构体用于 MCM 比较)。装饰材料有多级限值,用一张分级表表达: ```rust pub struct LimitTier { pub label: &'static str, pub ira_limit: Option, pub ir_limit: Option } impl MaterialType { /// 返回从严到宽的限值阶梯。主体材料/空心材料各 1 级;装饰材料 A/B/C 三级。 pub fn tiers(&self) -> &'static [LimitTier] { /* 见下表 */ } } ``` 限值表(来自 PDF 3.2): | 材料类型 | 级别 | IRa 限 | Ir 限 | |---|---|---|---| | 主体材料 | 合格 | 1.0 | 1.0 | | 空心率>25% | 合格 | 1.0 | 1.3 | | 装饰装修 | A | 1.0 | 1.3 | | 装饰装修 | B | 1.3 | 1.9 | | 装饰装修 | C | — | 2.8 | > C 类只约束 Ir(`ira_limit = None`)。 ### 3.2 指数结果扩展 ```rust pub struct IndexResult { pub value: f64, pub standard_uncertainty: f64, // u, 已有 pub expanded_uncertainty: f64, // U = u·k (k=2),新增 pub relative_uncertainty_percent: f64, // k=1,已有 pub relative_expanded_uncertainty_percent: f64, // k=2,新增 pub p2_5: f64, // value - U,新增(GUM 解析区间) pub p97_5: f64, // value + U,新增 } ``` 指数包含因子固定 `k = 2`(PDF 2.2.4/2.2.6)。 ### 3.3 判定结果 ```rust pub struct CalculationResult { /* 既有字段 ... */ pub analysis: AnalysisResult, // 新增 } pub struct AnalysisResult { pub total_calibrated_activity: f64, // A1·a+A2·b+A3·c pub validity: Validity, pub verdict: Verdict, } pub enum Validity { LowActivityExempt, // ≤37 Bq/kg,直接有效 UncertaintyAcceptable, // >37 且 Ur(IRa)≤20% Invalid, // >37 且 Ur(IRa)>20% } pub enum Verdict { Qualified, // 主体/空心:合格 Unqualified, // 不合格 DecorativeClass(DecorClass), // 装饰:A/B/C NeedMoreMeasurements, // 真值区间跨越极限值,建议增加到 6 次 InvalidResult, // 有效性不成立 } pub enum DecorClass { A, B, C, Unqualified } ``` `Conclusion` 枚举保留(向后兼容),但 UI 主结论改用 `Verdict`。 ## 4. 计算逻辑变更(`calculator.rs`) ### 4.1 单次测量支持 `validate_input`:`count` 下限由 2 改为 1,且三核素次数一致。`type_a_uncertainty`:`n == 1` 时返回 `0.0`(PDF 2.2.1 uA=0),`n>=6` 走标准差法,`2<=n<6` 走极差法,`n` 其它非法值仍报错。 ### 4.2 合成不确定度修正 校准比活度 `C = mean·a`,对测量值 A 的灵敏系数是 `a`: ```rust // 修正前: combined = sqrt(uA² + (mean·uB)²) // 修正后: combined = sqrt((a·uA)² + (mean·uB)²) let combined = ((factor*type_a).powi(2) + (mean*type_b_uncertainty).powi(2)).sqrt(); ``` n=1(uA=0)时与现状一致,可与 PDF 单次算例对齐校验。 ### 4.3 GUM 真值区间 每个 `IndexResult` 计算 `U = u·2`,`p2_5 = value - U`,`p97_5 = value + U`,相对量两套(u/value 与 U/value)。 ### 4.4 有效性判定(3.1) ```rust let total = ra.mean_calibrated + th.mean_calibrated + k.mean_calibrated; // A1·a+A2·b+A3·c let validity = if total <= 37.0 { Validity::LowActivityExempt } else if ira.relative_expanded_uncertainty_percent <= 20.0 { Validity::UncertaintyAcceptable } else { Validity::Invalid }; ``` > **待确认 1**:3.1 的 `Ur(IRa)≤20%` 用 k=2 的相对扩展不确定度(与 2.2.5 命名一致)还是 k=1。本设计先取 k=2,见第 7 节。 ### 4.5 临界值判定(3.2) 核心是"真值区间 [P2.5,P97.5] 相对极限值 L 的位置"的三态函数: ```rust enum TierCheck { Pass, Fail, Straddle } // 全在限下 / 全在限上 / 跨越 fn check(idx: &IndexResult, limit: Option) -> TierCheck { let Some(l) = limit else { return TierCheck::Pass }; // 无约束(如 C 类的 IRa) if idx.p97_5 < l { TierCheck::Pass } // 区间不含 L 且值 < L else if idx.p2_5 > l { TierCheck::Fail } // 区间不含 L 且值 > L else { TierCheck::Straddle } // 区间含 L → 建议增加次数 } ``` 组合规则: - 若 `validity == Invalid` → `Verdict::InvalidResult`。 - **主体/空心材料**(单级):IRa、Ir 两项 `check`。 - 任一 `Straddle` → `NeedMoreMeasurements`。 - 两项均 `Pass` → `Qualified`。 - 否则(存在 `Fail`)→ `Unqualified`。 - **装饰材料**(A→B→C 级联):自严到宽逐级判断。 - 某级两项(C 级仅 Ir)均 `Pass` → 归该级(`DecorClass::A/B/C`)。 - 某级存在 `Straddle` 且尚未在更严级别通过 → `NeedMoreMeasurements`。 - 全部级别都不通过且 C 级 `Fail` → `DecorClass::Unqualified`(不可用于建材)。 ### 4.6 与 MCM 的衔接 GUM 路径给出确定性 `Verdict`;当 `Verdict::NeedMoreMeasurements`(区间跨越极限值)时,MCM 的 `overall_fail_probability` 即 PDF 6.3 的"95% 置信概率下不符合概率",作为补充量化结论展示。MCM 仍每次都算(用当前限值),无需新增接口。 > **待确认 2**:6 次测量后若仍跨越极限值,最终合格判据用 MCM 不符合概率阈值(如 <5% 判合格)还是仅展示概率由人判断。现有代码用 `pass_probability>=0.95`,本设计沿用并在第 7 节标注。 ## 5. 界面变更(`App.tsx`) - 顶部输入区:新增**材料类型**下拉(三选一)、**样品编号**输入、**计算日期**选择(默认今日)。移除手填 IRa/Ir 限值,改为根据材料类型只读展示当前限值表。 - 结果区新增"**分析判定**"卡片: - 有效性标签(有效/低活度豁免/无效)+ 总比活度 `A1·a+A2·b+A3·c` 与 37 对比。 - 最终判定标签:合格 / 不合格 / A 类·B 类·C 类 / 建议增加至 6 次 / 结果无效。 - 各指数 GUM 真值区间 `[P2.5, P97.5]`、U、相对扩展不确定度(k=1/k=2)。 - 报告头展示样品编号与计算日期,为三期导出做准备。 类型定义(TS)同步扩展 `MaterialType`、`AnalysisResult`、`Verdict`、`IndexResult` 新字段。 ## 6. 测试(`tests/calculator_tests.rs`) 新增: - **单次测量对齐 PDF 算例**:A1=83.439/a=0.916 等,断言 IRa≈0.38、Ir≈0.73、u(IRa)≈0.012、U(IRa)≈0.024、P2.5≈0.36、P97.5≈0.40、Ur(IRa,k=2)≈6.3%。 - **有效性**:total≤37 → `LowActivityExempt`;total>37 且 Ur 大 → `Invalid`。 - **临界值三态**:构造区间全低/全高/跨越,断言 `Qualified`/`Unqualified`/`NeedMoreMeasurements`。 - **装饰材料级联**:分别命中 A、B、C 与 Unqualified。 - **合成不确定度修正**:多次测量下 A 类项含 `a` 因子(与手算对比)。 - 既有 6 次测量与 MCM 测试保持通过(注意修正后数值会有小幅变化,需更新期望值)。 ## 7. 已确认决策 1. **3.1 的 Ur(IRa) 取 k=2 的相对扩展不确定度**(`relative_expanded_uncertainty_percent`),与 2.2.5 命名一致。✅ 已定 2. **6 次测量后的最终合格判据**:用 MCM 不符合概率,`overall_fail_probability < 5%`(即 `pass_probability ≥ 0.95`)自动判合格/不合格。✅ 已定 3. **材料类型限值只读**:移除前端手填 IRa/Ir 限值,严格按材料类型派生。✅ 已定 仍按本设计默认处理、无需进一步确认: 4. **计算日期来源**:由前端生成 ISO 字符串传入(本地时区可控,Rust 侧不引入 `chrono`)。 5. **单次测量仍跑 MCM**:n=1 时 uA=0,MCM 仅传播 B 类不确定度,仍有意义,默认保留。 ## 8. 实施顺序 1. `domain.rs`:`MaterialType`/限值表 + `IndexResult` 扩展 + `AnalysisResult/Verdict`。 2. `calculator.rs`:单次测量、合成不确定度修正、GUM 区间、有效性、临界值判定。 3. 补充/更新 Rust 测试至全绿(先对齐 PDF 单次算例)。 4. `lib.rs` 导出新类型;`main.rs` 命令签名无需变更(结构体透传)。 5. `App.tsx`:材料类型/样品信息输入 + 分析判定卡片。 6. 端到端手测三类材料的合格/不合格/分级/建议增加次数路径。