1use esoc_chart::v2::{
14 area, bar, boxplot, grouped_bar, histogram, pie_labeled, scatter, stacked_bar, Chart, Layer,
15 MarkType, NewTheme,
16};
17
18fn main() -> esoc_chart::error::Result<()> {
19 let mut seed: u64 = 42;
21 let mut rng = || -> f64 {
22 seed = seed.wrapping_mul(6_364_136_223_846_793_005).wrapping_add(1);
23 (seed >> 11) as f64 / (1u64 << 53) as f64
24 };
25 let mut normal = || -> f64 {
26 let u1 = rng().max(1e-15);
27 let u2 = rng();
28 (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos()
29 };
30
31 let n = 500;
33 let x: Vec<f64> = (0..n).map(|_| normal() * 3.0 + 5.0).collect();
34 let y: Vec<f64> = x.iter().map(|&xi| xi * 0.8 + normal() * 2.0).collect();
35
36 let svg = scatter(&x, &y)
37 .title("Dense Scatter — Opacity & Point Sizing")
38 .x_label("feature A")
39 .y_label("feature B")
40 .size(700.0, 500.0)
41 .to_svg()?;
42 std::fs::write("dense_scatter.svg", &svg)?;
43 println!("Saved dense_scatter.svg");
44
45 let hist_data: Vec<f64> = (0..400).map(|_| normal() * 1.5 + 10.0).collect();
47
48 let svg = histogram(&hist_data)
49 .bins(30)
50 .title("Normal Distribution — Tight Bins")
51 .x_label("value")
52 .y_label("count")
53 .size(700.0, 450.0)
54 .to_svg()?;
55 std::fs::write("hist_tight_bins.svg", &svg)?;
56 println!("Saved hist_tight_bins.svg");
57
58 let langs = [
60 "Rust",
61 "Python",
62 "TypeScript",
63 "Go",
64 "Java",
65 "C++",
66 "Ruby",
67 "Swift",
68 ];
69 let users: Vec<f64> = vec![
70 85_000.0,
71 1_200_000.0,
72 950_000.0,
73 420_000.0,
74 780_000.0,
75 650_000.0,
76 180_000.0,
77 310_000.0,
78 ];
79
80 let svg = bar(&langs, &users)
81 .title("Language Users (thousands)")
82 .size(700.0, 450.0)
83 .to_svg()?;
84 std::fs::write("bar_large_values.svg", &svg)?;
85 println!("Saved bar_large_values.svg");
86
87 let x_area: Vec<f64> = (0..60).map(|i| f64::from(i) * 0.5).collect();
89 let y_area: Vec<f64> = x_area
90 .iter()
91 .map(|&xi| (xi * 0.3).sin() * 20.0 + 25.0 + (xi * 0.1).cos() * 5.0)
92 .collect();
93
94 let svg = area(&x_area, &y_area)
95 .title("Server Load Over Time")
96 .x_label("minutes")
97 .y_label("requests / sec")
98 .size(700.0, 400.0)
99 .to_svg()?;
100 std::fs::write("area_chart.svg", &svg)?;
101 println!("Saved area_chart.svg");
102
103 let pie_vals = [35.0, 25.0, 20.0, 12.0, 8.0];
105 let pie_labels = ["Chrome", "Safari", "Firefox", "Edge", "Other"];
106
107 let svg = pie_labeled(&pie_labels, &pie_vals)
108 .title("Browser Market Share")
109 .size(500.0, 500.0)
110 .to_svg()?;
111 std::fs::write("pie_chart.svg", &svg)?;
112 println!("Saved pie_chart.svg");
113
114 let svg = pie_labeled(&pie_labels, &pie_vals)
116 .donut(0.5)
117 .title("Browser Share (Donut)")
118 .size(500.0, 500.0)
119 .to_svg()?;
120 std::fs::write("donut_chart.svg", &svg)?;
121 println!("Saved donut_chart.svg");
122
123 let stack_cats = ["Q1", "Q2", "Q3", "Q4"];
125 let stack_groups = [
126 "Product A",
127 "Product A",
128 "Product A",
129 "Product A",
130 "Product B",
131 "Product B",
132 "Product B",
133 "Product B",
134 "Product C",
135 "Product C",
136 "Product C",
137 "Product C",
138 ];
139 let stack_vals = [
140 30.0, 45.0, 55.0, 40.0, 20.0, 25.0, 30.0, 35.0, 15.0, 10.0, 20.0, 25.0, ];
144 let cats_expanded: Vec<&str> = stack_cats.iter().copied().cycle().take(12).collect();
146 let svg = stacked_bar(&cats_expanded, &stack_groups, &stack_vals)
148 .title("Quarterly Revenue by Product")
149 .x_label("Quarter")
150 .y_label("Revenue ($M)")
151 .size(700.0, 450.0)
152 .to_svg()?;
153 std::fs::write("stacked_bar.svg", &svg)?;
154 println!("Saved stacked_bar.svg");
155
156 let svg = grouped_bar(&cats_expanded, &stack_groups, &stack_vals)
158 .title("Quarterly Revenue — Grouped")
159 .x_label("Quarter")
160 .y_label("Revenue ($M)")
161 .size(700.0, 450.0)
162 .to_svg()?;
163 std::fs::write("grouped_bar.svg", &svg)?;
164 println!("Saved grouped_bar.svg");
165
166 let mut box_cats = Vec::new();
168 let mut box_vals = Vec::new();
169 for label in ["Setosa", "Versicolor", "Virginica"] {
170 let center = match label {
171 "Setosa" => 1.5,
172 "Versicolor" => 4.3,
173 _ => 5.8,
174 };
175 for _ in 0..60 {
176 box_cats.push(label);
177 box_vals.push(center + normal() * 0.5);
178 }
179 }
180
181 let svg = boxplot(&box_cats, &box_vals)
182 .title("Petal Length by Species")
183 .x_label("Species")
184 .y_label("Petal Length (cm)")
185 .size(600.0, 450.0)
186 .to_svg()?;
187 std::fs::write("boxplot_v2.svg", &svg)?;
188 println!("Saved boxplot_v2.svg");
189
190 let x_sm: Vec<f64> = (0..30).map(f64::from).collect();
192 let y_sm: Vec<f64> = x_sm.iter().map(|&xi| xi.sqrt() * 3.0 + normal()).collect();
193
194 let chart = Chart::new()
195 .layer(Layer::new(MarkType::Point).with_x(x_sm).with_y(y_sm))
196 .title("Growth Trend Analysis")
197 .subtitle("Subtitle uses muted color and smaller font")
198 .caption("Source: synthetic data")
199 .x_label("Day")
200 .y_label("Value")
201 .size(700.0, 500.0);
202
203 let svg = chart.to_svg()?;
204 std::fs::write("font_hierarchy.svg", &svg)?;
205 println!("Saved font_hierarchy.svg");
206
207 let mut cx = Vec::new();
209 let mut cy = Vec::new();
210 let mut cc = Vec::new();
211 for (label, cx_off, cy_off) in [
212 ("Group A", 0.0, 0.0),
213 ("Group B", 5.0, 3.0),
214 ("Group C", 2.5, 6.0),
215 ] {
216 for _ in 0..150 {
217 cx.push(cx_off + normal() * 1.2);
218 cy.push(cy_off + normal() * 1.2);
219 cc.push(label);
220 }
221 }
222
223 let svg = scatter(&cx, &cy)
224 .color_by(&cc)
225 .title("Dense Categorical Scatter")
226 .x_label("x")
227 .y_label("y")
228 .size(700.0, 500.0)
229 .to_svg()?;
230 std::fs::write("dense_categorical.svg", &svg)?;
231 println!("Saved dense_categorical.svg");
232
233 let epochs: Vec<f64> = (1..=40).map(f64::from).collect();
235 let loss1: Vec<f64> = epochs
236 .iter()
237 .map(|&e| 2.5 * (-e / 10.0).exp() + 0.1 + normal() * 0.02)
238 .collect();
239 let loss2: Vec<f64> = epochs
240 .iter()
241 .map(|&e| 2.0 * (-e / 15.0).exp() + 0.15 + normal() * 0.03)
242 .collect();
243
244 let chart = Chart::new()
245 .layer(
246 Layer::new(MarkType::Line)
247 .with_x(epochs.clone())
248 .with_y(loss1),
249 )
250 .layer(Layer::new(MarkType::Line).with_x(epochs).with_y(loss2))
251 .title("Model Comparison — Dark Theme")
252 .subtitle("Lower is better")
253 .x_label("Epoch")
254 .y_label("Loss")
255 .theme(NewTheme::dark())
256 .size(700.0, 450.0);
257
258 let svg = chart.to_svg()?;
259 std::fs::write("dark_theme.svg", &svg)?;
260 println!("Saved dark_theme.svg");
261
262 println!("\nAll P1 showcase charts generated!");
263 Ok(())
264}