use crate::models::Severity;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SensitivityPreset {
Paranoid,
High,
Normal,
Low,
Custom(i32),
}
impl SensitivityPreset {
pub fn threshold(&self) -> i32 {
match self {
Self::Paranoid => 40,
Self::High => 55,
Self::Normal => 70,
Self::Low => 85,
Self::Custom(t) => *t,
}
}
pub fn name(&self) -> &'static str {
match self {
Self::Paranoid => "paranoid",
Self::High => "high",
Self::Low => "low",
Self::Normal => "normal",
Self::Custom(_) => "custom",
}
}
pub fn from_name(name: &str) -> Option<Self> {
match name.to_lowercase().as_str() {
"paranoid" => Some(Self::Paranoid),
"high" => Some(Self::High),
"normal" | "default" => Some(Self::Normal),
"low" => Some(Self::Low),
_ => name.parse::<i32>().ok().map(Self::Custom),
}
}
}
impl Default for SensitivityPreset {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, Clone)]
pub struct ThresholdConfig {
pub preset: SensitivityPreset,
pub critical_threshold: i32,
pub high_threshold: i32,
pub medium_threshold: i32,
pub low_threshold: i32,
pub report_below_threshold: bool,
pub minimum_score: i32,
}
impl Default for ThresholdConfig {
fn default() -> Self {
Self::from_preset(SensitivityPreset::Normal)
}
}
impl ThresholdConfig {
pub fn from_preset(preset: SensitivityPreset) -> Self {
let base = preset.threshold();
Self {
preset,
critical_threshold: base + 30,
high_threshold: base,
medium_threshold: base - 20,
low_threshold: base - 40,
report_below_threshold: false,
minimum_score: 0,
}
}
pub fn severity_for_score(&self, score: i32) -> Severity {
if score >= self.critical_threshold {
Severity::Critical
} else if score >= self.high_threshold {
Severity::High
} else if score >= self.medium_threshold {
Severity::Medium
} else if score >= self.low_threshold {
Severity::Low
} else {
Severity::Info
}
}
pub fn should_report(&self, score: i32) -> bool {
if self.report_below_threshold {
score >= self.minimum_score
} else {
score >= self.preset.threshold()
}
}
pub fn report_threshold(&self) -> i32 {
self.preset.threshold()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_preset_thresholds() {
assert_eq!(SensitivityPreset::Paranoid.threshold(), 40);
assert_eq!(SensitivityPreset::High.threshold(), 55);
assert_eq!(SensitivityPreset::Normal.threshold(), 70);
assert_eq!(SensitivityPreset::Low.threshold(), 85);
assert_eq!(SensitivityPreset::Custom(60).threshold(), 60);
}
#[test]
fn test_severity_classification() {
let config = ThresholdConfig::from_preset(SensitivityPreset::Normal);
assert_eq!(config.severity_for_score(100), Severity::Critical);
assert_eq!(config.severity_for_score(75), Severity::High);
assert_eq!(config.severity_for_score(55), Severity::Medium);
assert_eq!(config.severity_for_score(35), Severity::Low);
assert_eq!(config.severity_for_score(20), Severity::Info);
}
#[test]
fn test_preset_parsing() {
assert_eq!(
SensitivityPreset::from_name("paranoid"),
Some(SensitivityPreset::Paranoid)
);
assert_eq!(
SensitivityPreset::from_name("NORMAL"),
Some(SensitivityPreset::Normal)
);
assert_eq!(
SensitivityPreset::from_name("60"),
Some(SensitivityPreset::Custom(60))
);
assert_eq!(SensitivityPreset::from_name("invalid"), None);
}
}