pub(crate) fn format_value(v: f64) -> String {
if v.fract() == 0.0 {
format!("{:.1}", v)
} else {
format!("{}", v)
}
}
pub(crate) fn split_hue_from_value(s: &str) -> Option<(String, String)> {
let upper = s.to_uppercase();
let mut families = ["BG", "GY", "YR", "RP", "PB", "B", "G", "Y", "R", "P"];
families.sort_by_key(|f| std::cmp::Reverse(f.len()));
for family in &families {
if let Some(pos) = upper.find(family) {
let after_family = pos + family.len();
let numeric_part = &upper[..pos];
if numeric_part.is_empty() {
continue;
}
if numeric_part.parse::<f64>().is_err() {
continue;
}
if after_family < upper.len() {
let hue = s[..after_family].to_string();
let rest = s[after_family..].to_string();
return Some((hue, rest));
}
}
}
None
}
pub(crate) fn is_valid_hue_format(hue: &str) -> bool {
let mut valid_families = ["R", "YR", "Y", "GY", "G", "BG", "B", "PB", "P", "RP"];
valid_families.sort_by_key(|s| std::cmp::Reverse(s.len()));
let family = valid_families.iter()
.find(|&&family| hue.ends_with(family));
let family = match family {
Some(f) => f,
None => return false,
};
let numeric_part = hue.strip_suffix(family).unwrap_or("");
if numeric_part.is_empty() {
return false;
}
match numeric_part.parse::<f64>() {
Ok(num) => num >= 0.0 && num <= 10.0,
Err(_) => false,
}
}