use crate::db::pauses::Pauses;
use crate::db::workdays::Workday;
use crate::libs::config::{Config, ProductivityConfig};
use crate::libs::pause::Pause;
use anyhow::Result;
use chrono::Duration;
pub struct Productivity {
pub workday: Workday,
pub short_pauses: Vec<Pause>,
pub long_pauses: Vec<Pause>,
pub config: ProductivityConfig,
}
impl Productivity {
pub fn new(workday: &Workday) -> Result<Self> {
let config = Config::read()?;
let monitor_config = config.monitor.unwrap_or_default();
let productivity_config = config.productivity.unwrap_or_default();
Ok(Self {
workday: workday.clone(),
short_pauses: Pauses::new()?.set_max_duration(monitor_config.min_pause_duration).get_workday_pauses(workday)?,
long_pauses: Pauses::new()?.set_min_duration(monitor_config.min_pause_duration).get_workday_pauses(workday)?,
config: productivity_config,
})
}
pub fn with_test_data(workday: &Workday, short_pauses: Vec<Pause>, long_pauses: Vec<Pause>) -> Self {
Self {
workday: workday.clone(),
short_pauses,
long_pauses,
config: ProductivityConfig::default(),
}
}
pub fn is_below_threshold(&self) -> bool {
let now = chrono::Local::now().naive_local();
let elapsed = now - self.workday.start;
let expected_duration = Duration::seconds((self.config.workday_hours * 3600.0) as i64);
let min_elapsed = Duration::seconds((expected_duration.num_seconds() as f64 * self.config.min_workday_fraction_before_suggest) as i64);
if elapsed < min_elapsed {
return false;
}
self.calculate_productivity() < self.config.min_productivity_threshold
}
pub fn calculate_productivity(&self) -> f64 {
let end_time = crate::libs::report::workday_end_time(&self.workday, &self.long_pauses);
let gross_duration = end_time - self.workday.start;
let long_pause_duration: Duration = self.long_pauses.iter().filter_map(|p| p.duration).sum();
let short_pause_duration: Duration = self.short_pauses.iter().filter_map(|p| p.duration).sum();
let work_time = gross_duration - long_pause_duration;
let net_work_time = work_time - short_pause_duration;
if work_time.num_seconds() > 0 {
let productivity = (net_work_time.num_seconds() as f64 / work_time.num_seconds() as f64) * 100.0;
productivity.clamp(0.0, 100.0)
} else {
0.0
}
}
}