Skip to content

Commit

Permalink
solvers ui
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruno02468 committed May 2, 2024
1 parent 22a2a35 commit 3bd2bbb
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 19 deletions.
30 changes: 26 additions & 4 deletions nastester/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ impl AppState {
))
}

/// Clears results for a specific solver pick. Might lock.
pub(crate) fn clear_results_of(&mut self, pick: SolverPick) {
let decks = self.suite.decks.keys().copied().collect::<Vec<_>>();
for u in decks {
let l = self.get_run_state(u);
let mut h = l.lock().unwrap();
*h.get_mut(pick) = RunState::Ready;
h.flagged.clear();
}
}

/// Clears all results.
pub(crate) fn clear_results(&mut self) {
self.runner.results.clear();
Expand Down Expand Up @@ -191,9 +202,9 @@ impl AppState {
*handle.lock().expect("mutex poisoned").get_mut(pick) = state;
}

/// Gets the current picked solver for something.
pub(crate) fn get_solver(&self, pick: SolverPick) -> Option<&RunnableSolver> {
return self.runner.get_solver(pick).and_then(|u| self.solvers.get(&u));
/// Gets a current picked solver.
pub(crate) fn get_solver(&self, p: SolverPick) -> Option<&RunnableSolver> {
return self.runner.get_solver(p).and_then(|u| self.solvers.get(&u));
}

/// Generates a job for a deck and a solver pick.
Expand Down Expand Up @@ -239,6 +250,7 @@ impl AppState {

/// Enqueues all jobs for a solver pick.
pub(crate) fn enqueue_solver(&mut self, pick: SolverPick) {
self.clear_results_of(pick);
let decks = self.suite.decks.keys().copied().collect::<Vec<_>>();
for u in decks {
self.enqueue_deck(u, pick);
Expand Down Expand Up @@ -300,11 +312,21 @@ impl AppState {
}
}

/// Re-computes all flagged values in the UI thread.
/// Re-computes all flagged values.
pub(crate) fn recompute_all_flagged(&mut self) {
let uuids = self.suite.decks.keys().copied().collect::<Vec<_>>();
for deck in uuids {
self.recompute_flagged(deck);
}
}

/// Removes a solver and all associated results.
pub(crate) fn remove_solver(&mut self, uuid: Uuid) {
self.solvers.remove(&uuid);
for pick in SolverPick::all() {
if self.runner.get_solver(*pick) == Some(uuid) {
self.clear_results_of(*pick);
}
}
}
}
157 changes: 142 additions & 15 deletions nastester/src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,20 @@ impl Gui {
}
}

/// Add a solver binary. Returns whether it's been added.
fn add_solver_bin(&mut self, _ui: &mut Ui) -> Result<bool, Box<dyn Error>> {
/// Fila dialog to pick a solver binary.
fn solver_bin_dialog() -> Option<PathBuf> {
let mut dialog = rfd::FileDialog::new()
.set_title("Choose solver binary...")
.set_can_create_directories(true);
if !BINARY_EXTENSIONS.is_empty() {
dialog = dialog.add_filter("Executable file", BINARY_EXTENSIONS);
}
let binary = dialog.pick_file();
return dialog.pick_file();
}

/// Add a solver binary. Returns whether it's been added.
fn add_solver_bin(&mut self, _ui: &mut Ui) -> Result<bool, Box<dyn Error>> {
let binary = Self::solver_bin_dialog();
if let Some(bin) = binary {
log::info!("Added solver binary {}.", bin.display());
self.state.add_solver_bin(bin);
Expand All @@ -198,12 +203,17 @@ impl Gui {
}
}

/// Dialog to pick an F06 directory.
fn solver_dir_dialog() -> Option<PathBuf> {
return rfd::FileDialog::new()
.set_title("Choose F06 directory...")
.set_can_create_directories(true)
.pick_folder();
}

/// Add a solver as an F06 directory. Returns whether it's been added.
fn add_solver_dir(&mut self, _ui: &mut Ui) -> Result<bool, Box<dyn Error>> {
let directory = rfd::FileDialog::new()
.set_title("Choose F06 directory...")
.set_can_create_directories(true)
.pick_folder();
let directory = Self::solver_dir_dialog();
if let Some(dir) = directory {
log::info!("Added solver as F06 directory {}.", dir.display());
self.state.add_solver_dir(dir);
Expand Down Expand Up @@ -242,6 +252,26 @@ impl Gui {
}
}

/// Change a solver's path. Returns whether it's been changed.
fn change_solver(&mut self, solver: Uuid) -> Result<bool, Box<dyn Error>> {
let current = self.state.solvers.get_mut(&solver).unwrap();
match current.method {
RunMethod::ImportFromDir(ref mut p) => {
if let Some(np) = Self::solver_dir_dialog() {
*p = np;
return Ok(true);
}
},
RunMethod::RunSolver(ref mut p) => {
if let Some(np) = Self::solver_bin_dialog() {
*p = np;
return Ok(true);
}
}
};
return Ok(false);
}

/// Run a function and, if an error happens, do a pop-up.
fn show_error(err: Box<dyn Error>) {
MessageDialog::new()
Expand Down Expand Up @@ -446,6 +476,8 @@ impl Gui {
ui.menu_button("Suite", |ui| {
if ui.button("New").clicked() {
self.state = AppState::default();
self.suite_clean = true;
self.suite_file = None;
}
if ui.button("Save").clicked() {
self.try_run(ui, Gui::save_suite);
Expand All @@ -468,15 +500,21 @@ impl Gui {
});
// generates sub-menu solver buttons
let btn = |
state: &mut AppState,
ui: &mut Ui,
opt: Option<Uuid>,
lbl: &str,
tgt: &mut Option<Uuid>
pick: SolverPick,
| {
let mut rt = RichText::new(lbl);
let tgt = match pick {
SolverPick::Reference => &mut state.runner.ref_solver,
SolverPick::Testing => &mut state.runner.test_solver,
};
if opt == *tgt { rt = rt.strong(); }
if ui.button(rt).clicked() {
*tgt = opt
if ui.button(rt).clicked() && opt != *tgt {
*tgt = opt;
state.clear_results_of(pick);
}
};
// solvers menu
Expand All @@ -494,24 +532,26 @@ impl Gui {
.map(|(s, u)| (s.to_owned(), u))
.collect::<Vec<_>>();
ui.menu_button("Set reference solver", |ui| {
btn(ui, None, "<none>", &mut self.state.runner.ref_solver);
btn(&mut self.state, ui, None, "<none>", SolverPick::Reference);
for (s, u) in snames.iter() {
btn(
&mut self.state,
ui,
Some(*u),
s.as_str(),
&mut self.state.runner.ref_solver
SolverPick::Reference
);
}
});
ui.menu_button("Set solver under test", |ui| {
btn(ui, None, "<none>", &mut self.state.runner.test_solver);
btn(&mut self.state, ui, None, "<none>", SolverPick::Testing);
for (s, u) in snames.iter() {
btn(
&mut self.state,
ui,
Some(*u),
s.as_str(),
&mut self.state.runner.test_solver
SolverPick::Testing
);
}
});
Expand Down Expand Up @@ -1010,6 +1050,93 @@ impl Gui {
});
}

/// Render function for the solvers.
fn view_solvers(&mut self, ctx: &Context) {
egui::CentralPanel::default().show(ctx, |ui| {
self.show_menu(ctx, ui);
let heading_height = ui.text_style_height(&TextStyle::Heading);
let dy = ui.spacing().item_spacing.y;
let body_height = ui.text_style_height(&TextStyle::Body) + dy;
let mut cells = Layout::left_to_right(Align::Center);
let nsolvers = self.state.solvers.len();
let snames = self.state.solvers_names()
.map(|(s, u)| (s.to_owned(), u))
.collect::<Vec<_>>();
cells.main_wrap = false;
ui.vertical_centered(|ui| {
ui.strong("Solvers:");
if ui.button("Add binary").clicked() {
self.try_run(ui, Gui::add_solver_bin);
}
if ui.button("Add F06 directory").clicked() {
self.try_run(ui, Gui::add_solver_dir);
}
TableBuilder::new(ui)
.vscroll(true)
.auto_shrink(true)
.striped(true)
.cell_layout(cells)
.column(Column::auto().resizable(true))
.column(Column::auto().resizable(true))
.column(Column::auto().resizable(true))
.column(Column::auto().resizable(true))
.column(Column::auto().resizable(true))
.header(heading_height, |mut header| {
header.col(|ui| { ui.heading("Solver nickname"); });
header.col(|ui| { ui.heading("F06 acquisition method"); });
header.col(|ui| { ui.heading("Current reference solver"); });
header.col(|ui| { ui.heading("Current solver under test"); });
header.col(|ui| { ui.heading("Actions"); });
})
.body(|body| {
body.rows(body_height, nsolvers, |mut row| {
let (_name, uuid) = snames.get(row.index()).unwrap();
let solver = self.state.solvers.get_mut(uuid)
.expect("missing solver UUID!");
// nickname
row.col(|ui| {
ui.text_edit_singleline(&mut solver.nickname);
});
// method
row.col(|ui| {
ui.label(match &solver.method {
RunMethod::ImportFromDir(p) => {
format!("Get from {}", p.display())
},
RunMethod::RunSolver(p) => {
format!("Run solver {}", p.display())
}
});
});
// columns for solver picks
for pick in SolverPick::all() {
let tgt = match pick {
SolverPick::Reference => &mut self.state.runner.ref_solver,
SolverPick::Testing => &mut self.state.runner.test_solver,
};
row.col(|ui| {
if *tgt == Some(*uuid) {
ui.label("Is current");
} else if ui.button("Make current").clicked() {
*tgt = Some(*uuid);
}
});
}
// actions
row.col(|ui| {
if ui.button("Change path").clicked() {
self.change_solver(*uuid).ok();
}
if ui.button("Remove").clicked() {
self.state.remove_solver(*uuid);
}
});
});
});
});
});
}

/// Render function for a deck's results, side-by-side.
fn view_results(&mut self, _ctx: &Context, _d: Uuid, _exn: Option<usize>) {

Expand All @@ -1023,7 +1150,7 @@ impl eframe::App for Gui {
//}
match self.view {
View::Decks => self.view_decks(ctx),
View::Solvers => todo!(),
View::Solvers => self.view_solvers(ctx),
View::CriteriaSets => self.view_criteria_sets(ctx),
View::Extractions(uuid) => self.view_deck_exns(ctx, uuid),
View::Results(uuid, n) => self.view_results(ctx, uuid, n)
Expand Down
7 changes: 7 additions & 0 deletions nastester/src/running.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ pub(crate) enum SolverPick {
Testing
}

impl SolverPick {
/// Returns all variants.
pub(crate) fn all() -> &'static [Self] {
return &[Self::Reference, Self::Testing];
}
}

/// This specifies a run job.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct Job {
Expand Down

0 comments on commit 3bd2bbb

Please sign in to comment.