oxihuman_export/
anim_notify_export.rs1#![allow(dead_code)]
4
5#[allow(dead_code)]
8#[derive(Debug, Clone)]
9pub struct AnimNotify {
10 pub name: String,
11 pub time: f32,
12 pub payload: String,
13}
14
15#[allow(dead_code)]
16#[derive(Debug, Clone)]
17pub struct AnimNotifyTrack {
18 pub track_name: String,
19 pub notifies: Vec<AnimNotify>,
20}
21
22#[allow(dead_code)]
23pub fn new_notify_track(name: &str) -> AnimNotifyTrack {
24 AnimNotifyTrack {
25 track_name: name.to_string(),
26 notifies: Vec::new(),
27 }
28}
29
30#[allow(dead_code)]
31pub fn add_notify(track: &mut AnimNotifyTrack, name: &str, time: f32, payload: &str) {
32 track.notifies.push(AnimNotify {
33 name: name.to_string(),
34 time,
35 payload: payload.to_string(),
36 });
37}
38
39#[allow(dead_code)]
40pub fn notify_count(track: &AnimNotifyTrack) -> usize {
41 track.notifies.len()
42}
43
44#[allow(dead_code)]
45pub fn find_notify<'a>(track: &'a AnimNotifyTrack, name: &str) -> Option<&'a AnimNotify> {
46 track.notifies.iter().find(|n| n.name == name)
47}
48
49#[allow(dead_code)]
50pub fn notifies_in_range(track: &AnimNotifyTrack, start: f32, end: f32) -> Vec<&AnimNotify> {
51 track
52 .notifies
53 .iter()
54 .filter(|n| n.time >= start && n.time <= end)
55 .collect()
56}
57
58#[allow(dead_code)]
59pub fn track_duration(track: &AnimNotifyTrack) -> f32 {
60 track
61 .notifies
62 .iter()
63 .map(|n| n.time)
64 .fold(0.0_f32, f32::max)
65}
66
67#[allow(dead_code)]
68pub fn sort_notifies(track: &mut AnimNotifyTrack) {
69 track.notifies.sort_by(|a, b| {
70 a.time
71 .partial_cmp(&b.time)
72 .unwrap_or(std::cmp::Ordering::Equal)
73 });
74}
75
76#[allow(dead_code)]
77pub fn notify_track_to_json(track: &AnimNotifyTrack) -> String {
78 format!(
79 "{{\"track\":\"{}\",\"notify_count\":{}}}",
80 track.track_name,
81 track.notifies.len()
82 )
83}
84
85#[allow(dead_code)]
86pub fn clear_notifies(track: &mut AnimNotifyTrack) {
87 track.notifies.clear();
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_new_track_empty() {
96 let t = new_notify_track("events");
97 assert_eq!(notify_count(&t), 0);
98 }
99
100 #[test]
101 fn test_add_notify() {
102 let mut t = new_notify_track("events");
103 add_notify(&mut t, "hit", 0.5, "{}");
104 assert_eq!(notify_count(&t), 1);
105 }
106
107 #[test]
108 fn test_find_notify() {
109 let mut t = new_notify_track("events");
110 add_notify(&mut t, "footstep", 0.3, "left");
111 assert!(find_notify(&t, "footstep").is_some());
112 }
113
114 #[test]
115 fn test_find_missing() {
116 let t = new_notify_track("events");
117 assert!(find_notify(&t, "missing").is_none());
118 }
119
120 #[test]
121 fn test_notifies_in_range() {
122 let mut t = new_notify_track("events");
123 add_notify(&mut t, "a", 0.1, "");
124 add_notify(&mut t, "b", 0.5, "");
125 add_notify(&mut t, "c", 0.9, "");
126 let r = notifies_in_range(&t, 0.0, 0.6);
127 assert_eq!(r.len(), 2);
128 }
129
130 #[test]
131 fn test_track_duration() {
132 let mut t = new_notify_track("events");
133 add_notify(&mut t, "end", 2.0, "");
134 assert!((track_duration(&t) - 2.0).abs() < 1e-5);
135 }
136
137 #[test]
138 fn test_sort_notifies() {
139 let mut t = new_notify_track("events");
140 add_notify(&mut t, "b", 0.5, "");
141 add_notify(&mut t, "a", 0.1, "");
142 sort_notifies(&mut t);
143 assert!((t.notifies[0].time - 0.1).abs() < 1e-5);
144 }
145
146 #[test]
147 fn test_json_output() {
148 let t = new_notify_track("events");
149 let j = notify_track_to_json(&t);
150 assert!(j.contains("events"));
151 }
152
153 #[test]
154 fn test_clear_notifies() {
155 let mut t = new_notify_track("events");
156 add_notify(&mut t, "x", 0.0, "");
157 clear_notifies(&mut t);
158 assert_eq!(notify_count(&t), 0);
159 }
160
161 #[test]
162 fn test_payload_stored() {
163 let mut t = new_notify_track("events");
164 add_notify(&mut t, "pickup", 1.0, "gold");
165 let n = find_notify(&t, "pickup").expect("should succeed");
166 assert_eq!(n.payload, "gold".to_string());
167 }
168}