xdl_charts/
lib.rs

1//! XDL Charts - ECharts-based visualization generation
2//!
3//! This crate provides chart generation using Apache ECharts,
4//! supporting 2D plots, 3D visualizations, and dashboards.
5
6use anyhow::Result;
7use serde::{Deserialize, Serialize};
8
9pub mod echarts;
10pub mod templates;
11
12/// Chart type enumeration
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
14#[serde(rename_all = "lowercase")]
15pub enum ChartType {
16    /// 2D line chart
17    Line,
18    /// 2D scatter plot
19    Scatter,
20    /// Bar chart
21    Bar,
22    /// Area chart
23    Area,
24    /// Heatmap
25    Heatmap,
26    /// 3D scatter plot
27    Scatter3D,
28    /// 3D surface plot
29    Surface3D,
30    /// 3D bar chart
31    Bar3D,
32}
33
34/// Chart configuration
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct ChartConfig {
37    /// Chart type
38    pub chart_type: ChartType,
39    /// Chart title
40    pub title: String,
41    /// X-axis label
42    pub x_label: Option<String>,
43    /// Y-axis label
44    pub y_label: Option<String>,
45    /// Z-axis label (for 3D charts)
46    pub z_label: Option<String>,
47    /// Chart width in pixels
48    pub width: u32,
49    /// Chart height in pixels
50    pub height: u32,
51    /// Use WebGL renderer (for better performance)
52    pub use_webgl: bool,
53    /// Color scheme/theme
54    pub theme: String,
55}
56
57impl Default for ChartConfig {
58    fn default() -> Self {
59        Self {
60            chart_type: ChartType::Line,
61            title: "XDL Chart".to_string(),
62            x_label: None,
63            y_label: None,
64            z_label: None,
65            width: 800,
66            height: 600,
67            use_webgl: false,
68            theme: "default".to_string(),
69        }
70    }
71}
72
73/// Data series for 2D charts
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct Series2D {
76    /// Series name
77    pub name: String,
78    /// X data points
79    pub x_data: Vec<f64>,
80    /// Y data points
81    pub y_data: Vec<f64>,
82}
83
84/// Data series for 3D charts
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct Series3D {
87    /// Series name
88    pub name: String,
89    /// Data points as [x, y, z] triplets
90    pub data: Vec<[f64; 3]>,
91}
92
93/// Generate HTML for a 2D chart
94pub fn generate_2d_chart(config: &ChartConfig, series: &[Series2D]) -> Result<String> {
95    let echarts_option = echarts::build_2d_option(config, series)?;
96    let html = templates::create_echarts_html(config, &echarts_option)?;
97    Ok(html)
98}
99
100/// Generate HTML for a 3D chart
101pub fn generate_3d_chart(config: &ChartConfig, series: &[Series3D]) -> Result<String> {
102    let echarts_option = echarts::build_3d_option(config, series)?;
103    let html = templates::create_echarts_html(config, &echarts_option)?;
104    Ok(html)
105}
106
107/// Generate HTML for a surface plot from a 2D matrix
108pub fn generate_surface_plot(
109    config: &ChartConfig,
110    z_data: &[Vec<f64>],
111    x_range: (f64, f64),
112    y_range: (f64, f64),
113) -> Result<String> {
114    let echarts_option = echarts::build_surface_option(config, z_data, x_range, y_range)?;
115    let html = templates::create_echarts_html(config, &echarts_option)?;
116    Ok(html)
117}
118
119/// Generate HTML for a heatmap/contour plot
120pub fn generate_heatmap(config: &ChartConfig, data: &[[f64; 3]]) -> Result<String> {
121    let echarts_option = echarts::build_heatmap_option(config, data)?;
122    let html = templates::create_echarts_html(config, &echarts_option)?;
123    Ok(html)
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129
130    #[test]
131    fn test_chart_config_default() {
132        let config = ChartConfig::default();
133        assert_eq!(config.chart_type, ChartType::Line);
134        assert_eq!(config.width, 800);
135        assert_eq!(config.height, 600);
136    }
137
138    #[test]
139    fn test_series_2d_creation() {
140        let series = Series2D {
141            name: "Test".to_string(),
142            x_data: vec![1.0, 2.0, 3.0],
143            y_data: vec![4.0, 5.0, 6.0],
144        };
145        assert_eq!(series.x_data.len(), 3);
146        assert_eq!(series.y_data.len(), 3);
147    }
148}