diff --git a/smart-house/README.md b/smart-house/README.md index 6412abc..0e0a2fc 100644 --- a/smart-house/README.md +++ b/smart-house/README.md @@ -35,11 +35,11 @@ - [x] Можно получить ссылку на устройство по указанному индексу. - [x] Можно получить мутабельную ссылку на устройство по указанному индексу. - [x] Выводить в стандартный вывод отчёт о всех устройствах в комнате. -- [ ] Опишите тип: умный дом, содержащий массив комнат. Тип должен предоставлять следующий функционал: - - [ ] Конструктор, принимающий массив комнат. - - [ ] Можно получить ссылку на комнату по указанному индексу. - - [ ] Можно получить мутабельную ссылку на комнату по указанному индексу. - - [ ] Выводить в стандартный вывод отчёт о всех комнатах. +- [x] Опишите тип: умный дом, содержащий массив комнат. Тип должен предоставлять следующий функционал: + - [x] Конструктор, принимающий массив комнат. + - [x] Можно получить ссылку на комнату по указанному индексу. + - [x] Можно получить мутабельную ссылку на комнату по указанному индексу. + - [x] Выводить в стандартный вывод отчёт о всех комнатах. - Размеры массивов можно выбрать произвольно. - В случае, если указан индекс, выходящий за пределы массива, приложение должно аварийно завершаться (макрос `panic!()`). diff --git a/smart-house/src/house.rs b/smart-house/src/house.rs new file mode 100644 index 0000000..f94f241 --- /dev/null +++ b/smart-house/src/house.rs @@ -0,0 +1,91 @@ +use crate::Room; + +pub struct House { + address: String, + rooms: Box<[Room]>, +} + +impl House { + pub fn new(address: impl AsRef, rooms: Box<[Room]>) -> Self { + Self { + address: address.as_ref().to_string(), + rooms, + } + } + + fn check_bounds(&self, idx: usize) { + if idx >= self.rooms.len() { + panic!("Index is out of bounds") + } + } + + pub fn get_room(&self, idx: usize) -> &Room { + self.check_bounds(idx); + &self.rooms[idx] + } + + pub fn get_room_mut(&mut self, idx: usize) -> &mut Room { + self.check_bounds(idx); + &mut self.rooms[idx] + } + + pub fn print_status(&self) { + println!("HOUSE '{}':", self.address); + println!("{}", "=".repeat(32)); + for d in self.rooms.iter() { + d.print_status(); + println!(); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Device, PowerSocket, Thermometer}; + + fn create_test_house() -> House { + House::new( + "Best street, 777", + Box::new([ + Room::new( + "main", + Box::new([ + Device::Thermometer(Thermometer::new(20.0)), + Device::PowerSocket(PowerSocket::new(12.34, false)), + Device::PowerSocket(PowerSocket::new(10.01, true)), + ]), + ), + Room::new( + "bedroom", + Box::new([Device::PowerSocket(PowerSocket::new(11.11, true)), Device::Thermometer(Thermometer::new(17.99))]), + ), + ]), + ) + } + + #[test] + fn smoke_test() { + let mut house = create_test_house(); + house.print_status(); + assert_eq!(house.address, "Best street, 777"); + + assert_eq!(format!("{}", house.get_room(0).get_device(0).display()), "DEV:Thermometer[ 20.0 ]"); + assert_eq!(format!("{}", house.get_room(0).get_device(1).display()), "DEV:PowerSocket[ OFF : 0.0 ]"); + assert_eq!(format!("{}", house.get_room(1).get_device(0).display()), "DEV:PowerSocket[ ON : 11.1 ]"); + + let Device::PowerSocket(powers_socket) = house.get_room_mut(0).get_device_mut(1) else { + unreachable!() + }; + powers_socket.set_on(true); + + assert_eq!(format!("{}", house.get_room(0).get_device(1).display()), "DEV:PowerSocket[ ON : 12.3 ]"); + } + + #[test] + #[should_panic(expected = "Index is out of bounds")] + fn panic_test() { + let house = create_test_house(); + house.check_bounds(2); + } +} diff --git a/smart-house/src/lib.rs b/smart-house/src/lib.rs index 0001a49..106c327 100644 --- a/smart-house/src/lib.rs +++ b/smart-house/src/lib.rs @@ -1,8 +1,11 @@ mod device; +mod house; mod power_socket; mod room; mod thermometer; pub use device::Device; +pub use house::House; pub use power_socket::PowerSocket; +pub use room::Room; pub use thermometer::Thermometer; diff --git a/smart-house/src/room.rs b/smart-house/src/room.rs index 2b0828a..be5fa4e 100644 --- a/smart-house/src/room.rs +++ b/smart-house/src/room.rs @@ -32,13 +32,11 @@ impl Room { } pub fn print_status(&self) { - println!("{}", "=".repeat(16)); - println!("{}:", self.name); - println!("{}", "-".repeat(16)); + println!("ROOM '{}':", self.name); + println!("{}", "-".repeat(24)); for d in self.devices.iter() { d.print_status(); } - println!("{}", "=".repeat(16)); } } @@ -60,9 +58,8 @@ mod tests { assert_eq!(format!("{}", room.get_device(0).display()), "DEV:PowerSocket[ OFF : 0.0 ]"); assert_eq!(format!("{}", room.get_device(1).display()), "DEV:Thermometer[ 21.6 ]"); - let power_socket = match room.get_device_mut(0) { - Device::PowerSocket(ps) => ps, - _ => unreachable!(), + let Device::PowerSocket(power_socket) = room.get_device_mut(0) else { + unreachable!() }; power_socket.set_on(true);