code and user experience improvements

This commit is contained in:
Simon Gardling
2022-02-17 10:49:33 -05:00
parent 0f081efa6a
commit 95b57f711c
5 changed files with 57 additions and 48 deletions

View File

@@ -30,7 +30,7 @@ pub struct ChartManager {
min_y: f32,
max_y: f32,
num_interval: usize,
resolution: i32,
resolution: usize,
back_cache: Cache<Vec<(f32, f32)>>,
front_cache: Cache<(Vec<(f32, f32, f32)>, f32)>,
}
@@ -39,7 +39,7 @@ pub struct ChartManager {
impl ChartManager {
pub fn new(
func_str: String, min_x: f32, max_x: f32, min_y: f32, max_y: f32, num_interval: usize,
resolution: i32,
resolution: usize,
) -> Self {
Self {
func_str,
@@ -63,6 +63,7 @@ impl ChartManager {
func
}
// Tests function to make sure it's able to be parsed. Returns the string of the Error produced, or an empty string if it runs successfully.
pub fn test_func(function_string: String) -> String {
let new_func_str: String = add_asterisks(function_string.clone());
let expr_result = new_func_str.parse();
@@ -87,13 +88,6 @@ impl ChartManager {
"".to_string()
}
// Recommends a possible solution to an error from method `test_func`
pub fn error_recommend(error_string: String) -> String {
match error_string.as_str() {
_ => "Make sure you're using proper syntax! Check the 'Frequent issues' for possible fixes."
}.to_string()
}
#[inline]
fn draw(
&mut self, element: HtmlCanvasElement, dark_mode: bool
@@ -192,7 +186,7 @@ impl ChartManager {
#[allow(clippy::too_many_arguments)]
pub fn update(
&mut self, canvas: HtmlCanvasElement, func_str_new: String, min_x: f32, max_x: f32, min_y: f32,
max_y: f32, num_interval: usize, resolution: i32, dark_mode: bool
max_y: f32, num_interval: usize, resolution: usize, dark_mode: bool
) -> Result<ChartOutput, JsValue> {
let func_str: String = add_asterisks(func_str_new);
@@ -204,20 +198,6 @@ impl ChartManager {
| (max_y != self.max_y);
if 0 > resolution {
panic!("resolution cannot be less than 0");
}
if underlying_update {
if min_x >= max_x {
panic!("min_x is greater than (or equal to) than max_x!");
}
if min_y >= max_y {
panic!("min_y is greater than (or equal to) than max_y!");
}
}
if underlying_update | (self.resolution != resolution) {
self.back_cache.invalidate();
}

View File

@@ -2,9 +2,11 @@ use wasm_bindgen::prelude::*;
pub type DrawResult<T> = Result<T, Box<dyn std::error::Error>>;
// EXTREMELY Janky function that tries to put asterisks in the proper places to be parsed. This is so cursed
// EXTREMELY Janky function that tries to put asterisks in the proper places to be parsed. This is so cursed. But it works, and I hopefully won't ever have to touch it again.
// One limitation though, variables with multiple characters like `pi` cannot be multiplied (like `pipipipi` won't result in `pi*pi*pi*pi`). But that's such a niche use case (and that same thing could be done by using exponents) that it doesn't really matter.
pub fn add_asterisks(function_in: String) -> String {
let function = function_in.replace("log10(", "log("); // replace log10 with log
let valid_variables: Vec<char> = "xe".chars().collect();
let letters: Vec<char>= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".chars().collect();
let numbers: Vec<char> = "0123456789".chars().collect();
let function_chars: Vec<char> = function.chars().collect();
@@ -12,6 +14,7 @@ pub fn add_asterisks(function_in: String) -> String {
let mut output_string: String = String::new();
let mut prev_chars: Vec<char> = Vec::new();
for c in function_chars.clone() {
let mut add_asterisk: bool = false;
let prev_chars_len = prev_chars.len();
let curr_i: usize = func_chars_len-prev_chars_len;
@@ -41,32 +44,37 @@ pub fn add_asterisks(function_in: String) -> String {
let prev_pi = (prev_prev_char == 'p') && (prev_char == 'i');
let for_pi = (for_char == 'i') && (c == 'p');
if prev_char == ')' {
if (c == '(') | numbers.contains(&c) | letters.contains(&c) {
output_string += "*";
add_asterisk = true;
}
} else if c == '(' {
if ((prev_char == 'x') | (prev_char == 'e') | (prev_char == ')') | numbers.contains(&prev_char)) && !letters.contains(&prev_prev_char) {
output_string += "*";
if (valid_variables.contains(&prev_char) | (prev_char == ')') | numbers.contains(&prev_char)) && !letters.contains(&prev_prev_char) {
add_asterisk = true;
} else if prev_pi {
output_string += "*";
add_asterisk = true;
}
} else if numbers.contains(&prev_char) {
if (c == '(') | letters.contains(&c) | for_pi {
output_string += "*";
add_asterisk = true;
}
} else if letters.contains(&c) {
if numbers.contains(&prev_char) {
output_string += "*";
} else if ((c == 'x') | (c == 'e')) && ((prev_char == 'x') | (prev_char == 'e')) | prev_pi {
output_string += "*";
add_asterisk = true;
} else if (valid_variables.contains(&prev_char) && valid_variables.contains(&c)) | prev_pi {
add_asterisk = true;
}
} else if numbers.contains(&c) {
if letters.contains(&prev_char) | prev_pi {
output_string += "*";
add_asterisk = true;
}
}
if add_asterisk {
output_string += "*";
}
prev_chars.push(c);
output_string += &c.to_string();
}
@@ -153,6 +161,7 @@ impl<T> Cache<T> {
pub fn is_valid(&self) -> bool { self.valid }
}
// Tests to make sure my cursed function works as intended
#[test]
fn asterisk_test() {
assert_eq!(&add_asterisks("2x".to_string()), "2*x");