use parlov_core::{DifferentialSet, Technique};
use super::control::{control_integrity, ControlDecision};
use super::precondition::{precondition_confidence, PreconditionBlock};
use super::surface::{surface_relevance, SurfaceDecision};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct EvidenceModifiers {
pub surface_relevance: f64,
pub precondition_confidence: f64,
pub control_integrity: f64,
}
impl Default for EvidenceModifiers {
fn default() -> Self {
Self {
surface_relevance: 1.0,
precondition_confidence: 1.0,
control_integrity: 1.0,
}
}
}
impl EvidenceModifiers {
#[must_use]
pub fn total(&self) -> f64 {
self.surface_relevance * self.precondition_confidence * self.control_integrity
}
#[must_use]
pub fn is_blocked(&self) -> bool {
self.surface_relevance == 0.0
|| self.precondition_confidence == 0.0
|| self.control_integrity == 0.0
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ModifierResult {
pub modifiers: EvidenceModifiers,
pub block_reason: Option<PreconditionBlock>,
}
impl ModifierResult {
#[must_use]
pub fn is_blocked(&self) -> bool {
self.modifiers.is_blocked()
}
}
#[must_use]
pub fn compute_modifiers(technique: &Technique, differential: &DifferentialSet) -> ModifierResult {
let pc = precondition_confidence(technique, differential);
let ci = control_integrity(differential);
let sr = surface_relevance(technique, differential);
let control_block = if matches!(ci, ControlDecision::Blocked) {
Some(PreconditionBlock::MutationDestroyedControl)
} else {
None
};
let surface_block = if matches!(sr, SurfaceDecision::Blocked) {
Some(PreconditionBlock::SurfaceMismatch)
} else {
None
};
let block_reason = pc.block_reason().or(control_block).or(surface_block);
ModifierResult {
modifiers: EvidenceModifiers {
surface_relevance: sr.confidence(),
precondition_confidence: pc.confidence(),
control_integrity: ci.confidence(),
},
block_reason,
}
}
#[cfg(test)]
#[path = "modifiers_tests.rs"]
mod tests;