Skip to main content

oxihuman_morph/
mesomorph_morph.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Mesomorph body type morph — medium, muscular build.
6
7/// Configuration for the mesomorph morph.
8#[derive(Debug, Clone)]
9pub struct MesomorphConfig {
10    pub chest_width: f32,
11    pub muscle_tone: f32,
12    pub waist_ratio: f32,
13}
14
15impl Default for MesomorphConfig {
16    fn default() -> Self {
17        MesomorphConfig {
18            chest_width: 0.7,
19            muscle_tone: 0.6,
20            waist_ratio: 0.75,
21        }
22    }
23}
24
25/// State for the mesomorph morph.
26#[derive(Debug, Clone)]
27pub struct MesomorphMorph {
28    pub intensity: f32,
29    pub config: MesomorphConfig,
30    pub enabled: bool,
31}
32
33/// Create a new mesomorph morph.
34pub fn new_mesomorph_morph() -> MesomorphMorph {
35    MesomorphMorph {
36        intensity: 0.0,
37        config: MesomorphConfig::default(),
38        enabled: true,
39    }
40}
41
42/// Set intensity [0, 1].
43pub fn meso_set_intensity(m: &mut MesomorphMorph, v: f32) {
44    m.intensity = v.clamp(0.0, 1.0);
45}
46
47/// Chest width delta.
48pub fn meso_chest_delta(m: &MesomorphMorph) -> f32 {
49    m.intensity * m.config.chest_width
50}
51
52/// Muscle tone weight.
53pub fn meso_muscle_tone(m: &MesomorphMorph) -> f32 {
54    m.intensity * m.config.muscle_tone
55}
56
57/// Waist-to-hip ratio parameter.
58pub fn meso_waist_ratio(m: &MesomorphMorph) -> f32 {
59    1.0 - m.intensity * (1.0 - m.config.waist_ratio)
60}
61
62/// Serialise to JSON.
63pub fn meso_to_json(m: &MesomorphMorph) -> String {
64    format!(
65        r#"{{"intensity":{:.3},"muscle_tone":{:.3},"enabled":{}}}"#,
66        m.intensity,
67        meso_muscle_tone(m),
68        m.enabled
69    )
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn default_zero() {
78        let m = new_mesomorph_morph();
79        assert!((m.intensity - 0.0).abs() < 1e-6 /* zero intensity */);
80    }
81
82    #[test]
83    fn clamp_upper() {
84        let mut m = new_mesomorph_morph();
85        meso_set_intensity(&mut m, 5.0);
86        assert!((m.intensity - 1.0).abs() < 1e-6 /* clamped to 1 */);
87    }
88
89    #[test]
90    fn chest_delta_increases() {
91        let mut m = new_mesomorph_morph();
92        meso_set_intensity(&mut m, 1.0);
93        assert!(meso_chest_delta(&m) > 0.0 /* positive delta */);
94    }
95
96    #[test]
97    fn muscle_tone_zero_at_zero() {
98        let m = new_mesomorph_morph();
99        assert!((meso_muscle_tone(&m) - 0.0).abs() < 1e-6 /* zero tone */);
100    }
101
102    #[test]
103    fn waist_ratio_at_zero_is_one() {
104        let m = new_mesomorph_morph();
105        assert!((meso_waist_ratio(&m) - 1.0).abs() < 1e-6 /* neutral ratio */);
106    }
107
108    #[test]
109    fn json_contains_field() {
110        let mut m = new_mesomorph_morph();
111        meso_set_intensity(&mut m, 0.9);
112        assert!(meso_to_json(&m).contains("0.900") /* in json */);
113    }
114
115    #[test]
116    fn enabled_default() {
117        let m = new_mesomorph_morph();
118        assert!(m.enabled /* enabled */);
119    }
120
121    #[test]
122    fn config_chest_positive() {
123        let m = new_mesomorph_morph();
124        assert!(m.config.chest_width > 0.0 /* positive */);
125    }
126}