tcjs/docs/superpowers/specs/2026-06-11-judgment-logic-d...

246 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 判定逻辑补全设计(二期)
> 关联文档:一期设计 `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.42.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<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 比较)。装饰材料有多级限值,用一张分级表表达:
```rust
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 指数结果扩展
```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=1uA=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<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`
- **主体/空心材料**单级IRaIr 两项 `check`
- 任一 `Straddle` `NeedMoreMeasurements`
- 两项均 `Pass` `Qualified`
- 否则存在 `Fail`)→ `Unqualified`
- **装饰材料**ABC 级联自严到宽逐级判断
- 某级两项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 断言 IRa0.38Ir0.73u(IRa)≈0.012U(IRa)≈0.024P2.50.36P97.50.40Ur(IRa,k=2)≈6.3%。
- **有效性**total37 `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=0MCM 仅传播 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. 端到端手测三类材料的合格/不合格/分级/建议增加次数路径