mod engine;
mod remote_lane;
mod scan;
mod wiring;
pub use engine::{save_tilt_curves_for_entry, tilt_curves_for_planes};
pub use wiring::{offer_regeneration, setup_tilt_batch_callbacks};
#[cfg(test)]
mod tests {
use super::*;
use crate::gui::batch::test_records::{
ASC_MAST, ASC_TEXT, ENTRY_ID, angle_table_planes, angle_table_record, assert_gem_geometry,
gem_record, has_plane_at, record_with,
};
use indicatrix::{
geometry::{GpuFacetPlane, cuts::StandardGemCuts},
optics::materials::GemMaterial,
};
use indicatrix_vault::{
db::sqlite::Database,
model::{
entry::FullDiagramRecord,
tilt_curves::{AxisTiltCurves, TILT_CURVE_AXIS_COUNT, TiltPerformanceCurves},
},
};
use std::{
collections::BTreeSet,
sync::{Mutex, atomic::AtomicBool},
};
fn tilt_planes(full: &FullDiagramRecord) -> (Option<Vec<GpuFacetPlane>>, BTreeSet<i64>) {
let db = Mutex::new(Database::new(Some(":memory:")).expect("in-memory database opens"));
let angle_table_entries = Mutex::new(BTreeSet::new());
let ctx = engine::BatchContext {
db: &db,
material_candidates: &[],
angle_table_entries: &angle_table_entries,
};
let planes = engine::record_planes(&ctx, full);
let fallbacks = angle_table_entries
.into_inner()
.expect("the fallback set is never poisoned in a test");
(planes, fallbacks)
}
#[test]
fn tilt_batch_sweeps_a_gem_only_record_from_its_design_file() {
let full = gem_record();
let (planes, fallbacks) = tilt_planes(&full);
let planes = planes.expect("the .gem yields planes");
assert_gem_geometry(&planes);
assert_ne!(planes, angle_table_planes(&full));
assert!(fallbacks.is_empty());
assert_eq!(
planes,
crate::gui::editor::resolve_catalogue_planes(&full).planes
);
}
#[test]
fn tilt_batch_prefers_the_asc_over_a_differing_angle_table() {
let full = record_with("design.asc", ASC_TEXT.as_bytes().to_vec());
let (planes, fallbacks) = tilt_planes(&full);
let planes = planes.expect("the .asc yields planes");
assert!(has_plane_at(&planes, ASC_MAST));
assert_ne!(planes, angle_table_planes(&full));
assert!(fallbacks.is_empty());
}
#[test]
fn tilt_batch_sweeps_a_record_without_a_design_file_from_its_angle_table() {
let full = angle_table_record();
let (planes, fallbacks) = tilt_planes(&full);
assert_eq!(planes, Some(angle_table_planes(&full)));
assert_eq!(fallbacks, BTreeSet::from([ENTRY_ID]));
}
#[test]
fn tilt_batch_falls_back_to_the_angle_table_for_a_corrupt_gem() {
let full = record_with("broken.gem", vec![1, 2, 3]);
let (planes, fallbacks) = tilt_planes(&full);
assert_eq!(planes, Some(angle_table_planes(&full)));
assert_eq!(fallbacks, BTreeSet::from([ENTRY_ID]));
}
#[test]
fn tilt_curves_for_planes_honours_an_already_set_cancel_flag() {
let planes = StandardGemCuts::standard_round_brilliant();
let material = GemMaterial::diamond();
let cancel = AtomicBool::new(true);
assert!(tilt_curves_for_planes(&planes, &material, None, &cancel, &mut |_| {}).is_none());
}
#[test]
fn tilt_curves_for_planes_computes_a_real_local_sweep_for_the_open_design_path() {
let planes = StandardGemCuts::standard_round_brilliant();
let material = GemMaterial::diamond();
let cancel = AtomicBool::new(false);
let mut steps = 0usize;
let curves = tilt_curves_for_planes(&planes, &material, None, &cancel, &mut |_| {
steps += 1;
})
.expect("a standard round brilliant must sweep successfully");
assert_eq!(steps, 724, "one progress report per raytrace evaluation");
assert!(
curves
.axes
.iter()
.any(|axis| axis.brilliance_pct.iter().any(|&v| v > 0.0)),
"expected at least one nonzero brilliance sample across the swept axes -- \
a real sweep, not a degenerate all-zero placeholder"
);
}
fn blank_curves() -> TiltPerformanceCurves {
let axis = AxisTiltCurves {
brilliance_pct: [0.0; indicatrix_vault::model::tilt_curves::TILT_CURVE_POINTS_PER_AXIS],
extinction_pct: [0.0; indicatrix_vault::model::tilt_curves::TILT_CURVE_POINTS_PER_AXIS],
windowing_pct: [0.0; indicatrix_vault::model::tilt_curves::TILT_CURVE_POINTS_PER_AXIS],
};
TiltPerformanceCurves {
axes: [axis; TILT_CURVE_AXIS_COUNT],
}
}
#[test]
fn save_tilt_curves_for_entry_fails_cleanly_for_a_nonexistent_entry() {
let db = Database::new(Some(":memory:")).expect("in-memory database must open");
let db = std::sync::Mutex::new(db);
let saved = save_tilt_curves_for_entry(&db, 999_999, &blank_curves());
assert!(!saved, "no diagram_entries row exists for this id");
}
}