i love clippy
This commit is contained in:
parent
af5bbd466c
commit
c88a34595e
|
@ -56,7 +56,6 @@ pub fn MainWindow() -> Html {
|
||||||
|
|
||||||
let new_button_callback = {
|
let new_button_callback = {
|
||||||
let main_dispatch = main_dispatch.clone();
|
let main_dispatch = main_dispatch.clone();
|
||||||
let ct_dispatch = ct_dispatch.clone();
|
|
||||||
Callback::from(move |_| {
|
Callback::from(move |_| {
|
||||||
let window = web_sys::window().unwrap();
|
let window = web_sys::window().unwrap();
|
||||||
let confirm =
|
let confirm =
|
||||||
|
@ -73,12 +72,12 @@ pub fn MainWindow() -> Html {
|
||||||
let export_csv_button_callback = {
|
let export_csv_button_callback = {
|
||||||
let main_state = main_state.clone();
|
let main_state = main_state.clone();
|
||||||
Callback::from(move |_| {
|
Callback::from(move |_| {
|
||||||
if main_state.transfers.len() == 0 {
|
if main_state.transfers.is_empty() {
|
||||||
web_sys::window()
|
web_sys::window()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.alert_with_message("No transfers to export.")
|
.alert_with_message("No transfers to export.")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
return ();
|
return;
|
||||||
}
|
}
|
||||||
web_sys::window().unwrap().alert_with_message("CSV export is currently not importable. Export as JSON if you'd like to back up your work!").unwrap();
|
web_sys::window().unwrap().alert_with_message("CSV export is currently not importable. Export as JSON if you'd like to back up your work!").unwrap();
|
||||||
if let Ok(csv) = state_to_csv(&main_state) {
|
if let Ok(csv) = state_to_csv(&main_state) {
|
||||||
|
@ -88,7 +87,6 @@ pub fn MainWindow() -> Html {
|
||||||
};
|
};
|
||||||
|
|
||||||
let export_json_button_callback = {
|
let export_json_button_callback = {
|
||||||
let main_state = main_state.clone();
|
|
||||||
Callback::from(move |_| {
|
Callback::from(move |_| {
|
||||||
if let Ok(json) = serde_json::to_string(&main_state) {
|
if let Ok(json) = serde_json::to_string(&main_state) {
|
||||||
save_str(&json, "plate-tool-state.json");
|
save_str(&json, "plate-tool-state.json");
|
||||||
|
@ -102,7 +100,6 @@ pub fn MainWindow() -> Html {
|
||||||
};
|
};
|
||||||
|
|
||||||
let import_json_button_callback = {
|
let import_json_button_callback = {
|
||||||
let main_dispatch = main_dispatch.clone();
|
|
||||||
Callback::from(move |_| {
|
Callback::from(move |_| {
|
||||||
let window = web_sys::window().unwrap();
|
let window = web_sys::window().unwrap();
|
||||||
let document = window.document().unwrap();
|
let document = window.document().unwrap();
|
||||||
|
@ -119,7 +116,7 @@ pub fn MainWindow() -> Html {
|
||||||
modal.remove();
|
modal.remove();
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
modal.set_onclose(Some(&onclose_callback.as_ref().unchecked_ref()));
|
modal.set_onclose(Some(onclose_callback.as_ref().unchecked_ref()));
|
||||||
onclose_callback.forget();
|
onclose_callback.forget();
|
||||||
|
|
||||||
let form = document
|
let form = document
|
||||||
|
@ -164,14 +161,14 @@ pub fn MainWindow() -> Html {
|
||||||
modal.close();
|
modal.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fr.set_onload(Some(&onload.as_ref().unchecked_ref()));
|
fr.set_onload(Some(onload.as_ref().unchecked_ref()));
|
||||||
onload.forget(); // Magic (don't touch)
|
onload.forget(); // Magic (don't touch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
input.set_onchange(Some(&input_callback.as_ref().unchecked_ref()));
|
input.set_onchange(Some(input_callback.as_ref().unchecked_ref()));
|
||||||
input_callback.forget(); // Magic straight from the docs, don't touch :(
|
input_callback.forget(); // Magic straight from the docs, don't touch :(
|
||||||
|
|
||||||
modal.append_child(&form).unwrap();
|
modal.append_child(&form).unwrap();
|
||||||
|
|
|
@ -18,7 +18,6 @@ pub fn NewPlateDialog(props: &NewPlateDialogProps) -> Html {
|
||||||
let (_, dispatch) = use_store::<MainState>();
|
let (_, dispatch) = use_store::<MainState>();
|
||||||
|
|
||||||
let new_plate_callback = {
|
let new_plate_callback = {
|
||||||
let dispatch = dispatch.clone();
|
|
||||||
let close_callback = props.close_callback.clone();
|
let close_callback = props.close_callback.clone();
|
||||||
Callback::from(move |e: SubmitEvent| {
|
Callback::from(move |e: SubmitEvent| {
|
||||||
e.prevent_default();
|
e.prevent_default();
|
||||||
|
|
|
@ -27,8 +27,6 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html {
|
||||||
let m_start_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
let m_start_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
||||||
let m_end_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
let m_end_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
||||||
let m_stat_handle: UseStateHandle<bool> = use_state_eq(|| false);
|
let m_stat_handle: UseStateHandle<bool> = use_state_eq(|| false);
|
||||||
let m_start = m_start_handle.clone();
|
|
||||||
let m_end = m_end_handle.clone();
|
|
||||||
|
|
||||||
if !(*m_stat_handle) {
|
if !(*m_stat_handle) {
|
||||||
let (pt1, pt2) = match ct_state.transfer.transfer_region.dest_region {
|
let (pt1, pt2) = match ct_state.transfer.transfer_region.dest_region {
|
||||||
|
@ -46,12 +44,12 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html {
|
||||||
let m_stat_handle = m_stat_handle.clone();
|
let m_stat_handle = m_stat_handle.clone();
|
||||||
|
|
||||||
Callback::from(move |(i, j, t)| match t {
|
Callback::from(move |(i, j, t)| match t {
|
||||||
MouseEventType::MOUSEDOWN => {
|
MouseEventType::Mousedown => {
|
||||||
m_start_handle.set(Some((i, j)));
|
m_start_handle.set(Some((i, j)));
|
||||||
m_end_handle.set(Some((i, j)));
|
m_end_handle.set(Some((i, j)));
|
||||||
m_stat_handle.set(true);
|
m_stat_handle.set(true);
|
||||||
}
|
}
|
||||||
MouseEventType::MOUSEENTER => {
|
MouseEventType::Mouseenter => {
|
||||||
if *m_stat_handle {
|
if *m_stat_handle {
|
||||||
m_end_handle.set(Some((i, j)));
|
m_end_handle.set(Some((i, j)));
|
||||||
}
|
}
|
||||||
|
@ -79,7 +77,6 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html {
|
||||||
let mouseup_callback = {
|
let mouseup_callback = {
|
||||||
let m_start_handle = m_start_handle.clone();
|
let m_start_handle = m_start_handle.clone();
|
||||||
let m_end_handle = m_end_handle.clone();
|
let m_end_handle = m_end_handle.clone();
|
||||||
let m_stat_handle = m_stat_handle.clone();
|
|
||||||
|
|
||||||
Callback::from(move |_: MouseEvent| {
|
Callback::from(move |_: MouseEvent| {
|
||||||
m_stat_handle.set(false);
|
m_stat_handle.set(false);
|
||||||
|
@ -111,10 +108,10 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html {
|
||||||
let row = (1..=props.destination_plate.plate.size().1).map(|j| {
|
let row = (1..=props.destination_plate.plate.size().1).map(|j| {
|
||||||
html! {
|
html! {
|
||||||
<DestPlateCell i={i} j={j}
|
<DestPlateCell i={i} j={j}
|
||||||
selected={super::source_plate::in_rect(*m_start.clone(), *m_end.clone(), (i,j))}
|
selected={super::source_plate::in_rect(*m_start_handle.clone(), *m_end_handle.clone(), (i,j))}
|
||||||
mouse={mouse_callback.clone()}
|
mouse={mouse_callback.clone()}
|
||||||
in_transfer={destination_wells.contains(&(i,j))}
|
in_transfer={destination_wells.contains(&(i,j))}
|
||||||
color={color_map.get(&(i,j)).map(|x| *x).and_then(|y| Some((y,color_counter)))}
|
color={color_map.get(&(i,j)).copied().map(|y| (y,color_counter))}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
}).collect::<Html>();
|
}).collect::<Html>();
|
||||||
|
@ -143,8 +140,8 @@ pub fn DestinationPlate(props: &DestinationPlateProps) -> Html {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum MouseEventType {
|
pub enum MouseEventType {
|
||||||
MOUSEDOWN,
|
Mousedown,
|
||||||
MOUSEENTER,
|
Mouseenter,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Properties, PartialEq)]
|
#[derive(Properties, PartialEq)]
|
||||||
|
@ -173,15 +170,15 @@ fn DestPlateCell(props: &DestPlateCellProps) -> Html {
|
||||||
};
|
};
|
||||||
let mouse = Callback::clone(&props.mouse);
|
let mouse = Callback::clone(&props.mouse);
|
||||||
let mouse2 = Callback::clone(&props.mouse);
|
let mouse2 = Callback::clone(&props.mouse);
|
||||||
let (i, j) = (props.i.clone(), props.j.clone());
|
let (i, j) = (props.i, props.j);
|
||||||
|
|
||||||
html! {
|
html! {
|
||||||
<td class={classes!("plate_cell", selected_class, in_transfer_class)}
|
<td class={classes!("plate_cell", selected_class, in_transfer_class)}
|
||||||
onmousedown={move |_| {
|
onmousedown={move |_| {
|
||||||
mouse.emit((i,j, MouseEventType::MOUSEDOWN))
|
mouse.emit((i,j, MouseEventType::Mousedown))
|
||||||
}}
|
}}
|
||||||
onmouseenter={move |_| {
|
onmouseenter={move |_| {
|
||||||
mouse2.emit((i,j, MouseEventType::MOUSEENTER))
|
mouse2.emit((i,j, MouseEventType::Mouseenter))
|
||||||
}}>
|
}}>
|
||||||
<div class="plate_cell_inner"
|
<div class="plate_cell_inner"
|
||||||
style={format!("background: rgba({},{},{},1);", color[0], color[1], color[2])}/>
|
style={format!("background: rgba({},{},{},1);", color[0], color[1], color[2])}/>
|
||||||
|
|
|
@ -27,8 +27,6 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html {
|
||||||
let m_start_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
let m_start_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
||||||
let m_end_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
let m_end_handle: UseStateHandle<Option<(u8, u8)>> = use_state_eq(|| None);
|
||||||
let m_stat_handle: UseStateHandle<bool> = use_state_eq(|| false);
|
let m_stat_handle: UseStateHandle<bool> = use_state_eq(|| false);
|
||||||
let m_start = m_start_handle.clone();
|
|
||||||
let m_end = m_end_handle.clone();
|
|
||||||
|
|
||||||
if !(*m_stat_handle) {
|
if !(*m_stat_handle) {
|
||||||
let (pt1, pt2) = match ct_state.transfer.transfer_region.source_region {
|
let (pt1, pt2) = match ct_state.transfer.transfer_region.source_region {
|
||||||
|
@ -64,12 +62,12 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html {
|
||||||
let m_stat_handle = m_stat_handle.clone();
|
let m_stat_handle = m_stat_handle.clone();
|
||||||
|
|
||||||
Callback::from(move |(i, j, t)| match t {
|
Callback::from(move |(i, j, t)| match t {
|
||||||
MouseEventType::MOUSEDOWN => {
|
MouseEventType::Mousedown => {
|
||||||
m_start_handle.set(Some((i, j)));
|
m_start_handle.set(Some((i, j)));
|
||||||
m_end_handle.set(Some((i, j)));
|
m_end_handle.set(Some((i, j)));
|
||||||
m_stat_handle.set(true);
|
m_stat_handle.set(true);
|
||||||
}
|
}
|
||||||
MouseEventType::MOUSEENTER => {
|
MouseEventType::Mouseenter => {
|
||||||
if *m_stat_handle {
|
if *m_stat_handle {
|
||||||
m_end_handle.set(Some((i, j)));
|
m_end_handle.set(Some((i, j)));
|
||||||
}
|
}
|
||||||
|
@ -80,7 +78,6 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html {
|
||||||
let mouseup_callback = {
|
let mouseup_callback = {
|
||||||
let m_start_handle = m_start_handle.clone();
|
let m_start_handle = m_start_handle.clone();
|
||||||
let m_end_handle = m_end_handle.clone();
|
let m_end_handle = m_end_handle.clone();
|
||||||
let m_stat_handle = m_stat_handle.clone();
|
|
||||||
|
|
||||||
Callback::from(move |_: MouseEvent| {
|
Callback::from(move |_: MouseEvent| {
|
||||||
m_stat_handle.set(false);
|
m_stat_handle.set(false);
|
||||||
|
@ -113,10 +110,10 @@ pub fn SourcePlate(props: &SourcePlateProps) -> Html {
|
||||||
.map(|j| {
|
.map(|j| {
|
||||||
html! {
|
html! {
|
||||||
<SourcePlateCell i={i} j={j}
|
<SourcePlateCell i={i} j={j}
|
||||||
selected={in_rect(*m_start.clone(), *m_end.clone(), (i,j))}
|
selected={in_rect(*m_start_handle.clone(), *m_end_handle.clone(), (i,j))}
|
||||||
mouse={mouse_callback.clone()}
|
mouse={mouse_callback.clone()}
|
||||||
in_transfer={source_wells.contains(&(i,j))}
|
in_transfer={source_wells.contains(&(i,j))}
|
||||||
color={color_map.get(&(i,j)).map(|x| *x).and_then(|y| Some((y,color_counter)))}
|
color={color_map.get(&(i,j)).copied().map(|y| (y,color_counter))}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -156,8 +153,8 @@ pub struct SourcePlateCellProps {
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum MouseEventType {
|
pub enum MouseEventType {
|
||||||
MOUSEDOWN,
|
Mousedown,
|
||||||
MOUSEENTER,
|
Mouseenter,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
|
@ -176,16 +173,16 @@ fn SourcePlateCell(props: &SourcePlateCellProps) -> Html {
|
||||||
};
|
};
|
||||||
let mouse = Callback::clone(&props.mouse);
|
let mouse = Callback::clone(&props.mouse);
|
||||||
let mouse2 = Callback::clone(&props.mouse);
|
let mouse2 = Callback::clone(&props.mouse);
|
||||||
let (i, j) = (props.i.clone(), props.j.clone());
|
let (i, j) = (props.i, props.j);
|
||||||
|
|
||||||
html! {
|
html! {
|
||||||
<td class={classes!("plate_cell", selected_class, in_transfer_class)}
|
<td class={classes!("plate_cell", selected_class, in_transfer_class)}
|
||||||
id={format!("color={:?}", props.color)}
|
id={format!("color={:?}", props.color)}
|
||||||
onmousedown={move |_| {
|
onmousedown={move |_| {
|
||||||
mouse.emit((i,j, MouseEventType::MOUSEDOWN))
|
mouse.emit((i,j, MouseEventType::Mousedown))
|
||||||
}}
|
}}
|
||||||
onmouseenter={move |_| {
|
onmouseenter={move |_| {
|
||||||
mouse2.emit((i,j, MouseEventType::MOUSEENTER))
|
mouse2.emit((i,j, MouseEventType::Mouseenter))
|
||||||
}}>
|
}}>
|
||||||
<div class="plate_cell_inner"
|
<div class="plate_cell_inner"
|
||||||
style={format!("background: rgba({},{},{},1);", color[0], color[1], color[2])}/>
|
style={format!("background: rgba({},{},{},1);", color[0], color[1], color[2])}/>
|
||||||
|
@ -195,12 +192,12 @@ fn SourcePlateCell(props: &SourcePlateCellProps) -> Html {
|
||||||
|
|
||||||
pub fn in_rect(corner1: Option<(u8, u8)>, corner2: Option<(u8, u8)>, pt: (u8, u8)) -> bool {
|
pub fn in_rect(corner1: Option<(u8, u8)>, corner2: Option<(u8, u8)>, pt: (u8, u8)) -> bool {
|
||||||
if let (Some(c1), Some(c2)) = (corner1, corner2) {
|
if let (Some(c1), Some(c2)) = (corner1, corner2) {
|
||||||
return pt.0 <= u8::max(c1.0, c2.0)
|
pt.0 <= u8::max(c1.0, c2.0)
|
||||||
&& pt.0 >= u8::min(c1.0, c2.0)
|
&& pt.0 >= u8::min(c1.0, c2.0)
|
||||||
&& pt.1 <= u8::max(c1.1, c2.1)
|
&& pt.1 <= u8::max(c1.1, c2.1)
|
||||||
&& pt.1 >= u8::min(c1.1, c2.1);
|
&& pt.1 >= u8::min(c1.1, c2.1)
|
||||||
} else {
|
} else {
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,12 @@ impl ColorPalette {
|
||||||
|
|
||||||
pub fn get(&self, t: f64) -> [f64; 3] {
|
pub fn get(&self, t: f64) -> [f64; 3] {
|
||||||
[
|
[
|
||||||
(self.a[0] + self.b[0] * f64::cos(6.28318 * (self.c[0] * t + self.d[0]))) * 255.0,
|
(self.a[0] + self.b[0] * f64::cos(std::f64::consts::TAU * (self.c[0] * t + self.d[0])))
|
||||||
(self.a[1] + self.b[1] * f64::cos(6.28318 * (self.c[1] * t + self.d[1]))) * 255.0,
|
* 255.0,
|
||||||
(self.a[2] + self.b[2] * f64::cos(6.28318 * (self.c[2] * t + self.d[2]))) * 255.0,
|
(self.a[1] + self.b[1] * f64::cos(std::f64::consts::TAU * (self.c[1] * t + self.d[1])))
|
||||||
|
* 255.0,
|
||||||
|
(self.a[2] + self.b[2] * f64::cos(std::f64::consts::TAU * (self.c[2] * t + self.d[2])))
|
||||||
|
* 255.0,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,7 @@ impl Store for MainState {
|
||||||
impl MainState {
|
impl MainState {
|
||||||
pub fn _purge_transfers(&mut self) {
|
pub fn _purge_transfers(&mut self) {
|
||||||
// Removes any transfers for which the associated plates are gone
|
// Removes any transfers for which the associated plates are gone
|
||||||
self.transfers = self
|
self.transfers.retain(|tr| {
|
||||||
.transfers
|
|
||||||
.iter()
|
|
||||||
.filter(|tr| {
|
|
||||||
self.source_plates
|
self.source_plates
|
||||||
.iter()
|
.iter()
|
||||||
.any(|spi| spi.get_uuid() == tr.source_id)
|
.any(|spi| spi.get_uuid() == tr.source_id)
|
||||||
|
@ -52,9 +49,7 @@ impl MainState {
|
||||||
.destination_plates
|
.destination_plates
|
||||||
.iter()
|
.iter()
|
||||||
.any(|dpi| dpi.get_uuid() == tr.dest_id)
|
.any(|dpi| dpi.get_uuid() == tr.dest_id)
|
||||||
})
|
});
|
||||||
.map(|tr| tr.clone())
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_source_plate(&mut self, plate: PlateInstance) {
|
pub fn add_source_plate(&mut self, plate: PlateInstance) {
|
||||||
|
|
|
@ -26,10 +26,10 @@ pub fn TransferMenu() -> Html {
|
||||||
let input = target.and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
|
let input = target.and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
|
||||||
if let Some(input) = input {
|
if let Some(input) = input {
|
||||||
if input.value() == "" {
|
if input.value() == "" {
|
||||||
return ();
|
return;
|
||||||
} // We do not want empty inputs!
|
} // We do not want empty inputs!
|
||||||
ct_dispatch.reduce_mut(|state| {
|
ct_dispatch.reduce_mut(|state| {
|
||||||
state.transfer.name = input.value().clone();
|
state.transfer.name = input.value();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -145,7 +145,6 @@ pub fn TransferMenu() -> Html {
|
||||||
.target()
|
.target()
|
||||||
.expect("Event must have target")
|
.expect("Event must have target")
|
||||||
.dyn_into::<HtmlInputElement>()
|
.dyn_into::<HtmlInputElement>()
|
||||||
.ok()
|
|
||||||
.expect("Must have been emitted by input");
|
.expect("Must have been emitted by input");
|
||||||
if let Ok(num) = input.value().parse::<f32>() {
|
if let Ok(num) = input.value().parse::<f32>() {
|
||||||
ct_dispatch.reduce_mut(|state| {
|
ct_dispatch.reduce_mut(|state| {
|
||||||
|
@ -158,7 +157,6 @@ pub fn TransferMenu() -> Html {
|
||||||
let new_transfer_button_callback = {
|
let new_transfer_button_callback = {
|
||||||
let main_dispatch = main_dispatch.clone();
|
let main_dispatch = main_dispatch.clone();
|
||||||
let main_state = main_state.clone();
|
let main_state = main_state.clone();
|
||||||
let ct_dispatch = ct_dispatch.clone();
|
|
||||||
|
|
||||||
Callback::from(move |_: MouseEvent| {
|
Callback::from(move |_: MouseEvent| {
|
||||||
main_dispatch.reduce_mut(|state| {
|
main_dispatch.reduce_mut(|state| {
|
||||||
|
@ -206,8 +204,7 @@ pub fn TransferMenu() -> Html {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(index) = main_state
|
||||||
if let Some(index) = main_state
|
|
||||||
.transfers
|
.transfers
|
||||||
.iter()
|
.iter()
|
||||||
.position(|t| t.get_uuid() == main_state.selected_transfer)
|
.position(|t| t.get_uuid() == main_state.selected_transfer)
|
||||||
|
@ -216,21 +213,17 @@ pub fn TransferMenu() -> Html {
|
||||||
state.transfers[index] = ct_state.transfer.clone();
|
state.transfers[index] = ct_state.transfer.clone();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let delete_transfer_button_callback = {
|
let delete_transfer_button_callback = {
|
||||||
let main_dispatch = main_dispatch.clone();
|
|
||||||
let main_state = main_state.clone();
|
|
||||||
let ct_state = ct_state.clone();
|
let ct_state = ct_state.clone();
|
||||||
let new_callback = new_transfer_button_callback.clone();
|
let new_callback = new_transfer_button_callback.clone();
|
||||||
|
|
||||||
Callback::from(move |e: MouseEvent| {
|
Callback::from(move |e: MouseEvent| {
|
||||||
if main_state.selected_transfer.is_nil() {
|
if main_state.selected_transfer.is_nil() {
|
||||||
() // Maybe reset transfer?
|
// Maybe reset transfer?
|
||||||
} else {
|
} else if let Some(index) = main_state
|
||||||
if let Some(index) = main_state
|
|
||||||
.transfers
|
.transfers
|
||||||
.iter()
|
.iter()
|
||||||
.position(|t| t.get_uuid() == ct_state.transfer.get_uuid())
|
.position(|t| t.get_uuid() == ct_state.transfer.get_uuid())
|
||||||
|
@ -241,7 +234,6 @@ pub fn TransferMenu() -> Html {
|
||||||
});
|
});
|
||||||
new_callback.emit(e); // We need a new transfer now
|
new_callback.emit(e); // We need a new transfer now
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -336,15 +328,15 @@ impl TryFrom<String> for RegionDisplay {
|
||||||
let row_end: u8 = captures[4]
|
let row_end: u8 = captures[4]
|
||||||
.parse::<u8>()
|
.parse::<u8>()
|
||||||
.or(Err("Row end failed to parse"))?;
|
.or(Err("Row end failed to parse"))?;
|
||||||
return Ok(RegionDisplay {
|
Ok(RegionDisplay {
|
||||||
text: value,
|
text: value,
|
||||||
col_start,
|
col_start,
|
||||||
row_start,
|
row_start,
|
||||||
col_end,
|
col_end,
|
||||||
row_end,
|
row_end,
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
return Err("Regex match failed");
|
Err("Regex match failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,12 +385,12 @@ fn letters_to_num(letters: &str) -> Option<u8> {
|
||||||
let mut num: u8 = 0;
|
let mut num: u8 = 0;
|
||||||
for (i, letter) in letters.chars().rev().enumerate() {
|
for (i, letter) in letters.chars().rev().enumerate() {
|
||||||
let n = letter as u8;
|
let n = letter as u8;
|
||||||
if n < 65 || n > 90 {
|
if !(65..=90).contains(&n) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
num = num.checked_add((26_i32.pow(i as u32) * (n as i32 - 64)).try_into().ok()?)?;
|
num = num.checked_add((26_i32.pow(i as u32) * (n as i32 - 64)).try_into().ok()?)?;
|
||||||
}
|
}
|
||||||
return Some(num);
|
Some(num)
|
||||||
}
|
}
|
||||||
pub fn num_to_letters(num: u8) -> Option<String> {
|
pub fn num_to_letters(num: u8) -> Option<String> {
|
||||||
if num == 0 {
|
if num == 0 {
|
||||||
|
@ -418,7 +410,7 @@ pub fn num_to_letters(num: u8) -> Option<String> {
|
||||||
}
|
}
|
||||||
text.push((64 + digit2) as char);
|
text.push((64 + digit2) as char);
|
||||||
|
|
||||||
return Some(text.to_string());
|
Some(text.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub fn Tree(props: &TreeProps) -> Html {
|
||||||
let target: Option<EventTarget> = e.target();
|
let target: Option<EventTarget> = e.target();
|
||||||
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
||||||
if let Some(li) = li {
|
if let Some(li) = li {
|
||||||
if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) {
|
if let Ok(id) = li.id().as_str().parse::<u128>() {
|
||||||
plate_menu_id.set(Some(Uuid::from_u128(id)));
|
plate_menu_id.set(Some(Uuid::from_u128(id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ pub fn Tree(props: &TreeProps) -> Html {
|
||||||
let target: Option<EventTarget> = e.target();
|
let target: Option<EventTarget> = e.target();
|
||||||
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
||||||
if let Some(li) = li {
|
if let Some(li) = li {
|
||||||
if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) {
|
if let Ok(id) = li.id().as_str().parse::<u128>() {
|
||||||
ct_dispatch.reduce_mut(|state| {
|
ct_dispatch.reduce_mut(|state| {
|
||||||
state.transfer.transfer_region.source_region = Region::default();
|
state.transfer.transfer_region.source_region = Region::default();
|
||||||
state.transfer.transfer_region.dest_region = Region::default();
|
state.transfer.transfer_region.dest_region = Region::default();
|
||||||
|
@ -78,7 +78,7 @@ pub fn Tree(props: &TreeProps) -> Html {
|
||||||
let target: Option<EventTarget> = e.target();
|
let target: Option<EventTarget> = e.target();
|
||||||
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
||||||
if let Some(li) = li {
|
if let Some(li) = li {
|
||||||
if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) {
|
if let Ok(id) = li.id().as_str().parse::<u128>() {
|
||||||
ct_dispatch.reduce_mut(|state| {
|
ct_dispatch.reduce_mut(|state| {
|
||||||
state.transfer.transfer_region.source_region = Region::default();
|
state.transfer.transfer_region.source_region = Region::default();
|
||||||
state.transfer.transfer_region.dest_region = Region::default();
|
state.transfer.transfer_region.dest_region = Region::default();
|
||||||
|
@ -94,14 +94,12 @@ pub fn Tree(props: &TreeProps) -> Html {
|
||||||
|
|
||||||
let transfer_select_callback = {
|
let transfer_select_callback = {
|
||||||
let main_state = main_state.clone();
|
let main_state = main_state.clone();
|
||||||
let main_dispatch = main_dispatch.clone();
|
|
||||||
let ct_dispatch = ct_dispatch.clone();
|
|
||||||
|
|
||||||
Callback::from(move |e: MouseEvent| {
|
Callback::from(move |e: MouseEvent| {
|
||||||
let target: Option<EventTarget> = e.target();
|
let target: Option<EventTarget> = e.target();
|
||||||
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
let li = target.and_then(|t| t.dyn_into::<HtmlElement>().ok());
|
||||||
if let Some(li) = li {
|
if let Some(li) = li {
|
||||||
if let Ok(id) = u128::from_str_radix(li.id().as_str(), 10) {
|
if let Ok(id) = li.id().as_str().parse::<u128>() {
|
||||||
let id = Uuid::from_u128(id);
|
let id = Uuid::from_u128(id);
|
||||||
if let Some(transfer) = main_state
|
if let Some(transfer) = main_state
|
||||||
.transfers
|
.transfers
|
||||||
|
@ -218,7 +216,7 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html {
|
||||||
.source_plates
|
.source_plates
|
||||||
.iter()
|
.iter()
|
||||||
.find(|spi| spi.get_uuid() == props.id);
|
.find(|spi| spi.get_uuid() == props.id);
|
||||||
if plate == None {
|
if plate.is_none() {
|
||||||
plate = main_state
|
plate = main_state
|
||||||
.destination_plates
|
.destination_plates
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -234,7 +232,6 @@ fn PlateInfoModal(props: &PlateInfoModalProps) -> Html {
|
||||||
};
|
};
|
||||||
|
|
||||||
let rename_onchange = {
|
let rename_onchange = {
|
||||||
let main_dispatch = main_dispatch.clone();
|
|
||||||
let id = props.id;
|
let id = props.id;
|
||||||
Callback::from(move |e: Event| {
|
Callback::from(move |e: Event| {
|
||||||
log::debug!("Changed name");
|
log::debug!("Changed name");
|
||||||
|
|
|
@ -68,7 +68,7 @@ fn transfer_to_records(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records;
|
records
|
||||||
}
|
}
|
||||||
|
|
||||||
fn records_to_csv(trs: Vec<TransferRecord>) -> Result<String, Box<dyn Error>> {
|
fn records_to_csv(trs: Vec<TransferRecord>) -> Result<String, Box<dyn Error>> {
|
||||||
|
@ -77,5 +77,5 @@ fn records_to_csv(trs: Vec<TransferRecord>) -> Result<String, Box<dyn Error>> {
|
||||||
wtr.serialize(record)?
|
wtr.serialize(record)?
|
||||||
}
|
}
|
||||||
let data = String::from_utf8(wtr.into_inner()?)?;
|
let data = String::from_utf8(wtr.into_inner()?)?;
|
||||||
return Ok(data);
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,9 @@ impl TransferRegion {
|
||||||
wells.push((i, j))
|
wells.push((i, j))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wells;
|
wells
|
||||||
}
|
}
|
||||||
Region::Point(p) => return vec![p],
|
Region::Point(p) => vec![p],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,9 +90,10 @@ impl TransferRegion {
|
||||||
}
|
}
|
||||||
// log::debug!("GDW END.");
|
// log::debug!("GDW END.");
|
||||||
|
|
||||||
return wells;
|
wells
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)] // Resolving gives inherent associated type error
|
||||||
pub fn calculate_map(&self) -> Box<dyn Fn((u8, u8)) -> Option<Vec<(u8, u8)>> + '_> {
|
pub fn calculate_map(&self) -> Box<dyn Fn((u8, u8)) -> Option<Vec<(u8, u8)>> + '_> {
|
||||||
// By validating first, we have a stronger guarantee that
|
// By validating first, we have a stronger guarantee that
|
||||||
// this function will not panic. :)
|
// this function will not panic. :)
|
||||||
|
@ -121,30 +122,30 @@ impl TransferRegion {
|
||||||
// Non-replicate transfers:
|
// Non-replicate transfers:
|
||||||
match self.dest_region {
|
match self.dest_region {
|
||||||
Region::Point((x, y)) => {
|
Region::Point((x, y)) => {
|
||||||
return Box::new(move |(i, j)| {
|
Box::new(move |(i, j)| {
|
||||||
if source_wells.contains(&(i, j)) {
|
if source_wells.contains(&(i, j)) {
|
||||||
// Validity here already checked by self.validate()
|
// Validity here already checked by self.validate()
|
||||||
Some(vec![(
|
Some(vec![(
|
||||||
x + i
|
x + i
|
||||||
.checked_sub(source_ul.0)
|
.checked_sub(source_ul.0)
|
||||||
.expect("Point cannot have been less than UL")
|
.expect("Point cannot have been less than UL")
|
||||||
.checked_div(il_source.0.abs() as u8)
|
.checked_div(il_source.0.unsigned_abs())
|
||||||
.expect("Source interleave cannot be 0")
|
.expect("Source interleave cannot be 0")
|
||||||
.mul(il_dest.0.abs() as u8),
|
.mul(il_dest.0.unsigned_abs()),
|
||||||
y + j
|
y + j
|
||||||
.checked_sub(source_ul.1)
|
.checked_sub(source_ul.1)
|
||||||
.expect("Point cannot have been less than UL")
|
.expect("Point cannot have been less than UL")
|
||||||
.checked_div(il_source.1.abs() as u8)
|
.checked_div(il_source.1.unsigned_abs())
|
||||||
.expect("Source interleave cannot be 0")
|
.expect("Source interleave cannot be 0")
|
||||||
.mul(il_dest.1.abs() as u8),
|
.mul(il_dest.1.unsigned_abs()),
|
||||||
)])
|
)])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
Region::Rect(c1, c2) => {
|
Region::Rect(c1, c2) => {
|
||||||
return Box::new(move |(i, j)| {
|
Box::new(move |(i, j)| {
|
||||||
if source_wells.contains(&(i, j)) {
|
if source_wells.contains(&(i, j)) {
|
||||||
let possible_destination_wells = create_dense_rectangle(&c1, &c2);
|
let possible_destination_wells = create_dense_rectangle(&c1, &c2);
|
||||||
let (d_ul, d_br) = standardize_rectangle(&c1, &c2);
|
let (d_ul, d_br) = standardize_rectangle(&c1, &c2);
|
||||||
|
@ -160,58 +161,60 @@ impl TransferRegion {
|
||||||
);
|
);
|
||||||
let N_s = (
|
let N_s = (
|
||||||
// Number of used source wells
|
// Number of used source wells
|
||||||
(s_dims.0 + il_source.0.abs() as u8 - 1)
|
(s_dims.0 + il_source.0.unsigned_abs() - 1)
|
||||||
.div_euclid(il_source.0.abs() as u8),
|
.div_euclid(il_source.0.unsigned_abs()),
|
||||||
(s_dims.1 + il_source.1.abs() as u8 - 1)
|
(s_dims.1 + il_source.1.unsigned_abs() - 1)
|
||||||
.div_euclid(il_source.1.abs() as u8),
|
.div_euclid(il_source.1.unsigned_abs()),
|
||||||
);
|
);
|
||||||
let count = (
|
let count = (
|
||||||
// How many times can we replicate?
|
// How many times can we replicate?
|
||||||
(1..)
|
(1..)
|
||||||
.position(|n| {
|
.position(|n| {
|
||||||
n * N_s.0 * il_dest.0.abs() as u8 - il_dest.0.abs() as u8 + 1
|
n * N_s.0 * il_dest.0.unsigned_abs() - il_dest.0.unsigned_abs()
|
||||||
|
+ 1
|
||||||
> d_dims.0
|
> d_dims.0
|
||||||
})
|
})
|
||||||
.unwrap() as u8,
|
.unwrap() as u8,
|
||||||
(1..)
|
(1..)
|
||||||
.position(|n| {
|
.position(|n| {
|
||||||
n * N_s.1 * il_dest.1.abs() as u8 - il_dest.1.abs() as u8 + 1
|
n * N_s.1 * il_dest.1.unsigned_abs() - il_dest.1.unsigned_abs()
|
||||||
|
+ 1
|
||||||
> d_dims.1
|
> d_dims.1
|
||||||
})
|
})
|
||||||
.unwrap() as u8,
|
.unwrap() as u8,
|
||||||
);
|
);
|
||||||
let i = i
|
let i = i
|
||||||
.saturating_sub(s_ul.0)
|
.saturating_sub(s_ul.0)
|
||||||
.saturating_div(il_source.0.abs() as u8);
|
.saturating_div(il_source.0.unsigned_abs());
|
||||||
let j = j
|
let j = j
|
||||||
.saturating_sub(s_ul.1)
|
.saturating_sub(s_ul.1)
|
||||||
.saturating_div(il_source.1.abs() as u8);
|
.saturating_div(il_source.1.unsigned_abs());
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
possible_destination_wells
|
possible_destination_wells
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(x, _)| {
|
.filter(|(x, _)| {
|
||||||
x.checked_sub(d_ul.0).unwrap()
|
x.checked_sub(d_ul.0).unwrap()
|
||||||
% (N_s.0 * il_dest.0.abs() as u8) // Counter along x
|
% (N_s.0 * il_dest.0.unsigned_abs()) // Counter along x
|
||||||
== ((il_dest.0.abs() as u8 *i))
|
== (il_dest.0.unsigned_abs() *i)
|
||||||
% (N_s.0 * il_dest.0.abs() as u8)
|
% (N_s.0 * il_dest.0.unsigned_abs())
|
||||||
})
|
})
|
||||||
.filter(|(_, y)| {
|
.filter(|(_, y)| {
|
||||||
y.checked_sub(d_ul.1).unwrap()
|
y.checked_sub(d_ul.1).unwrap()
|
||||||
% (N_s.1 * il_dest.1.abs() as u8) // Counter along u
|
% (N_s.1 * il_dest.1.unsigned_abs()) // Counter along u
|
||||||
== ((il_dest.1.abs() as u8 *j))
|
== (il_dest.1.unsigned_abs() *j)
|
||||||
% (N_s.1 * il_dest.1.abs() as u8)
|
% (N_s.1 * il_dest.1.unsigned_abs())
|
||||||
})
|
})
|
||||||
.filter(|(x, y)| {
|
.filter(|(x, y)| {
|
||||||
// How many times have we replicated? < How many are we allowed
|
// How many times have we replicated? < How many are we allowed
|
||||||
// to replicate?
|
// to replicate?
|
||||||
x.checked_sub(d_ul.0)
|
x.checked_sub(d_ul.0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.div_euclid(N_s.0 * il_dest.0.abs() as u8)
|
.div_euclid(N_s.0 * il_dest.0.unsigned_abs())
|
||||||
< count.0
|
< count.0
|
||||||
&& y.checked_sub(d_ul.1)
|
&& y.checked_sub(d_ul.1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.div_euclid(N_s.1 * il_dest.1.abs() as u8)
|
.div_euclid(N_s.1 * il_dest.1.unsigned_abs())
|
||||||
< count.1
|
< count.1
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -219,7 +222,7 @@ impl TransferRegion {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,7 +268,7 @@ impl TransferRegion {
|
||||||
// Should *not* happen in this function---otherwise
|
// Should *not* happen in this function---otherwise
|
||||||
// we'd get a nasty recursive loop.
|
// we'd get a nasty recursive loop.
|
||||||
|
|
||||||
return Ok(());
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +283,7 @@ fn create_dense_rectangle(c1: &(u8, u8), c2: &(u8, u8)) -> Vec<(u8, u8)> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return points;
|
points
|
||||||
}
|
}
|
||||||
|
|
||||||
fn standardize_rectangle(c1: &(u8, u8), c2: &(u8, u8)) -> ((u8, u8), (u8, u8)) {
|
fn standardize_rectangle(c1: &(u8, u8), c2: &(u8, u8)) -> ((u8, u8), (u8, u8)) {
|
||||||
|
@ -288,10 +291,10 @@ fn standardize_rectangle(c1: &(u8, u8), c2: &(u8, u8)) -> ((u8, u8), (u8, u8)) {
|
||||||
let upper_left_j = u8::min(c1.1, c2.1);
|
let upper_left_j = u8::min(c1.1, c2.1);
|
||||||
let bottom_right_i = u8::max(c1.0, c2.0);
|
let bottom_right_i = u8::max(c1.0, c2.0);
|
||||||
let bottom_right_j = u8::max(c1.1, c2.1);
|
let bottom_right_j = u8::max(c1.1, c2.1);
|
||||||
return (
|
(
|
||||||
(upper_left_i, upper_left_j),
|
(upper_left_i, upper_left_j),
|
||||||
(bottom_right_i, bottom_right_j),
|
(bottom_right_i, bottom_right_j),
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
@ -308,12 +311,12 @@ impl fmt::Display for TransferRegion {
|
||||||
for i in 1..=source_dims.0 {
|
for i in 1..=source_dims.0 {
|
||||||
for j in 1..=source_dims.1 {
|
for j in 1..=source_dims.1 {
|
||||||
if source_wells.contains(&(i, j)) {
|
if source_wells.contains(&(i, j)) {
|
||||||
source_string.push_str("x")
|
source_string.push('x')
|
||||||
} else {
|
} else {
|
||||||
source_string.push_str(".")
|
source_string.push('.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
source_string.push_str("\n");
|
source_string.push('\n');
|
||||||
}
|
}
|
||||||
write!(f, "{}", source_string)?;
|
write!(f, "{}", source_string)?;
|
||||||
|
|
||||||
|
@ -324,12 +327,12 @@ impl fmt::Display for TransferRegion {
|
||||||
for i in 1..=dest_dims.0 {
|
for i in 1..=dest_dims.0 {
|
||||||
for j in 1..=dest_dims.1 {
|
for j in 1..=dest_dims.1 {
|
||||||
if dest_wells.contains(&(i, j)) {
|
if dest_wells.contains(&(i, j)) {
|
||||||
dest_string.push_str("x")
|
dest_string.push('x')
|
||||||
} else {
|
} else {
|
||||||
dest_string.push_str(".")
|
dest_string.push('.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dest_string.push_str("\n");
|
dest_string.push('\n');
|
||||||
}
|
}
|
||||||
write!(f, "{}", dest_string)
|
write!(f, "{}", dest_string)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use plate_tool::App;
|
use plate_tool::App;
|
||||||
use wasm_logger;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
wasm_logger::init(wasm_logger::Config::default());
|
wasm_logger::init(wasm_logger::Config::default());
|
||||||
|
|
Loading…
Reference in New Issue