use std::iter::zip; use yew::{Component, html}; use crate::{ constraint_input::ConstraintInput, simplex::Simplex, target_input::TargetInput, variable_input::VariableInput, }; #[derive(Debug)] pub struct App { current_variable: String, target_inputs: Vec, constraint_inputs: Vec, simplex: Simplex, solution: Option, final_values: Vec<(String, f32)>, theme: String, } pub enum Msg { VariableChange(String), ConstraintChange((String, usize)), TargetChange((String, usize)), AddVariable, ClearVariables, AddConstraint, ClearConstraints, RunSimplex, ChangeTheme, } impl App {} impl Default for App { fn default() -> Self { Self { current_variable: Default::default(), target_inputs: vec![], constraint_inputs: vec!["".to_string()], simplex: Default::default(), solution: None, final_values: Default::default(), theme: Default::default(), } } } impl Component for App { type Message = Msg; type Properties = (); fn create(_ctx: &yew::Context) -> Self { Self::default() } fn update(&mut self, _ctx: &yew::Context, msg: Self::Message) -> bool { match msg { Msg::VariableChange(text) => self.current_variable = text, Msg::ConstraintChange((text, i)) => { self.constraint_inputs[i] = text; web_sys::console::log_1(&format!("{:?}", self.constraint_inputs).into()); } Msg::TargetChange((text, i)) => self.target_inputs[i] = text, Msg::AddVariable => { if self.current_variable != "".to_string() && !self .simplex .get_variables() .contains(&self.current_variable) { self.simplex.add_variable(self.current_variable.clone()); self.current_variable = "".to_string(); for _ in 0..(1 + self.simplex.get_variables().len() - self.constraint_inputs.len()) { self.constraint_inputs.push("".to_string()); } for _ in 0..(1 + self.simplex.get_variables().len() - self.target_inputs.len()) { self.target_inputs.push("".to_string()); } web_sys::console::log_1(&format!("{:?}", self.simplex.get_variables()).into()); web_sys::console::log_1(&format!("{:?}", self.constraint_inputs).into()); } } Msg::ClearVariables => self.simplex.clear_variables(), Msg::AddConstraint => { let mut constraint = vec![0_f32; self.constraint_inputs.len()]; let mut is_ok = true; for (i, input) in self.constraint_inputs.iter().enumerate() { if *input == "".to_string() { constraint[i] = 0_f32; continue; } if let Ok(v) = input.parse::() { constraint[i] = v; } else { is_ok = false; break; } } if is_ok { self.simplex.add_constraint(constraint); } } Msg::ClearConstraints => self.simplex.clear_constraint(), //self.simplex.clear_constraint(), Msg::RunSimplex => { let mut target = vec![0_f32; self.target_inputs.len()]; let mut is_ok = true; for (i, input) in self.target_inputs.iter().enumerate() { if *input == "".to_string() { target[i] = 0_f32; continue; } if let Ok(v) = input.parse::() { target[i] = v; } else { is_ok = false; break; } } if is_ok { self.simplex.set_target(target); } let (sol, values) = self.simplex.run_simplex(); self.solution = Some(sol); self.final_values = values; } Msg::ChangeTheme => { if self.theme == "" { self.theme = "dark-theme".to_string() } else { self.theme = "".to_string() } } } true } fn view(&self, ctx: &yew::Context) -> yew::Html { let on_change_variable = ctx.link().callback(Msg::VariableChange); let on_change_constraint = ctx.link().callback(Msg::ConstraintChange); let on_change_target = ctx.link().callback(Msg::TargetChange); let add_variable = ctx.link().callback(|_| Msg::AddVariable); let clear_variables = ctx.link().callback(|_| Msg::ClearVariables); let clear_constraint = ctx.link().callback(|_| Msg::ClearConstraints); let add_constraint = ctx.link().callback(|_| Msg::AddConstraint); let run_simplex = ctx.link().callback(|_| Msg::RunSimplex); let change_theme = ctx.link().callback(|_| Msg::ChangeTheme); html! {
//

{"Simplex optimizer"}

//
//

{"Inputs"}

//

{"Variables"}

    { for self.simplex.get_variables().iter().map(|v| { html! {
  • {v}
  • } }) }
//

{"Constraints"}

    { for self.simplex.get_constraints().iter().map(|c| { html! {
  • { for zip(c, self.simplex.get_variables()).take(c.len() - 1).enumerate().map(|(i, (v, var))| { let v_2 = if i > 0 { v.abs() } else { *v }; html! { { format!("{}{} {} ", if v_2 == 1_f32 { "".to_string() } else {if v_2 == -1_f32 {" -".to_string()} else { format!("{}", v_2) }}, var, {if i < c.len() - 2 {if c[i + 1] < 0_f32 {" - "} else {" + "}} else { " " }} ) } } } )} { format!(" ≤ {}", c[c.len() - 1]) }
  • } }) }

{"Target Function"}

//
//

{"Steps"}

  • {"Step 1: Initial Tableau"}

{"Solution"}

// {" Final Result: Z = 50 at (x=10, y=5)"} { if let Some(solution) = self.solution { html! { <> {format!("Z = {} at ", solution)} {for self.final_values.iter().map(|(var, val)|{ html!{ <> {format!("{}={} ", var, val)} } })} } } else { html!{ {"Run the algorithm to find the solution"} } } }
} } }