use core::fmt; use plate_tool_lib::plate::PlateFormat; use plate_tool_lib::plate_instances::{self, PlateInstance}; use plate_tool_lib::transfer_region_cache::TransferRegionCache; #[derive(Default, serde::Serialize, serde::Deserialize)] pub struct MainState { /// Stores all plates and transfers /// /// It is not guaranteed that the current_* variables will refer /// to UUIDs that exist in the lists, only that they did at one time. /// This can happen if a plate or transfer is removed and set_* is not called. pub source_plates: Vec, pub destination_plates: Vec, pub transfers: Vec, current_source: Option, current_destination: Option, current_transfer: Option, #[serde(skip)] pub transfer_region_cache: plate_tool_lib::transfer_region_cache::TransferRegionCache, } impl MainState { pub fn get_current_source_uuid(&self) -> Option { self.current_source } pub fn get_current_source_plateinstance( &self, ) -> Option<&plate_tool_lib::plate_instances::PlateInstance> { if let Some(id) = self.current_source { self.source_plates.iter().find(|x| x.get_uuid() == id) } else { None } } pub fn get_current_destination_uuid(&self) -> Option { self.current_destination } pub fn get_current_destination_plateinstance( &self, ) -> Option<&plate_tool_lib::plate_instances::PlateInstance> { if let Some(id) = self.current_destination { self.destination_plates.iter().find(|x| x.get_uuid() == id) } else { None } } pub fn get_current_transfer_uuid(&self) -> Option { self.current_transfer } pub fn get_current_transfer_info(&self) -> Option<&plate_tool_lib::transfer::Transfer> { if let Some(id) = self.current_transfer { self.transfers.iter().find(|x| x.get_uuid() == id) } else { None } } pub fn get_current_source_transfers(&self) -> Option> { let source_uuid = self.get_current_source_uuid(); if let Some(source_uuid) = source_uuid { Some( self.transfers .iter() .filter(|tr| tr.source_id == source_uuid) .collect(), ) } else { None } } pub fn get_current_destination_transfers(&self) -> Option> { let destination_uuid = self.get_current_destination_uuid(); if let Some(destination_uuid) = destination_uuid { Some( self.transfers .iter() .filter(|tr| tr.dest_id == destination_uuid) .collect(), ) } else { None } } pub fn set_current_source(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool { if self.check_source_exists(id) { self.current_source = Some(id); self.set_no_current_transfer(); true } else { false } } pub fn set_current_destination(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool { if self.check_destination_exists(id) { self.current_destination = Some(id); self.set_no_current_transfer(); true } else { false } } pub fn set_current_transfer(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool { if let Some(tr) = self.transfers.iter().find(|x| x.get_uuid() == id) { let source_exists = self.check_source_exists(tr.source_id); let destination_exists = self.check_destination_exists(tr.dest_id); if source_exists && destination_exists { self.current_transfer = Some(id); self.current_source = Some(tr.source_id); self.current_destination = Some(tr.dest_id); } true } else { false } } pub fn set_no_current_source(&mut self) { self.current_source = None; } pub fn set_no_current_destination(&mut self) { self.current_destination = None; } pub fn set_no_current_transfer(&mut self) { self.current_transfer = None; } fn check_source_exists(&self, id: plate_tool_lib::uuid::Uuid) -> bool { self.source_plates .iter() .map(|x| x.get_uuid()) .find(|x| *x == id) .is_some() } pub fn get_source_by_uuid(&self, id: plate_tool_lib::uuid::Uuid) -> Option<&PlateInstance> { self.source_plates .iter() .find(|x| x.get_uuid() == id) } fn check_destination_exists(&self, id: plate_tool_lib::uuid::Uuid) -> bool { self.destination_plates .iter() .map(|x| x.get_uuid()) .find(|x| *x == id) .is_some() } pub fn get_destination_by_uuid(&self, id: plate_tool_lib::uuid::Uuid) -> Option<&PlateInstance> { self.destination_plates .iter() .find(|x| x.get_uuid() == id) } } impl fmt::Debug for MainState { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { #[derive(Debug)] #[allow(dead_code)] struct SelectedFields<'a> { pub source_plates: &'a Vec, pub destination_plates: &'a Vec, pub transfers: &'a Vec, current_source: &'a Option, current_destination: &'a Option, current_transfer: &'a Option, } let Self { source_plates, destination_plates, transfers, current_source, current_destination, current_transfer, transfer_region_cache: _, } = self; fmt::Debug::fmt( &SelectedFields { source_plates, destination_plates, transfers, current_source, current_destination, current_transfer, }, f, ) } } pub fn construct_fake_mainstate() -> MainState { let src_plate: plate_tool_lib::plate_instances::PlateInstance = plate_instances::PlateInstance::new( plate_tool_lib::plate::PlateType::Source, PlateFormat::W96, "src1".to_owned(), ); let dest_plate: plate_tool_lib::plate_instances::PlateInstance = plate_instances::PlateInstance::new( plate_tool_lib::plate::PlateType::Destination, PlateFormat::W96, "dest1".to_owned(), ); let well_a1 = plate_tool_lib::Well { row: 1, col: 1 }; let well_c3 = plate_tool_lib::Well { row: 3, col: 3 }; let well_a5 = plate_tool_lib::Well { row: 1, col: 5 }; let transfer1_region: plate_tool_lib::transfer_region::TransferRegion = plate_tool_lib::transfer_region::TransferRegion { source_plate: src_plate.plate, source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3), dest_plate: dest_plate.plate, dest_region: plate_tool_lib::transfer_region::Region::Point(well_a1), interleave_source: (1, 1), interleave_dest: (1, 1), }; let transfer1: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new( src_plate.clone(), dest_plate.clone(), transfer1_region, "Shrimp".to_owned(), ); let transfer2_region: plate_tool_lib::transfer_region::TransferRegion = plate_tool_lib::transfer_region::TransferRegion { source_plate: src_plate.plate, source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3), dest_plate: dest_plate.plate, dest_region: plate_tool_lib::transfer_region::Region::Point(well_a5), interleave_source: (1, 1), interleave_dest: (2, 2), }; let transfer2: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new( src_plate.clone(), dest_plate.clone(), transfer2_region, "Shrimp".to_owned(), ); MainState { source_plates: vec![src_plate], destination_plates: vec![dest_plate], transfers: vec![transfer1, transfer2], current_source: None, current_destination: None, current_transfer: None, transfer_region_cache: TransferRegionCache::default(), } }