code cleanup
This commit is contained in:
parent
e427e7a04e
commit
6f1d64ea02
2
build.rs
2
build.rs
@ -53,7 +53,7 @@ fn generate_hashmap() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
writeln!(&mut file, ";").unwrap();
|
writeln!(&mut file, ";").unwrap();
|
||||||
|
|
||||||
write!(&mut file, "const MAX_FUNC_LEN: usize = {};", max_len).unwrap();
|
write!(&mut file, "const MAX_COMPLETION_LEN: usize = {};", max_len).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
include!(concat!(
|
include!(concat!(
|
||||||
|
|||||||
@ -20,10 +20,11 @@ pub const BUILD_INFO: &str = formatc!(
|
|||||||
|
|
||||||
/// Range of acceptable input values for integral_num
|
/// Range of acceptable input values for integral_num
|
||||||
pub const INTEGRAL_NUM_RANGE: RangeInclusive<usize> = 1..=50000;
|
pub const INTEGRAL_NUM_RANGE: RangeInclusive<usize> = 1..=50000;
|
||||||
|
|
||||||
/// Minimum X value for calculating an Integral
|
/// Minimum X value for calculating an Integral
|
||||||
pub const INTEGRAL_X_MIN: f64 = -1000.0;
|
pub const INTEGRAL_X_MIN: f64 = -1000.0;
|
||||||
/// Maximum X value for calculating an Integral
|
|
||||||
|
|
||||||
|
/// Maximum X value for calculating an Integral
|
||||||
pub const INTEGRAL_X_MAX: f64 = 1000.0;
|
pub const INTEGRAL_X_MAX: f64 = 1000.0;
|
||||||
|
|
||||||
const_assert!(INTEGRAL_X_MAX > INTEGRAL_X_MIN);
|
const_assert!(INTEGRAL_X_MAX > INTEGRAL_X_MIN);
|
||||||
@ -40,7 +41,6 @@ pub const DEFAULT_RIEMANN: Riemann = Riemann::Left;
|
|||||||
pub const DEFAULT_MIN_X: f64 = -10.0;
|
pub const DEFAULT_MIN_X: f64 = -10.0;
|
||||||
|
|
||||||
/// Default Maxmimum X value to display
|
/// Default Maxmimum X value to display
|
||||||
|
|
||||||
pub const DEFAULT_MAX_X: f64 = 10.0;
|
pub const DEFAULT_MAX_X: f64 = 10.0;
|
||||||
|
|
||||||
const_assert!(DEFAULT_MAX_X > DEFAULT_MIN_X);
|
const_assert!(DEFAULT_MAX_X > DEFAULT_MIN_X);
|
||||||
@ -48,7 +48,10 @@ const_assert!(DEFAULT_MAX_X > DEFAULT_MIN_X);
|
|||||||
/// Default number of integral boxes
|
/// Default number of integral boxes
|
||||||
pub const DEFAULT_INTEGRAL_NUM: usize = 100;
|
pub const DEFAULT_INTEGRAL_NUM: usize = 100;
|
||||||
|
|
||||||
pub const COLORS: &'static [Color32; 14] = &[
|
/// Colors used for plotting
|
||||||
|
// Colors commented out are used elsewhere and are not included here for better
|
||||||
|
// user experience
|
||||||
|
pub const COLORS: &[Color32; 14] = &[
|
||||||
Color32::RED,
|
Color32::RED,
|
||||||
// Color32::GREEN,
|
// Color32::GREEN,
|
||||||
// Color32::YELLOW,
|
// Color32::YELLOW,
|
||||||
|
|||||||
@ -90,14 +90,11 @@ impl Default for FunctionEntry {
|
|||||||
impl FunctionEntry {
|
impl FunctionEntry {
|
||||||
pub fn get_func_raw(&self) -> String { self.raw_func_str.to_string() }
|
pub fn get_func_raw(&self) -> String { self.raw_func_str.to_string() }
|
||||||
|
|
||||||
pub fn auto_complete(
|
pub fn auto_complete(&mut self, ui: &mut egui::Ui, i: i32) -> (bool, bool, Option<String>) {
|
||||||
&mut self, ui: &mut egui::Ui, string: &mut String, i: i32,
|
let (output_string, in_focus) = self.autocomplete.ui(ui, self.raw_func_str.clone(), i);
|
||||||
) -> (bool, bool, Option<String>) {
|
|
||||||
let (output_string, in_focus) = self.autocomplete.ui(ui, string.to_string(), i);
|
|
||||||
|
|
||||||
let changed = output_string != *string;
|
let changed = output_string != self.raw_func_str;
|
||||||
if changed {
|
if changed {
|
||||||
*string = output_string.clone();
|
|
||||||
self.update_string(&output_string);
|
self.update_string(&output_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,17 +387,18 @@ impl FunctionEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Plot integral data
|
// Plot integral data
|
||||||
if let Some(integral_data) = &self.integral_data {
|
match &self.integral_data {
|
||||||
plot_ui.bar_chart(
|
Some(integral_data) => {
|
||||||
BarChart::new(integral_data.0.clone())
|
plot_ui.bar_chart(
|
||||||
.color(Color32::BLUE)
|
BarChart::new(integral_data.0.clone())
|
||||||
.width(step),
|
.color(Color32::BLUE)
|
||||||
);
|
.width(step),
|
||||||
|
);
|
||||||
|
|
||||||
// return value rounded to 8 decimal places
|
// return value rounded to 8 decimal places
|
||||||
Some(crate::misc::decimal_round(integral_data.1, 8))
|
Some(crate::misc::decimal_round(integral_data.1, 8))
|
||||||
} else {
|
}
|
||||||
None
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -276,6 +276,7 @@ impl Default for AppSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used to store the opened of windows/widgets
|
||||||
struct Opened {
|
struct Opened {
|
||||||
pub help: bool,
|
pub help: bool,
|
||||||
pub info: bool,
|
pub info: bool,
|
||||||
@ -299,13 +300,9 @@ pub struct MathApp {
|
|||||||
/// Stores vector of functions
|
/// Stores vector of functions
|
||||||
functions: Vec<FunctionEntry>,
|
functions: Vec<FunctionEntry>,
|
||||||
|
|
||||||
/// Stores vector containing the string representation of the functions.
|
|
||||||
/// This is used because of hacky reasons
|
|
||||||
func_strs: Vec<String>,
|
|
||||||
|
|
||||||
/// Stores last error from parsing functions (used to display the same error
|
/// Stores last error from parsing functions (used to display the same error
|
||||||
/// when side panel is minimized)
|
/// when side panel is minimized)
|
||||||
func_errors: Vec<Option<(usize, String)>>,
|
func_errors: Vec<Option<String>>,
|
||||||
|
|
||||||
/// Stores whether or not an error is stored in `self.func_errors`
|
/// Stores whether or not an error is stored in `self.func_errors`
|
||||||
exists_error: bool,
|
exists_error: bool,
|
||||||
@ -331,7 +328,6 @@ impl Default for MathApp {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
functions: vec![DEFAULT_FUNCTION_ENTRY.clone()],
|
functions: vec![DEFAULT_FUNCTION_ENTRY.clone()],
|
||||||
func_strs: vec![String::new()],
|
|
||||||
func_errors: vec![None],
|
func_errors: vec![None],
|
||||||
exists_error: false,
|
exists_error: false,
|
||||||
last_info: (vec![None], Duration::ZERO),
|
last_info: (vec![None], Duration::ZERO),
|
||||||
@ -502,41 +498,24 @@ impl MathApp {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Contains the function string in a text box that the user can edit
|
// Contains the function string in a text box that the user can edit
|
||||||
let (focused, changed, error) =
|
let (focused, changed, error) = function.auto_complete(ui, i as i32);
|
||||||
function.auto_complete(ui, &mut self.func_strs[i], i as i32);
|
|
||||||
if focused {
|
if focused {
|
||||||
self.text_boxes_focused = true;
|
self.text_boxes_focused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if error.is_some() {
|
if let Some(error_string) = error {
|
||||||
self.exists_error = true;
|
self.exists_error = true;
|
||||||
if changed {
|
if changed {
|
||||||
self.func_errors[i] =
|
self.func_errors[i] = Some(error_string);
|
||||||
function.get_test_result().map(|error| (i, error));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// let func_failed = self.func_errors[i].is_some();
|
|
||||||
// if func_failed {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let update_result = function
|
|
||||||
// .update(&self.func_strs[i], integral_enabled,
|
|
||||||
// derivative_enabled) .map(|error| (i, error));
|
|
||||||
|
|
||||||
// if update_result.is_some() {
|
|
||||||
// self.exists_error = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// self.func_errors[i] = update_result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove function if the user requests it
|
// Remove function if the user requests it
|
||||||
if let Some(remove_i_unwrap) = remove_i {
|
if let Some(remove_i_unwrap) = remove_i {
|
||||||
self.functions.remove(remove_i_unwrap);
|
self.functions.remove(remove_i_unwrap);
|
||||||
self.func_strs.remove(remove_i_unwrap);
|
|
||||||
self.func_errors.remove(remove_i_unwrap);
|
self.func_errors.remove(remove_i_unwrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,12 +572,14 @@ impl epi::App for MathApp {
|
|||||||
|
|
||||||
// Button to add a new function
|
// Button to add a new function
|
||||||
if ui
|
if ui
|
||||||
.add_enabled(14 > self.func_strs.len(), Button::new("Add Function"))
|
.add_enabled(
|
||||||
|
COLORS.len() > self.functions.len(),
|
||||||
|
Button::new("Add Function"),
|
||||||
|
)
|
||||||
.on_hover_text("Create and graph new function")
|
.on_hover_text("Create and graph new function")
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
self.functions.push(DEFAULT_FUNCTION_ENTRY.clone());
|
self.functions.push(DEFAULT_FUNCTION_ENTRY.clone());
|
||||||
self.func_strs.push(String::new());
|
|
||||||
self.func_errors.push(None);
|
self.func_errors.push(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,10 +694,11 @@ impl epi::App for MathApp {
|
|||||||
ui.centered_and_justified(|ui| {
|
ui.centered_and_justified(|ui| {
|
||||||
self.func_errors
|
self.func_errors
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|ele| ele.is_some())
|
.enumerate()
|
||||||
.map(|ele| ele.as_ref().unwrap())
|
.filter(|(_, error)| error.is_some())
|
||||||
.for_each(|ele| {
|
.map(|(i, error)| (i, error.as_ref().unwrap()))
|
||||||
ui.heading(format!("(Function #{}) {}\n", ele.0, ele.1));
|
.for_each(|(i, error)| {
|
||||||
|
ui.heading(format!("(Function #{}) {}\n", i, error));
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
14
src/misc.rs
14
src/misc.rs
@ -342,12 +342,18 @@ pub fn step_helper(max_i: usize, min_x: &f64, step: &f64) -> Vec<f64> {
|
|||||||
(0..max_i).map(|x| (x as f64 * step) + min_x).collect()
|
(0..max_i).map(|x| (x as f64 * step) + min_x).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chars_take(chars: &[char], i: usize) -> String {
|
pub fn chars_take(chars: &[char], take: usize) -> String {
|
||||||
if i > chars.len() {
|
let len = chars.len();
|
||||||
panic!("chars_take: i is larget than chars.len()");
|
assert!(len >= take);
|
||||||
|
if take == len {
|
||||||
|
// return `chars` turned into a string if `take == len`
|
||||||
|
return chars.iter().collect::<String>();
|
||||||
|
} else if take == 0 {
|
||||||
|
// return empty string if `take == 0`
|
||||||
|
return String::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
chars.iter().rev().take(i).rev().collect::<String>()
|
chars.iter().rev().take(take).rev().collect::<String>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -6,7 +6,7 @@ pub fn generate_hint(input: &str) -> HintEnum<'static> {
|
|||||||
return HintEnum::Single("x^2");
|
return HintEnum::Single("x^2");
|
||||||
}
|
}
|
||||||
|
|
||||||
let chars: Vec<char> = input.chars().collect();
|
let chars: Vec<char> = input.chars().collect::<Vec<char>>();
|
||||||
|
|
||||||
let mut open_parens: usize = 0;
|
let mut open_parens: usize = 0;
|
||||||
let mut closed_parens: usize = 0;
|
let mut closed_parens: usize = 0;
|
||||||
@ -22,8 +22,8 @@ pub fn generate_hint(input: &str) -> HintEnum<'static> {
|
|||||||
|
|
||||||
let len = chars.len();
|
let len = chars.len();
|
||||||
|
|
||||||
for i in (1..=MAX_FUNC_LEN).rev().filter(|i| len >= *i) {
|
for i in (1..=MAX_COMPLETION_LEN).rev().filter(|i| len >= *i) {
|
||||||
if let Some(output) = get_completion(chars_take(&chars, i)) {
|
if let Some(output) = get_completion(&chars_take(&chars, i)) {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,13 +72,6 @@ impl ToString for HintEnum<'static> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HintEnum<'static> {
|
impl HintEnum<'static> {
|
||||||
pub fn get_single(&self) -> Option<String> {
|
|
||||||
match self {
|
|
||||||
HintEnum::Single(x) => Some(x.to_string()),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_some(&self) -> bool { !matches!(self, HintEnum::None) }
|
pub fn is_some(&self) -> bool { !matches!(self, HintEnum::None) }
|
||||||
|
|
||||||
pub fn is_none(&self) -> bool { !self.is_some() }
|
pub fn is_none(&self) -> bool { !self.is_some() }
|
||||||
@ -87,12 +80,14 @@ impl HintEnum<'static> {
|
|||||||
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
|
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
|
||||||
|
|
||||||
/// Gets completion from `COMPLETION_HASHMAP`
|
/// Gets completion from `COMPLETION_HASHMAP`
|
||||||
pub fn get_completion(key: String) -> Option<HintEnum<'static>> {
|
pub fn get_completion(key: &str) -> Option<HintEnum<'static>> {
|
||||||
|
// If key is empty, just return None
|
||||||
if key.is_empty() {
|
if key.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPLETION_HASHMAP.get(&key).cloned()
|
// Get and clone the recieved data
|
||||||
|
COMPLETION_HASHMAP.get(key).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -55,9 +55,9 @@ impl AutoComplete {
|
|||||||
let enter_pressed = ui.input_mut().consume_key(Modifiers::NONE, Key::Enter);
|
let enter_pressed = ui.input_mut().consume_key(Modifiers::NONE, Key::Enter);
|
||||||
let tab_pressed = ui.input_mut().consume_key(Modifiers::NONE, Key::Tab);
|
let tab_pressed = ui.input_mut().consume_key(Modifiers::NONE, Key::Tab);
|
||||||
|
|
||||||
if let Some(single_hint) = self.hint.get_single() {
|
if let HintEnum::Single(single_hint) = self.hint {
|
||||||
let func_edit_2 = func_edit;
|
let func_edit_2 = func_edit;
|
||||||
func_edit = func_edit_2.hint_text(&single_hint);
|
func_edit = func_edit_2.hint_text(single_hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
let re = func_edit.id(te_id).ui(ui);
|
let re = func_edit.id(te_id).ui(ui);
|
||||||
@ -71,7 +71,7 @@ impl AutoComplete {
|
|||||||
let push_cursor: bool = match self.hint {
|
let push_cursor: bool = match self.hint {
|
||||||
HintEnum::Single(hint) => {
|
HintEnum::Single(hint) => {
|
||||||
if apply_key {
|
if apply_key {
|
||||||
new_string = string + &hint;
|
new_string += hint;
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user