#![allow(dead_code)]
use std::f32::consts::PI;
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FatDistributionConfig {
pub abdominal: f32,
pub gluteal: f32,
pub limb: f32,
pub visceral_ratio: f32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FatDistributionState {
pub abdominal: f32,
pub gluteal: f32,
pub limb: f32,
pub visceral_ratio: f32,
pub overall_fat: f32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FatDistributionWeights {
pub belly: f32,
pub hip: f32,
pub arm: f32,
pub leg: f32,
pub visceral: f32,
}
#[allow(dead_code)]
pub fn default_fat_distribution_config() -> FatDistributionConfig {
FatDistributionConfig { abdominal: 0.5, gluteal: 0.5, limb: 0.3, visceral_ratio: 0.2 }
}
#[allow(dead_code)]
pub fn new_fat_distribution_state() -> FatDistributionState {
FatDistributionState { abdominal: 0.5, gluteal: 0.5, limb: 0.3, visceral_ratio: 0.2, overall_fat: 0.3 }
}
#[allow(dead_code)]
pub fn set_abdominal_fat(state: &mut FatDistributionState, value: f32) {
state.abdominal = value.clamp(0.0, 1.0);
}
#[allow(dead_code)]
pub fn set_gluteal_fat(state: &mut FatDistributionState, value: f32) {
state.gluteal = value.clamp(0.0, 1.0);
}
#[allow(dead_code)]
pub fn set_limb_fat(state: &mut FatDistributionState, value: f32) {
state.limb = value.clamp(0.0, 1.0);
}
#[allow(dead_code)]
pub fn set_overall_fat(state: &mut FatDistributionState, value: f32) {
state.overall_fat = value.clamp(0.0, 1.0);
}
#[allow(dead_code)]
pub fn compute_fat_weights(state: &FatDistributionState, cfg: &FatDistributionConfig) -> FatDistributionWeights {
let belly = (state.abdominal * cfg.abdominal * state.overall_fat * (PI * 0.25).sin()).clamp(0.0, 1.0);
let hip = (state.gluteal * cfg.gluteal * state.overall_fat).clamp(0.0, 1.0);
let arm = (state.limb * cfg.limb * state.overall_fat * 0.7).clamp(0.0, 1.0);
let leg = (state.limb * cfg.limb * state.overall_fat).clamp(0.0, 1.0);
let visceral = (state.visceral_ratio * cfg.visceral_ratio * state.overall_fat).clamp(0.0, 1.0);
FatDistributionWeights { belly, hip, arm, leg, visceral }
}
#[allow(dead_code)]
pub fn fat_distribution_to_json(state: &FatDistributionState) -> String {
format!(
r#"{{"abdominal":{},"gluteal":{},"limb":{},"visceral_ratio":{},"overall_fat":{}}}"#,
state.abdominal, state.gluteal, state.limb, state.visceral_ratio, state.overall_fat
)
}
#[allow(dead_code)]
pub fn blend_fat_distributions(a: &FatDistributionState, b: &FatDistributionState, t: f32) -> FatDistributionState {
let t = t.clamp(0.0, 1.0);
FatDistributionState {
abdominal: a.abdominal + (b.abdominal - a.abdominal) * t,
gluteal: a.gluteal + (b.gluteal - a.gluteal) * t,
limb: a.limb + (b.limb - a.limb) * t,
visceral_ratio: a.visceral_ratio + (b.visceral_ratio - a.visceral_ratio) * t,
overall_fat: a.overall_fat + (b.overall_fat - a.overall_fat) * t,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let cfg = default_fat_distribution_config();
assert!((0.0..=1.0).contains(&cfg.abdominal));
}
#[test]
fn test_new_state() {
let s = new_fat_distribution_state();
assert!((s.abdominal - 0.5).abs() < 1e-6);
}
#[test]
fn test_set_abdominal_clamp() {
let mut s = new_fat_distribution_state();
set_abdominal_fat(&mut s, 1.5);
assert!((s.abdominal - 1.0).abs() < 1e-6);
}
#[test]
fn test_set_gluteal() {
let mut s = new_fat_distribution_state();
set_gluteal_fat(&mut s, 0.8);
assert!((s.gluteal - 0.8).abs() < 1e-6);
}
#[test]
fn test_set_limb() {
let mut s = new_fat_distribution_state();
set_limb_fat(&mut s, 0.7);
assert!((s.limb - 0.7).abs() < 1e-6);
}
#[test]
fn test_set_overall() {
let mut s = new_fat_distribution_state();
set_overall_fat(&mut s, 0.6);
assert!((s.overall_fat - 0.6).abs() < 1e-6);
}
#[test]
fn test_compute_weights() {
let s = new_fat_distribution_state();
let cfg = default_fat_distribution_config();
let w = compute_fat_weights(&s, &cfg);
assert!((0.0..=1.0).contains(&w.belly));
assert!((0.0..=1.0).contains(&w.hip));
}
#[test]
fn test_to_json() {
let s = new_fat_distribution_state();
let json = fat_distribution_to_json(&s);
assert!(json.contains("abdominal"));
assert!(json.contains("overall_fat"));
}
#[test]
fn test_blend() {
let a = new_fat_distribution_state();
let mut b = new_fat_distribution_state();
b.abdominal = 1.0;
let mid = blend_fat_distributions(&a, &b, 0.5);
assert!((mid.abdominal - 0.75).abs() < 1e-6);
}
#[test]
fn test_blend_identity() {
let a = new_fat_distribution_state();
let r = blend_fat_distributions(&a, &a, 0.5);
assert!((r.abdominal - a.abdominal).abs() < 1e-6);
}
}