oxihuman_morph/
acne_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum AcneLesionType {
10 Comedone,
11 Papule,
12 Pustule,
13 Nodule,
14 Cyst,
15}
16
17#[derive(Debug, Clone)]
19pub struct AcneLesion {
20 pub lesion_type: AcneLesionType,
21 pub position: [f32; 3],
22 pub size: f32,
23 pub inflammation: f32,
24}
25
26#[derive(Debug, Clone)]
28pub struct AcneMorph {
29 pub lesions: Vec<AcneLesion>,
30 pub severity: f32,
31 pub morph_count: usize,
32 pub enabled: bool,
33}
34
35impl AcneMorph {
36 pub fn new(morph_count: usize) -> Self {
37 AcneMorph {
38 lesions: Vec::new(),
39 severity: 0.0,
40 morph_count,
41 enabled: true,
42 }
43 }
44}
45
46pub fn new_acne_morph(morph_count: usize) -> AcneMorph {
48 AcneMorph::new(morph_count)
49}
50
51pub fn acm_add_lesion(morph: &mut AcneMorph, lesion: AcneLesion) {
53 morph.lesions.push(lesion);
54}
55
56pub fn acm_set_severity(morph: &mut AcneMorph, severity: f32) {
58 morph.severity = severity.clamp(0.0, 1.0);
59}
60
61pub fn acm_clear(morph: &mut AcneMorph) {
63 morph.lesions.clear();
64}
65
66pub fn acm_evaluate(morph: &AcneMorph) -> Vec<f32> {
68 if !morph.enabled || morph.morph_count == 0 {
70 return vec![];
71 }
72 vec![morph.severity; morph.morph_count]
73}
74
75pub fn acm_set_enabled(morph: &mut AcneMorph, enabled: bool) {
77 morph.enabled = enabled;
78}
79
80pub fn acm_lesion_count(morph: &AcneMorph) -> usize {
82 morph.lesions.len()
83}
84
85pub fn acm_to_json(morph: &AcneMorph) -> String {
87 format!(
88 r#"{{"lesion_count":{},"severity":{},"morph_count":{},"enabled":{}}}"#,
89 morph.lesions.len(),
90 morph.severity,
91 morph.morph_count,
92 morph.enabled
93 )
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 fn make_lesion() -> AcneLesion {
101 AcneLesion {
102 lesion_type: AcneLesionType::Papule,
103 position: [0.0, 0.1, 0.0],
104 size: 0.01,
105 inflammation: 0.7,
106 }
107 }
108
109 #[test]
110 fn test_initial_empty() {
111 let m = new_acne_morph(4);
112 assert_eq!(acm_lesion_count(&m), 0 );
113 }
114
115 #[test]
116 fn test_add_lesion() {
117 let mut m = new_acne_morph(4);
118 acm_add_lesion(&mut m, make_lesion());
119 assert_eq!(acm_lesion_count(&m), 1 );
120 }
121
122 #[test]
123 fn test_clear() {
124 let mut m = new_acne_morph(4);
125 acm_add_lesion(&mut m, make_lesion());
126 acm_clear(&mut m);
127 assert_eq!(acm_lesion_count(&m), 0 );
128 }
129
130 #[test]
131 fn test_severity_clamp() {
132 let mut m = new_acne_morph(4);
133 acm_set_severity(&mut m, 1.5);
134 assert!((m.severity - 1.0).abs() < 1e-6 );
135 }
136
137 #[test]
138 fn test_evaluate_length() {
139 let mut m = new_acne_morph(6);
140 acm_set_severity(&mut m, 0.5);
141 assert_eq!(
142 acm_evaluate(&m).len(),
143 6 );
145 }
146
147 #[test]
148 fn test_evaluate_disabled() {
149 let mut m = new_acne_morph(4);
150 acm_set_enabled(&mut m, false);
151 assert!(acm_evaluate(&m).is_empty() );
152 }
153
154 #[test]
155 fn test_to_json_has_lesion_count() {
156 let m = new_acne_morph(4);
157 let j = acm_to_json(&m);
158 assert!(j.contains("\"lesion_count\"") );
159 }
160
161 #[test]
162 fn test_enabled_default() {
163 let m = new_acne_morph(4);
164 assert!(m.enabled );
165 }
166
167 #[test]
168 fn test_evaluate_matches_severity() {
169 let mut m = new_acne_morph(3);
170 acm_set_severity(&mut m, 0.4);
171 let out = acm_evaluate(&m);
172 assert!((out[0] - 0.4).abs() < 1e-5 );
173 }
174
175 #[test]
176 fn test_lesion_type_variant() {
177 let l = make_lesion();
178 assert_eq!(
179 l.lesion_type,
180 AcneLesionType::Papule );
182 }
183}