use super::*;
#[allow(dead_code)]
pub fn parse_timestamp(s: &str) -> Result<f64> {
if let Ok(seconds) = s.parse::<f64>() {
return Ok(seconds);
}
let parts: Vec<&str> = s.split(':').collect();
match parts.len() {
1 => parts[0].parse().context("Invalid time format"),
2 => {
let minutes: f64 = parts[0].parse().context("Invalid minutes")?;
let seconds: f64 = parts[1].parse().context("Invalid seconds")?;
Ok(minutes * 60.0 + seconds)
}
3 => {
let hours: f64 = parts[0].parse().context("Invalid hours")?;
let minutes: f64 = parts[1].parse().context("Invalid minutes")?;
let seconds: f64 = parts[2].parse().context("Invalid seconds")?;
Ok(hours * 3600.0 + minutes * 60.0 + seconds)
}
_ => Err(anyhow!("Invalid time format: {}", s)),
}
}
pub fn parse_duration(s: &str) -> Result<f64> {
let s = s.trim();
if s.is_empty() {
return Err(anyhow!("Empty duration string"));
}
let last_char = s.chars().last().unwrap_or('\0');
if last_char.is_ascii_digit() || last_char == '.' {
s.parse().context("Invalid duration")
} else {
let (num_str, multiplier) = match last_char {
's' | 'S' => (&s[..s.len() - 1], 1.0),
'm' | 'M' => (&s[..s.len() - 1], 60.0),
'h' | 'H' => (&s[..s.len() - 1], 3600.0),
_ => return Err(anyhow!("Invalid duration suffix: {}", last_char)),
};
let num: f64 = num_str.parse().context("Invalid duration number")?;
Ok(num * multiplier)
}
}
#[allow(dead_code)]
pub fn calculate_optimal_grid(count: usize, aspect_ratio: f64) -> (usize, usize) {
if count == 0 {
return (0, 0);
}
if count == 1 {
return (1, 1);
}
let sqrt = (count as f64).sqrt();
let mut cols = sqrt.ceil() as usize;
let mut rows = (count as f64 / cols as f64).ceil() as usize;
if aspect_ratio > 1.5 {
cols = (sqrt * 1.2).ceil() as usize;
rows = (count as f64 / cols as f64).ceil() as usize;
} else if aspect_ratio < 0.67 {
rows = (sqrt * 1.2).ceil() as usize;
cols = (count as f64 / rows as f64).ceil() as usize;
}
(cols, rows)
}
#[allow(dead_code)]
pub fn adjust_grid_for_count(cols: usize, mut rows: usize, count: usize) -> (usize, usize) {
let total = cols * rows;
if total == count {
return (cols, rows);
}
if total > count {
let rows_needed = (count as f64 / cols as f64).ceil() as usize;
rows = rows_needed;
} else {
let rows_needed = (count as f64 / cols as f64).ceil() as usize;
rows = rows_needed;
}
(cols, rows)
}
pub fn validate_and_adjust_config(mut config: SpriteSheetConfig) -> Result<SpriteSheetConfig> {
match config.layout {
LayoutMode::Vertical => {
config.columns = 1;
if let Some(count) = config.count {
config.rows = count;
}
}
LayoutMode::Horizontal => {
config.rows = 1;
if let Some(count) = config.count {
config.columns = count;
}
}
LayoutMode::Auto => {
let count = config.count.unwrap_or(25);
let aspect = config.thumbnail_width as f64 / config.thumbnail_height as f64;
let (cols, rows) = calculate_optimal_grid(count, aspect);
config.columns = cols;
config.rows = rows;
config.count = Some(count);
}
LayoutMode::Grid => {
if config.count.is_none() {
config.count = Some(config.columns * config.rows);
}
}
}
config.validate()?;
Ok(config)
}