0 indexing is a blight

This commit is contained in:
Emilia Allison 2025-01-04 20:07:19 -05:00
parent d296854580
commit 453ad9ed35
Signed by: emilia
GPG Key ID: 05D5D1107E5100A1
2 changed files with 102 additions and 91 deletions

View File

@ -69,8 +69,18 @@ fn get_hover_well(
start_x: f32, start_x: f32,
start_y: f32, start_y: f32,
radius: f32, radius: f32,
rows: u8,
columns: u8,
) -> Option<(u8, u8)> { ) -> Option<(u8, u8)> {
get_well_from_pos(response.hover_pos(), start_x, start_y, radius) get_well_from_pos(
response.hover_pos(),
start_x,
start_y,
radius,
rows,
columns,
true,
)
} }
fn get_well_from_pos( fn get_well_from_pos(
@ -78,19 +88,35 @@ fn get_well_from_pos(
start_x: f32, start_x: f32,
start_y: f32, start_y: f32,
radius: f32, radius: f32,
rows: u8,
columns: u8,
saturate: bool,
) -> Option<(u8, u8)> { ) -> Option<(u8, u8)> {
// cool fact: the bounds of our frame aren't actually the bounds of what counts
// as hovering. as a result, we have to make sure that we check these bounds here.
// yippee
let max_width = start_x + radius * 2.0 * columns as f32;
let max_height = start_y + radius * 2.0 * rows as f32;
// Some((row, column)) // Some((row, column))
position position
.map(|p| Into::<(f32, f32)>::into(p)) .map(|p| Into::<(f32, f32)>::into(p))
.and_then(|(x, y)| { .and_then(|(x, y)| {
// Check bounds // Check bounds if no saturation
if x < start_x || y < start_y { if !saturate && (x < start_x || y < start_y || x > max_width || y > max_height) {
return None; return None;
} }
// CHECK Bottom Right BOUND
let solved_column: u8 = (x - start_x).div_euclid(radius * 2.0) as u8; let solved_column: u8 = match x {
let solved_row: u8 = (y - start_y).div_euclid(radius * 2.0) as u8; x if (x < start_x) => 1,
x if (x > max_width) => columns,
_ => (x - start_x).div_euclid(radius * 2.0) as u8 + 1u8,
};
let solved_row: u8 = match y {
y if (y < start_y) => 1,
y if (y > max_height) => rows,
_ => (y - start_y).div_euclid(radius * 2.0) as u8 + 1u8,
};
Some((solved_row, solved_column)) Some((solved_row, solved_column))
}) })
@ -110,19 +136,24 @@ fn calculate_shading_for_wells(
for transfer in transfers { for transfer in transfers {
let cache_result = match plate_type { let cache_result = match plate_type {
plate_tool_lib::plate::PlateType::Source => cache.get_or_calculate_source(transfer), plate_tool_lib::plate::PlateType::Source => cache.get_or_calculate_source(transfer),
plate_tool_lib::plate::PlateType::Destination => cache.get_or_calculate_destination(transfer), plate_tool_lib::plate::PlateType::Destination => {
cache.get_or_calculate_destination(transfer)
}
}; };
if let Some(wells) = cache_result { if let Some(wells) = cache_result {
for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) { for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) {
if let Some(mut x) = if let Some(mut x) =
well_infos[well.row as usize * columns as usize + well.col as usize] well_infos[(well.row - 1) as usize * columns as usize + (well.col - 1) as usize]
{ {
x.volume += 5.0; x.volume += 5.0;
x.color = PALETTE.get_ordered(transfer.id, ordered_ids); x.color = PALETTE.get_ordered(transfer.id, ordered_ids);
} else { } else {
well_infos[well.row as usize * columns as usize + well.col as usize] = Some( well_infos
WellInfo::new(5.0, PALETTE.get_ordered(transfer.id, ordered_ids)), [(well.row - 1) as usize * columns as usize + (well.col - 1) as usize] =
); Some(WellInfo::new(
5.0,
PALETTE.get_ordered(transfer.id, ordered_ids),
));
} }
} }
} }
@ -166,15 +197,20 @@ fn add_plate_sub(
state.drag_start_position = Some(response.hover_pos().unwrap()); state.drag_start_position = Some(response.hover_pos().unwrap());
} }
let drag_start_well = get_well_from_pos(state.drag_start_position, start_x, start_y, radius); let drag_start_well = get_well_from_pos(
let hovered_well = get_hover_well(&response, start_x, start_y, radius); state.drag_start_position,
start_x,
start_y,
radius,
rows,
columns,
false,
);
let hovered_well = get_hover_well(&response, start_x, start_y, radius, rows, columns);
if response.clicked() { if response.clicked() {
if let Some(cts) = current_transfer_state { if let Some(cts) = current_transfer_state {
let end_well: Option<Well> = hovered_well.map(|(row, col)| Well { let end_well: Option<Well> = hovered_well.map(|(row, col)| Well { row, col });
row: row + 1,
col: col + 1,
});
if let Some(end_well) = end_well { if let Some(end_well) = end_well {
let new_region = Region::new_from_wells(end_well, None); let new_region = Region::new_from_wells(end_well, None);
let mut cts = cts.lock().unwrap(); let mut cts = cts.lock().unwrap();
@ -189,17 +225,8 @@ fn add_plate_sub(
} }
if response.drag_stopped() { if response.drag_stopped() {
if let Some(cts) = current_transfer_state { if let Some(cts) = current_transfer_state {
let start_well: Well = drag_start_well if let Some(start_well) = drag_start_well.map(|(row, col)| Well { row, col }) {
.map(|(row, col)| Well { let end_well: Option<Well> = hovered_well.map(|(row, col)| Well { row, col });
// Lib uses 1-indexing!
row: row + 1,
col: col + 1,
})
.unwrap();
let end_well: Option<Well> = hovered_well.map(|(row, col)| Well {
row: row + 1,
col: col + 1,
});
let new_region = Region::new_from_wells(start_well, end_well); let new_region = Region::new_from_wells(start_well, end_well);
let mut cts = cts.lock().unwrap(); let mut cts = cts.lock().unwrap();
match plate_type { match plate_type {
@ -209,6 +236,7 @@ fn add_plate_sub(
} }
} }
} }
}
state.drag_start_position = None; state.drag_start_position = None;
} }
@ -227,7 +255,8 @@ fn add_plate_sub(
}; };
let well_infos = { let well_infos = {
// Get non-active transfer info // Get non-active transfer info
let mut well_infos = calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache); let mut well_infos =
calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache);
// Get wells in the current transfer to tack on to well_infos separately // Get wells in the current transfer to tack on to well_infos separately
let current_transfer_wells: Option<Box<[(usize, usize)]>> = { let current_transfer_wells: Option<Box<[(usize, usize)]>> = {
@ -239,27 +268,30 @@ fn add_plate_sub(
.and_then(|x| x.lock().ok()) .and_then(|x| x.lock().ok())
.map(|mut x| x.get_destination_wells()), .map(|mut x| x.get_destination_wells()),
}) })
// Drop back to 0-indexing here .map(|xs| {
.map(|xs| xs.iter().map(|x| (x.row as usize - 1, x.col as usize - 1)).collect()) xs.iter()
.map(|x| (x.row as usize, x.col as usize))
.collect()
})
}; };
if let Some(wells) = current_transfer_wells { if let Some(wells) = current_transfer_wells {
for w in wells { for w in wells {
let well_info = &mut well_infos[w.0 * columns as usize + w.1]; let well_info = &mut well_infos[(w.0 - 1) * columns as usize + (w.1 - 1)];
let volume = well_info.map(|x| x.volume).unwrap_or(0.0) let volume = well_info.map(|x| x.volume).unwrap_or(0.0)
+ current_transfer_state.and_then(|x| x.lock().ok()) + current_transfer_state
.and_then(|x| x.lock().ok())
.map(|x| x.volume) .map(|x| x.volume)
.unwrap_or(0.0); .unwrap_or(0.0);
*well_info = Some(WellInfo { *well_info = Some(WellInfo {
color: [255.0, 255.0, 255.0], color: [255.0, 255.0, 255.0],
volume: 1.0 volume: 1.0,
}) })
} }
} }
well_infos well_infos
}; };
// Plate Frame // Plate Frame
painter.rect_stroke( painter.rect_stroke(
egui::Rect { egui::Rect {
@ -274,11 +306,11 @@ fn add_plate_sub(
); );
// Draw wells // Draw wells
for c_row in 0..rows { for c_row in 1..=rows {
for c_column in 0..columns { for c_column in 1..=columns {
let center = egui::pos2( let center = egui::pos2(
start_x + radius + 2.0 * radius * c_column as f32, start_x + radius + 2.0 * radius * (c_column - 1) as f32,
start_y + radius + 2.0 * radius * c_row as f32, start_y + radius + 2.0 * radius * (c_row - 1) as f32,
); );
// //
@ -286,7 +318,7 @@ fn add_plate_sub(
// //
if let Some(well_info) = if let Some(well_info) =
well_infos[c_row as usize * columns as usize + c_column as usize] well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize]
{ {
painter.circle_filled(center, radius * 0.80, f64_to_color32(well_info.color)); painter.circle_filled(center, radius * 0.80, f64_to_color32(well_info.color));
} }
@ -301,8 +333,8 @@ fn add_plate_sub(
if current_selection.as_ref().is_some_and(|x| { if current_selection.as_ref().is_some_and(|x| {
x.contains_well( x.contains_well(
&Well { &Well {
row: c_row + 1, row: c_row,
col: c_column + 1, col: c_column,
}, },
None, None,
) )
@ -364,11 +396,10 @@ pub fn add_plate(
ui: &mut egui::Ui, ui: &mut egui::Ui,
state: &mut PlateUiState, state: &mut PlateUiState,
) { ) {
match pf { add_plate_sub(
PlateFormat::W96 => add_plate_sub(
size, size,
8, pf.rows(),
12, pf.columns(),
transfers, transfers,
plate_type, plate_type,
ordered_ids, ordered_ids,
@ -376,31 +407,5 @@ pub fn add_plate(
current_transfer_state, current_transfer_state,
ui, ui,
state, state,
), );
PlateFormat::W384 => add_plate_sub(
size,
16,
24,
transfers,
plate_type,
ordered_ids,
cache,
current_transfer_state,
ui,
state,
),
PlateFormat::W1536 => add_plate_sub(
size,
32,
48,
transfers,
plate_type,
ordered_ids,
cache,
current_transfer_state,
ui,
state,
),
_ => unimplemented!(),
}
} }

View File

@ -114,4 +114,10 @@ impl PlateFormat {
PlateFormat::W3456 => (48, 72), PlateFormat::W3456 => (48, 72),
} }
} }
pub fn rows(&self) -> u8 {
self.size().0
}
pub fn columns(&self) -> u8 {
self.size().1
}
} }