ccboard_types/models/
invocations.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9pub struct InvocationStats {
10 pub agents: HashMap<String, usize>,
13
14 pub commands: HashMap<String, usize>,
17
18 pub skills: HashMap<String, usize>,
21
22 pub last_computed: DateTime<Utc>,
24
25 pub sessions_analyzed: usize,
27}
28
29impl InvocationStats {
30 pub fn new() -> Self {
32 Self {
33 agents: HashMap::new(),
34 commands: HashMap::new(),
35 skills: HashMap::new(),
36 last_computed: Utc::now(),
37 sessions_analyzed: 0,
38 }
39 }
40
41 pub fn total_invocations(&self) -> usize {
43 self.agents.values().sum::<usize>()
44 + self.commands.values().sum::<usize>()
45 + self.skills.values().sum::<usize>()
46 }
47
48 pub fn merge(&mut self, other: &InvocationStats) {
50 for (name, count) in &other.agents {
51 *self.agents.entry(name.clone()).or_insert(0) += count;
52 }
53 for (name, count) in &other.commands {
54 *self.commands.entry(name.clone()).or_insert(0) += count;
55 }
56 for (name, count) in &other.skills {
57 *self.skills.entry(name.clone()).or_insert(0) += count;
58 }
59 self.sessions_analyzed += other.sessions_analyzed;
60 if other.last_computed > self.last_computed {
62 self.last_computed = other.last_computed;
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_total_invocations() {
73 let mut stats = InvocationStats::new();
74 stats.agents.insert("technical-writer".to_string(), 5);
75 stats.commands.insert("/commit".to_string(), 12);
76 stats.skills.insert("pdf-generator".to_string(), 3);
77
78 assert_eq!(stats.total_invocations(), 20);
79 }
80
81 #[test]
82 fn test_merge() {
83 let mut stats1 = InvocationStats::new();
84 stats1.agents.insert("debugger".to_string(), 3);
85 stats1.commands.insert("/commit".to_string(), 5);
86 stats1.sessions_analyzed = 10;
87
88 let mut stats2 = InvocationStats::new();
89 stats2.agents.insert("debugger".to_string(), 2);
90 stats2.agents.insert("code-reviewer".to_string(), 1);
91 stats2.commands.insert("/commit".to_string(), 7);
92 stats2.sessions_analyzed = 5;
93
94 stats1.merge(&stats2);
95
96 assert_eq!(stats1.agents.get("debugger"), Some(&5));
97 assert_eq!(stats1.agents.get("code-reviewer"), Some(&1));
98 assert_eq!(stats1.commands.get("/commit"), Some(&12));
99 assert_eq!(stats1.sessions_analyzed, 15);
100 }
101}