agentic_evolve_core/collective/
usage.rs1use std::collections::HashMap;
4
5#[derive(Debug, Clone, Default)]
7pub struct UsageRecord {
8 pub total_uses: u64,
9 pub successful_uses: u64,
10 pub failed_uses: u64,
11 pub last_used: i64,
12 pub first_used: i64,
13 pub domains: HashMap<String, u64>,
14}
15
16#[derive(Debug, Default)]
18pub struct UsageTracker {
19 records: HashMap<String, UsageRecord>,
20}
21
22impl UsageTracker {
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn record_use(&mut self, pattern_id: &str, domain: &str, success: bool) {
28 let now = chrono::Utc::now().timestamp();
29 let record = self
30 .records
31 .entry(pattern_id.to_string())
32 .or_insert_with(|| UsageRecord {
33 first_used: now,
34 ..Default::default()
35 });
36 record.total_uses += 1;
37 if success {
38 record.successful_uses += 1;
39 } else {
40 record.failed_uses += 1;
41 }
42 record.last_used = now;
43 *record.domains.entry(domain.to_string()).or_insert(0) += 1;
44 }
45
46 pub fn get_usage(&self, pattern_id: &str) -> Option<&UsageRecord> {
47 self.records.get(pattern_id)
48 }
49
50 pub fn success_rate(&self, pattern_id: &str) -> f64 {
51 self.records.get(pattern_id).map_or(0.0, |r| {
52 if r.total_uses == 0 {
53 0.0
54 } else {
55 r.successful_uses as f64 / r.total_uses as f64
56 }
57 })
58 }
59
60 pub fn most_used(&self, limit: usize) -> Vec<(&str, &UsageRecord)> {
61 let mut entries: Vec<_> = self.records.iter().map(|(k, v)| (k.as_str(), v)).collect();
62 entries.sort_by(|a, b| b.1.total_uses.cmp(&a.1.total_uses));
63 entries.truncate(limit);
64 entries
65 }
66
67 pub fn least_used(&self, limit: usize) -> Vec<(&str, &UsageRecord)> {
68 let mut entries: Vec<_> = self.records.iter().map(|(k, v)| (k.as_str(), v)).collect();
69 entries.sort_by(|a, b| a.1.total_uses.cmp(&b.1.total_uses));
70 entries.truncate(limit);
71 entries
72 }
73
74 pub fn total_patterns_tracked(&self) -> usize {
75 self.records.len()
76 }
77
78 pub fn clear(&mut self) {
79 self.records.clear();
80 }
81}