#![allow(clippy::type_complexity)]
use crossterm::cursor::{DisableBlinking, Hide, Show};
use crossterm::{
cursor, execute,
style::{Color, Print, ResetColor, SetBackgroundColor},
};
use rand::{rng, Rng};
use std::cmp::Ordering;
use std::process::Command;
use std::thread;
use std::time::Duration;
use terminal_size::{terminal_size, Height, Width};
pub fn rgb(r: u8, g: u8, b: u8) -> Color {
Color::Rgb { r, g, b }
}
pub fn show_curser() {
let mut stdout = std::io::stdout();
execute!(stdout, Show).unwrap();
}
pub fn real_cell(x: u16, y: u16, color: Color) {
execute!(
std::io::stdout(),
cursor::MoveTo(x, y),
SetBackgroundColor(color),
Print(" "),
DisableBlinking,
ResetColor,
Hide,
)
.unwrap();
}
pub fn cell(x: u16, y: u16, color: Color) {
let doubled_x = x.checked_mul(2).unwrap_or(u16::MAX);
let first_pixel_x = doubled_x.saturating_sub(1);
let second_pixel_x = doubled_x;
real_cell(first_pixel_x, y, color);
real_cell(second_pixel_x, y, color);
}
pub fn fill_row_cell(y: u16, color: Color) {
let size = terminal_size();
if let Some((Width(w), Height(_))) = size {
let width = w;
for x in 0..(width / 2) {
cell(x, y, color);
}
} else {
println!("Unable to get terminal size");
}
}
pub fn fill_colum_real_cell(x: u16, color: Color) {
let size = terminal_size();
if let Some((Width(_), Height(h))) = size {
for y in 0..h {
real_cell(x, y, color);
}
} else {
println!("Unable to get terminal size");
}
}
pub fn fill_colum_cell(x: u16, color: Color) {
let doubled_x = x.checked_mul(2).unwrap_or(u16::MAX);
let first_pixel_x = doubled_x.saturating_sub(1);
let second_pixel_x = doubled_x;
fill_colum_real_cell(first_pixel_x, color);
fill_colum_real_cell(second_pixel_x, color);
}
pub fn fill_screen_cell(color: Color) {
let size = terminal_size();
if let Some((Width(_), Height(h))) = size {
for y in 0..h {
fill_row_cell(y, color);
}
} else {
println!("Unable to get terminal size");
}
}
pub fn screen_test_cell() {
let size = terminal_size();
if let Some((Width(_), Height(h))) = size {
for y in 1..h {
if let Some((Width(w), Height(_))) = size {
for x in 1..(w / 2) {
let mut rng = rng();
let random_r: u8 = rng.random_range(0..=255);
let random_g: u8 = rng.random_range(0..=255);
let random_b: u8 = rng.random_range(0..=255);
cell(x, y, rgb(random_r, random_g, random_b));
}
} else {
println!("Unable to get terminal size");
return;
}
}
} else {
println!("Unable to get terminal size");
}
}
pub fn row_test_cell(y: u16) {
let size = terminal_size();
if let Some((Width(w), Height(_h))) = size {
for x in 0..(w / 2) {
let mut rng = rng();
let random_r: u8 = rng.random_range(0..=255);
let random_g: u8 = rng.random_range(0..=255);
let random_b: u8 = rng.random_range(0..=255);
cell(x, y, rgb(random_r, random_g, random_b));
}
} else {
println!("Unable to get terminal size");
}
}
pub fn center(xy: [i64; 2]) -> [i64; 2] {
let x: i64 = 1; let y: i64 = 1;
let centered_x = x.center_x_cell(&xy);
let centered_y = y.center_y_cell(&xy);
[centered_x, centered_y]
}
pub trait CenterCell {
fn center_x_cell(&self, array: &[i64]) -> i64;
fn center_y_cell(&self, array: &[i64]) -> i64;
}
pub trait FCenterCell {
fn fcenter_x_cell(&self, array: &[f64]) -> f64;
fn fcenter_y_cell(&self, array: &[f64]) -> f64;
}
impl CenterCell for i64 {
fn center_x_cell(&self, array: &[i64]) -> i64 {
let size = terminal_size();
if let Some((Width(w), _)) = size {
let range = match (array.iter().max(), array.iter().min()) {
(Some(max_val), Some(min_val)) => max_val - min_val,
_ => 0,
};
(*self + (w / 4) as i64) - (range / 2) } else {
println!("Unable to get terminal width");
*self
}
}
fn center_y_cell(&self, array: &[i64]) -> i64 {
let size = terminal_size();
if let Some((_, Height(h))) = size {
let range = match (array.iter().max(), array.iter().min()) {
(Some(max_val), Some(min_val)) => max_val - min_val,
_ => 0,
};
(*self + (h / 2) as i64) - (range / 2) } else {
println!("Unable to get terminal width");
*self
}
}
}
impl FCenterCell for f64 {
fn fcenter_x_cell(&self, array: &[f64]) -> f64 {
let size = terminal_size();
if let Some((Width(w), _)) = size {
let range = match (
array
.iter()
.max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)),
array
.iter()
.min_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)),
) {
(Some(max_val), Some(min_val)) => max_val - min_val,
_ => 0.0,
};
(*self + (w / 4) as f64) - (range / 2.0) } else {
println!("Unable to get terminal width");
*self
}
}
fn fcenter_y_cell(&self, array: &[f64]) -> f64 {
let size = terminal_size();
if let Some((_, Height(h))) = size {
let range = match (
array
.iter()
.max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)),
array
.iter()
.min_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal)),
) {
(Some(max_val), Some(min_val)) => max_val - min_val,
_ => 0.0,
};
(*self + (h / 2) as f64) - (range / 2.0) } else {
println!("Unable to get terminal width");
*self
}
}
}
pub fn clear() {
let _ = Command::new("clear").status();
}
pub fn d2_map_cell(cords: &[(f64, f64)]) {
let count = cords.len();
let mut first_numbers = Vec::new();
let mut second_numbers = Vec::new();
for &(first, second) in cords.iter() {
first_numbers.push(first);
second_numbers.push(second);
}
for i in 0..count {
let x = (first_numbers[i] + 1.0).floor() as u16;
let y = (second_numbers[i] + 1.0).floor() as u16;
cell(x, y, rgb(100, 100, 255));
}
}
pub fn d2_path(points: &[((f64, f64), (f64, f64))], color: Color) {
for points in points {
let a_x = points.0 .0;
let a_y = points.0 .1;
let b_x = points.1 .0;
let b_y = points.1 .1;
let distance = ((b_x - a_x).powi(2) + (b_y - a_y).powi(2)).sqrt();
let min_steps = 1000;
let max_steps = 100000;
let min_distance = 10.0;
let max_distance = 100.0;
let steps = ((distance - min_distance) / (max_distance - min_distance)
* ((max_steps - min_steps) as f64)
+ (min_steps as f64)) as usize;
let step_size = distance / steps as f64;
let steps_x = (b_x - a_x) / distance * step_size;
let steps_y = (b_y - a_y) / distance * step_size;
cell(a_x as u16, a_y as u16, color);
let mut current_point = (a_x, a_y);
for _ in 0..steps {
current_point.0 += steps_x;
current_point.1 += steps_y;
cell(current_point.0 as u16, current_point.1 as u16, color);
}
}
}
pub fn square(bl: [i32; 2], rt: [i32; 2], line_color: Color, fill_color: Color) {
let _a = bl;
let _b = rt;
let _c = line_color;
let _d = fill_color;
}
pub fn thread_sleep_mil(mills: u64) {
thread::sleep(Duration::from_millis(mills));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn real_cell_test() {
clear();
real_cell(1, 1, Color::DarkBlue);
real_cell(0, 1, Color::Red);
thread_sleep_mil(100);
clear();
fill_colum_cell(1, Color::DarkBlue);
fill_colum_cell(2, Color::Red);
thread_sleep_mil(500);
clear();
show_curser();
}
#[test]
fn cell_test() {
clear();
cell(1, 1, Color::DarkBlue);
cell(2, 1, Color::Red);
cell(2, 2, Color::DarkBlue);
cell(3, 2, Color::Red);
thread_sleep_mil(1000);
clear();
show_curser();
}
#[test]
fn fill_row_cell_test() {
clear();
fill_row_cell(1, Color::DarkBlue);
fill_row_cell(2, Color::Red);
thread_sleep_mil(500);
clear();
show_curser();
}
#[test]
fn fill_colum_real_cell_test() {
clear();
fill_colum_real_cell(1, Color::DarkBlue);
fill_colum_real_cell(2, Color::Red);
thread_sleep_mil(500);
clear();
show_curser();
}
#[test]
fn fill_colum_cell_test() {
clear();
fill_colum_cell(1, Color::DarkBlue);
fill_colum_cell(2, Color::Red);
thread_sleep_mil(500);
clear();
show_curser();
}
#[test]
fn fill_screen_test() {
clear();
fill_screen_cell(rgb(255, 255, 255));
thread_sleep_mil(500);
clear();
show_curser();
}
#[test]
fn center_test() {
println!("{:?}", center([1, 1]));
}
#[test]
fn center_cell_test() {
clear();
let centered = center([1, 1]);
println!("{:?}", centered);
cell(centered[0] as u16, centered[1] as u16, rgb(255, 255, 255));
thread_sleep_mil(5000);
clear();
show_curser();
}
}