1#[allow(dead_code)]
4#[derive(Clone, PartialEq, Debug)]
5pub enum NotificationSeverity {
6 Info,
7 Warning,
8 Error,
9 Success,
10}
11
12#[allow(dead_code)]
13#[derive(Clone)]
14pub struct Notification {
15 pub id: u64,
16 pub title: String,
17 pub message: String,
18 pub severity: NotificationSeverity,
19 pub timestamp: f64,
20 pub dismissed: bool,
21 pub persistent: bool,
22 pub duration_secs: f32,
23}
24
25#[allow(dead_code)]
26pub struct NotificationSystem {
27 pub notifications: Vec<Notification>,
28 pub next_id: u64,
29 pub current_time: f64,
30 pub max_notifications: usize,
31}
32
33#[allow(dead_code)]
34pub fn new_notification_system(max: usize) -> NotificationSystem {
35 NotificationSystem {
36 notifications: Vec::new(),
37 next_id: 1,
38 current_time: 0.0,
39 max_notifications: max,
40 }
41}
42
43#[allow(dead_code)]
44pub fn push_notification(
45 sys: &mut NotificationSystem,
46 title: &str,
47 msg: &str,
48 severity: NotificationSeverity,
49 duration: f32,
50) -> u64 {
51 let id = sys.next_id;
52 sys.next_id += 1;
53 let persistent = duration <= 0.0;
54 sys.notifications.push(Notification {
55 id,
56 title: title.to_string(),
57 message: msg.to_string(),
58 severity,
59 timestamp: sys.current_time,
60 dismissed: false,
61 persistent,
62 duration_secs: duration,
63 });
64 if sys.notifications.len() > sys.max_notifications {
66 let excess = sys.notifications.len() - sys.max_notifications;
67 let mut removed = 0;
68 sys.notifications.retain(|n| {
69 if removed < excess && n.dismissed {
70 removed += 1;
71 false
72 } else {
73 true
74 }
75 });
76 if sys.notifications.len() > sys.max_notifications {
77 let still_excess = sys.notifications.len() - sys.max_notifications;
78 sys.notifications.drain(0..still_excess);
79 }
80 }
81 id
82}
83
84#[allow(dead_code)]
85pub fn dismiss_notification(sys: &mut NotificationSystem, id: u64) -> bool {
86 if let Some(n) = sys.notifications.iter_mut().find(|n| n.id == id) {
87 if !n.dismissed {
88 n.dismissed = true;
89 return true;
90 }
91 }
92 false
93}
94
95#[allow(dead_code)]
96pub fn advance_notifications(sys: &mut NotificationSystem, dt: f64) {
97 sys.current_time += dt;
98 for n in &mut sys.notifications {
99 if !n.dismissed && !n.persistent {
100 let elapsed = sys.current_time - n.timestamp;
101 if elapsed >= n.duration_secs as f64 {
102 n.dismissed = true;
103 }
104 }
105 }
106 while sys.notifications.len() > sys.max_notifications {
108 let pos = sys.notifications.iter().position(|n| n.dismissed);
109 match pos {
110 Some(i) => {
111 sys.notifications.remove(i);
112 }
113 None => break,
114 }
115 }
116}
117
118#[allow(dead_code)]
119pub fn active_notifications(sys: &NotificationSystem) -> Vec<&Notification> {
120 sys.notifications.iter().filter(|n| !n.dismissed).collect()
121}
122
123#[allow(dead_code)]
124pub fn notification_by_id(sys: &NotificationSystem, id: u64) -> Option<&Notification> {
125 sys.notifications.iter().find(|n| n.id == id)
126}
127
128#[allow(dead_code)]
129pub fn notification_count(sys: &NotificationSystem) -> usize {
130 sys.notifications.len()
131}
132
133#[allow(dead_code)]
134pub fn active_count(sys: &NotificationSystem) -> usize {
135 sys.notifications.iter().filter(|n| !n.dismissed).count()
136}
137
138#[allow(dead_code)]
139pub fn notifications_by_severity(
140 sys: &NotificationSystem,
141 sev: NotificationSeverity,
142) -> Vec<&Notification> {
143 sys.notifications
144 .iter()
145 .filter(|n| n.severity == sev)
146 .collect()
147}
148
149#[allow(dead_code)]
150pub fn clear_all_notifications(sys: &mut NotificationSystem) {
151 sys.notifications.clear();
152}
153
154#[allow(dead_code)]
155pub fn has_errors(sys: &NotificationSystem) -> bool {
156 sys.notifications
157 .iter()
158 .any(|n| !n.dismissed && n.severity == NotificationSeverity::Error)
159}
160
161#[allow(dead_code)]
162pub fn push_info(sys: &mut NotificationSystem, title: &str, msg: &str) -> u64 {
163 push_notification(sys, title, msg, NotificationSeverity::Info, 5.0)
164}
165
166#[allow(dead_code)]
167pub fn push_error(sys: &mut NotificationSystem, title: &str, msg: &str) -> u64 {
168 push_notification(sys, title, msg, NotificationSeverity::Error, 10.0)
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174
175 #[test]
176 fn test_new_notification_system() {
177 let sys = new_notification_system(10);
178 assert_eq!(notification_count(&sys), 0);
179 assert_eq!(sys.max_notifications, 10);
180 assert_eq!(sys.next_id, 1);
181 }
182
183 #[test]
184 fn test_push_notification() {
185 let mut sys = new_notification_system(10);
186 let id = push_notification(&mut sys, "Test", "Message", NotificationSeverity::Info, 5.0);
187 assert_eq!(id, 1);
188 assert_eq!(notification_count(&sys), 1);
189 }
190
191 #[test]
192 fn test_dismiss_notification() {
193 let mut sys = new_notification_system(10);
194 let id = push_notification(&mut sys, "Test", "Msg", NotificationSeverity::Info, 5.0);
195 assert!(dismiss_notification(&mut sys, id));
196 assert!(!dismiss_notification(&mut sys, id));
197 assert_eq!(active_count(&sys), 0);
198 }
199
200 #[test]
201 fn test_dismiss_nonexistent() {
202 let mut sys = new_notification_system(10);
203 assert!(!dismiss_notification(&mut sys, 999));
204 }
205
206 #[test]
207 fn test_advance_auto_dismisses() {
208 let mut sys = new_notification_system(10);
209 push_notification(&mut sys, "T", "M", NotificationSeverity::Info, 3.0);
210 assert_eq!(active_count(&sys), 1);
211 advance_notifications(&mut sys, 4.0);
212 assert_eq!(active_count(&sys), 0);
213 }
214
215 #[test]
216 fn test_advance_persistent_not_dismissed() {
217 let mut sys = new_notification_system(10);
218 push_notification(&mut sys, "T", "M", NotificationSeverity::Warning, 0.0);
219 advance_notifications(&mut sys, 100.0);
220 assert_eq!(active_count(&sys), 1);
221 }
222
223 #[test]
224 fn test_active_notifications() {
225 let mut sys = new_notification_system(10);
226 let id1 = push_notification(&mut sys, "A", "M1", NotificationSeverity::Info, 5.0);
227 push_notification(&mut sys, "B", "M2", NotificationSeverity::Warning, 5.0);
228 dismiss_notification(&mut sys, id1);
229 let active = active_notifications(&sys);
230 assert_eq!(active.len(), 1);
231 assert_eq!(active[0].title, "B");
232 }
233
234 #[test]
235 fn test_notification_by_id() {
236 let mut sys = new_notification_system(10);
237 let id = push_notification(&mut sys, "Title", "Msg", NotificationSeverity::Info, 5.0);
238 let n = notification_by_id(&sys, id);
239 assert!(n.is_some());
240 assert_eq!(n.expect("should succeed").title, "Title");
241 assert!(notification_by_id(&sys, 999).is_none());
242 }
243
244 #[test]
245 fn test_notifications_by_severity() {
246 let mut sys = new_notification_system(10);
247 push_notification(&mut sys, "E1", "M", NotificationSeverity::Error, 5.0);
248 push_notification(&mut sys, "E2", "M", NotificationSeverity::Error, 5.0);
249 push_notification(&mut sys, "I1", "M", NotificationSeverity::Info, 5.0);
250 let errors = notifications_by_severity(&sys, NotificationSeverity::Error);
251 assert_eq!(errors.len(), 2);
252 }
253
254 #[test]
255 fn test_has_errors_true() {
256 let mut sys = new_notification_system(10);
257 push_error(&mut sys, "Error", "Something broke");
258 assert!(has_errors(&sys));
259 }
260
261 #[test]
262 fn test_has_errors_false() {
263 let mut sys = new_notification_system(10);
264 push_info(&mut sys, "Info", "All good");
265 assert!(!has_errors(&sys));
266 }
267
268 #[test]
269 fn test_has_errors_dismissed() {
270 let mut sys = new_notification_system(10);
271 let id = push_error(&mut sys, "Error", "Bad");
272 dismiss_notification(&mut sys, id);
273 assert!(!has_errors(&sys));
274 }
275
276 #[test]
277 fn test_clear_all_notifications() {
278 let mut sys = new_notification_system(10);
279 push_info(&mut sys, "A", "M1");
280 push_info(&mut sys, "B", "M2");
281 clear_all_notifications(&mut sys);
282 assert_eq!(notification_count(&sys), 0);
283 }
284
285 #[test]
286 fn test_push_info() {
287 let mut sys = new_notification_system(10);
288 let id = push_info(&mut sys, "Hello", "World");
289 let n = notification_by_id(&sys, id).expect("should succeed");
290 assert_eq!(n.severity, NotificationSeverity::Info);
291 assert!((n.duration_secs - 5.0).abs() < 1e-6);
292 }
293
294 #[test]
295 fn test_push_error() {
296 let mut sys = new_notification_system(10);
297 let id = push_error(&mut sys, "Oops", "Failed");
298 let n = notification_by_id(&sys, id).expect("should succeed");
299 assert_eq!(n.severity, NotificationSeverity::Error);
300 assert!((n.duration_secs - 10.0).abs() < 1e-6);
301 }
302
303 #[test]
304 fn test_notification_count() {
305 let mut sys = new_notification_system(10);
306 assert_eq!(notification_count(&sys), 0);
307 push_info(&mut sys, "A", "M");
308 push_info(&mut sys, "B", "M");
309 assert_eq!(notification_count(&sys), 2);
310 }
311
312 #[test]
313 fn test_active_count() {
314 let mut sys = new_notification_system(10);
315 let id = push_info(&mut sys, "A", "M");
316 push_info(&mut sys, "B", "M");
317 assert_eq!(active_count(&sys), 2);
318 dismiss_notification(&mut sys, id);
319 assert_eq!(active_count(&sys), 1);
320 }
321}