use super::svg::{wrap_in_svg, DEFAULT_TEXT_COLOR}; pub fn generate_bar_chart(data: &[(String, i64)]) -> String { if data.is_empty() { return r##" No data available "##.to_string(); } let bar_height = 24.0; let gap = 14.0; let pad_top = 10.0; let pad_bottom = 10.0; let pad_left = 130.0; let pad_right = 70.0; let width = 600.0; let height = pad_top + pad_bottom + (data.len() as f64 * (bar_height + gap)) - gap; let chart_w = width - pad_left - pad_right; let max_val = data.iter().map(|(_, v)| *v).max().unwrap_or(0); let max_x = if max_val == 0 { 1.0 } else { max_val as f64 }; let mut bars = String::new(); let total_count: i64 = data.iter().map(|(_, v)| *v).sum(); for (i, (label, val)) in data.iter().enumerate() { let y = pad_top + (i as f64 * (bar_height + gap)); let bar_w = (*val as f64 / max_x) * chart_w; let pct = if total_count > 0 { (*val as f64 / total_count as f64) * 100.0 } else { 0.0 }; // Truncate long labels let display_label = if label.len() > 18 { format!("{}...", &label[0..15]) } else { label.to_string() }; bars.push_str(&format!( r##" {label} {val} ({pct:.1}%) "##, i = i, pad_left_label = pad_left - 10.0, text_y = y + (bar_height / 2.0) + 1.0, label = display_label, pad_left = pad_left, y = y, bar_w = bar_w.max(2.0), bar_height = bar_height, val_x = pad_left + bar_w.max(2.0) + 8.0, val = val, pct = pct, text_color = DEFAULT_TEXT_COLOR )); } wrap_in_svg(width, height, &bars) }