somatize_study/pruner/
threshold.rs1use super::judging::{latest, not_a_number};
4use super::{Pruner, Reason, Verdict};
5use std::fmt;
6
7#[derive(Debug, Clone, PartialEq)]
13pub struct Threshold {
14 pub lower: Option<f64>,
16 pub upper: Option<f64>,
18}
19
20impl Threshold {
21 pub fn diverged() -> Self {
24 Self {
25 lower: None,
26 upper: None,
27 }
28 }
29
30 pub fn verdict(&self, mine: &[f64], _others: &[Vec<f64>]) -> Verdict {
32 let Some((at, value)) = latest(mine) else {
33 return Verdict::Continue;
34 };
35 if let Some(why) = not_a_number(at, value) {
36 return Verdict::Prune(why);
37 }
38 if let Some(bound) = self.lower.filter(|&bound| value < bound) {
39 return Verdict::Prune(Reason::OutOfBounds { value, bound });
40 }
41 if let Some(bound) = self.upper.filter(|&bound| value > bound) {
42 return Verdict::Prune(Reason::OutOfBounds { value, bound });
43 }
44 Verdict::Continue
45 }
46}
47
48impl fmt::Display for Threshold {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(
51 f,
52 "threshold:lower:{}:upper:{}",
53 said(self.lower),
54 said(self.upper)
55 )
56 }
57}
58
59fn said(bound: Option<f64>) -> String {
62 match bound {
63 None => "none".to_string(),
64 Some(bound) => bound.to_string(),
65 }
66}
67
68impl From<Threshold> for Pruner {
69 fn from(rule: Threshold) -> Self {
70 Self::Threshold(rule)
71 }
72}