sql_cli/chart/
types.rs

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        // Smart Y-axis scaling with padding
64        let y_span = data.y_range.1 - data.y_range.0;
65        let padding = y_span * 0.1; // 10% padding
66        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}