From d0c44cdcbe30a15aa0fa9ea0d3d09cba703a341d Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 01:51:08 +0300 Subject: [PATCH 01/10] added methods on buiilder --- src/executor.rs | 7 ++- src/executor/builder.rs | 106 ++++++++++++++++++++++++++++++---------- 2 files changed, 86 insertions(+), 27 deletions(-) diff --git a/src/executor.rs b/src/executor.rs index 6cbb152..31df8ff 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -6,7 +6,10 @@ use std::{ use crate::{Algorithm, Maze, Pos}; -use self::builder::{new_builder, BuildableMazeState, ExecutorBuilder, Unprovided}; +use self::builder::{ + maze_state::{BuildableMazeState, Unprovided}, + new_builder, ExecutorBuilder, +}; /// A guess to pass to the current [`Executor`] at the end of every `progress` call. pub struct Guess(Vec); @@ -112,7 +115,7 @@ where F: Fn(ExecutorBuilder) -> ExecutorBuilder, { let operation = builder; - let mut builder = (operation)(new_builder()); + let builder = (operation)(new_builder()); let (maze, delay) = builder.build(); Self::new(maze, algorithm, delay) } diff --git a/src/executor/builder.rs b/src/executor/builder.rs index a0d5d74..4a55396 100644 --- a/src/executor/builder.rs +++ b/src/executor/builder.rs @@ -2,37 +2,59 @@ use std::time::Duration; use crate::{labyrinth::generator::MazeGenerator, Maze}; -pub trait MazeState {} -pub trait BuildableMazeState: MazeState { - fn get(self) -> Maze; -} +use self::maze_state::{BuildableMazeState, Generated, MazeState, Provided, Unprovided}; -pub struct Unprovided; +pub mod maze_state { -impl MazeState for Unprovided {} + use crate::{labyrinth::generator::MazeGenerator, Maze}; -struct Provided { - maze: Maze, -} + pub trait MazeState {} + pub trait BuildableMazeState: MazeState { + fn get(self) -> Maze; + } -impl MazeState for Provided {} -impl BuildableMazeState for Provided { - fn get(self) -> Maze { - self.maze + pub struct Unprovided; + + impl MazeState for Unprovided {} + + pub struct Provided { + maze: Maze, + } + + impl Provided { + pub fn new(maze: Maze) -> Self { + Self { maze } + } + } + + impl MazeState for Provided {} + impl BuildableMazeState for Provided { + fn get(self) -> Maze { + self.maze + } + } + + pub struct Generated { + generator: Box, + } + + impl Generated { + pub fn new(generator: G) -> Self + where + G: MazeGenerator + 'static, + { + let generator = Box::new(generator); + Self { generator } + } + } + + impl MazeState for Generated {} + impl BuildableMazeState for Generated { + fn get(mut self) -> Maze { + self.generator.generate() + } } } - -struct Generated { - generator: Box, -} - -impl MazeState for Generated {} -impl BuildableMazeState for Generated { - fn get(mut self) -> Maze { - self.generator.generate() - } -} - pub struct ExecutorBuilder where MS: MazeState, @@ -48,6 +70,40 @@ pub fn new_builder() -> ExecutorBuilder { } } +impl ExecutorBuilder { + pub fn maze(self, maze: Maze) -> ExecutorBuilder { + let Self { + delay, + maze_state: _, + } = self; + ExecutorBuilder { + delay, + maze_state: Provided::new(maze), + } + } + pub fn generated(self, generator: G) -> ExecutorBuilder + where + G: MazeGenerator + 'static, + { + let Self { + delay, + maze_state: _, + } = self; + ExecutorBuilder { + delay, + maze_state: Generated::new(generator), + } + } + pub fn delay_ms(self, delay: u64) -> Self { + let delay = Duration::from_millis(delay); + let Self { + maze_state, + delay: _, + } = self; + Self { maze_state, delay } + } +} + impl ExecutorBuilder { pub fn build(self) -> (Maze, Duration) { let maze = self.maze_state.get(); From b21dc88b68dafa6ab22053714ce7e3faa3e8c2b0 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 02:03:02 +0300 Subject: [PATCH 02/10] implemented generator and updated examples --- src/executor/builder.rs | 2 +- src/implementations.rs | 14 ++++---- src/labyrinth/generator.rs | 72 +++++++++++++++++++++++--------------- src/lib.rs | 5 ++- 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/executor/builder.rs b/src/executor/builder.rs index 4a55396..2be41d3 100644 --- a/src/executor/builder.rs +++ b/src/executor/builder.rs @@ -50,7 +50,7 @@ pub mod maze_state { impl MazeState for Generated {} impl BuildableMazeState for Generated { - fn get(mut self) -> Maze { + fn get(self) -> Maze { self.generator.generate() } } diff --git a/src/implementations.rs b/src/implementations.rs index 54fbc40..1c906a5 100644 --- a/src/implementations.rs +++ b/src/implementations.rs @@ -12,18 +12,16 @@ pub use depth_first::DepthFirst; #[test] fn depth_first() { - use crate::{generate, Executor}; + use crate::{Executor, SimpleGenerator}; let algorithm = DepthFirst::new(); - let maze = generate(20, 20); - // let mut executor = Executor::new(maze, algorithm); - // executor.run(); + let mut executor = Executor::build(algorithm, |b| b.generated(SimpleGenerator::new(40, 20))); + executor.run(); } #[test] fn breath_first() { - use crate::{generate, Executor}; + use crate::{Executor, SimpleGenerator}; let algorithm = BreathFirst::new(); - let maze = generate(20, 20); - // let mut executor = Executor::new(maze, algorithm); - // executor.run(); + let mut executor = Executor::build(algorithm, |b| b.generated(SimpleGenerator::new(40, 20))); + executor.run(); } diff --git a/src/labyrinth/generator.rs b/src/labyrinth/generator.rs index 81e76be..e540666 100644 --- a/src/labyrinth/generator.rs +++ b/src/labyrinth/generator.rs @@ -8,43 +8,59 @@ use rand::{prelude::SliceRandom, thread_rng}; use crate::{Maze, Pos}; +/// Trait encapsulating the behavior of a type capable to create mazes. +pub trait MazeGenerator { + fn generate(&self) -> Maze; +} + /// Most common maze generation technique, recursively creating paths to unvisited cells, each time choosing next direction at random. -pub fn generate(width: isize, height: isize) -> Maze { - let mut result = Maze::new( - width, - height, - Pos::zero(), - (width - 1, height - 1).into(), - Vec::new(), - ); +pub struct SimpleGenerator { + width: isize, + height: isize, +} - fn recursive(current: Pos, result: &mut Maze, visited: &mut HashSet) { - visited.insert(current); - let mut adjascent_positions = result.adjascent(current); - adjascent_positions.shuffle(&mut thread_rng()); - for neighbor in adjascent_positions { - if visited.contains(&neighbor) { - continue; - } - result.create_path(current, neighbor); - recursive(neighbor, result, visited); - } +impl SimpleGenerator { + pub fn new(width: isize, height: isize) -> Self { + Self { height, width } } +} - let mut visited = HashSet::new(); - let current = Pos::zero(); - recursive(current, &mut result, &mut visited); +impl MazeGenerator for SimpleGenerator { + fn generate(&self) -> Maze { + let Self { width, height } = *self; + let mut result = Maze::new( + width, + height, + Pos::zero(), + (width - 1, height - 1).into(), + Vec::new(), + ); - result + fn recursive(current: Pos, result: &mut Maze, visited: &mut HashSet) { + visited.insert(current); + let mut adjascent_positions = result.adjascent(current); + adjascent_positions.shuffle(&mut thread_rng()); + for neighbor in adjascent_positions { + if visited.contains(&neighbor) { + continue; + } + result.create_path(current, neighbor); + recursive(neighbor, result, visited); + } + } + + let mut visited = HashSet::new(); + let current = Pos::zero(); + recursive(current, &mut result, &mut visited); + + result + } } #[test] fn generation() { - let maze = generate(20, 20); + let generator = SimpleGenerator::new(10, 10); + let maze = generator.generate(); let text = maze.display(None); println!("{text}"); } - -pub trait MazeGenerator { - fn generate(&mut self) -> Maze; -} diff --git a/src/lib.rs b/src/lib.rs index ad82e27..8d0d348 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,5 +14,8 @@ mod position; pub use algorithm::Algorithm; pub use executor::{Context, Executor, Guess, Insight}; -pub use labyrinth::{generator::generate, Maze}; +pub use labyrinth::{ + generator::{MazeGenerator, SimpleGenerator}, + Maze, +}; pub use position::Pos; From 31f2e25cdcbc22615a6343d64e733a48341e1b04 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 02:10:33 +0300 Subject: [PATCH 03/10] added documentation --- src/executor.rs | 5 +++++ src/executor/builder.rs | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/executor.rs b/src/executor.rs index 31df8ff..5a51205 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,3 +1,8 @@ +//! ## Executor +//! +//! This module contains the definition of an [`Executor`], used to run an [`Algorithm`] and have a graphical output in the terminal. +//! This type is supposed to be created using the builder pattern (c.f. [`Executor`]`::build`). + use std::{ collections::{HashMap, HashSet}, thread, diff --git a/src/executor/builder.rs b/src/executor/builder.rs index 2be41d3..58bea23 100644 --- a/src/executor/builder.rs +++ b/src/executor/builder.rs @@ -8,6 +8,7 @@ pub mod maze_state { use crate::{labyrinth::generator::MazeGenerator, Maze}; + /// Describe the state of the [`Maze`] parameter in the builder of an [`crate::Executor`]. Not ment to be implemented. pub trait MazeState {} pub trait BuildableMazeState: MazeState { fn get(self) -> Maze; @@ -55,6 +56,8 @@ pub mod maze_state { } } } + +/// Builder for an [`crate::Executor`], needs at least a [`Maze`]. pub struct ExecutorBuilder where MS: MazeState, @@ -63,7 +66,7 @@ where delay: Duration, } -pub fn new_builder() -> ExecutorBuilder { +pub(crate) fn new_builder() -> ExecutorBuilder { ExecutorBuilder { maze_state: Unprovided, delay: Duration::from_millis(100), @@ -71,6 +74,7 @@ pub fn new_builder() -> ExecutorBuilder { } impl ExecutorBuilder { + /// Provide a specific [`Maze`] for the execution. pub fn maze(self, maze: Maze) -> ExecutorBuilder { let Self { delay, @@ -81,6 +85,8 @@ impl ExecutorBuilder { maze_state: Provided::new(maze), } } + + /// Provide a generator to generate a [`Maze`] for the execution. pub fn generated(self, generator: G) -> ExecutorBuilder where G: MazeGenerator + 'static, @@ -94,6 +100,8 @@ impl ExecutorBuilder { maze_state: Generated::new(generator), } } + + /// Sets the delay between terminal redraws, default is 100ms. pub fn delay_ms(self, delay: u64) -> Self { let delay = Duration::from_millis(delay); let Self { @@ -105,7 +113,7 @@ impl ExecutorBuilder { } impl ExecutorBuilder { - pub fn build(self) -> (Maze, Duration) { + pub(crate) fn build(self) -> (Maze, Duration) { let maze = self.maze_state.get(); let delay = self.delay; (maze, delay) From 82912dbc443c8484dd1de1f3cd896bdf5836df49 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 02:10:53 +0300 Subject: [PATCH 04/10] incremented version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e557a16..4eb8513 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "labirust" -version = "0.1.1" +version = "0.2.0" dependencies = [ "rand", "termion", diff --git a/Cargo.toml b/Cargo.toml index 8d62dbe..9a6bad7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "labirust" -version = "0.1.1" +version = "0.2.0" edition = "2021" license = "MIT" authors = ["JOLIMAITRE Matthieu "] From 33f808f0adff57af2301bb2ef7706ee621b91788 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 02:50:44 +0300 Subject: [PATCH 05/10] improved default display --- src/executor.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/executor.rs b/src/executor.rs index 5a51205..9b8b42e 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -163,25 +163,26 @@ where fn draw(maze: &Maze, tried: &HashSet, tick: usize, path: &Vec) { let mut overlay = HashMap::new(); for position in tried { - overlay.insert(*position, '#'); + overlay.insert(*position, '░'); } - for position in path { - overlay.insert(*position, 'P'); + overlay.insert(*position, '█'); } + overlay.insert(maze.start(), 'S'); + overlay.insert(maze.end(), 'E'); + overlay.insert(*path.last().unwrap(), 'G'); - overlay.insert(*path.last().unwrap(), 'x'); - - let text = maze.display(Some(overlay)); + let grid = maze.display(Some(overlay)); + let text = format!("tick {tick}:\n{grid}\n"); // DIRTY! // print the frame on top of the previous one if tick > 0 { - let count = text.lines().count() + 1; + let count = text.lines().count(); let up = termion::cursor::Up(count as u16); print!("{up}") } - print!("tick {tick}:\n{text}\n"); + print!("{text}"); } } From cf133e462f0f62cc4bacf3afacce0eb9c9fbe81b Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 02:51:25 +0300 Subject: [PATCH 06/10] incremented version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4eb8513..775f4c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "labirust" -version = "0.2.0" +version = "0.2.1" dependencies = [ "rand", "termion", diff --git a/Cargo.toml b/Cargo.toml index 9a6bad7..ab69e17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "labirust" -version = "0.2.0" +version = "0.2.1" edition = "2021" license = "MIT" authors = ["JOLIMAITRE Matthieu "] From 618c6d57e8f79b048f298af74b3f52c59228d246 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 14:53:39 +0300 Subject: [PATCH 07/10] split repository between CLI and librarry --- Cargo.lock | 224 ++++++++++++++++++ Cargo.toml | 14 +- labirust-cli/Cargo.toml | 10 + labirust-cli/src/main.rs | 37 +++ labirust/Cargo.toml | 12 + {src => labirust/src}/algorithm.rs | 0 {src => labirust/src}/executor.rs | 9 +- {src => labirust/src}/executor/builder.rs | 2 + {src => labirust/src}/implementations.rs | 0 .../src}/implementations/breath_first.rs | 0 .../src}/implementations/depth_first.rs | 0 {src => labirust/src}/labyrinth.rs | 0 {src => labirust/src}/labyrinth/generator.rs | 0 {src => labirust/src}/lib.rs | 0 {src => labirust/src}/position.rs | 0 15 files changed, 295 insertions(+), 13 deletions(-) create mode 100644 labirust-cli/Cargo.toml create mode 100644 labirust-cli/src/main.rs create mode 100644 labirust/Cargo.toml rename {src => labirust/src}/algorithm.rs (100%) rename {src => labirust/src}/executor.rs (96%) rename {src => labirust/src}/executor/builder.rs (98%) rename {src => labirust/src}/implementations.rs (100%) rename {src => labirust/src}/implementations/breath_first.rs (100%) rename {src => labirust/src}/implementations/depth_first.rs (100%) rename {src => labirust/src}/labyrinth.rs (100%) rename {src => labirust/src}/labyrinth/generator.rs (100%) rename {src => labirust/src}/lib.rs (100%) rename {src => labirust/src}/position.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 775f4c6..f8ee1c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,23 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" @@ -14,6 +31,45 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "getrandom" version = "0.2.6" @@ -25,6 +81,37 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "labirust" version = "0.2.1" @@ -33,6 +120,20 @@ dependencies = [ "termion", ] +[[package]] +name = "labirust-cli" +version = "0.1.0" +dependencies = [ + "clap", + "labirust", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.126" @@ -45,12 +146,60 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "ppv-lite86" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.8.5" @@ -99,6 +248,32 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "termion" version = "1.5.6" @@ -111,8 +286,57 @@ dependencies = [ "redox_termios", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index ab69e17..509c747 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,2 @@ -[package] -name = "labirust" -version = "0.2.1" -edition = "2021" -license = "MIT" -authors = ["JOLIMAITRE Matthieu "] -description = "Naive rust crate for implementing and testing maze solving Algorithms." -repository = "https://github.com/MajorBarnulf/labirust/" - -[dependencies] -rand = "0.8" -termion = "1.5" +[workspace] +members = ["labirust", "labirust-cli"] diff --git a/labirust-cli/Cargo.toml b/labirust-cli/Cargo.toml new file mode 100644 index 0000000..e5830d1 --- /dev/null +++ b/labirust-cli/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "labirust-cli" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +labirust = { path = "../labirust" } +clap = { version = "3.1.18", features = ["derive"] } diff --git a/labirust-cli/src/main.rs b/labirust-cli/src/main.rs new file mode 100644 index 0000000..389aa77 --- /dev/null +++ b/labirust-cli/src/main.rs @@ -0,0 +1,37 @@ +use std::str::FromStr; + +use clap::Parser; +use labirust::{implementations::*, Executor}; + +enum Algorithms { + DepthFirst, + BreathFirst, +} + +impl FromStr for Algorithms { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "depth-first" => Ok(Self::DepthFirst), + "breath-first" => Ok(Self::BreathFirst), + _ => Err("No right pattern".into()), + } + } +} + +#[derive(Parser)] +struct Parameters { + algorithm_kind: Algorithms, + width: usize, + height: usize, + delay: usize, +} + +fn main() { + let params = Parameters::parse(); + + let executor = todo!(); + + println!("Hello, world!"); +} diff --git a/labirust/Cargo.toml b/labirust/Cargo.toml new file mode 100644 index 0000000..ab69e17 --- /dev/null +++ b/labirust/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "labirust" +version = "0.2.1" +edition = "2021" +license = "MIT" +authors = ["JOLIMAITRE Matthieu "] +description = "Naive rust crate for implementing and testing maze solving Algorithms." +repository = "https://github.com/MajorBarnulf/labirust/" + +[dependencies] +rand = "0.8" +termion = "1.5" diff --git a/src/algorithm.rs b/labirust/src/algorithm.rs similarity index 100% rename from src/algorithm.rs rename to labirust/src/algorithm.rs diff --git a/src/executor.rs b/labirust/src/executor.rs similarity index 96% rename from src/executor.rs rename to labirust/src/executor.rs index 9b8b42e..99b1794 100644 --- a/src/executor.rs +++ b/labirust/src/executor.rs @@ -13,7 +13,7 @@ use crate::{Algorithm, Maze, Pos}; use self::builder::{ maze_state::{BuildableMazeState, Unprovided}, - new_builder, ExecutorBuilder, + new_builder, DynExecutorBuilder, ExecutorBuilder, }; /// A guess to pass to the current [`Executor`] at the end of every `progress` call. @@ -125,6 +125,13 @@ where Self::new(maze, algorithm, delay) } + pub fn build_dyn(algorithm: A, builder: F) -> Self + where + F: Fn(DynExecutorBuilder) -> DynExecutorBuilder, + { + todo!() + } + /// Submit the maze to the [`Algorithm`] and iteratively progress through the maze driven by said algorithm. pub fn run(&mut self) { let Self { diff --git a/src/executor/builder.rs b/labirust/src/executor/builder.rs similarity index 98% rename from src/executor/builder.rs rename to labirust/src/executor/builder.rs index 58bea23..d08e862 100644 --- a/src/executor/builder.rs +++ b/labirust/src/executor/builder.rs @@ -119,3 +119,5 @@ impl ExecutorBuilder { (maze, delay) } } + +pub struct DynExecutorBuilder {} diff --git a/src/implementations.rs b/labirust/src/implementations.rs similarity index 100% rename from src/implementations.rs rename to labirust/src/implementations.rs diff --git a/src/implementations/breath_first.rs b/labirust/src/implementations/breath_first.rs similarity index 100% rename from src/implementations/breath_first.rs rename to labirust/src/implementations/breath_first.rs diff --git a/src/implementations/depth_first.rs b/labirust/src/implementations/depth_first.rs similarity index 100% rename from src/implementations/depth_first.rs rename to labirust/src/implementations/depth_first.rs diff --git a/src/labyrinth.rs b/labirust/src/labyrinth.rs similarity index 100% rename from src/labyrinth.rs rename to labirust/src/labyrinth.rs diff --git a/src/labyrinth/generator.rs b/labirust/src/labyrinth/generator.rs similarity index 100% rename from src/labyrinth/generator.rs rename to labirust/src/labyrinth/generator.rs diff --git a/src/lib.rs b/labirust/src/lib.rs similarity index 100% rename from src/lib.rs rename to labirust/src/lib.rs diff --git a/src/position.rs b/labirust/src/position.rs similarity index 100% rename from src/position.rs rename to labirust/src/position.rs From c2604040652db32d07215d1a20b5df152daba9e4 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 15:04:44 +0300 Subject: [PATCH 08/10] made executor dynamic and added dynamic builder --- labirust/src/executor.rs | 25 ++++++++++---------- labirust/src/executor/builder.rs | 40 ++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/labirust/src/executor.rs b/labirust/src/executor.rs index 99b1794..b9e3320 100644 --- a/labirust/src/executor.rs +++ b/labirust/src/executor.rs @@ -92,21 +92,15 @@ impl<'m> Context<'m> { mod builder; /// A structure holding a [`Maze`] and iteratively solving it with a provided [`Algorithm`]. -pub struct Executor -where - Algo: Algorithm, -{ +pub struct Executor { delay: Duration, maze: Maze, - algorithm: Algo, + algorithm: Box, } -impl Executor -where - A: Algorithm, -{ +impl Executor { /// Constructor. - fn new(maze: Maze, algorithm: A, delay: Duration) -> Self { + fn new(maze: Maze, algorithm: Box, delay: Duration) -> Self { Self { maze, algorithm, @@ -114,22 +108,27 @@ where } } - pub fn build<'f, F, MS>(algorithm: A, builder: F) -> Self + pub fn build<'f, A, F, MS>(algorithm: A, builder: F) -> Self where + A: Algorithm + 'static, MS: BuildableMazeState, F: Fn(ExecutorBuilder) -> ExecutorBuilder, { let operation = builder; let builder = (operation)(new_builder()); let (maze, delay) = builder.build(); + let algorithm = Box::new(algorithm); Self::new(maze, algorithm, delay) } - pub fn build_dyn(algorithm: A, builder: F) -> Self + pub fn build_dyn(algorithm: Box, builder: F) -> Self where F: Fn(DynExecutorBuilder) -> DynExecutorBuilder, { - todo!() + let operation = builder; + let builder = (operation)(DynExecutorBuilder::new()); + let (maze, delay) = builder.build(); + Self::new(maze, algorithm, delay) } /// Submit the maze to the [`Algorithm`] and iteratively progress through the maze driven by said algorithm. diff --git a/labirust/src/executor/builder.rs b/labirust/src/executor/builder.rs index d08e862..994b737 100644 --- a/labirust/src/executor/builder.rs +++ b/labirust/src/executor/builder.rs @@ -11,7 +11,7 @@ pub mod maze_state { /// Describe the state of the [`Maze`] parameter in the builder of an [`crate::Executor`]. Not ment to be implemented. pub trait MazeState {} pub trait BuildableMazeState: MazeState { - fn get(self) -> Maze; + fn get(&self) -> Maze; } pub struct Unprovided; @@ -30,8 +30,8 @@ pub mod maze_state { impl MazeState for Provided {} impl BuildableMazeState for Provided { - fn get(self) -> Maze { - self.maze + fn get(&self) -> Maze { + self.maze.clone() } } @@ -51,7 +51,7 @@ pub mod maze_state { impl MazeState for Generated {} impl BuildableMazeState for Generated { - fn get(self) -> Maze { + fn get(&self) -> Maze { self.generator.generate() } } @@ -120,4 +120,34 @@ impl ExecutorBuilder { } } -pub struct DynExecutorBuilder {} +pub struct DynExecutorBuilder { + maze: Option>, + delay: Duration, +} + +impl DynExecutorBuilder { + pub(crate) fn new() -> Self { + Self { + maze: None, + delay: Duration::from_millis(100), + } + } + + pub fn maze(self, maze: Maze) -> Self { + todo!() + } + + pub fn generated(self, maze: Box) -> Self { + todo!() + } + + pub fn delay_ms(self, delay: u64) -> Self { + todo!() + } + + pub(crate) fn build(self) -> (Maze, Duration) { + let maze = self.maze.expect("no buildable maze provided").get(); + let delay = self.delay; + (maze, delay) + } +} From e8102f0e72518ce845861d1721afb467afb67c57 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 15:29:07 +0300 Subject: [PATCH 09/10] finished to implement the dynamic builder --- labirust-cli/src/main.rs | 29 +++++++++++++++++++---- labirust/src/executor/builder.rs | 40 ++++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/labirust-cli/src/main.rs b/labirust-cli/src/main.rs index 389aa77..534713d 100644 --- a/labirust-cli/src/main.rs +++ b/labirust-cli/src/main.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use clap::Parser; -use labirust::{implementations::*, Executor}; +use labirust::{implementations::*, Algorithm, Executor, SimpleGenerator}; enum Algorithms { DepthFirst, @@ -22,16 +22,37 @@ impl FromStr for Algorithms { #[derive(Parser)] struct Parameters { - algorithm_kind: Algorithms, + /// Algorithm to use in the simulation. + /// One of: "depth-first", "breath-first" + algorithm: Algorithms, + + /// Width of the maze to solve. + #[clap(short, default_value_t = 40)] width: usize, + + /// Height of the maze to solve. + #[clap(short, default_value_t = 20)] height: usize, + + /// Delay between two simulation ticks. + #[clap(short, default_value_t = 100)] delay: usize, } fn main() { let params = Parameters::parse(); - let executor = todo!(); + let algorithm: Box = match params.algorithm { + Algorithms::DepthFirst => Box::new(DepthFirst::new()), + Algorithms::BreathFirst => Box::new(BreathFirst::new()), + }; - println!("Hello, world!"); + let mut executor = Executor::build_dyn(algorithm, |b| { + b.generated(Box::new(SimpleGenerator::new( + params.width as isize, + params.height as isize, + ))) + }); + + executor.run(); } diff --git a/labirust/src/executor/builder.rs b/labirust/src/executor/builder.rs index 994b737..b63606b 100644 --- a/labirust/src/executor/builder.rs +++ b/labirust/src/executor/builder.rs @@ -47,6 +47,10 @@ pub mod maze_state { let generator = Box::new(generator); Self { generator } } + + pub fn new_dyn(generator: Box) -> Self { + Self { generator } + } } impl MazeState for Generated {} @@ -120,33 +124,55 @@ impl ExecutorBuilder { } } +pub enum DynMazeState { + None, + Provided(Provided), + Generated(Generated), +} + +impl DynMazeState { + pub fn get(self) -> Option { + match self { + DynMazeState::None => None, + DynMazeState::Provided(provided) => Some(provided.get()), + DynMazeState::Generated(generated) => Some(generated.get()), + } + } +} + pub struct DynExecutorBuilder { - maze: Option>, + maze: DynMazeState, delay: Duration, } impl DynExecutorBuilder { pub(crate) fn new() -> Self { Self { - maze: None, + maze: DynMazeState::None, delay: Duration::from_millis(100), } } pub fn maze(self, maze: Maze) -> Self { - todo!() + let maze = DynMazeState::Provided(Provided::new(maze)); + let Self { maze: _, delay } = self; + Self { maze, delay } } - pub fn generated(self, maze: Box) -> Self { - todo!() + pub fn generated(self, generator: Box) -> Self { + let maze = DynMazeState::Generated(Generated::new_dyn(generator)); + let Self { maze: _, delay } = self; + Self { delay, maze } } pub fn delay_ms(self, delay: u64) -> Self { - todo!() + let delay = Duration::from_millis(delay); + let Self { maze, delay: _ } = self; + Self { maze, delay } } pub(crate) fn build(self) -> (Maze, Duration) { - let maze = self.maze.expect("no buildable maze provided").get(); + let maze = self.maze.get().expect("no buildable maze provided"); let delay = self.delay; (maze, delay) } From 86bd6fc78971380a776e8f80bb2ae3b4936fc7e2 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 30 May 2022 15:48:46 +0300 Subject: [PATCH 10/10] updated readmes --- Cargo.lock | 14 ++++++++++++-- labirust-cli/Cargo.toml | 10 ++++++---- labirust-cli/README.md | 12 ++++++++++++ labirust/Cargo.toml | 2 +- README.md => labirust/README.md | 17 +++++++++++------ 5 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 labirust-cli/README.md rename README.md => labirust/README.md (63%) diff --git a/Cargo.lock b/Cargo.lock index f8ee1c3..a58f65d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,7 +114,17 @@ dependencies = [ [[package]] name = "labirust" -version = "0.2.1" +version = "0.3.0" +dependencies = [ + "rand", + "termion", +] + +[[package]] +name = "labirust" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be89e6ef8c189ed1fa5acb4475a3b43c2aa835c0788fb38b11df3ddb58359f8c" dependencies = [ "rand", "termion", @@ -125,7 +135,7 @@ name = "labirust-cli" version = "0.1.0" dependencies = [ "clap", - "labirust", + "labirust 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/labirust-cli/Cargo.toml b/labirust-cli/Cargo.toml index e5830d1..4951c28 100644 --- a/labirust-cli/Cargo.toml +++ b/labirust-cli/Cargo.toml @@ -2,9 +2,11 @@ name = "labirust-cli" version = "0.1.0" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +license = "MIT" +authors = ["JOLIMAITRE Matthieu "] +description = "A cli to run labirust algorithms." +repository = "https://github.com/MajorBarnulf/labirust/" [dependencies] -labirust = { path = "../labirust" } -clap = { version = "3.1.18", features = ["derive"] } +labirust = "0.3" +clap = { version = "3.1", features = ["derive"] } diff --git a/labirust-cli/README.md b/labirust-cli/README.md new file mode 100644 index 0000000..c33c727 --- /dev/null +++ b/labirust-cli/README.md @@ -0,0 +1,12 @@ +# labirust-cli + +## Description + +A cli to run labirust algorithms. + +## Installation + +```sh +# through cargo +cargo install labirust-cli +``` \ No newline at end of file diff --git a/labirust/Cargo.toml b/labirust/Cargo.toml index ab69e17..44a4360 100644 --- a/labirust/Cargo.toml +++ b/labirust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "labirust" -version = "0.2.1" +version = "0.3.0" edition = "2021" license = "MIT" authors = ["JOLIMAITRE Matthieu "] diff --git a/README.md b/labirust/README.md similarity index 63% rename from README.md rename to labirust/README.md index c837557..80899ec 100644 --- a/README.md +++ b/labirust/README.md @@ -14,14 +14,19 @@ Hi, I am a junior rust dev (yes, how original, I know) and this is one of the sm ## Usage -If you want to see what the library is capable of, you can clone this repo and run the tests to see mazes solving themselves on the terminal. - -for you to see anything during the execution of tests, don't forget to add these arguments: +If you want to see what the library is capable of, you can try the CLI, either by clonning this repo and building it with cargo or by installing it through the crates.io depot. ```sh --- --nocapture +# installation +cargo install labirust-cli -# example: -cargo test -- implementations::breath_first --nocapture +# usage +labirust-cli --help ``` + If you want to implement more resolution algorithm yourself and for some reason you think this is the right crate to provide frameworks, you can explore the crate documentation and add this crate to your project dependencies. +```toml +# in Cargo.toml +[dependencies] +labirust = "0.3" +```