mod charts;
mod dataframe_ext;
mod sparkline;
pub use charts::{
BarChart, BarChartConfig, BarOrientation, Histogram, HistogramConfig, LinePlot, LinePlotConfig,
ScatterPlot, ScatterPlotConfig,
};
pub use dataframe_ext::{quick as viz_quick, DataFrameVizExt};
pub use sparkline::{Sparkline, SparklineStyle};
pub trait Chart {
fn render(&self) -> String;
fn display(&self) {
println!("{}", self.render());
}
}
#[derive(Debug, Clone)]
pub struct ChartConfig {
pub width: usize,
pub height: usize,
pub show_labels: bool,
pub show_grid: bool,
pub title: Option<String>,
pub x_label: Option<String>,
pub y_label: Option<String>,
}
impl Default for ChartConfig {
fn default() -> Self {
Self {
width: 60,
height: 20,
show_labels: true,
show_grid: false,
title: None,
x_label: None,
y_label: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChartStyle {
Ascii,
Unicode,
Braille,
}
impl Default for ChartStyle {
fn default() -> Self {
Self::Unicode
}
}
pub mod quick {
use super::*;
pub fn histogram(data: &[f64], bins: usize) -> String {
let hist = Histogram::new(data, bins);
hist.render()
}
pub fn bar_chart(labels: &[&str], values: &[f64]) -> String {
let chart = BarChart::new(labels, values);
chart.render()
}
pub fn hbar_chart(labels: &[&str], values: &[f64]) -> String {
let chart = BarChart::horizontal(labels, values);
chart.render()
}
pub fn line_plot(data: &[f64]) -> String {
let plot = LinePlot::new(data);
plot.render()
}
pub fn sparkline(data: &[f64]) -> String {
let spark = Sparkline::new(data);
spark.render()
}
pub fn scatter(x: &[f64], y: &[f64]) -> String {
let plot = ScatterPlot::new(x, y);
plot.render()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_chart_config_default() {
let config = ChartConfig::default();
assert_eq!(config.width, 60);
assert_eq!(config.height, 20);
assert!(config.show_labels);
}
#[test]
fn test_quick_histogram() {
let data = vec![1.0, 2.0, 2.0, 3.0, 3.0, 3.0, 4.0, 4.0, 5.0];
let result = quick::histogram(&data, 5);
assert!(!result.is_empty());
assert!(result.contains("█") || result.contains("#"));
}
#[test]
fn test_quick_sparkline() {
let data = vec![1.0, 2.0, 3.0, 2.0, 1.0];
let result = quick::sparkline(&data);
assert!(!result.is_empty());
}
}