1use std::cmp;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{relative_from_absolute_position, Position};
6
7pub const MAX_DISTANCE: u32 = 4;
8
9pub fn index_proximity(lhs: u32, rhs: u32) -> u32 {
10 if lhs <= rhs {
11 cmp::min(rhs - lhs, MAX_DISTANCE)
12 } else {
13 cmp::min((lhs - rhs) + 1, MAX_DISTANCE)
14 }
15}
16
17pub fn positions_proximity(lhs: Position, rhs: Position) -> u32 {
18 let (lhs_attr, lhs_index) = relative_from_absolute_position(lhs);
19 let (rhs_attr, rhs_index) = relative_from_absolute_position(rhs);
20 if lhs_attr != rhs_attr {
21 MAX_DISTANCE
22 } else {
23 index_proximity(lhs_index as u32, rhs_index as u32)
24 }
25}
26
27pub fn path_proximity(path: &[Position]) -> u32 {
28 path.windows(2).map(|w| positions_proximity(w[0], w[1])).sum::<u32>()
29}
30
31#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
32#[serde(rename_all = "camelCase")]
33pub enum ProximityPrecision {
34 #[default]
35 ByWord,
36 ByAttribute,
37}