use super::{
Palette, Party, RenderContext,
style::{bold, cyan, gray, green, yellow},
};
pub struct Stats;
impl Party for Stats {
fn id(&self) -> &'static str {
"stats"
}
fn name(&self) -> &'static str {
"Stats Party"
}
fn description(&self) -> &'static str {
"Shows information about your commit and push trends."
}
fn cost(&self) -> u64 {
100
}
fn supports_color(&self) -> bool {
false
}
fn render(&self, ctx: &RenderContext, _palette: &Palette) -> bool {
let clock = ctx.clock;
let push_commits = ctx.push.commits();
let push_commit_count = push_commits.len();
let push_lines = ctx
.push
.commits()
.iter()
.map(|c| c.lines_changed())
.sum::<u64>();
let push_points = ctx.breakdown.total;
let Ok(today_stats) = ctx
.history
.stats_since(clock.today_start(), clock.tz_offset_secs())
else {
return true;
};
let Ok(all_time_stats) = ctx.history.stats_since(0, clock.tz_offset_secs()) else {
return true;
};
let daily_avg_commit_count = all_time_stats.commits / all_time_stats.active_days;
let daily_avg_lines = all_time_stats.lines / all_time_stats.active_days;
let daily_avg_points = all_time_stats.points / all_time_stats.active_days;
let w_commits = col_width([
push_commit_count as u64,
today_stats.commits,
daily_avg_commit_count,
all_time_stats.commits,
]);
let w_lines = col_width([
push_lines,
today_stats.lines,
daily_avg_lines,
all_time_stats.lines,
]);
let w_points = col_width([
push_points,
today_stats.points,
daily_avg_points,
all_time_stats.points,
]);
let print_row =
|header: &str, commits: u64, lines: u64, points: u64, extra: Option<String>| {
let commit_word = if commits == 1 { "commit" } else { "commits" };
let point_word = if points == 1 { "point" } else { "points" };
let line_word = if lines == 1 { "line" } else { "lines" };
let header = bold(format!("{header:>wh$}", wh = 10));
let commits = format!("{} {commit_word},", green(commits));
let lines = format!("{} {line_word} changed,", cyan(lines));
let points = format!("{} {point_word}", yellow(points));
let extra = extra.unwrap_or_default();
println!(
"{header}: {commits:<wc$} {lines:<wl$} {points:<wp$}{extra}",
wc = w_commits + 19,
wl = w_lines + 24,
wp = w_points + 6
);
};
println!(" Stats");
println!(" {}", gray("─────"));
if push_commit_count > 0 {
let most_pts_ever = (push_points >= all_time_stats.max_points)
.then_some(yellow(" (biggest push ever!)"));
print_row(
"This Push",
push_commit_count as u64,
push_lines,
push_points,
most_pts_ever,
);
}
print_row(
"Today",
today_stats.commits,
today_stats.lines,
today_stats.points,
None,
);
print_row(
"Daily Avg",
daily_avg_commit_count,
daily_avg_lines,
daily_avg_points,
None,
);
print_row(
"All Time",
all_time_stats.commits,
all_time_stats.lines,
all_time_stats.points,
None,
);
true
}
}
fn col_width(vals: [u64; 4]) -> usize {
vals.iter().map(|n| n.to_string().len()).max().unwrap_or(1)
}