Quantum Debugging Log Analyzer: Parse and Classify Developer Curse Words in Build Logs

Build a tool that reads CI/CD pipeline logs and uses a hilariously over-engineered state machine to detect, classify, and rate the severity of developer expletives based on context, frequency, and adjacent keywords. The output should generate a 'developer frustration report' with visualizations and recovery suggestions.

use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Result as IoResult};
use std::fmt::Display;

// Define the frustration severity spectrum with quantum-inspired naming
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum FrustrationLevel {
    Serene = 0,
    Mildly_Annoyed = 1,
    Visibly_Agitated = 2,
    Existentially_Questioning = 3,
    Keyboard_In_Peril = 4,
}

impl Display for FrustrationLevel {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

struct CursewordClassifier {
    curse_words: HashMap<String, FrustrationLevel>,
    context_multipliers: HashMap<String, f32>,
    buffer: Vec<String>,
}

impl CursewordClassifier {
    fn new() -> Self {
        let mut curse_words = HashMap::new();
        curse_words.insert("bloody".to_string(), FrustrationLevel::Mildly_Annoyed);
        curse_words.insert("damn".to_string(), FrustrationLevel::Visibly_Agitated);
        curse_words.insert("hell".to_string(), FrustrationLevel::Existentially_Questioning);
        
        let mut context_multipliers = HashMap::new();
        context_multipliers.insert("segmentation".to_string(), 2.5);
        context_multipliers.insert("undefined".to_string(), 1.8);
        context_multipliers.insert("null".to_string(), 1.2);
        
        CursewordClassifier {
            curse_words,
            context_multipliers,
            buffer: Vec::new(),
        }
    }
    
    // Analyze the emotional state encoded within the log line
    fn analyze_line(&self, line: &str) -> Option<(String, FrustrationLevel, f32)> {
        let lower_line = line.to_lowercase();
        
        for (curse, base_level) in &self.curse_words {
            if lower_line.contains(curse) {
                let mut multiplier = 1.0_f32;
                
                for (context_word, context_mult) in &self.context_multipliers {
                    if lower_line.contains(context_word) {
                        multiplier *= context_mult;
                    }
                }
                
                return Some((curse.clone(), *base_level, multiplier));
            }
        }
        None
    }
    
    // Process the log file with defensive error handling for supernatural events
    fn process_log_file(&self, path: &str) -> IoResult<Vec<(String, FrustrationLevel, f32)>> {
        let file = File::open(path)?;
        let reader = BufReader::new(file);
        let mut results = Vec::new();
        
        for line in reader.lines() {
            match line {
                Ok(log_line) => {
                    if let Some(analysis) = self.analyze_line(&log_line) {
                        results.push(analysis);
                    }
                },
                Err(e) => eprintln!("Warning: Could not read line due to: {}", e),
            }
        }
        
        Ok(results)
    }
}

struct FrustrationReport {
    entries: Vec<(String, FrustrationLevel, f32)>,
}

impl FrustrationReport {
    fn from_analyses(entries: Vec<(String, FrustrationLevel, f32)>) -> Self {
        FrustrationReport { entries }
    }
    
    // Calculate the maximum frustration intensity achieved
    fn peak_frustration(&self) -> Option<FrustrationLevel> {
        self.entries.iter().map(|(_, level, _)| level).max().copied()
    }
    
    // Generate ASCII art therapy suggestions
    fn generate_recovery_suggestion(&self) -> String {
        match self.peak_frustration() {
            Some(FrustrationLevel::Keyboard_In_Peril) => {
                "CRITICAL: Go touch grass immediately. Consider a career change.".to_string()
            },
            Some(FrustrationLevel::Existentially_Questioning) => {
                "Take a 15-minute walk. Drink water. Reevaluate your life choices.".to_string()
            },
            _ => "You're doing fine. Carry on.".to_string(),
        }
    }
}

fn main() {
    println!("=== Quantum Debugging Log Analyzer v1.0.0 ===");
    let classifier = CursewordClassifier::new();
    
    // Demonstrate with mock data instead of actual file I/O
    let mock_logs = vec![
        "Error: damn segmentation fault occurred in module_x",
        "Build failed: bloody hell, undefined variable on line 42",
        "Success: compilation completed without incidents",
    ];
    
    let mut results = Vec::new();
    for log in mock_logs {
        if let Some(analysis) = classifier.analyze_line(log) {
            results.push(analysis);
        }
    }
    
    let report = FrustrationReport::from_analyses(results);
    println!("Peak Frustration Level: {:?}", report.peak_frustration());
    println!("Recommendation: {}", report.generate_recovery_suggestion());
}

Code Review

1. Lines 5-13. The FrustrationLevel enum with quantum-inspired naming (Existentially_Questioning, Keyboard_In_Peril) is delightful but the Display implementation just derives the debug format anyway. The naming is clever but gives no additional meaning. Why not just use descriptive variants?

2. Lines 24-26. Creating a HashMap in the constructor and hardcoding curse words defeats the entire point of having a data structure. This should be loaded from a config file or passed as a parameter, but instead we're pretending this is extensible while it absolutely is not.

3. Line 35. The comment 'Analyze the emotional state encoded within the log line' is pure poetry but also completely restates what the function name already says. The word 'encoded' makes it sound mysterious when we're just doing substring matching.

4. Lines 47-49. The Option return type here is fine, but the tuple return (String, FrustrationLevel, f32) could absolutely be a proper struct. This screams struct composition but instead we're returning anonymous tuples that lose semantic meaning.

5. Line 56. The comment 'Process the log file with defensive error handling for supernatural events' is the kind of comment that makes me question my career. We're literally just calling File::open() and iterating lines. There are no supernatural events.

6. Lines 85-88. Creating a FrustrationReport struct just to wrap a Vec and add two methods is textbook over-engineering. The from_analyses constructor is unnecessary; just use the struct directly. This is a builder pattern in search of a problem.

7. Lines 95-103. The generate_recovery_suggestion() function with hardcoded therapy advice wrapped in recovery suggestions is genuinely funny but completely disconnected from the rest of the code. It doesn't actually get used anywhere in main(), so it's dead code with a purpose.

8. Lines 110-120. The actual main function just uses mock data instead of taking a file path argument. All that infrastructure in process_log_file() is unused. Either delete it or actually use it, but creating an API you don't call is confusing.