use crate::grid::Grid;
use crate::primitives::ArrowType;
#[inline]
#[allow(dead_code)] const fn is_vertical_arrow(ch: char) -> bool {
matches!(
ch,
'↓' | '↑' |
'⇓' | '⇑' |
'│' | '┃'
)
}
#[inline]
#[allow(dead_code)] const fn is_filled_triangle_arrow(ch: char) -> bool {
matches!(ch, '▼' | '▲')
}
#[inline]
#[allow(dead_code)] const fn is_horizontal_arrow(ch: char) -> bool {
matches!(
ch,
'→' | '←' |
'⇒' | '⇐' |
'⟶' | '⟹' |
'─'
)
}
#[inline]
#[allow(dead_code)] const fn is_downward_arrow(ch: char) -> bool {
matches!(ch, '↓' | '⇓')
}
#[inline]
#[allow(dead_code)] const fn is_upward_arrow(ch: char) -> bool {
matches!(ch, '↑' | '⇑')
}
#[inline]
#[allow(dead_code)] const fn is_rightward_arrow(ch: char) -> bool {
matches!(ch, '→' | '⇒' | '⟶')
}
#[inline]
#[allow(dead_code)] const fn is_leftward_arrow(ch: char) -> bool {
matches!(ch, '←' | '⇐' | '⟹')
}
#[allow(dead_code)] #[must_use]
pub fn detect_vertical_arrows(grid: &Grid) -> Vec<crate::primitives::VerticalArrow> {
let mut arrows = Vec::new();
for col in 0..grid.width() {
let mut row = 0;
while row < grid.height() {
if let Some(ch) = grid.get(row, col) {
if is_vertical_arrow(ch) {
let start_row = row;
let mut end_row = row;
while end_row < grid.height() {
if let Some(c) = grid.get(end_row, col) {
if is_vertical_arrow(c) {
end_row += 1;
} else {
break;
}
} else {
break;
}
}
end_row -= 1;
if start_row < end_row || is_downward_arrow(ch) || is_upward_arrow(ch) {
let is_downward = grid
.get(start_row, col)
.is_none_or(|start_char| !is_upward_arrow(start_char));
let mut arrow_char = grid.get(start_row, col).and_then(|c| {
if is_downward_arrow(c) || is_upward_arrow(c) {
Some(c)
} else {
None
}
});
if arrow_char.is_none() {
for scan_row in start_row..=end_row {
if let Some(c) = grid.get(scan_row, col) {
if is_filled_triangle_arrow(c) {
arrow_char = Some(c);
break;
}
}
}
}
arrows.push(crate::primitives::VerticalArrow {
col,
start_row,
end_row,
arrow_type: ArrowType::Standard,
downward: is_downward,
arrow_char,
});
}
row = end_row + 1;
} else {
row += 1;
}
} else {
row += 1;
}
}
}
arrows
}
#[allow(dead_code)] #[must_use]
pub fn detect_horizontal_arrows(grid: &Grid) -> Vec<crate::primitives::HorizontalArrow> {
let mut arrows = Vec::new();
for row in 0..grid.height() {
let mut col = 0;
while col < grid.width() {
if let Some(ch) = grid.get(row, col) {
if is_horizontal_arrow(ch) {
let start_col = col;
let mut end_col = col;
while end_col < grid.width() {
if let Some(c) = grid.get(row, end_col) {
if is_horizontal_arrow(c) || c == '─' {
end_col += 1;
} else {
break;
}
} else {
break;
}
}
end_col -= 1;
let has_arrow_tip = (start_col..=end_col).any(|c| {
grid.get(row, c)
.is_some_and(|ch| is_rightward_arrow(ch) || is_leftward_arrow(ch))
});
if has_arrow_tip {
let arrow_char = (start_col..=end_col).find_map(|c| {
grid.get(row, c).and_then(|ch| {
if ArrowType::from_char(ch).is_some() {
Some(ch)
} else {
None
}
})
});
arrows.push(crate::primitives::HorizontalArrow {
row,
start_col,
end_col,
arrow_type: ArrowType::Standard,
rightward: true,
arrow_char,
});
}
col = end_col + 1;
} else {
col += 1;
}
} else {
col += 1;
}
}
}
arrows
}