refactor: split utils into math module

This commit is contained in:
2026-08-13 17:42:21 +02:00
parent c8b07b168a
commit cf513352bb
9 changed files with 158 additions and 152 deletions

View File

@@ -1,9 +1,10 @@
use crate::logic::{ use crate::logic::{
field::Field, field::Field,
pawn::{Pawn, PawnState}, math::{position::Position, vector::Vector2D},
pawn::{CapturePath, Pawn, PawnState},
player::Player, player::Player,
utils::{CapturePath, DeltaPosition, Position},
}; };
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use log::{debug, info, warn}; use log::{debug, info, warn};
@@ -20,11 +21,10 @@ impl Board {
info!("Creating new board of size: {}", size); info!("Creating new board of size: {}", size);
player1.end_row = Some(size - 1); player1.end_row = Some(size - 1);
player1.vertical_direction = Some(crate::logic::utils::DeltaPosition { row: 1, column: 0 }); player1.vertical_direction = Some(Vector2D { row: 1, column: 0 });
player2.end_row = Some(0); player2.end_row = Some(0);
player2.vertical_direction = player2.vertical_direction = Some(Vector2D { row: -1, column: 0 });
Some(crate::logic::utils::DeltaPosition { row: -1, column: 0 });
let p1_ref: &Player = &*player1; let p1_ref: &Player = &*player1;
let p2_ref: &Player = &*player2; let p2_ref: &Player = &*player2;
@@ -96,7 +96,7 @@ impl Board {
fn get_available_moves(&self, pos: Position, player: &Player) -> Option<Vec<Position>> { fn get_available_moves(&self, pos: Position, player: &Player) -> Option<Vec<Position>> {
let mut available_moves: Vec<Position> = vec![]; let mut available_moves: Vec<Position> = vec![];
let mut possible_directions: Vec<DeltaPosition> = vec![]; let mut possible_directions: Vec<Vector2D> = vec![];
if !pos.is_in_range(self.size) { if !pos.is_in_range(self.size) {
debug!( debug!(
@@ -115,14 +115,14 @@ impl Board {
return None; return None;
}; };
possible_directions.push(DeltaPosition { row: 0, column: -1 } + direction); possible_directions.push(Vector2D { row: 0, column: -1 } + direction);
possible_directions.push(DeltaPosition { row: 0, column: 1 } + direction); possible_directions.push(Vector2D { row: 0, column: 1 } + direction);
let max_multiplier: usize; let max_multiplier: usize;
if pawn.state == PawnState::Dame { if pawn.state == PawnState::Dame {
possible_directions.push(DeltaPosition { row: 0, column: -1 } - direction); possible_directions.push(Vector2D { row: 0, column: -1 } - direction);
possible_directions.push(DeltaPosition { row: 0, column: 1 } - direction); possible_directions.push(Vector2D { row: 0, column: 1 } - direction);
max_multiplier = self.size - 1; max_multiplier = self.size - 1;
} else { } else {
max_multiplier = 1; max_multiplier = 1;
@@ -162,7 +162,7 @@ impl Board {
return false; return false;
} }
let delta_distance: DeltaPosition = to - from; let delta_distance: Vector2D = to - from;
let player_direction = player let player_direction = player
.vertical_direction .vertical_direction
.expect("Player vertical_direction not set!"); .expect("Player vertical_direction not set!");

View File

@@ -1,6 +1,6 @@
use std::fmt; use std::fmt;
use crate::logic::{pawn::Pawn, utils::Position}; use crate::logic::{math::position::Position, pawn::Pawn};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Field { pub struct Field {

2
src/logic/math/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod position;
pub mod vector;

View File

@@ -0,0 +1,50 @@
use core::fmt;
use std::ops::Sub;
use log::debug;
use crate::logic::math::vector::Vector2D;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Position {
pub row: usize,
pub column: usize,
}
impl fmt::Display for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.row, self.column)
}
}
impl Position {
pub fn checked_add(&self, delta: &Vector2D) -> Option<Position> {
let new_row = self.row.checked_add_signed(delta.row as isize)?;
let new_column = self.column.checked_add_signed(delta.column as isize)?;
debug!("Adding row: {} + {} = {}", self.row, delta.row, new_row);
debug!(
"Adding column: {} + {} = {}",
self.column, delta.column, new_column
);
Some(Position {
row: new_row,
column: new_column,
})
}
pub fn is_in_range(&self, range: usize) -> bool {
self.row < range && self.column < range
}
}
impl Sub for Position {
type Output = Vector2D;
fn sub(self, rhs: Self) -> Self::Output {
Vector2D {
row: self.row as i8 - rhs.row as i8,
column: self.column as i8 - rhs.column as i8,
}
}
}

86
src/logic/math/vector.rs Normal file
View File

@@ -0,0 +1,86 @@
use core::fmt;
use std::ops::{Add, Mul, Sub};
/// Vector for moving `Position`
#[derive(Debug, Copy, Clone)]
pub struct Vector2D {
pub row: i8,
pub column: i8,
}
impl fmt::Display for Vector2D {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.row, self.column)
}
}
impl Add for Vector2D {
type Output = Vector2D;
fn add(self, rhs: Vector2D) -> Self::Output {
Vector2D {
row: self.row + rhs.row,
column: self.column + rhs.column,
}
}
}
impl Sub for Vector2D {
type Output = Vector2D;
fn sub(self, rhs: Vector2D) -> Self::Output {
Vector2D {
row: self.row - rhs.row,
column: self.column - rhs.column,
}
}
}
impl Mul<usize> for Vector2D {
type Output = Vector2D;
fn mul(self, rhs: usize) -> Self::Output {
Vector2D {
row: self.row * rhs as i8,
column: self.column * rhs as i8,
}
}
}
#[cfg(test)]
mod tests {
use crate::logic::math::{position::Position, vector::Vector2D};
fn init_logger() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[test]
fn test_adding_positions() {
init_logger();
let pos1: Position = Position { row: 1, column: 1 };
let delta_ok: Vector2D = Vector2D { row: 1, column: 1 };
let result1: Option<Position> = pos1.checked_add(&delta_ok);
assert!(result1.is_some());
assert_eq!(result1.unwrap(), Position { row: 2, column: 2 });
let delta_minus_ok: Vector2D = Vector2D {
row: -1,
column: -1,
};
let result1: Option<Position> = pos1.checked_add(&delta_minus_ok);
assert!(result1.is_some());
assert_eq!(result1.unwrap(), Position { row: 0, column: 0 });
let delta_not_ok: Vector2D = Vector2D {
row: -10,
column: -10,
};
let result3: Option<Position> = pos1.checked_add(&delta_not_ok);
assert!(result3.is_none());
}
}

View File

@@ -1,5 +1,5 @@
mod board; mod board;
mod field; mod field;
mod math;
mod pawn; mod pawn;
mod player; mod player;
mod utils;

View File

@@ -1,6 +1,6 @@
use uuid::Uuid; use uuid::Uuid;
use crate::logic::{player::Player, utils::Position}; use crate::logic::{math::position::Position, player::Player};
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
pub enum PawnState { pub enum PawnState {
@@ -24,3 +24,7 @@ impl Pawn {
} }
} }
} }
pub struct CapturePath {
pub steps: Vec<Position>,
}

View File

@@ -2,12 +2,12 @@ use std::fmt::Display;
use uuid::Uuid; use uuid::Uuid;
use crate::logic::utils::DeltaPosition; use crate::logic::math::vector::Vector2D;
pub struct Player { pub struct Player {
pub name: String, pub name: String,
pub id: Uuid, pub id: Uuid,
pub vertical_direction: Option<DeltaPosition>, pub vertical_direction: Option<Vector2D>,
pub end_row: Option<usize>, pub end_row: Option<usize>,
} }

View File

@@ -1,136 +0,0 @@
use core::fmt;
use std::ops::{Add, Mul, Sub};
use log::debug;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Position {
pub row: usize,
pub column: usize,
}
impl fmt::Display for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.row, self.column)
}
}
impl Position {
pub fn checked_add(&self, delta: &DeltaPosition) -> Option<Position> {
let new_row = self.row.checked_add_signed(delta.row as isize)?;
let new_column = self.column.checked_add_signed(delta.column as isize)?;
debug!("Adding row: {} + {} = {}", self.row, delta.row, new_row);
debug!(
"Adding column: {} + {} = {}",
self.column, delta.column, new_column
);
Some(Position {
row: new_row,
column: new_column,
})
}
pub fn is_in_range(&self, range: usize) -> bool {
self.row < range && self.column < range
}
}
impl Sub for Position {
type Output = DeltaPosition;
fn sub(self, rhs: Self) -> Self::Output {
DeltaPosition {
row: self.row as i8 - rhs.row as i8,
column: self.column as i8 - rhs.column as i8,
}
}
}
/// Vector for moving `Position`
#[derive(Debug, Copy, Clone)]
pub struct DeltaPosition {
pub row: i8,
pub column: i8,
}
impl fmt::Display for DeltaPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.row, self.column)
}
}
impl Add for DeltaPosition {
type Output = DeltaPosition;
fn add(self, rhs: DeltaPosition) -> Self::Output {
DeltaPosition {
row: self.row + rhs.row,
column: self.column + rhs.column,
}
}
}
impl Sub for DeltaPosition {
type Output = DeltaPosition;
fn sub(self, rhs: DeltaPosition) -> Self::Output {
DeltaPosition {
row: self.row - rhs.row,
column: self.column - rhs.column,
}
}
}
impl Mul<usize> for DeltaPosition {
type Output = DeltaPosition;
fn mul(self, rhs: usize) -> Self::Output {
DeltaPosition {
row: self.row * rhs as i8,
column: self.column * rhs as i8,
}
}
}
pub struct CapturePath {
pub steps: Vec<Position>,
}
#[cfg(test)]
mod tests {
use super::*;
fn init_logger() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[test]
fn test_adding_positions() {
init_logger();
let pos1: Position = Position { row: 1, column: 1 };
let delta_ok: DeltaPosition = DeltaPosition { row: 1, column: 1 };
let result1: Option<Position> = pos1.checked_add(&delta_ok);
assert!(result1.is_some());
assert_eq!(result1.unwrap(), Position { row: 2, column: 2 });
let delta_minus_ok: DeltaPosition = DeltaPosition {
row: -1,
column: -1,
};
let result1: Option<Position> = pos1.checked_add(&delta_minus_ok);
assert!(result1.is_some());
assert_eq!(result1.unwrap(), Position { row: 0, column: 0 });
let delta_not_ok: DeltaPosition = DeltaPosition {
row: -10,
column: -10,
};
let result3: Option<Position> = pos1.checked_add(&delta_not_ok);
assert!(result3.is_none());
}
}