reputation-core 0.1.0

Core calculation engine for the KnowThat Reputation System with advanced scoring algorithms
Documentation
//! Complete guide to Phase 2 features of the reputation engine
//! 
//! This example demonstrates all major features introduced in Phase 2:
//! - Enhanced score structure with detailed breakdowns
//! - Batch processing with progress tracking
//! - Builder pattern for configuration
//! - Utility methods for analysis

use reputation_core::{Calculator, CalculatorPreset, BatchOptions};
use reputation_types::AgentDataBuilder;
use std::sync::{Arc, Mutex};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== KnowThat Reputation Engine - Phase 2 Complete Guide ===\n");
    
    // 1. Builder Pattern Configuration
    println!("1. BUILDER PATTERN CONFIGURATION");
    println!("--------------------------------");
    demonstrate_builder_pattern()?;
    
    // 2. Enhanced Score Structure
    println!("\n2. ENHANCED SCORE STRUCTURE");
    println!("---------------------------");
    demonstrate_enhanced_scores()?;
    
    // 3. Batch Processing
    println!("\n3. BATCH PROCESSING");
    println!("-------------------");
    demonstrate_batch_processing()?;
    
    // 4. Utility Methods
    println!("\n4. UTILITY METHODS");
    println!("------------------");
    demonstrate_utility_methods()?;
    
    // 5. Integration Example
    println!("\n5. COMPLETE INTEGRATION EXAMPLE");
    println!("-------------------------------");
    demonstrate_integration()?;
    
    Ok(())
}

fn demonstrate_builder_pattern() -> Result<(), Box<dyn std::error::Error>> {
    // Default calculator
    let default_calc = Calculator::default();
    println!("Default calculator: k={}", default_calc.confidence_k());
    
    // Custom configuration
    let custom_calc = Calculator::builder()
        .confidence_k(25.0)
        .prior_base(55.0)
        .prior_max(85.0)
        .build()?;
    println!("Custom calculator: k={}, base={}, max={}", 
        custom_calc.confidence_k(),
        custom_calc.prior_base(),
        custom_calc.prior_max()
    );
    
    // Using presets
    let conservative = Calculator::builder()
        .preset(CalculatorPreset::Conservative)
        .build()?;
    println!("Conservative preset: k={}", conservative.confidence_k());
    
    let testing = Calculator::builder()
        .preset(CalculatorPreset::Testing)
        .prior_base(60.0) // Override preset value
        .build()?;
    println!("Testing preset with override: k={}, base={}", 
        testing.confidence_k(),
        testing.prior_base()
    );
    
    Ok(())
}

fn demonstrate_enhanced_scores() -> Result<(), Box<dyn std::error::Error>> {
    let calc = Calculator::default();
    
    // Create agents with different profiles
    let new_agent = AgentDataBuilder::new("did:example:new")
        .with_reviews(2, 4.5)
        .total_interactions(2)
        .build()?;
    
    let established_agent = AgentDataBuilder::new("did:example:established")
        .with_reviews(100, 4.2)
        .total_interactions(150)
        .mcp_level(2)
        .identity_verified(true)
        .security_audit_passed(true)
        .build()?;
    
    // Calculate and display scores
    for (name, agent) in [("New Agent", &new_agent), ("Established Agent", &established_agent)] {
        let score = calc.calculate(agent)?;
        
        println!("\n{}:", name);
        println!("  Score: {:.1}", score.score);
        println!("  Confidence: {:.1}% ({:?})", score.confidence * 100.0, score.level);
        println!("  Is Provisional: {}", score.is_provisional);
        println!("  Data Points: {}", score.data_points);
        
        // Show component breakdown
        println!("  Components:");
        println!("    Prior Score: {:.1}", score.components.prior_score);
        println!("    Empirical Score: {:.1}", score.components.empirical_score);
        
        // Show prior breakdown for established agent
        if agent.mcp_level.is_some() {
            let breakdown = &score.components.prior_breakdown;
            println!("  Prior Breakdown:");
            println!("    Base: {:.1}", breakdown.base_score);
            println!("    MCP Bonus: {:.1}", breakdown.mcp_bonus);
            println!("    Identity Bonus: {:.1}", breakdown.identity_bonus);
            println!("    Security Audit Bonus: {:.1}", breakdown.security_audit_bonus);
            println!("    Total: {:.1}", breakdown.total);
        }
    }
    
    Ok(())
}

fn demonstrate_batch_processing() -> Result<(), Box<dyn std::error::Error>> {
    let calc = Calculator::default();
    
    // Generate test agents
    let agents: Vec<_> = (0..20)
        .map(|i| {
            let mut builder = AgentDataBuilder::new(&format!("did:example:batch{}", i))
                .total_interactions(i * 10);
            
            if i > 0 {
                builder = builder.with_reviews(i * 5, 3.5 + (i as f64 * 0.05));
            }
            
            if i % 3 == 0 {
                builder = builder.mcp_level(1);
            }
            
            builder.build().unwrap()
        })
        .collect();
    
    // Simple batch processing
    println!("Simple batch processing:");
    let start = std::time::Instant::now();
    let results = calc.calculate_batch(&agents);
    let duration = start.elapsed();
    
    let successful = results.iter().filter(|r| r.is_ok()).count();
    println!("  Processed {} agents in {:?}", agents.len(), duration);
    println!("  Successful: {}", successful);
    
    // Batch with progress tracking
    println!("\nBatch with progress tracking:");
    let progress_log = Arc::new(Mutex::new(Vec::new()));
    let progress_clone = Arc::clone(&progress_log);
    
    let options = BatchOptions {
        chunk_size: Some(5),
        fail_fast: false,
        progress_callback: Some(Box::new(move |completed, total| {
            progress_clone.lock().unwrap().push((completed, total));
            print!(".");
            std::io::Write::flush(&mut std::io::stdout()).unwrap();
        })),
    };
    
    let _start = std::time::Instant::now();
    let batch_result = calc.calculate_batch_with_options(&agents, options);
    println!();
    
    println!("  Total duration: {:?}", batch_result.total_duration);
    println!("  Successful: {}", batch_result.successful_count);
    println!("  Failed: {}", batch_result.failed_count);
    println!("  Progress updates: {}", progress_log.lock().unwrap().len());
    
    // Show some results
    println!("\n  Sample results:");
    for (i, calc) in batch_result.calculations.iter().take(3).enumerate() {
        if let Ok(score) = &calc.result {
            println!("    Agent {}: score={:.1}, confidence={:.1}%, time={:?}",
                i, score.score, score.confidence * 100.0, calc.duration);
        }
    }
    
    Ok(())
}

