diff --git a/src/engine.rs b/src/engine.rs index 6f66b21..05c05c4 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -7,7 +7,8 @@ use models::coordinate::Coordinate; use placement_error::PlacementError; use rules; use models::tile::Tile; - +use standard_tile_factory::StandardTileFactory; +use tile_factory::TileFactory; type Result = ::std::result::Result>; @@ -15,30 +16,40 @@ pub type TileMap = HashMap; #[derive(Debug, Clone, PartialEq)] pub struct Engine { - tiles: TileMap, + board: TileMap, + tile_pool: Vec, } impl Engine { pub fn new() -> Self { - let mut tiles = HashMap::new(); + let tile_pool = StandardTileFactory::get_tile_pool(); + Self::new_with_tile_pool(tile_pool) + } - tiles.insert([0, 0].into(), (Tile::new(), Orientation::Up)); + pub fn new_with_tile_pool(tile_pool: Vec) -> Self { + let tiles = HashMap::new(); - Engine { tiles: tiles } + Engine { + board: tiles, + tile_pool: tile_pool, + } } - // This will avoid tiles being ever mutable. - pub fn get_tiles(&self) -> &TileMap { - &self.tiles + // This will avoid tiles ever being mutable. + pub fn get_board(&self) -> &TileMap { + &self.board } pub fn place_next>(&self, coordinate: T, orientation: Orientation) -> Result { - let next_tile = Tile::new(); - - self.place(next_tile, coordinate, orientation) + if self.tile_pool.len() >= 1 { + let next_tile = self.tile_pool[0].clone(); + self.place(next_tile, coordinate, orientation) + } else { + Err(vec![PlacementError::PoolOutOfTiles]) + } } fn place>(&self, @@ -48,18 +59,27 @@ impl Engine { -> Result { let coordinate: Coordinate = coordinate.into(); - let broken_rules = rules::check(self.get_tiles(), &tile, &coordinate, &orientation); + let broken_rules = rules::check(self.get_board(), &tile, &coordinate, &orientation); if broken_rules.is_err() { return Err(broken_rules.unwrap_err()); } - let mut new_tiles = self.tiles.clone(); - new_tiles.insert(coordinate, (tile, orientation)); - let new_engine = Engine { tiles: new_tiles }; + let mut new_board = self.board.clone(); + new_board.insert(coordinate, (tile, orientation)); + let (_, new_tile_pool) = self.tile_pool.split_first().unwrap(); + + let new_engine = Engine { + board: new_board, + tile_pool: new_tile_pool.to_vec(), + }; Ok(new_engine) } + + pub fn get_next_tile(&self) -> Option { + Some(Tile::new()) + } } #[cfg(test)] @@ -68,80 +88,61 @@ mod test { #[test] fn test_can_place_tile() { - let engine = Engine::new(); let tile = Tile::new(); + let engine = Engine::new_with_tile_pool(vec![tile.clone()]); - let new_engine = engine.place(tile, [0, 1], Orientation::Up); - - assert!(new_engine.is_ok()); - } - - #[test] - fn test_can_place_next_tile() { - let engine = Engine::new(); - - let new_engine = engine.place_next([0, 1], Orientation::Up); + let place_result = engine.place(tile, [0, 1], Orientation::Up); - assert!(new_engine.is_ok()); + assert!(place_result.is_ok()); } #[test] fn test_placing_not_adjectent_returns_error() { let engine = Engine::new(); - let new_engine = engine.place_next([0, 99], Orientation::Up); - - assert!(new_engine.is_err()); - } + let place_result = engine.place_next([0, 99], Orientation::Up); - #[test] - fn test_new_has_center_tile() { - assert!(Engine::new() - .get_tiles() - .contains_key(&Coordinate::from([0, 0]))); - } - - #[test] - fn test_new_only_has_single_tile() { - assert_eq!(1, Engine::new().get_tiles().len()); + assert!(place_result.is_err()); } #[test] - fn test_coord_exists_in_tiles_after_place_next() { - let engine = Engine::new(); - let coordinate = Coordinate::from([0, 1]); + fn test_tile_exists_after_place_next() { + let tile = Tile::new(); + let engine = Engine::new_with_tile_pool(vec![tile]); + let coordinate = Coordinate::from([0, 0]); let new_engine = engine .place_next(coordinate.clone(), Orientation::Up) .unwrap(); - assert!(!engine.get_tiles().contains_key(&coordinate)); - assert!(new_engine.get_tiles().contains_key(&coordinate)); + assert!(!engine.get_board().contains_key(&coordinate)); + assert!(new_engine.get_board().contains_key(&coordinate)); } #[test] - fn test_tile_exists_in_tiles_after_place() { - let engine = Engine::new(); - let coordinate = Coordinate::from([0, 1]); + fn test_tile_exists_after_place() { let tile = Tile::new(); + let engine = Engine::new_with_tile_pool(vec![tile.clone()]); + let coordinate = Coordinate::from([0, 0]); let orientation = Orientation::Up; let new_engine = engine .place(tile.clone(), coordinate.clone(), orientation.clone()) .unwrap(); - let original_contains_tile = engine.get_tiles().contains_key(&coordinate); - let new_contained_tile_placement = new_engine.get_tiles().get(&coordinate).unwrap(); + let original_contains_tile = engine.get_board().contains_key(&coordinate); + let new_contained_tile_placement = new_engine.get_board().get(&coordinate).unwrap(); assert!(!original_contains_tile); assert_eq!(new_contained_tile_placement, &(tile, orientation)); } #[test] - fn test_cannot_place_on_center() { - let engine = Engine::new(); - let result = engine.place_next([0, 0], Orientation::Up); + fn test_can_get_next_tile() { + let tile = Tile::new(); + let engine = Engine::new_with_tile_pool(vec![tile]); + + let next_tile = engine.get_next_tile(); - assert_eq!(result, - Err(vec![PlacementError::TileAlreadyAtCoordinate, PlacementError::NotAdjacent])); + assert!(next_tile.is_some()); } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index f90b8da..7ab24d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,8 @@ mod models; mod engine; mod placement_error; mod rules; +mod tile_factory; +mod standard_tile_factory; use models::direction; diff --git a/src/models/mod.rs b/src/models/mod.rs index 2add75b..6c5dca8 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -3,5 +3,3 @@ pub mod feature; pub mod tile; pub mod coordinate; pub mod orientation; - -use ::*; diff --git a/src/models/orientation.rs b/src/models/orientation.rs index 73c447f..ef049e4 100644 --- a/src/models/orientation.rs +++ b/src/models/orientation.rs @@ -1,4 +1,5 @@ #[derive(PartialEq, Eq, Debug, Clone)] +#[allow(dead_code)] pub enum Orientation { Up, Right, diff --git a/src/placement_error.rs b/src/placement_error.rs index 4db8bf6..8f4dbb2 100644 --- a/src/placement_error.rs +++ b/src/placement_error.rs @@ -1,5 +1,7 @@ #[derive(Debug, PartialEq)] +#[allow(dead_code)] pub enum PlacementError { NotAdjacent, TileAlreadyAtCoordinate, -} \ No newline at end of file + PoolOutOfTiles, +} diff --git a/src/rules.rs b/src/rules.rs index 19f54bf..8fc7e94 100644 --- a/src/rules.rs +++ b/src/rules.rs @@ -6,7 +6,11 @@ use models::tile::Tile; use placement_error::PlacementError; use engine::TileMap; -pub fn check(board: &TileMap, tile: &Tile, coordinate: &Coordinate, orientation: &Orientation) -> Result<(), Vec> { +pub fn check(board: &TileMap, + tile: &Tile, + coordinate: &Coordinate, + orientation: &Orientation) + -> Result<(), Vec> { let checks: Vec Option> = vec![check_tile_already_at_coordinate, check_not_adjecent]; @@ -34,6 +38,10 @@ fn check_tile_already_at_coordinate(board: &TileMap, } fn check_not_adjecent(board: &TileMap, coordinate: &Coordinate) -> Option { + if board.len() == 0 { + return None; + } + //////// UNDERENGINEERED //////// TODO: OVERENGINEER let has_adjecent_tiles = board.contains_key(&[coordinate.x, coordinate.y - 1].into()) || diff --git a/src/standard_tile_factory.rs b/src/standard_tile_factory.rs new file mode 100644 index 0000000..5058ff3 --- /dev/null +++ b/src/standard_tile_factory.rs @@ -0,0 +1,10 @@ +use tile_factory::TileFactory; +use models::tile::Tile; + +pub struct StandardTileFactory; + +impl TileFactory for StandardTileFactory { + fn get_tile_pool() -> Vec { + Vec::new() + } +} diff --git a/src/tile_factory.rs b/src/tile_factory.rs new file mode 100644 index 0000000..f6402d5 --- /dev/null +++ b/src/tile_factory.rs @@ -0,0 +1,5 @@ +use models::tile::Tile; + +pub trait TileFactory { + fn get_tile_pool() -> Vec; +}