use litequad::prelude::*;
use crate::{LineType, Marker, Plot, max_matrix, max_display, get_font_size_y, get_steps, get_font_size_x, divs, sub, count_inv_tens};
use super::{TITLE_SIZE, COORD_THICKNESS, YLABEL_SIZE};
pub async fn run(plot: Plot, min_y: f64, other_scaling: bool) {
let spacing_x = plot.desc.spacing_x;
let spacing_y = plot.desc.spacing_y;
let mut max_x = max_matrix(&plot.xs);
max_x = max_display(max_x, other_scaling);
let x_font_size = get_font_size_x(max_x);
let steps = get_steps(max_x, plot.desc.min_steps_x.into());
let step_x = max_x / steps;
let start_x = step_x;
let mut max_y = max_matrix(&plot.ys);
max_y = max_display(max_y, other_scaling);
let y_font_size = get_font_size_y(max_y);
let steps_y = get_steps(max_y, plot.desc.min_steps_y.into());
let step_y = (max_y) / steps_y;
let start_y = if min_y > 0. { min_y } else { step_y };
loop {
clear_background(WHITE);
let half_height = screen_height() / 2.;
let half_width = screen_width() / 2.;
if !plot.axis_desc.title.is_empty() {
let len = plot.axis_desc.title.len() as f32 * (TITLE_SIZE / 4. - COORD_THICKNESS / 2.);
draw_text(
&plot.axis_desc.title,
half_width - len,
half_height - spacing_y * steps_y as f32 - 50.,
TITLE_SIZE,
BLACK,
);
}
if !plot.axis_desc.y_label.is_empty() {
let len =
plot.axis_desc.y_label.len() as f32 * (YLABEL_SIZE / 4. - COORD_THICKNESS / 2.);
draw_text(
&plot.axis_desc.y_label,
half_width - len,
half_height - spacing_y * steps_y as f32 - 20.,
YLABEL_SIZE,
BLACK,
);
}
if !plot.axis_desc.x_label.is_empty() {
for (idx, char) in plot.axis_desc.x_label.chars().into_iter().enumerate() {
let adding = if char == 'i' { 3. } else { 0. };
draw_text_rot(
&format!("{char}"),
half_width + spacing_x * steps as f32 + 20. + adding,
half_height
- plot.axis_desc.x_label.len() as f32
* (YLABEL_SIZE / 4. - COORD_THICKNESS / 2.)
+ idx as f32 * YLABEL_SIZE / 2.,
YLABEL_SIZE,
BLACK,
std::f32::consts::PI / 2.,
);
}
}
let (subtract_x, subtract_y) = if !plot.axis_desc.y_label.is_empty()
|| !plot.axis_desc.x_label.is_empty()
|| !plot.axis_desc.title.is_empty()
{
(spacing_x * steps as f32, (spacing_y * steps_y as f32))
} else {
(half_width, half_height)
};
draw_line(
half_width,
half_height - subtract_y,
half_width,
screen_height(),
COORD_THICKNESS,
GRAY,
);
draw_line(
0.0,
half_height,
half_width + subtract_x,
half_height,
COORD_THICKNESS,
GRAY,
);
for (idx, xs) in plot.xs.iter().enumerate() {
let xs = divs(xs, step_x);
let move_up = if min_y > 0. {step_y} else {0.};
let ys = sub(&plot.ys[idx], min_y - move_up);
let ys = divs(&ys, step_y);
let line_desc = &plot.line_desc[idx];
let mut coords = Vec::new();
for i in 0..xs.len() {
let x = xs[i] as f32;
let y = ys[i] as f32;
let x = half_width + spacing_x * x;
let y = half_height - spacing_y * y;
coords.push((x, y));
match line_desc.marker {
Marker::Circle(r) => draw_circle(x, y, r, line_desc.color),
Marker::None => {}
}
if coords.len() >= 2 {
match line_desc.line_type {
LineType::Solid => draw_line(
coords[0].0,
coords[0].1,
coords[1].0,
coords[1].1,
3.,
line_desc.color,
),
LineType::None => {}
}
coords.remove(0);
}
}
}
let y_half_font = y_font_size / 2.;
let x_half_font = x_font_size / 2.;
if step_y > 1. {
for (idx, val) in (start_y as i128..=max_y as i128)
.step_by(step_y as usize)
.enumerate()
{
let y = (half_height - spacing_y * idx as f32) - spacing_y;
axis_desc_y(val , y, half_width, y_half_font, y_font_size);
}
} else {
let tens_start = count_inv_tens(start_y);
let tens_step = count_inv_tens(step_y);
let start_y = start_y * tens_start as f64;
let max_y = max_y * tens_start as f64;
let step_y = step_y * tens_step as f64;
for (idx, val) in (start_y as i128..=max_y as i128)
.step_by(step_y as usize)
.enumerate()
{
let y = (half_height - spacing_y * idx as f32) - spacing_y;
axis_desc_y(val as f64 / tens_start as f64, y, half_width, y_half_font, y_font_size);
}
}
if step_y > 1. {
for (idx, val) in (start_y as i128..=max_y as i128)
.step_by(step_y as usize)
.enumerate()
{
let y = (half_height - spacing_y * -(idx as f32)) + spacing_y;
axis_desc_y(-val , y, half_width, y_half_font, y_font_size);
}
} else {
let tens_start = count_inv_tens(start_y);
let tens_step = count_inv_tens(step_y);
let start_y = start_y * tens_start as f64;
let max_y = max_y * tens_start as f64;
let step_y = step_y * tens_step as f64;
for (idx, val) in (start_y as i128..=max_y as i128)
.step_by(step_y as usize)
.enumerate()
{
let y = (half_height - spacing_y * -(idx as f32)) + spacing_y;
axis_desc_y(-val as f64 / tens_start as f64 , y, half_width, y_half_font, y_font_size);
}
}
if step_x > 1. {
for (idx, val) in (start_x as i128..=max_x as i128)
.step_by(step_x as usize)
.enumerate()
{
let x = (half_width + spacing_x * idx as f32) + spacing_x;
axis_desc_x(val, x, x_half_font, x_font_size, half_height);
}
} else {
let tens_start = count_inv_tens(start_x);
let tens_step = count_inv_tens(step_x);
let start_x = start_x * tens_start as f64;
let max_x = max_x * tens_start as f64;
let step_x = step_x * tens_step as f64;
for (idx, val) in (start_x as i128..=max_x as i128)
.step_by(step_x as usize)
.enumerate()
{
let x = (half_width + spacing_x * idx as f32) + spacing_x;
axis_desc_x(val as f64 / tens_start as f64, x, x_half_font, x_font_size, half_height);
}
}
if step_x > 1. {
for (idx, val) in (start_x as i128..=max_x as i128)
.step_by(step_x as usize)
.enumerate()
{
let x = (half_width + spacing_x * -(idx as f32)) - spacing_x;
axis_desc_x(-val, x, x_half_font, x_font_size, half_height);
}
} else {
let tens_start = count_inv_tens(start_x);
let tens_step = count_inv_tens(step_x);
let start_x = start_x * tens_start as f64;
let max_x = max_x * tens_start as f64;
let step_x = step_x * tens_step as f64;
for (idx, val) in (start_x as i128..=max_x as i128)
.step_by(step_x as usize)
.enumerate()
{
let x = (half_width + spacing_x * -(idx as f32)) - spacing_x;
axis_desc_x(-val as f64 / tens_start as f64, x, x_half_font, x_font_size, half_height);
}
}
if is_key_pressed(KeyCode::Escape) {
break;
}
next_frame().await;
std::thread::sleep(std::time::Duration::from_millis(16));
}
}
fn axis_desc_y<T: std::fmt::Display>(val: T, y: f32, half_width: f32, y_half_font: f32, y_font_size: f32) {
let text = format!("{}", val);
let move_away = text.len();
draw_text(
&text,
half_width - 5. - (y_half_font * move_away as f32),
y + (y_half_font / 2.),
y_font_size,
BLACK,
);
draw_line(half_width - 4., y, half_width + 4., y, 3., DARKGRAY);
}
fn axis_desc_x<T: std::fmt::Display>(val: T, x: f32, x_half_font: f32, x_font_size: f32, half_height: f32) {
let text = format!("{}", val);
draw_text(
&text,
x - text.len() as f32 * (x_half_font / 2.),
half_height + x_half_font + 7.,
x_font_size,
BLACK,
);
draw_line(x, half_height + 4., x, half_height - 4., 3., DARKGRAY);
}