fn demonstrate_utility_methods() -> Result<(), Box<dyn std::error::Error>> {
    let calc = Calculator::default();
    
    let agent = AgentDataBuilder::new("did:example:utility")
        .with_reviews(30, 4.0)
        .total_interactions(40)
        .mcp_level(1)
        .identity_verified(true)
        .build()?;
    
    // 1. Score explanation
    println!("Score Explanation:");
    let explanation = calc.explain_score(&agent)?;
    println!("{}", explanation.explanation);
    
    // 2. Confidence planning
    println!("\nConfidence Planning:");
    let current_conf = calc.confidence_after_interactions(40, 0);
    println!("  Current confidence: {:.1}%", current_conf * 100.0);
    
    for target in [0.7, 0.8, 0.9] {
        let needed = calc.interactions_for_confidence(40, target)?;
        println!("  Need {} more interactions for {:.0}% confidence", 
            needed, target * 100.0);
    }
    
    // 3. Score predictions
    println!("\nScore Predictions:");
    let scenarios = vec![
        (20, 5.0, "20 five-star reviews"),
        (20, 3.0, "20 three-star reviews"),
        (50, 4.0, "50 four-star reviews"),
    ];
    
    for (count, rating, desc) in scenarios {
        let prediction = calc.predict_score_change(&agent, count, rating)?;
        println!("  {}: {:+.1} points (→ {:.1})",
            desc, prediction.score_change, prediction.predicted_score);
    }
    
    // 4. Agent comparison
    println!("\nAgent Comparison:");
    let competitor = AgentDataBuilder::new("did:example:competitor")
        .with_reviews(100, 3.8)
        .total_interactions(150)
        .build()?;
    
    let comparison = calc.compare_agents(&agent, &competitor)?;
    println!("  Agent A: score={:.1}, confidence={:.1}%", 
        comparison.score_a, comparison.confidence_a * 100.0);
    println!("  Agent B: score={:.1}, confidence={:.1}%", 
        comparison.score_b, comparison.confidence_b * 100.0);
    println!("  Higher score: {}", 
        if comparison.higher_score_agent.contains("utility") { "Agent A" } else { "Agent B" });
    println!("  More reliable: {}", 
        if comparison.more_reliable_agent.contains("utility") { "Agent A" } else { "Agent B" });
    
    Ok(())
}

fn demonstrate_integration() -> Result<(), Box<dyn std::error::Error>> {
    println!("Simulating a reputation analysis workflow...\n");
    
    // Step 1: Configure calculator for our use case
    let calc = Calculator::builder()
        .preset(CalculatorPreset::Default)
        .build()?;
    
    // Step 2: Load agents (simulated)
    let agents = vec![
        AgentDataBuilder::new("did:example:alice")
            .with_reviews(50, 4.5)
            .total_interactions(60)
            .mcp_level(2)
            .identity_verified(true)
            .build()?,
        AgentDataBuilder::new("did:example:bob")
            .with_reviews(20, 4.8)
            .total_interactions(25)
            .mcp_level(1)
            .build()?,
        AgentDataBuilder::new("did:example:charlie")
            .with_reviews(200, 3.9)
            .total_interactions(300)
            .security_audit_passed(true)
            .build()?,
    ];
    
    // Step 3: Process in batch
    let batch_result = calc.calculate_batch_with_options(&agents, BatchOptions::default());
    
    // Step 4: Find best agent
    let mut best_score = 0.0;
    let mut best_agent = None;
    
    for (agent, calc_result) in agents.iter().zip(batch_result.calculations.iter()) {
        if let Ok(score) = &calc_result.result {
            if score.score > best_score {
                best_score = score.score;
                best_agent = Some(agent);
            }
        }
    }
    
    if let Some(best) = best_agent {
        println!("Best agent: {} with score {:.1}", best.did, best_score);
        
        // Step 5: Analyze the best agent
        let explanation = calc.explain_score(best)?;
        println!("\nDetailed Analysis:");
        println!("{}", explanation.explanation);
        
        // Step 6: Make recommendations
        println!("\nRecommendations:");
        
        // Check if they need more interactions
        let current_conf = calc.confidence_after_interactions(best.total_interactions, 0);
        if current_conf < 0.9 {
            let needed = calc.interactions_for_confidence(best.total_interactions, 0.9)?;
            println!("- Gain {} more interactions to reach 90% confidence", needed);
        }
        
        // Predict impact of maintaining quality
        let prediction = calc.predict_score_change(best, 50, 4.5)?;
        println!("- Maintaining 4.5★ for 50 reviews would {:+.1} points",
            prediction.score_change);
    }
    
    Ok(())
}