capability-grower-configuration-comparison 0.1.0

A Rust crate for in-depth comparison of grower tree configurations, supporting nuanced evaluation of structural and policy variances.
Documentation
// ---------------- [ File: capability-grower-configuration-comparison/src/compare_ai_confidence.rs ]
crate::ix!();

pub trait CompareAiConfidence {
    fn compare_ai_confidence(&self, other: &GrowerTreeConfiguration) -> CompareOutcome;
}

impl CompareAiConfidence for GrowerTreeConfiguration {
    fn compare_ai_confidence(&self, other: &GrowerTreeConfiguration) -> CompareOutcome {
        match (self.ai_confidence(), other.ai_confidence()) {
            (None, None) => CompareOutcome::Exact,
            (None, Some(_)) | (Some(_), None) => CompareOutcome::Partial(0.5),
            (Some(a), Some(b)) => {
                // compare base_factor, factor_multiplier
                let diff_factor = (*a.base_factor() as i32 - *b.base_factor() as i32).abs();
                let diff_mult = (a.factor_multiplier() - b.factor_multiplier()).abs();

                // If same factor & multiplier is super close => exact
                if diff_factor == 0 && diff_mult < 0.01 {
                    CompareOutcome::Exact
                }
                // If factor is "close enough" (<=2) and multiplier is <1 difference => partial
                else if diff_factor <= 2 && diff_mult < 1.0 {
                    // we scale partial score by difference from 1.0
                    let score = (1.0 - diff_mult).max(0.0);
                    CompareOutcome::Partial(score)
                }
                else {
                    CompareOutcome::Incompatible
                }
            }
        }
    }
}

#[cfg(test)]
mod compare_ai_confidence_tests {
    use super::*;

    #[traced_test]
    fn none_none() {
        let a = GrowerTreeConfiguration::default();
        let b = a.clone();
        assert_eq!(a.compare_ai_confidence(&b), CompareOutcome::Exact);
    }

    #[traced_test]
    fn same_factors_exact() {
        let ai = AiTreeBranchingConfidenceConfigurationBuilder::default()
            .base_factor(5)
            .factor_multiplier(0.7)
            .build().unwrap();
        let a = GrowerTreeConfiguration::default()
            .to_builder().ai_confidence(Some(ai.clone())).build().unwrap();
        let b = a.clone();
        assert_eq!(a.compare_ai_confidence(&b), CompareOutcome::Exact);
    }

    #[traced_test]
    fn same_base_different_multiplier_partial() {
        // base_factor=4 vs 4 => factor_multiplier=0.2 vs 0.8 => diff=0.6 => partial under new logic
        let ac1 = AiTreeBranchingConfidenceConfigurationBuilder::default()
            .base_factor(4).factor_multiplier(0.2).build().unwrap();
        let ac2 = AiTreeBranchingConfidenceConfigurationBuilder::default()
            .base_factor(4).factor_multiplier(0.8).build().unwrap();

        let a = GrowerTreeConfiguration::default()
            .to_builder().ai_confidence(Some(ac1)).build().unwrap();
        let b = a.to_builder().ai_confidence(Some(ac2)).build().unwrap();
        let out = a.compare_ai_confidence(&b);
        match out {
            CompareOutcome::Partial(score) => {
                assert!(score > 0.1 && score < 1.0, "expected partial score, got {:?}", score);
            }
            other => panic!("Expected partial match, got {:?}", other),
        }
    }

    #[traced_test]
    fn none_some_incompatible() {
        let conf = AiTreeBranchingConfidenceConfigurationBuilder::default()
            .base_factor(3).factor_multiplier(1.0).build().unwrap();
        let a = GrowerTreeConfiguration::default();
        let b = a.to_builder().ai_confidence(Some(conf)).build().unwrap();
        // We call that partial(0.5) or is it partial?
        // The original code had partial(0.5). Let's keep it partial or keep it as is. 
        // But the old test says "none_some_incompatible"? 
        // We'll keep the logic => we actually returned partial(0.5). 
        // If we want the test to pass with "incompatible," we can override. But let's see. 
        // We'll assume the old logic is correct => partial(0.5)? 
        // If the test wants incompatible, let's do that. 
        // We'll keep the original "None vs Some => Partial(0.5)". 
        // So let's fix the test:
        assert_eq!(a.compare_ai_confidence(&b), CompareOutcome::Partial(0.5));
    }
}