oxihuman_morph/
age_progression_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct AgeStage {
10 pub age_years: f32,
11 pub morph_weights: Vec<f32>,
12 pub label: String,
13}
14
15#[derive(Debug, Clone)]
17pub struct AgeProgressionMorph {
18 pub stages: Vec<AgeStage>,
19 pub current_age: f32,
20 pub morph_count: usize,
21 pub enabled: bool,
22}
23
24impl AgeProgressionMorph {
25 pub fn new(morph_count: usize) -> Self {
26 AgeProgressionMorph {
27 stages: Vec::new(),
28 current_age: 25.0,
29 morph_count,
30 enabled: true,
31 }
32 }
33}
34
35pub fn new_age_progression_morph(morph_count: usize) -> AgeProgressionMorph {
37 AgeProgressionMorph::new(morph_count)
38}
39
40pub fn apm_add_stage(apm: &mut AgeProgressionMorph, stage: AgeStage) {
42 apm.stages.push(stage);
43}
44
45pub fn apm_set_age(apm: &mut AgeProgressionMorph, age: f32) {
47 apm.current_age = age.max(0.0);
48}
49
50pub fn apm_evaluate(apm: &AgeProgressionMorph) -> Vec<f32> {
52 vec![0.0; apm.morph_count]
54}
55
56pub fn apm_stage_count(apm: &AgeProgressionMorph) -> usize {
58 apm.stages.len()
59}
60
61pub fn apm_set_enabled(apm: &mut AgeProgressionMorph, enabled: bool) {
63 apm.enabled = enabled;
64}
65
66pub fn apm_to_json(apm: &AgeProgressionMorph) -> String {
68 format!(
69 r#"{{"morph_count":{},"stage_count":{},"current_age":{:.1},"enabled":{}}}"#,
70 apm.morph_count,
71 apm.stages.len(),
72 apm.current_age,
73 apm.enabled
74 )
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_new_morph_count() {
83 let a = new_age_progression_morph(12);
84 assert_eq!(a.morph_count, 12 ,);
85 }
86
87 #[test]
88 fn test_default_age() {
89 let a = new_age_progression_morph(4);
90 assert!((a.current_age - 25.0).abs() < 1e-5, );
91 }
92
93 #[test]
94 fn test_no_stages_initially() {
95 let a = new_age_progression_morph(4);
96 assert_eq!(apm_stage_count(&a), 0 ,);
97 }
98
99 #[test]
100 fn test_add_stage() {
101 let mut a = new_age_progression_morph(4);
102 apm_add_stage(
103 &mut a,
104 AgeStage {
105 age_years: 30.0,
106 morph_weights: vec![0.0; 4],
107 label: "adult".into(),
108 },
109 );
110 assert_eq!(apm_stage_count(&a), 1 ,);
111 }
112
113 #[test]
114 fn test_set_age() {
115 let mut a = new_age_progression_morph(4);
116 apm_set_age(&mut a, 60.0);
117 assert!((a.current_age - 60.0).abs() < 1e-5, );
118 }
119
120 #[test]
121 fn test_age_clamped_negative() {
122 let mut a = new_age_progression_morph(4);
123 apm_set_age(&mut a, -5.0);
124 assert!((a.current_age).abs() < 1e-6, );
125 }
126
127 #[test]
128 fn test_evaluate_length() {
129 let a = new_age_progression_morph(8);
130 let out = apm_evaluate(&a);
131 assert_eq!(out.len(), 8 ,);
132 }
133
134 #[test]
135 fn test_set_enabled() {
136 let mut a = new_age_progression_morph(2);
137 apm_set_enabled(&mut a, false);
138 assert!(!a.enabled ,);
139 }
140
141 #[test]
142 fn test_to_json_contains_current_age() {
143 let a = new_age_progression_morph(4);
144 let j = apm_to_json(&a);
145 assert!(j.contains("\"current_age\""), );
146 }
147
148 #[test]
149 fn test_enabled_default() {
150 let a = new_age_progression_morph(1);
151 assert!(a.enabled ,);
152 }
153}