1#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub struct FieldConfig {
12 pub dims: usize,
14
15 pub frame_count: usize,
17
18 pub retention: u8,
21
22 pub tick_rate_hz: u32,
24}
25
26impl FieldConfig {
27 pub fn new(dims: usize, frame_count: usize, retention: u8) -> Self {
30 Self {
31 dims,
32 frame_count,
33 retention,
34 tick_rate_hz: 100,
35 }
36 }
37
38 pub fn window_ms(&self) -> u32 {
40 (self.frame_count as u32 * 1000) / self.tick_rate_hz
41 }
42
43 pub fn validate(&self) -> Result<(), &'static str> {
45 if self.dims == 0 {
46 return Err("dims must be > 0");
47 }
48 if self.frame_count == 0 {
49 return Err("frame_count must be > 0");
50 }
51 Ok(())
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_config_new() {
62 let config = FieldConfig::new(64, 10, 242); assert_eq!(config.dims, 64);
64 assert_eq!(config.frame_count, 10);
65 assert_eq!(config.retention, 242);
66 }
67
68 #[test]
69 fn test_window_ms() {
70 let config = FieldConfig::new(64, 50, 255);
71 assert_eq!(config.window_ms(), 500);
73 }
74
75 #[test]
76 fn test_validate() {
77 let valid = FieldConfig::new(64, 10, 242);
78 assert!(valid.validate().is_ok());
79
80 let invalid_dims = FieldConfig::new(0, 10, 242);
81 assert!(invalid_dims.validate().is_err());
82
83 let invalid_frames = FieldConfig::new(64, 0, 242);
84 assert!(invalid_frames.validate().is_err());
85 }
86}