use std::collections::BTreeSet;
use crate::test_support::corpus::{CLASSES, fixture, root};
const SHAPE: &str = "help.json";
const CONTROL: &str = "control";
const MACHINE: &str = "machine";
pub(crate) struct Roster {
pub(crate) ops: BTreeSet<String>,
pub(crate) control: BTreeSet<String>,
}
pub(crate) fn classify(row: &serde_json::Value) -> Result<(String, bool), String> {
let Some(verb) = row["verb"].as_str() else {
return Err(format!("a help row names no verb: {row}"));
};
match row["surface"].as_str() {
Some(CONTROL) => Ok((verb.to_owned(), true)),
Some(MACHINE) => Ok((verb.to_owned(), false)),
stated => Err(format!(
"the help row {verb:?} is classed {stated:?}, which this seat has no \
reading for — refresh the corpus"
)),
}
}
pub(crate) fn roster() -> Roster {
let path = CLASSES
.iter()
.map(|class| root().join(class).join(SHAPE))
.find(|path| path.exists())
.unwrap_or_else(|| panic!("no {SHAPE} in any of {CLASSES:?} — refresh the corpus"));
let help = fixture(&path);
let mut ops = BTreeSet::new();
let mut control = BTreeSet::new();
for frame in &help.frames {
for row in frame["rows"].as_array().expect("the help rows") {
let (verb, owed) = classify(row).unwrap_or_else(|why| panic!("{why}"));
if owed {
control.insert(verb.clone());
}
ops.insert(verb);
}
}
Roster { ops, control }
}