1use std::fmt::Display;
2
3use litequad::prelude::{clear_background, next_frame, WHITE, draw_line, GRAY, screen_width, screen_height, BLACK, draw_rectangle, draw_text, DARKGRAY, draw_text_rot, is_key_pressed, KeyCode};
4use crate::{Bar, get_font_size_y, min, divs, count_inv_tens, negative};
5use super::{COORD_THICKNESS, YLABEL_SIZE, TITLE_SIZE, DISTANCE_X_AXIS};
6const DISTANCE: f32 = 80.;
7
8pub async fn run(bar: Bar, _min_y: f64, max_y: f64, steps_y: f64) {
9 let min_y = min(&bar.ys);
10
11 let y_font_size = get_font_size_y(max_y);
12 let y_half_font = y_font_size / 2.;
13
14 let step_y = (max_y) / steps_y;
15
16 let ys = divs(&bar.ys, step_y);
17
18 if min_y >= 0. {
19 return positive_only(bar, step_y, y_half_font, y_font_size, max_y, ys).await;
20 }
21 if negative(&ys) {
22 return negative_only(bar, step_y, y_half_font, y_font_size, max_y, ys).await;
23 }
24 positive_negative(bar, step_y, y_half_font, y_font_size, max_y, ys).await
25}
26
27pub async fn draw_line_with_text<T: Display>(y: f32, val: T, y_half_font: f32, y_font_size: f32) {
28 let text = format!("{}", val);
29 let move_away = text.len();
30
31 draw_text(
32 &text,
33 DISTANCE - 5. - (y_half_font * move_away as f32),
34 y + (y_half_font / 2.),
35 y_font_size,
36 BLACK,
37 );
38 draw_line(DISTANCE - 4., y, DISTANCE + 4., y, 3., DARKGRAY);
39}
40
41pub async fn draw_bars(x_level: f32, ys: &[f64], bar: &Bar) {
42 let mut line_x = DISTANCE;
43 let mut bar_x = DISTANCE + 20.;
44 for (bar_entity, y) in bar.bars.iter().zip(ys) {
45 let y = *y as f32;
46 draw_rectangle(bar_x, x_level-bar.desc.spacing_y * y, bar_entity.width, bar.desc.spacing_y * y, bar_entity.color);
47
48 line_x += bar_entity.width / 2. + 20.;
49 draw_line(line_x, x_level-6., line_x, x_level+6., COORD_THICKNESS, BLACK);
50
51 let text_pos = line_x - bar_entity.label.len() as f32 * (10. / 2.) + COORD_THICKNESS;
52
53 draw_text(&bar_entity.label, text_pos, x_level + 20. / 2. + 8., 20., BLACK);
54 line_x += bar_entity.width / 2.;
55 bar_x += bar_entity.width + 20.;
56 }
57}
58
59pub async fn negative_only(bar: Bar, step_y: f64, y_half_font: f32, y_font_size: f32, max_y: f64, ys: Vec<f64>) {
60 loop {
61 clear_background(WHITE);
62
63 for (idx, char) in bar.axis_desc.y_label.chars().into_iter().enumerate() {
64 draw_text_rot(&char.to_string(), 7., screen_height() / 2. - (YLABEL_SIZE / 2. * idx as f32) , YLABEL_SIZE, BLACK, -std::f32::consts::PI / 2.,);
65 }
66
67 draw_text(&bar.axis_desc.title, screen_width() / 2., DISTANCE_X_AXIS / 3. + 7., TITLE_SIZE, BLACK);
68 draw_text(&bar.axis_desc.x_label, screen_width() / 2., screen_height() - DISTANCE_X_AXIS / 3., YLABEL_SIZE, BLACK);
69
70 draw_line(0., DISTANCE_X_AXIS, screen_width(), DISTANCE_X_AXIS, COORD_THICKNESS, GRAY);
72
73 draw_line(DISTANCE, 0., DISTANCE, screen_height(), COORD_THICKNESS, GRAY);
75
76 if step_y > 1. {
77 for (idx, val) in (step_y as i128..=max_y as i128)
78 .step_by(step_y as usize)
79 .enumerate()
80 {
81 let y = DISTANCE_X_AXIS + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
82 draw_line_with_text(y, -val, y_half_font, y_font_size).await;
83 }
84 } else {
85 let tens_step = count_inv_tens(step_y);
86
87 let max_y = max_y * tens_step as f64;
88 let step_y = step_y * tens_step as f64;
89
90 for (idx, val) in (step_y as i128..=max_y as i128)
91 .step_by(step_y as usize)
92 .enumerate()
93 {
94 let y = (screen_height() / 2.) + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
95 draw_line_with_text(y, -val as f64 / tens_step as f64, y_half_font, y_font_size).await;
96 }
97 }
98
99 if is_key_pressed(KeyCode::Escape) {
100 break;
101 }
102 draw_bars(DISTANCE_X_AXIS, &ys, &bar).await;
103 next_frame().await;
104 std::thread::sleep(std::time::Duration::from_millis(16));
105 }
106}
107
108pub async fn positive_negative(bar: Bar, step_y: f64, y_half_font: f32, y_font_size: f32, max_y: f64, ys: Vec<f64>) {
109 loop {
110 clear_background(WHITE);
111
112 for (idx, char) in bar.axis_desc.y_label.chars().into_iter().enumerate() {
113 draw_text_rot(&char.to_string(), 7., screen_height() / 2. - (YLABEL_SIZE / 2. * idx as f32) , YLABEL_SIZE, BLACK, -std::f32::consts::PI / 2.,);
114 }
115
116 draw_text(&bar.axis_desc.title, screen_width() / 2., DISTANCE_X_AXIS / 3. + 7., TITLE_SIZE, BLACK);
117 draw_text(&bar.axis_desc.x_label, screen_width() / 2., screen_height() - DISTANCE_X_AXIS / 3., YLABEL_SIZE, BLACK);
118
119 draw_line(0., screen_height() / 2., screen_width(), screen_height() / 2., COORD_THICKNESS, GRAY);
121
122 draw_line(DISTANCE, 0., DISTANCE, screen_height(), COORD_THICKNESS, GRAY);
124
125 if is_key_pressed(KeyCode::Escape) {
126 break;
127 }
128
129 if step_y > 1. {
130 for (idx, val) in (step_y as i128..=max_y as i128)
131 .step_by(step_y as usize)
132 .enumerate()
133 {
134 let y = (screen_height() / 2.) - bar.desc.spacing_y * idx as f32 - bar.desc.spacing_y;
135 draw_line_with_text(y, val, y_half_font, y_font_size).await;
136 }
137 } else {
138 let tens_step = count_inv_tens(step_y);
139
140 let max_y = max_y * tens_step as f64;
141 let step_y = step_y * tens_step as f64;
142
143 for (idx, val) in (step_y as i128..=max_y as i128)
144 .step_by(step_y as usize)
145 .enumerate()
146 {
147 let y = (screen_height() / 2.) - bar.desc.spacing_y * idx as f32 - bar.desc.spacing_y;
148 draw_line_with_text(y, val as f64 / tens_step as f64, y_half_font, y_font_size).await;
149 }
150 }
151
152 if step_y > 1. {
153 for (idx, val) in (step_y as i128..=max_y as i128)
154 .step_by(step_y as usize)
155 .enumerate()
156 {
157 let y = (screen_height() / 2.) + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
158 draw_line_with_text(y, -val, y_half_font, y_font_size).await;
159 }
160 } else {
161 let tens_step = count_inv_tens(step_y);
162
163 let max_y = max_y * tens_step as f64;
164 let step_y = step_y * tens_step as f64;
165
166 for (idx, val) in (step_y as i128..=max_y as i128)
167 .step_by(step_y as usize)
168 .enumerate()
169 {
170 let y = (screen_height() / 2.) + bar.desc.spacing_y * idx as f32 + bar.desc.spacing_y;
171 draw_line_with_text(y, -val as f64 / tens_step as f64, y_half_font, y_font_size).await;
172 }
173 }
174 draw_bars(screen_height() / 2., &ys, &bar).await;
175
176 next_frame().await;
177 std::thread::sleep(std::time::Duration::from_millis(16));
178 }
179
180}
181
182pub async fn positive_only(bar: Bar, step_y: f64, y_half_font: f32, y_font_size: f32, max_y: f64, ys: Vec<f64>) {
183 loop {
184 clear_background(WHITE);
185
186 for (idx, char) in bar.axis_desc.y_label.chars().into_iter().enumerate() {
187 draw_text_rot(&char.to_string(), 7., screen_height() / 2. - (YLABEL_SIZE / 2. * idx as f32) , YLABEL_SIZE, BLACK, -std::f32::consts::PI / 2.,);
188 }
189
190 draw_text(&bar.axis_desc.title, screen_width() / 2., DISTANCE_X_AXIS / 3. + 7., TITLE_SIZE, BLACK);
191 draw_text(&bar.axis_desc.x_label, screen_width() / 2., screen_height() - DISTANCE_X_AXIS / 3., YLABEL_SIZE, BLACK);
192
193 if step_y > 1. {
194 for (idx, val) in (step_y as i128..=max_y as i128)
195 .step_by(step_y as usize)
196 .enumerate()
197 {
198 let y = (screen_height() - bar.desc.spacing_y * idx as f32) - DISTANCE_X_AXIS - bar.desc.spacing_y;
199 draw_line_with_text(y, val, y_half_font, y_font_size).await;
200 }
201
202 } else {
203 let tens_step = count_inv_tens(step_y);
204
205 let max_y = max_y * tens_step as f64;
206 let step_y = step_y * tens_step as f64;
207
208 for (idx, val) in (step_y as i128..=max_y as i128)
209 .step_by(step_y as usize)
210 .enumerate()
211 {
212 let y = (screen_height() - bar.desc.spacing_y * idx as f32) - DISTANCE_X_AXIS - bar.desc.spacing_y;
213 draw_line_with_text(y, val as f64 / tens_step as f64, y_half_font, y_font_size).await;
214 }
215 }
216
217 let x_level = screen_height()-DISTANCE_X_AXIS;
218 draw_bars(x_level, &ys, &bar).await;
219
220 draw_line(0., x_level, screen_width(), x_level, COORD_THICKNESS, GRAY);
222
223 draw_line(DISTANCE, 0., DISTANCE, screen_height(), COORD_THICKNESS, GRAY);
225
226 if is_key_pressed(KeyCode::Escape) {
227 break;
228 }
229
230 next_frame().await;
231 std::thread::sleep(std::time::Duration::from_millis(16));
232 }
233}