use super::{auto_solve, view};
use crate::{MainWindow, bridge::render_thread::RenderContext};
use indicatrix::geometry::meet_solver::SolvedTier;
use indicatrix_cut_core::{Design, ManufacturabilityWarning};
use std::sync::{Arc, Mutex, PoisonError, atomic::Ordering};
#[must_use]
const fn findings_are_current(generation: u64, live: u64) -> bool {
generation == live
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::gui) enum LatePush {
Settled,
Held,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Decision {
Show,
Moved,
Held,
}
#[must_use]
const fn decide(live: Option<u64>, generation: u64) -> Decision {
match live {
None => Decision::Held,
Some(live) if findings_are_current(generation, live) => Decision::Show,
Some(_) => Decision::Moved,
}
}
pub(in crate::gui) fn apply_late_findings(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
generation: u64,
design: &Design,
solved: &[SolvedTier],
findings: &[ManufacturabilityWarning],
) -> LatePush {
let Some(state) = auto_solve::editor_state() else {
return LatePush::Settled;
};
let read = state.try_borrow().ok().map(|state| {
(
state.generation.load(Ordering::Relaxed),
state.multi_selected.clone(),
)
});
match decide(read.as_ref().map(|(live, _)| *live), generation) {
Decision::Held => return LatePush::Held,
Decision::Moved => return LatePush::Settled,
Decision::Show => {}
}
let multi_selected = read.map(|(_, selected)| selected).unwrap_or_default();
let custom_materials = render_ctx
.lock()
.unwrap_or_else(PoisonError::into_inner)
.custom_materials
.as_ref()
.clone();
view::push_late_findings(
ui,
design,
solved,
&multi_selected,
&custom_materials,
findings,
);
LatePush::Settled
}
#[cfg(test)]
mod tests {
use super::{Decision, decide, findings_are_current};
#[test]
fn findings_describe_only_the_generation_they_were_computed_for() {
assert!(findings_are_current(7, 7));
assert!(!findings_are_current(7, 8), "one edit later");
assert!(
!findings_are_current(8, 7),
"a plan for a design not yet reached"
);
}
#[test]
fn a_held_editor_state_is_retried_and_a_moved_design_is_dropped() {
assert_eq!(decide(Some(7), 7), Decision::Show);
assert_eq!(decide(Some(8), 7), Decision::Moved);
assert_eq!(decide(Some(7), 8), Decision::Moved);
assert_eq!(decide(None, 7), Decision::Held);
}
}