use std::ops::AddAssign;
pub fn ms_to_readable(mut ms: u128, round: Option<u128>) -> String {
if let Some(r) = round {
if r != 0 {
ms = round_ms(r, ms);
}
}
if ms >= 1000 {
let remain_ms = ms % 1000;
ms -= remain_ms;
let mut s = ms / 1000;
if s >= 60 {
let remain_s = s % 60;
s -= remain_s;
let mut min = s / 60;
if min >= 60 {
let remain_min = min % 60;
min -= remain_min;
let hr = min / 60;
return format!("{}:{:02}:{:02}.{:03}", hr, remain_min, remain_s, remain_ms);
} else {
return format!("{}:{:02}.{:03}", min, remain_s, remain_ms);
}
} else {
return format!("{}.{:03}", s, remain_ms);
}
}
format!("0.{:03}", ms)
}
pub fn diff_text(mut ms: i128) -> String {
let pre: char = if ms < 0 {
ms *= -1;
'-'
} else {
'+'
};
let mut tenths = ms / 100;
let mut full_s = tenths / 10;
tenths -= full_s * 10;
if full_s >= 60 {
let mut min = full_s / 60;
full_s -= min * 60;
if min >= 60 {
let hr = min / 60;
min -= hr * 60;
format!("{}{}:{:02}:{:02}.{}", pre, hr, min, full_s, tenths)
} else {
format!("{}{}:{:02}.{}", pre, min, full_s, tenths)
}
} else {
format!("{}{}.{}", pre, full_s, tenths)
}
}
pub fn split_time_text(ms: u128) -> String {
let mut tenths = ms / 100;
let mut full_s: u128;
if tenths > 10 {
full_s = tenths / 10;
tenths -= full_s * 10;
if full_s >= 60 {
let mut min = full_s / 60;
full_s -= min * 60;
if min >= 60 {
let hr = min / 60;
min -= hr * 60;
format!("{}:{:02}:{:02}.{}", hr, min, full_s, tenths)
} else {
format!("{}:{:02}.{}", min, full_s, tenths)
}
} else {
format!("{}.{}", full_s, tenths)
}
} else {
format!("0.{}", tenths)
}
}
pub fn split_time_sum<T: AddAssign + Default + Copy>(ms_vec: &[T]) -> Vec<T> {
let mut total = Default::default();
let mut vec = vec![];
for &num in ms_vec {
total += num;
vec.push(total);
}
vec
}
fn round_ms(frames: u128, ms: u128) -> u128 {
let hundreds = ms / 100;
let mut rem = ms % 100;
let rounds = gen_round_values(frames);
for val in &rounds {
if rem <= *val {
rem = val - rounds[0];
if *val % 10 >= 5 && rounds[0] % 10 < 5 {
rem -= 1;
}
break;
}
}
rem + (hundreds * 100)
}
fn gen_round_values(frames: u128) -> Vec<u128> {
let frame = 1000 / frames;
let mut sum = frame;
let mut ret = vec![];
while sum < 100 {
if sum % 10 >= 5 {
sum += 1;
}
ret.push(sum);
sum += frame;
}
ret.push(sum);
ret
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_readable() {
assert_eq!(ms_to_readable(3_661_111, None), "1:01:01.111");
}
#[test]
fn test_rounding_30() {
assert_eq!(round_ms(30, 500), 500);
assert_eq!(round_ms(30, 710), 700);
assert_eq!(round_ms(30, 645), 633);
assert_eq!(round_ms(30, 384), 367);
assert_eq!(round_ms(30, 399), 367);
}
#[test]
fn test_rounding_60() {
assert_eq!(round_ms(60, 500), 500);
assert_eq!(round_ms(60, 710), 700);
assert_eq!(round_ms(60, 460), 450);
assert_eq!(round_ms(60, 645), 633);
assert_eq!(round_ms(60, 384), 383);
assert_eq!(round_ms(60, 399), 383);
}
#[test]
fn test_sum() {
assert_eq!(split_time_sum(&vec![6, 7, 8]), vec![6, 13, 21]);
assert_eq!(split_time_sum(&vec![0]), vec![0]);
}
#[test]
fn test_diff() {
assert_eq!(diff_text(3_661_111), "+1:01:01.1");
assert_eq!(diff_text(-3_661_111), "-1:01:01.1");
}
#[test]
fn test_split() {
assert_eq!(split_time_text(3_661_111), "1:01:01.1");
}
}