#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ChildMorphConfig {
pub limb_elongation: f32,
pub torso_narrowness: f32,
pub head_ratio: f32,
}
impl Default for ChildMorphConfig {
fn default() -> Self {
ChildMorphConfig {
limb_elongation: 0.7,
torso_narrowness: 0.85,
head_ratio: 0.85,
}
}
}
#[derive(Debug, Clone)]
pub struct ChildMorph {
pub age_years: f32,
pub config: ChildMorphConfig,
pub enabled: bool,
}
pub fn new_child_morph() -> ChildMorph {
ChildMorph {
age_years: 2.0,
config: ChildMorphConfig::default(),
enabled: true,
}
}
pub fn cm_set_age(m: &mut ChildMorph, years: f32) {
m.age_years = years.clamp(2.0, 12.0);
}
pub fn cm_progress(m: &ChildMorph) -> f32 {
(m.age_years - 2.0) / 10.0
}
pub fn cm_height_scale(m: &ChildMorph) -> f32 {
0.45 + 0.35 * cm_progress(m)
}
pub fn cm_limb_scale(m: &ChildMorph) -> f32 {
m.config.limb_elongation + 0.15 * cm_progress(m)
}
pub fn cm_to_json(m: &ChildMorph) -> String {
format!(
r#"{{"age_years":{:.1},"height_scale":{:.3},"enabled":{}}}"#,
m.age_years,
cm_height_scale(m),
m.enabled
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_age_is_two() {
let m = new_child_morph();
assert!((m.age_years - 2.0).abs() < 1e-6 );
}
#[test]
fn set_age_clamps_bounds() {
let mut m = new_child_morph();
cm_set_age(&mut m, 0.0);
assert!((m.age_years - 2.0).abs() < 1e-6 );
cm_set_age(&mut m, 99.0);
assert!((m.age_years - 12.0).abs() < 1e-6 );
}
#[test]
fn progress_at_age_12_is_one() {
let mut m = new_child_morph();
cm_set_age(&mut m, 12.0);
assert!((cm_progress(&m) - 1.0).abs() < 1e-6 );
}
#[test]
fn height_increases_with_age() {
let mut m = new_child_morph();
cm_set_age(&mut m, 2.0);
let h2 = cm_height_scale(&m);
cm_set_age(&mut m, 12.0);
let h12 = cm_height_scale(&m);
assert!(h12 > h2 );
}
#[test]
fn limb_scale_increases() {
let mut m = new_child_morph();
cm_set_age(&mut m, 2.0);
let l2 = cm_limb_scale(&m);
cm_set_age(&mut m, 12.0);
let l12 = cm_limb_scale(&m);
assert!(l12 > l2 );
}
#[test]
fn json_contains_age() {
let mut m = new_child_morph();
cm_set_age(&mut m, 8.0);
assert!(cm_to_json(&m).contains("8.0") );
}
#[test]
fn enabled_flag_works() {
let mut m = new_child_morph();
m.enabled = false;
assert!(!m.enabled );
}
#[test]
fn torso_narrowness_positive() {
let m = new_child_morph();
assert!(m.config.torso_narrowness > 0.0 );
}
}