11 KiB
判定逻辑补全设计(二期)
关联文档:一期设计
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 输入
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<String>, // 新增 6.1
#[serde(default)]
pub calculation_date: Option<String>, // 新增 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 比较)。装饰材料有多级限值,用一张分级表表达:
pub struct LimitTier { pub label: &'static str, pub ira_limit: Option<f64>, pub ir_limit: Option<f64> }
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 指数结果扩展
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 判定结果
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:
// 修正前: 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)
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 的位置"的三态函数:
enum TierCheck { Pass, Fail, Straddle } // 全在限下 / 全在限上 / 跨越
fn check(idx: &IndexResult, limit: Option<f64>) -> 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(不可用于建材)。
- 某级两项(C 级仅 Ir)均
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. 已确认决策
- 3.1 的 Ur(IRa) 取 k=2 的相对扩展不确定度(
relative_expanded_uncertainty_percent),与 2.2.5 命名一致。✅ 已定 - 6 次测量后的最终合格判据:用 MCM 不符合概率,
overall_fail_probability < 5%(即pass_probability ≥ 0.95)自动判合格/不合格。✅ 已定 - 材料类型限值只读:移除前端手填 IRa/Ir 限值,严格按材料类型派生。✅ 已定
仍按本设计默认处理、无需进一步确认:
- 计算日期来源:由前端生成 ISO 字符串传入(本地时区可控,Rust 侧不引入
chrono)。 - 单次测量仍跑 MCM:n=1 时 uA=0,MCM 仅传播 B 类不确定度,仍有意义,默认保留。
8. 实施顺序
domain.rs:MaterialType/限值表 +IndexResult扩展 +AnalysisResult/Verdict。calculator.rs:单次测量、合成不确定度修正、GUM 区间、有效性、临界值判定。- 补充/更新 Rust 测试至全绿(先对齐 PDF 单次算例)。
lib.rs导出新类型;main.rs命令签名无需变更(结构体透传)。App.tsx:材料类型/样品信息输入 + 分析判定卡片。- 端到端手测三类材料的合格/不合格/分级/建议增加次数路径。