1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct ChartConfig {
6 pub title: String,
7 pub x_axis: String,
8 pub y_axis: String,
9 pub chart_type: ChartType,
10 pub query: String,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, Default)]
14pub enum ChartType {
15 #[default]
16 Line,
17 Scatter,
18 Bar,
19 Candlestick,
20}
21
22#[derive(Debug, Clone)]
23pub struct DataSeries {
24 pub name: String,
25 pub points: Vec<DataPoint>,
26 pub x_range: (f64, f64),
27 pub y_range: (f64, f64),
28}
29
30#[derive(Debug, Clone)]
31pub struct DataPoint {
32 pub x: f64,
33 pub y: f64,
34 pub timestamp: Option<DateTime<Utc>>,
35 pub label: Option<String>,
36}
37
38#[derive(Debug, Clone)]
39pub struct ChartViewport {
40 pub x_min: f64,
41 pub x_max: f64,
42 pub y_min: f64,
43 pub y_max: f64,
44 pub zoom_level: f64,
45}
46
47impl ChartViewport {
48 #[must_use]
49 pub fn new(x_range: (f64, f64), y_range: (f64, f64)) -> Self {
50 Self {
51 x_min: x_range.0,
52 x_max: x_range.1,
53 y_min: y_range.0,
54 y_max: y_range.1,
55 zoom_level: 1.0,
56 }
57 }
58
59 pub fn auto_scale(&mut self, data: &DataSeries) {
60 self.x_min = data.x_range.0;
61 self.x_max = data.x_range.1;
62
63 let y_span = data.y_range.1 - data.y_range.0;
65 let padding = y_span * 0.1; self.y_min = data.y_range.0 - padding;
67 self.y_max = data.y_range.1 + padding;
68 }
69
70 pub fn pan(&mut self, dx: f64, dy: f64) {
71 let x_span = self.x_max - self.x_min;
72 let y_span = self.y_max - self.y_min;
73
74 self.x_min += dx * x_span * 0.1;
75 self.x_max += dx * x_span * 0.1;
76 self.y_min += dy * y_span * 0.1;
77 self.y_max += dy * y_span * 0.1;
78 }
79
80 pub fn zoom(&mut self, factor: f64, center_x: f64, center_y: f64) {
81 let x_span = self.x_max - self.x_min;
82 let y_span = self.y_max - self.y_min;
83
84 let new_x_span = x_span / factor;
85 let new_y_span = y_span / factor;
86
87 self.x_min = center_x - new_x_span / 2.0;
88 self.x_max = center_x + new_x_span / 2.0;
89 self.y_min = center_y - new_y_span / 2.0;
90 self.y_max = center_y + new_y_span / 2.0;
91
92 self.zoom_level *= factor;
93 }
94}