use clap::{App, Arg}; use queues::*; use std::fs; use std::io; /// Struct to store the world. struct World { x: u32, y: u32, map: Vec, } impl World { /// Create a new map full of dots. fn create_map(&mut self) { self.map = vec!['.'; (self.x * self.y) as usize]; } /// Set robot on the map. fn set_robot(&mut self, r: Robot) { self.map[(r.p.x * r.p.y) as usize] = match r.o { Orientation::N => '↑', Orientation::S => '↓', Orientation::E => '→', Orientation::W => '←', } } /// Check if a position is free. fn empty_position(&mut self, p: Position) -> bool { self.map[(p.x * p.y) as usize] == '.' } } /// Struct to store robot position. struct Position { x: u32, y: u32, } /// A Robot *aka droid* is represented here. /// Each robot must have a unique id. struct Robot { id: u32, o: Orientation, p: Position, q: Queue, } impl Robot { /// Apply forward instruction to the robot. fn move_forward(&mut self) { match self.o { Orientation::N => self.p.y -= 1, Orientation::S => self.p.y += 1, Orientation::E => self.p.x += 1, Orientation::W => self.p.x -= 1, } } /// Apply right instruction to the robot. fn move_right(&mut self) { match self.o { Orientation::N => self.p.x += 1, Orientation::S => self.p.x -= 1, Orientation::E => self.p.y += 1, Orientation::W => self.p.y -= 1, } } /// Apply left instruction to the robot. fn move_left(&mut self) { match self.o { Orientation::N => self.p.x -= 1, Orientation::S => self.p.x += 1, Orientation::E => self.p.y -= 1, Orientation::W => self.p.y += 1, } } /// Apply North orientation to the robot. fn turn_north(&mut self) { self.o = Orientation::N } /// Apply South orientation to the robot. fn turn_south(&mut self) { self.o = Orientation::S } /// Apply East orientation to the robot. fn turn_east(&mut self) { self.o = Orientation::E } /// Apply West orientation to the robot. fn turn_west(&mut self) { self.o = Orientation::W } } /// Enum to store all possible orientations. enum Orientation { N, E, S, W, } /// Enum to store all possible instructions. enum Instruction { L, R, F, } /// Parse char and return corresponding orientation. fn parse_orientation(c: char) -> Result { match c { 'N' => Ok(Orientation::N), 'E' => Ok(Orientation::E), 'S' => Ok(Orientation::S), 'W' => Ok(Orientation::W), _ => Err("Invalid character, does not match any orientations"), } } /// Parse char and return corresponding instruction. fn parse_instruction(c: char) -> Result { match c { 'L' => Ok(Instruction::L), 'R' => Ok(Instruction::R), 'F' => Ok(Instruction::F), _ => Err("Invalid character, does not match any instructions"), } } /// Retrieve the content of a file and return it as a string. fn open_file(filename: &str) -> io::Result { let content = fs::read_to_string(filename)?; Ok(content) } fn main() -> Result<(), Box> { // We handle CLI flags here. let matches = App::new("DancingDroids") .version("0.1.0") .about("When droids dance togethers") .arg( Arg::with_name("file") .short("f") .long("file") .takes_value(true) .help("Configuration file"), ) .get_matches(); let raw_conf = open_file(matches.value_of("file").unwrap_or("two_robots.txt"))?; // We store all the robots inside a pool O_o let mut robot_pool: Vec = Vec::new(); Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_orientation() { assert!(parse_orientation('N').is_ok()); assert!(parse_orientation('E').is_ok()); assert!(parse_orientation('S').is_ok()); assert!(parse_orientation('W').is_ok()); assert!(parse_orientation('Z').is_err()); } #[test] fn test_parse_instruction() { assert!(parse_instruction('L').is_ok()); assert!(parse_instruction('R').is_ok()); assert!(parse_instruction('F').is_ok()); assert!(parse_instruction('Z').is_err()); } #[test] fn test_open_file() { assert!(open_file("two_robots.txt").is_ok()); assert!(open_file("test_unexisting_file.extension").is_err()); } #[test] fn test_create_map() { let mut w: World = World { x: 5, y: 5, map: Vec::new(), }; w.create_map(); assert_eq!(w.map, vec!['.'; 25]); } #[test] fn test_set_robot() { let r = Robot { id: 0, o: Orientation::N, p: Position { x: 0, y: 0 }, q: Queue::new(), }; let mut w: World = World { x: 2, y: 2, map: Vec::new(), }; w.create_map(); w.set_robot(r); assert_eq!(w.map, vec!['↑', '.', '.', '.']); } #[test] fn test_empty_position() { let mut w: World = World { x: 2, y: 2, map: Vec::new(), }; w.create_map(); assert!(w.empty_position(Position { x: 0, y: 0 })); } }