#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ElderlyMorphConfig {
pub kyphosis_max: f32,
pub height_loss_max: f32,
pub skin_sag_factor: f32,
}
impl Default for ElderlyMorphConfig {
fn default() -> Self {
ElderlyMorphConfig {
kyphosis_max: 0.4,
height_loss_max: 0.08,
skin_sag_factor: 0.6,
}
}
}
#[derive(Debug, Clone)]
pub struct ElderlyMorph {
pub age_years: f32,
pub config: ElderlyMorphConfig,
pub enabled: bool,
}
pub fn new_elderly_morph() -> ElderlyMorph {
ElderlyMorph {
age_years: 60.0,
config: ElderlyMorphConfig::default(),
enabled: true,
}
}
pub fn em_set_age(m: &mut ElderlyMorph, years: f32) {
m.age_years = years.clamp(60.0, 100.0);
}
pub fn em_progress(m: &ElderlyMorph) -> f32 {
(m.age_years - 60.0) / 40.0
}
pub fn em_kyphosis(m: &ElderlyMorph) -> f32 {
let t = em_progress(m);
t * t * m.config.kyphosis_max
}
pub fn em_height_loss(m: &ElderlyMorph) -> f32 {
em_progress(m) * m.config.height_loss_max
}
pub fn em_skin_sag(m: &ElderlyMorph) -> f32 {
em_progress(m) * m.config.skin_sag_factor
}
pub fn em_to_json(m: &ElderlyMorph) -> String {
format!(
r#"{{"age_years":{:.1},"kyphosis":{:.3},"height_loss":{:.4},"enabled":{}}}"#,
m.age_years,
em_kyphosis(m),
em_height_loss(m),
m.enabled
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_age_is_60() {
let m = new_elderly_morph();
assert!((m.age_years - 60.0).abs() < 1e-6 );
}
#[test]
fn clamp_to_range() {
let mut m = new_elderly_morph();
em_set_age(&mut m, 30.0);
assert!((m.age_years - 60.0).abs() < 1e-6 );
em_set_age(&mut m, 999.0);
assert!((m.age_years - 100.0).abs() < 1e-6 );
}
#[test]
fn kyphosis_zero_at_60() {
let mut m = new_elderly_morph();
em_set_age(&mut m, 60.0);
assert!((em_kyphosis(&m) - 0.0).abs() < 1e-6 );
}
#[test]
fn kyphosis_increases_with_age() {
let mut m = new_elderly_morph();
em_set_age(&mut m, 70.0);
let k70 = em_kyphosis(&m);
em_set_age(&mut m, 90.0);
let k90 = em_kyphosis(&m);
assert!(k90 > k70 );
}
#[test]
fn height_loss_at_100() {
let mut m = new_elderly_morph();
em_set_age(&mut m, 100.0);
let loss = em_height_loss(&m);
assert!(loss > 0.0 );
}
#[test]
fn skin_sag_in_range() {
let mut m = new_elderly_morph();
em_set_age(&mut m, 80.0);
let s = em_skin_sag(&m);
assert!((0.0..=1.0).contains(&s) );
}
#[test]
fn json_contains_age() {
let mut m = new_elderly_morph();
em_set_age(&mut m, 75.0);
assert!(em_to_json(&m).contains("75.0") );
}
#[test]
fn enabled_default() {
let m = new_elderly_morph();
assert!(m.enabled );
}
}