use super::Claim;
use super::text::normalise;
pub(super) const DERIVATIVE_MARKERS: &[&str] = &[
"reply",
"erratum",
"errata",
"corrigendum",
"correction",
"comment on",
"response to",
"in response",
"faculty opinions recommendation",
"retraction of",
"expression of concern",
];
const LEADING_MARKERS: &[&str] = &["comment on", "response to", "in response", "correction"];
pub fn is_derivative(title: &str) -> bool {
derivative_kind(title).is_some()
}
pub fn derivative_kind(title: &str) -> Option<&'static str> {
let norm = normalise(title);
let words = format!(" {norm} ");
let leading = |m: &str| match m {
"correction" => {
norm == "correction"
|| norm.starts_with("correction to ")
|| title
.trim_start()
.get(..11)
.is_some_and(|h| h.eq_ignore_ascii_case("correction:"))
}
_ => words.starts_with(&format!(" {m} ")),
};
let marker = DERIVATIVE_MARKERS
.iter()
.find(|m| match LEADING_MARKERS.contains(m) {
true => leading(m),
false => words.contains(&format!(" {m} ")),
})?;
Some(match *marker {
"reply" | "response to" | "in response" => "reply",
"erratum" | "errata" | "corrigendum" | "correction" => "correction",
"comment on" => "comment",
"retraction of" => "retraction",
"expression of concern" => "expression of concern",
_ => "recommendation",
})
}
pub fn claim_mentions_derivative(claim: &Claim) -> bool {
[claim.text.as_deref(), claim.title.as_deref()]
.into_iter()
.flatten()
.any(|text| {
let words = format!(" {} ", normalise(text));
DERIVATIVE_MARKERS
.iter()
.any(|m| words.contains(&format!(" {m} ")))
})
}