From cca204ad5fcb7b07dafcbaffcbe48ced28930121 Mon Sep 17 00:00:00 2001 From: Oliver With Date: Tue, 20 May 2025 12:23:41 +0200 Subject: [PATCH] No need to use refcell in domain --- src/decision_model/model.rs | 159 ++++++++++++++++-------------------- src/main.rs | 29 ++++--- 2 files changed, 86 insertions(+), 102 deletions(-) diff --git a/src/decision_model/model.rs b/src/decision_model/model.rs index b25ce98..780e086 100644 --- a/src/decision_model/model.rs +++ b/src/decision_model/model.rs @@ -1,5 +1,3 @@ -use std::cell::RefCell; - pub enum Side { Lhs, Rhs, @@ -19,119 +17,111 @@ impl Parameters { } pub struct DecisionModel { - parameters: RefCell>, - indices: RefCell>, - current_index: RefCell>, + parameters: Vec, + indices: Vec<(usize, usize)>, + current_index: Option, } impl DecisionModel { pub fn new() -> Self { Self { - parameters: RefCell::new(Vec::new()), - indices: RefCell::new(Vec::new()), - current_index: RefCell::new(None), + parameters: Vec::new(), + indices: Vec::new(), + current_index: None, } } - pub fn reset(&self) { - let mut params = self.parameters.borrow_mut(); - let mut idx = self.indices.borrow_mut(); - let mut ci = self.current_index.borrow_mut(); + pub fn reset(&mut self) { + // let mut params = self.parameters.borrow_mut(); + // let mut idx = self.indices.borrow_mut(); + // let mut ci = self.current_index.borrow_mut(); - *params = Vec::new(); - *idx = Vec::new(); - *ci = None; + self.parameters = Vec::new(); + self.indices = Vec::new(); + self.current_index = None; } - pub fn move_to_next_pair(&self) { - let mut ci = self.current_index.borrow_mut(); - let idx = self.indices.borrow(); + pub fn move_to_next_pair(&mut self) { + let ci = self.current_index; + + let idx = &self.indices; if ci.is_some() { match idx.get(ci.unwrap() + 1) { - Some(_) => *ci = Some(ci.unwrap() + 1), - None => *ci = None, + Some(_) => self.current_index = Some(ci.unwrap() + 1), + None => self.current_index = None, }; } } - pub fn get_current_pair(&self) -> Option<(Parameters, Parameters)> { - let ci = self.current_index.borrow(); - let params = self.parameters.borrow(); - let idx = self.indices.borrow(); - match *ci { - Some(p) => Some((params[idx[p].0].clone(), params[idx[p].1].clone())), - None => None, - } + pub fn get_current_pair(&mut self) -> Option<(Parameters, Parameters)> { + self.current_index.map(|p| { + ( + self.parameters[self.indices[p].0].clone(), + self.parameters[self.indices[p].1].clone(), + ) + }) } - pub fn record_score_of_current_pair(&self, winner: Side, points_to_add: u32) { - let ci = self.current_index.borrow(); - let mut params = self.parameters.borrow_mut(); - let idx = self.indices.borrow(); + pub fn record_score_of_current_pair(&mut self, winner: Side, points_to_add: u32) { + let ci = self.current_index; if ci.is_some() { match winner { Side::Lhs => { - params[idx[ci.unwrap()].0].score += points_to_add; + self.parameters[self.indices[ci.unwrap()].0].score += points_to_add; } Side::Rhs => { - params[idx[ci.unwrap()].1].score += points_to_add; + self.parameters[self.indices[ci.unwrap()].1].score += points_to_add; } _ => {} }; } } - pub fn prepare_model(&self, param_list: &Vec, randomize: bool) { - let mut parameters = self.parameters.borrow_mut(); + pub fn prepare_model(&mut self, param_list: &Vec, randomize: bool) { for param in param_list { - parameters.push(Parameters { + self.parameters.push(Parameters { name: param.to_string(), score: 0, }); } - parameters.sort_by(|a, b| a.name.cmp(&b.name)); - parameters.retain(|i| i.name.ne("")); - parameters.dedup_by(|a, b| a.name.eq_ignore_ascii_case(&b.name)); + self.parameters.sort_by(|a, b| a.name.cmp(&b.name)); + self.parameters.retain(|i| !i.name.is_empty()); + self.parameters + .dedup_by(|a, b| a.name.eq_ignore_ascii_case(&b.name)); - let mut indices = self.indices.borrow_mut(); - *indices = index_pairs(parameters.len()); + self.indices = index_pairs(self.parameters.len()); if randomize { let mut rng = rand::thread_rng(); - rand::seq::SliceRandom::shuffle(&mut indices[..], &mut rng); + rand::seq::SliceRandom::shuffle(&mut self.indices[..], &mut rng); } - match parameters.len() > 1 { + match self.parameters.len() > 1 { true => { - let mut ci = self.current_index.borrow_mut(); - *ci = Some(0); + self.current_index = Some(0); } false => { - let mut ci = self.current_index.borrow_mut(); - *ci = None; + self.current_index = None; } } } - pub fn reset_score_and_indices(&self) { - let mut parameters: std::cell::RefMut> = self.parameters.borrow_mut(); - parameters.iter_mut().for_each(|p| p.score = 0); + pub fn reset_score_and_indices(&mut self) { + // let mut parameters: std::cell::RefMut> = self.parameters.borrow_mut(); + self.parameters.iter_mut().for_each(|p| p.score = 0); - if parameters.len() > 1 { - let mut ci = self.current_index.borrow_mut(); - *ci = Some(0); + if self.parameters.len() > 1 { + self.current_index = Some(0); } } - pub fn is_model_ready_to_play(&self) -> bool { - (self.parameters.borrow().len() >= 2) - && (self.parameters.borrow().iter().all(|x| x.score == 0)) + pub fn is_model_ready_to_play(&mut self) -> bool { + (self.parameters.len() >= 2) && (self.parameters.iter().all(|x| x.score == 0)) } - pub fn get_parameters(&self) -> String { + pub fn get_parameters(&mut self) -> String { self.parameters - .borrow() .iter() .map(|x| x.name.to_string()) .collect::>() @@ -139,7 +129,7 @@ impl DecisionModel { } pub fn sorted_by_score(&self) -> Vec { - let mut params: Vec = self.parameters.borrow().clone(); + let mut params = self.parameters.clone(); params.sort_by(|a, b| b.score.cmp(&a.score)); params } @@ -158,7 +148,7 @@ fn index_pairs(matrix_size: usize) -> Vec<(usize, usize)> { pub fn clean_input(input: &str) -> Vec { let mut v: Vec = input.split('\n').map(str::to_string).collect(); v = v.into_iter().map(|s| s.trim().to_string()).collect(); - v.retain(|i| i.ne("")); + v.retain(|i| !i.is_empty()); v } @@ -168,12 +158,12 @@ mod tests { #[test] fn return_sorted() { - let input: Vec = vec!["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); - let model = DecisionModel::new(); + let input = ["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); + let mut model = DecisionModel::new(); model.prepare_model(&input, false); - model.parameters.borrow_mut()[0].score = 1; - model.parameters.borrow_mut()[1].score = 2; - model.parameters.borrow_mut()[2].score = 3; + model.parameters[0].score = 1; + model.parameters[1].score = 2; + model.parameters[2].score = 3; let result = model.sorted_by_score(); assert_eq!(3, result[0].score); @@ -181,8 +171,8 @@ mod tests { } #[test] fn model_go_to_next_pair() { - let input: Vec = vec!["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); - let model = DecisionModel::new(); + let input: Vec = ["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); + let mut model = DecisionModel::new(); model.prepare_model(&input, false); model.move_to_next_pair(); @@ -192,8 +182,8 @@ mod tests { #[test] fn model_increment_score() { - let input: Vec = vec!["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); - let model = DecisionModel::new(); + let input: Vec = ["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); + let mut model = DecisionModel::new(); model.prepare_model(&input, false); model.record_score_of_current_pair(Side::Rhs, 15); @@ -204,9 +194,9 @@ mod tests { #[test] fn model_current_pair_good_model() { - let input: Vec = vec!["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); + let input: Vec = ["a", "b", "c"].iter().map(|&s| s.to_string()).collect(); - let model = DecisionModel::new(); + let mut model = DecisionModel::new(); model.prepare_model(&input, false); assert_eq!( @@ -226,9 +216,9 @@ mod tests { #[test] fn model_current_pair_bad_model() { - let input: Vec = vec!["a"].iter().map(|&s| s.to_string()).collect(); + let input: Vec = ["a"].iter().map(|&s| s.to_string()).collect(); - let model = DecisionModel::new(); + let mut model = DecisionModel::new(); model.prepare_model(&input, false); assert_eq!(None, model.get_current_pair()); @@ -236,35 +226,26 @@ mod tests { #[test] fn model_parameter_list() { - let input: Vec = vec!["a", "miao", "x"] - .iter() - .map(|&s| s.to_string()) - .collect(); + let input: Vec = ["a", "miao", "x"].iter().map(|&s| s.to_string()).collect(); - let model = DecisionModel::new(); + let mut model = DecisionModel::new(); model.prepare_model(&input, false); assert_eq!("a\nmiao\nx", model.get_parameters()); } #[test] fn model_prepare() { - let input: Vec = vec!["a", "miao", "x"] - .iter() - .map(|&s| s.to_string()) - .collect(); + let input: Vec = ["a", "miao", "x"].iter().map(|&s| s.to_string()).collect(); - let model = DecisionModel::new(); + let mut model = DecisionModel::new(); model.prepare_model(&input, false); - assert_eq!(true, model.is_model_ready_to_play()); + assert!(model.is_model_ready_to_play()); } #[test] fn model_dedupe() { - let expected: Vec = vec!["a", "miao", "x"] - .iter() - .map(|&s| s.to_string()) - .collect(); + let expected: Vec = ["a", "miao", "x"].iter().map(|&s| s.to_string()).collect(); let input = String::from("a \nmiao\n\nx\n"); let result = clean_input(&input); diff --git a/src/main.rs b/src/main.rs index b55e136..264e60d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,21 +2,22 @@ mod decision_model; use decision_model::model as DM; -use std::rc::Rc; +use std::{cell::RefCell, rc::Rc}; use slint::{SharedString, VecModel}; slint::include_modules!(); fn main() { let main_window = MainWindow::new().unwrap(); - let model = Rc::new(DM::DecisionModel::new()); + // let model = Rc::new(DM::DecisionModel::new()); + let model = Rc::new(RefCell::new(DM::DecisionModel::new())); let mw = main_window.as_weak(); let mdl = model.clone(); main_window.on_dialog_play(move || { - mdl.reset_score_and_indices(); + mdl.borrow_mut().reset_score_and_indices(); - let current_pair = mdl.get_current_pair().unwrap(); + let current_pair = mdl.borrow_mut().get_current_pair().unwrap(); mw.unwrap() .set_lhs_param_name(current_pair.0.get_name_and_score().0.into()); @@ -29,14 +30,14 @@ fn main() { let mw = main_window.as_weak(); let mdl = model.clone(); main_window.on_dialog_return_edit(move || { - mdl.reset_score_and_indices(); + mdl.borrow_mut().reset_score_and_indices(); View::Edit.set_visible(&mw.unwrap()) }); let mw = main_window.as_weak(); let mdl = model.clone(); main_window.on_dialog_results(move || { - let params = mdl.sorted_by_score(); + let params = mdl.borrow_mut().sorted_by_score(); let vm = Rc::new(VecModel::::default()); vm.extend(params.into_iter().map(|i| Parameter { @@ -58,11 +59,12 @@ fn main() { _ => DM::Side::Other, }; - mdl.record_score_of_current_pair(winner_side, 1); + mdl.borrow_mut() + .record_score_of_current_pair(winner_side, 1); - mdl.move_to_next_pair(); + mdl.borrow_mut().move_to_next_pair(); - match mdl.get_current_pair() { + match mdl.borrow_mut().get_current_pair() { Some(p) => { mw.unwrap() .set_lhs_param_name(p.0.get_name_and_score().0.into()); @@ -80,7 +82,8 @@ fn main() { let mw = main_window.as_weak(); let mdl = model.clone(); main_window.on_show(move || { - mw.unwrap().set_parameters(mdl.get_parameters().into()); + mw.unwrap() + .set_parameters(mdl.borrow_mut().get_parameters().into()); }); let mw = main_window.as_weak(); @@ -89,7 +92,7 @@ fn main() { mw.unwrap().set_parameters(SharedString::new()); mw.unwrap().set_play_enabled(false); - mdl.reset(); + mdl.borrow_mut().reset(); }); let mw = main_window.as_weak(); @@ -99,9 +102,9 @@ fn main() { println!("add params clicked:\n{}", parameters_ui); let parameter_list = DM::clean_input(¶meters_ui); - mdl.prepare_model(¶meter_list, true); + mdl.borrow_mut().prepare_model(¶meter_list, true); - if mdl.is_model_ready_to_play() { + if mdl.borrow_mut().is_model_ready_to_play() { mw.unwrap().set_play_enabled(true); } });