fix: normalize --chapters filter input to padded chapter numbers
The --chapters filter compared the raw CLI token by exact string
equality against the zero-padded chapter tags ("01".."22") that
the corpus carries (roman_to_padded, src/claml.rs). The CLI only
split and trimmed the input, so the intuitive forms — `--chapters 4`
or `--chapters E,I` — never matched any candidate and the suggestion
list came back empty, indistinguishable from "no clinical match".
Add a pure `normalize_chapters` helper that zero-pads bare 1-2 digit
chapter numbers to two digits and partitions the token list into
known chapters (1..=22) and unrecognised tokens. The Suggest arm now
feeds the padded set into the filter and emits a stderr warning for
each unrecognised token, so misuse is visible instead of silent.
`--chapters 4` and `--chapters 04` now behave identically. ICD
code-letter mapping (E -> chapter) is deliberately left out of scope:
under this contract a letter is simply an unrecognised token and
triggers the warning.
closes #1
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+9
-2
@@ -1,4 +1,4 @@
|
||||
use alpha_id::model::{Config, Filter, Mode};
|
||||
use alpha_id::model::{normalize_chapters, Config, Filter, Mode};
|
||||
use alpha_id::pipeline::Pipeline;
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::io::Read;
|
||||
@@ -126,9 +126,16 @@ fn main() {
|
||||
Cmd::Suggest { input, mode, top, billable_only, valid_only, exclude_exotic, chapters, json } => {
|
||||
let p = Pipeline::load(&cfg).expect("load");
|
||||
let m: Mode = mode.parse().expect("mode");
|
||||
let chapters = chapters.map(|c| {
|
||||
let (padded, unknown) = normalize_chapters(&c);
|
||||
for tok in &unknown {
|
||||
eprintln!("warning: --chapters token '{tok}' matches no known chapter (01..22); ignored");
|
||||
}
|
||||
padded
|
||||
});
|
||||
let filter = Filter {
|
||||
billable_only, valid_only, exclude_exotic,
|
||||
chapters: chapters.map(|c| c.split(',').map(|s| s.trim().to_string()).collect()),
|
||||
chapters,
|
||||
};
|
||||
let text = read_input(&input);
|
||||
let res = p.suggest(&text, m, &filter, top);
|
||||
|
||||
@@ -42,6 +42,29 @@ pub struct Filter {
|
||||
pub exclude_exotic: bool,
|
||||
}
|
||||
|
||||
/// Normalize a raw `--chapters` token list to the zero-padded chapter-tag form
|
||||
/// ("01".."22") that `Filter::accepts` compares against. Splits on ',', trims
|
||||
/// each token, and classifies: a token that parses as one of the 22 known
|
||||
/// ICD-10-GM chapters (1..=22) goes — zero-padded to two digits — into the first
|
||||
/// returned vec (in input order); every other non-empty token goes verbatim
|
||||
/// (trimmed) into the second (unrecognised) vec. Empty-after-trim tokens are
|
||||
/// skipped. Both "4" and "04" yield "04".
|
||||
pub fn normalize_chapters(raw: &str) -> (Vec<String>, Vec<String>) {
|
||||
let mut known = Vec::new();
|
||||
let mut unknown = Vec::new();
|
||||
for tok in raw.split(',') {
|
||||
let tok = tok.trim();
|
||||
if tok.is_empty() {
|
||||
continue;
|
||||
}
|
||||
match tok.parse::<u32>() {
|
||||
Ok(n) if (1..=22).contains(&n) => known.push(format!("{n:02}")),
|
||||
_ => unknown.push(tok.to_string()),
|
||||
}
|
||||
}
|
||||
(known, unknown)
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
pub fn accepts(&self, t: &Tags) -> bool {
|
||||
if self.billable_only && !t.billable { return false; }
|
||||
|
||||
Reference in New Issue
Block a user