use crate::config::Config;
use chrono::{Duration, NaiveTime};
pub fn month_name(month: &str) -> &'static str {
match month {
"01" => "January",
"02" => "February",
"03" => "March",
"04" => "April",
"05" => "May",
"06" => "June",
"07" => "July",
"08" => "August",
"09" => "September",
"10" => "October",
"11" => "November",
"12" => "December",
_ => "Unknown",
}
}
pub fn calculate_expected_exit(
start: &str,
work_minutes: i64,
lunch: i32,
config: &Config,
) -> NaiveTime {
let start_time = NaiveTime::parse_from_str(start, "%H:%M").expect("Invalid start time format");
let min_l = config.min_duration_lunch_break as i64;
let max_l = config.max_duration_lunch_break as i64;
let lunch_eff = (lunch as i64).clamp(min_l, max_l);
start_time + Duration::minutes(work_minutes + lunch_eff)
}
pub fn calculate_surplus(
start: &str,
lunch: i32,
end: &str,
work_minutes: i64,
config: &Config,
) -> Duration {
let expected = calculate_expected_exit(start, work_minutes, lunch, config);
let actual = NaiveTime::parse_from_str(end, "%H:%M").expect("Invalid end time format");
actual - expected
}
pub fn crosses_lunch_window(start: &str, end: &str) -> bool {
let start_time = match NaiveTime::parse_from_str(start, "%H:%M") {
Ok(t) => t,
Err(_) => return false,
};
let end_time = match NaiveTime::parse_from_str(end, "%H:%M") {
Ok(t) => t,
Err(_) => return false,
};
let lunch_start = NaiveTime::parse_from_str("12:30", "%H:%M").unwrap();
let lunch_end = NaiveTime::parse_from_str("14:30", "%H:%M").unwrap();
start_time < lunch_end && end_time > lunch_start
}
pub fn effective_lunch_minutes(
lunch: i32,
start: &str,
end: &str,
position: char,
config: &Config,
) -> i32 {
let crosses = crosses_lunch_window(start, end);
match position {
'O' => {
if crosses {
let l = lunch.clamp(
config.min_duration_lunch_break,
config.max_duration_lunch_break,
);
if l < config.min_duration_lunch_break {
config.min_duration_lunch_break
} else {
l
}
} else {
0
}
}
'H' => 0,
_ => lunch.clamp(0, config.max_duration_lunch_break),
}
}