ringkernel_procint/models/
activity.rs1use rkyv::{Archive, Deserialize, Serialize};
4use std::collections::HashMap;
5
6pub type ActivityId = u32;
8
9#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
11pub struct Activity {
12 pub id: ActivityId,
14 pub name: String,
16 pub category: ActivityCategory,
18 pub expected_duration_ms: u32,
20 pub cost: f32,
22 pub required_resources: Vec<String>,
24}
25
26impl Activity {
27 pub fn new(id: ActivityId, name: impl Into<String>) -> Self {
29 Self {
30 id,
31 name: name.into(),
32 category: ActivityCategory::Task,
33 expected_duration_ms: 0,
34 cost: 0.0,
35 required_resources: Vec::new(),
36 }
37 }
38
39 pub fn with_duration(mut self, duration_ms: u32) -> Self {
41 self.expected_duration_ms = duration_ms;
42 self
43 }
44
45 pub fn with_category(mut self, category: ActivityCategory) -> Self {
47 self.category = category;
48 self
49 }
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Archive, Serialize, Deserialize)]
54#[repr(u8)]
55pub enum ActivityCategory {
56 Start = 0,
58 End = 1,
60 #[default]
62 Task = 2,
63 Gateway = 3,
65 SubProcess = 4,
67 System = 5,
69 Manual = 6,
71}
72
73#[derive(Debug, Clone, Default)]
75pub struct ActivityRegistry {
76 activities: HashMap<ActivityId, Activity>,
78 name_to_id: HashMap<String, ActivityId>,
80 next_id: ActivityId,
82}
83
84impl ActivityRegistry {
85 pub fn new() -> Self {
87 Self::default()
88 }
89
90 pub fn register(&mut self, activity: Activity) -> ActivityId {
92 let id = activity.id;
93 self.name_to_id.insert(activity.name.clone(), id);
94 self.activities.insert(id, activity);
95 self.next_id = self.next_id.max(id + 1);
96 id
97 }
98
99 pub fn get_or_create(&mut self, name: &str) -> ActivityId {
101 if let Some(&id) = self.name_to_id.get(name) {
102 id
103 } else {
104 let id = self.next_id;
105 self.next_id += 1;
106 let activity = Activity::new(id, name);
107 self.register(activity)
108 }
109 }
110
111 pub fn get(&self, id: ActivityId) -> Option<&Activity> {
113 self.activities.get(&id)
114 }
115
116 pub fn get_by_name(&self, name: &str) -> Option<&Activity> {
118 self.name_to_id
119 .get(name)
120 .and_then(|id| self.activities.get(id))
121 }
122
123 pub fn get_name(&self, id: ActivityId) -> Option<&str> {
125 self.activities.get(&id).map(|a| a.name.as_str())
126 }
127
128 pub fn all(&self) -> impl Iterator<Item = &Activity> {
130 self.activities.values()
131 }
132
133 pub fn len(&self) -> usize {
135 self.activities.len()
136 }
137
138 pub fn is_empty(&self) -> bool {
140 self.activities.is_empty()
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn test_activity_registry() {
150 let mut registry = ActivityRegistry::new();
151
152 let id1 = registry.get_or_create("Register");
153 let id2 = registry.get_or_create("Process");
154 let id3 = registry.get_or_create("Register"); assert_eq!(id1, id3);
157 assert_ne!(id1, id2);
158 assert_eq!(registry.len(), 2);
159 }
160}