Skip to main content

entrenar/citl/pattern_store/
fix_pattern.rs

1//! Fix pattern representation for error adjusts.
2
3use super::ChunkId;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7/// A pattern representing a successful fix for an error
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct FixPattern {
10    /// Unique identifier for this pattern
11    pub id: ChunkId,
12    /// The error code this pattern fixes (e.g., "E0308", "E0382")
13    pub error_code: String,
14    /// Sequence of decisions that led to this fix
15    pub decision_sequence: Vec<String>,
16    /// The actual fix diff (unified diff format)
17    pub fix_diff: String,
18    /// Number of times this pattern was successfully applied
19    pub success_count: u32,
20    /// Number of times this pattern was attempted
21    pub attempt_count: u32,
22    /// Optional metadata
23    pub metadata: HashMap<String, String>,
24}
25
26impl FixPattern {
27    /// Create a new fix pattern
28    #[must_use]
29    pub fn new(error_code: impl Into<String>, fix_diff: impl Into<String>) -> Self {
30        Self {
31            id: ChunkId::new(),
32            error_code: error_code.into(),
33            decision_sequence: Vec::new(),
34            fix_diff: fix_diff.into(),
35            success_count: 0,
36            attempt_count: 0,
37            metadata: HashMap::new(),
38        }
39    }
40
41    /// Add a decision to the sequence
42    #[must_use]
43    pub fn with_decision(mut self, decision: impl Into<String>) -> Self {
44        self.decision_sequence.push(decision.into());
45        self
46    }
47
48    /// Add multiple decisions to the sequence
49    #[must_use]
50    pub fn with_decisions(mut self, decisions: Vec<String>) -> Self {
51        self.decision_sequence.extend(decisions);
52        self
53    }
54
55    /// Record a successful application
56    pub fn record_success(&mut self) {
57        self.success_count += 1;
58        self.attempt_count += 1;
59    }
60
61    /// Record a failed application
62    pub fn record_failure(&mut self) {
63        self.attempt_count += 1;
64    }
65
66    /// Calculate success rate
67    #[must_use]
68    pub fn success_rate(&self) -> f32 {
69        if self.attempt_count == 0 {
70            0.0
71        } else {
72            self.success_count as f32 / self.attempt_count as f32
73        }
74    }
75
76    /// Convert to searchable text for indexing
77    #[must_use]
78    pub fn to_searchable_text(&self) -> String {
79        let decisions = self.decision_sequence.join(" ");
80        format!("{} {} {}", self.error_code, decisions, self.fix_diff)
81    }
82}