#![allow(dead_code)]
#[derive(Debug, Clone, Default)]
pub struct ToeCurlState {
pub big_toe: f32,
pub long_toe: f32,
pub middle_toe: f32,
pub ring_toe: f32,
pub little_toe: f32,
pub spread: f32,
}
pub fn tc_set_all_curl(state: &mut ToeCurlState, amount: f32) {
let a = amount.clamp(0.0, 1.0);
state.big_toe = a;
state.long_toe = a;
state.middle_toe = a;
state.ring_toe = a;
state.little_toe = a;
}
pub fn tc_set_spread(state: &mut ToeCurlState, amount: f32) {
state.spread = amount.clamp(0.0, 1.0);
}
pub fn tc_mean_curl(state: &ToeCurlState) -> f32 {
(state.big_toe + state.long_toe + state.middle_toe + state.ring_toe + state.little_toe) / 5.0
}
pub fn tc_is_neutral(state: &ToeCurlState) -> bool {
tc_mean_curl(state) < 0.05 && state.spread < 0.05
}
pub fn tc_reset(state: &mut ToeCurlState) {
*state = ToeCurlState::default();
}
pub fn tc_set_big_toe(state: &mut ToeCurlState, amount: f32) {
state.big_toe = amount.clamp(0.0, 1.0);
}
pub fn tc_blend_toward_curl(state: &mut ToeCurlState, target: f32, t: f32) {
let t = t.clamp(0.0, 1.0);
let target = target.clamp(0.0, 1.0);
state.big_toe += (target - state.big_toe) * t;
state.long_toe += (target - state.long_toe) * t;
state.middle_toe += (target - state.middle_toe) * t;
state.ring_toe += (target - state.ring_toe) * t;
state.little_toe += (target - state.little_toe) * t;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_neutral() {
let s = ToeCurlState::default();
assert!(tc_is_neutral(&s));
}
#[test]
fn test_set_all_curl() {
let mut s = ToeCurlState::default();
tc_set_all_curl(&mut s, 0.8);
assert!((s.big_toe - 0.8).abs() < 1e-6);
assert!((s.little_toe - 0.8).abs() < 1e-6);
}
#[test]
fn test_mean_curl() {
let mut s = ToeCurlState::default();
tc_set_all_curl(&mut s, 0.6);
assert!((tc_mean_curl(&s) - 0.6).abs() < 1e-5);
}
#[test]
fn test_spread() {
let mut s = ToeCurlState::default();
tc_set_spread(&mut s, 0.5);
assert!((s.spread - 0.5).abs() < 1e-6);
}
#[test]
fn test_not_neutral_when_curled() {
let mut s = ToeCurlState::default();
tc_set_all_curl(&mut s, 0.5);
assert!(!tc_is_neutral(&s));
}
#[test]
fn test_reset() {
let mut s = ToeCurlState::default();
tc_set_all_curl(&mut s, 1.0);
tc_reset(&mut s);
assert!(tc_is_neutral(&s));
}
#[test]
fn test_big_toe_independent() {
let mut s = ToeCurlState::default();
tc_set_big_toe(&mut s, 0.7);
assert!((s.big_toe - 0.7).abs() < 1e-6);
assert_eq!(s.long_toe, 0.0);
}
#[test]
fn test_blend_toward() {
let mut s = ToeCurlState::default();
tc_blend_toward_curl(&mut s, 1.0, 0.5);
assert!(tc_mean_curl(&s) > 0.0 && tc_mean_curl(&s) < 1.0);
}
#[test]
fn test_clamp_above_one() {
let mut s = ToeCurlState::default();
tc_set_all_curl(&mut s, 5.0);
assert!((s.big_toe - 1.0).abs() < 1e-6);
}
}