1use crate::axis_typing::{AxisKindMarker, ValueAxis};
2use crate::common::Size;
3use crate::options::*;
4use crate::templates::ScriptTemplate;
5use serde::Serialize;
6use serde_json::json;
7use uuid::Uuid;
8use crate::common;
9use crate::options::Position::Percent;
10
11impl<X, Y> EChartOptions<X,Y>
13where X: AxisKindMarker<AxisType=ValueAxis>+ Serialize,
14 Y: AxisKindMarker<AxisType=ValueAxis>+ Serialize,
15{
16
17 fn add_linear_regression_dataset(self, data_source_index: usize) -> usize {
18 self.add_regression_dataset(data_source_index, RegressionMethod::Linear, None)
19 }
20
21 fn add_polynomial_regression_dataset(self, data_source_index: usize, order: u8) -> usize {
22 self.add_regression_dataset(data_source_index, RegressionMethod::Polynomial, Some(order))
23 }
24
25 fn add_exponential_regression_dataset(self, data_source_index: usize) -> usize {
26 self.add_regression_dataset(data_source_index, RegressionMethod::Exponential, None)
27 }
28
29 fn add_regression_dataset(mut self, data_source_index: usize, method: RegressionMethod, order: Option<u8>) -> usize {
30 let index = self.dataset.as_mut().unwrap().len();
31 let regression_config = RegressionConfig {
32 method: method.clone(),
33 order,
34 extra: None,
35 };
36 let dataset = DatasetTransform::regression(regression_config);
37 self.dataset.as_mut().unwrap().push(DatasetComponent::tr(dataset, data_source_index));
38 index
39 }
40
41
42 fn add_regression_series<TData: Into<DatasetComponent<X,Y>>>(mut self, series_label: &str, data: TData,
44 method: RegressionMethod, order: Option<u8>) -> Self {
45 if self.dataset.is_none() {
47 self.dataset = Some(Vec::new());
48 }
49
50 let datasets = self.dataset.as_mut().unwrap();
52 let source_index = datasets.len();
53 datasets.push(data.into());
54
55
56 let transform_index = datasets.len();
58 let mut regression_config = RegressionConfig {
59 method: method.clone(),
60 order: None,
61 extra: None,
62 };
63
64 if method == RegressionMethod::Polynomial {
66 regression_config.order = order;
67 }
68
69 datasets.push(
70 DatasetComponent::tr(
71 DatasetTransform::regression(regression_config),
72 source_index
73 )
74 );
75
76 self.series.as_mut().unwrap().push(Series {
78 r#type: Some(SeriesType::Scatter),
79 name: Some(format!("{} (data)", series_label)),
80 smooth: None,
81 area_style: None,
82 data: SeriesDataSource::DatasetIndex(source_index),
83 show_symbol: None,
84 symbol: Some(DataPointSymbol::Circle),
85 symbol_size: Some(8),
86 extra: None,
87 });
88
89 self.series.as_mut().unwrap().push(Series {
91 r#type: Some(SeriesType::Line),
92 name: Some(format!("{} (regression)", series_label)),
93 smooth: Some(true),
94 area_style: None,
95 data: SeriesDataSource::DatasetIndex(transform_index),
96 show_symbol: None,
97 symbol: Some(DataPointSymbol::None),
98 symbol_size: None,
99 extra: None
100 });
101
102 self
103 }
104
105 pub fn add_linear_regression_series<TData:Into<DatasetComponent<X,Y>>>(self, series_label: &str, data: TData) -> Self {
107 self.add_regression_series(series_label, data, RegressionMethod::Linear, None)
108 }
109
110 fn add_polynomial_regression_series<TData:Into<DatasetComponent<X,Y>>>(self, series_label: &str, data: TData, order: u8) -> Self {
112 self.add_regression_series(series_label, data, RegressionMethod::Polynomial, Some(order))
113 }
114
115 fn add_exponential_regression_series<TData:Into<DatasetComponent<X,Y>>>(self, series_label: &str, data: TData) -> Self
117 {
118 self.add_regression_series(series_label, data, RegressionMethod::Exponential, None)
119 }
120
121 fn add_logarithmic_regression_series<TData:Into<DatasetComponent<X,Y>>>(self, series_label: &str, data: TData) -> Self {
123 self.add_regression_series(series_label, data, RegressionMethod::Logarithmic, None)
124 }
125}
126
127
128impl<X, Y> Default for EChartOptions<X,Y>
129where X: AxisKindMarker, Y: AxisKindMarker, EChartOptions<X,Y>:Serialize{
130 fn default() -> Self {
131 Self {
132 title: None,
133 tooltip: Some(Tooltip {
134 show: true,
135 show_delay: None,
136 hide_delay: None,
137 trigger: Some(TooltipTrigger::Item),
138 formatter: None,
139 axis_pointer: Some(AxisPointer {
140 r#type: Some(AxisPointerType::Cross),
141 snap: Some(false),
142 animation: None,
143 axis: None,
144 })
145 }),
146 legend: None, grid: None, extra: None, dataset: None,
147 x_axis: Axis::default(),
148 y_axis: Axis::default(),
149 series: Some(Vec::new()),
150 }
151 }
152}
153
154impl<X, Y> EChartOptions<X,Y>
155where X: AxisKindMarker, Y: AxisKindMarker, EChartOptions<X,Y>:Serialize {
156 pub fn new(x_axis:Axis<X>,y_axis: Axis<Y>) -> Self {
157 Self {
158 title: None,
159 tooltip: Some(Tooltip {
160 show: true,
161 show_delay: None,
162 hide_delay: None,
163 trigger: Some(TooltipTrigger::Item),
164 formatter: None,
165 axis_pointer: Some(AxisPointer {
166 r#type: Some(AxisPointerType::Cross),
167 snap: Some(false),
168 animation: None,
169 axis: None,
170 })
171 }),
172 legend: None, grid: None, extra: None, dataset: None,
173 x_axis,
174 y_axis,
175 series: Some(Vec::new()),
176 }
177 }
178
179
180 pub fn enable_legend(mut self) -> Self{
181 if self.legend.is_none(){
182 self.legend = Some(Legend{
183 data: None,
184 orient: Some(LegendOrient::Vertical),
185 left: None,
186 right: Some(Percent(common::Percent(0.0))),
187 top: Some(Percent(common::Percent(20.0))),
188 bottom: Some(Percent(common::Percent(20.0)))
189 })
190 }else {
191 let mut legend = self.legend.unwrap();
192 legend.right = Some(Percent(common::Percent(0.0)));
193 legend.top = Some(Percent(common::Percent(20.0)));
194 legend.bottom = Some(Percent(common::Percent(20.0)));
195 legend.orient = Some(LegendOrient::Vertical);
196 self.legend = Some(legend);
197 }
198 if self.grid.is_none(){
199 self.grid = Some( Grid{
200 left: None,
201 right: Some(Percent(common::Percent(20.0))),
202 top: None,
203 bottom: None,
204 contain_label: None,
205 background_color: None,
206 border_color: None,
207 border_width: None,
208 show: None,
209 z: None,
210 zlevel: None,
211 extra: None,
212 })
213 }else {
214 let mut grid = self.grid.unwrap();
215 grid.right = Some(Percent(common::Percent(20.0)));
216 self.grid = Some(grid);
217 }
218 self
219 }
220
221 pub fn title_str(mut self, title: String) -> Self {
223 let t = self.title.get_or_insert_default();
224 t.left = Some(Position::Keyword(PositionKeyword::Center));
225 t.text = Some(title);
226 self
227 }
228
229 pub fn subtitle_str(mut self, subtitle: String) -> Self {
230 self.title.get_or_insert_default().sub_text = Some(subtitle);
231 self
232 }
233
234 pub fn title(mut self, title: Title) -> Self {
235 self.title = Some(title);
236 self
237 }
238
239
240 pub fn x_axis_label(mut self, x: String) -> Self {
241 self.x_axis.name = Some(x);
242 self
243 }
244
245 pub fn y_axis_label(mut self, y: String) -> Self {
246 self.y_axis.name = Some(y);
247 self
248 }
249
250 pub fn add_dataset<TData:Into<DatasetComponent<X,Y>>>(mut self, data: TData) -> usize {
252 let index = self.dataset.as_mut().unwrap().len();
253 self.dataset.as_mut().unwrap().push(data.into());
254 index
255 }
256
257 pub fn add_dataset_visualisation(mut self, series_label:String, series_type: SeriesType, dataset_index: usize) -> Self {
260 let datasets = &self.dataset;
261 if let Some(datasets) = datasets {
262 if let Some(dataset) = datasets.get(dataset_index){
263 match dataset {
264 DatasetComponent::Source(_) | DatasetComponent::Transform(_) => {
265 self.series.as_mut().unwrap().push(Series {
266 r#type: Some(series_type),
267 name: Some(series_label),
268 smooth: Some(true),
269 area_style: None,
270 symbol: None,
271 symbol_size: None,
272 data: SeriesDataSource::DatasetIndex(dataset_index),
273 extra: None,
274 show_symbol: None,
275 });
276 }
277 DatasetComponent::LabelledSource(_) => {
278 self.series.as_mut().unwrap().push(Series {
279 r#type: Some(series_type),
280 name: Some(series_label),
281 smooth: Some(true),
282 area_style: None,
283 symbol: None,
284 symbol_size: None,
285 data: SeriesDataSource::DatasetIndex(dataset_index),
286 extra: Some(json!(
287 {"encode": {"tooltip": [2,1], "x": 0, "y": 1 }}
288 )),
289 show_symbol: None,
290 });
291 }
292 }
293
294 }
295 }
296 self
297 }
298
299 pub fn add_series_direct(mut self, series:Series<X,Y>) -> Self {
300 self.series.as_mut().unwrap().push(series);
301 self
302 }
303
304
305
306 pub fn add_series<TData:Into<SeriesDataSource<X,Y>>>(mut self, series_type: SeriesType, series_label:String, data: TData) -> Self {
307 self.series.as_mut().unwrap().push(
308 Series::new(series_label,series_type,data.into())
309 );
310 self
311 }
312
313 pub fn build(self, width: Size, height: Size) -> ScriptTemplate<X,Y>{
314 ScriptTemplate::new(Uuid::new_v4().to_string(), width, height, self)
315 }
316}