homework: add method to retrieve device to house and implement From trait for PowerSocket and Thermometer

This commit is contained in:
5 changed files with 68 additions and 10 deletions

View File

@@ -79,10 +79,10 @@
- [x] Реализовать трейт Debug на всех типах. - [x] Реализовать трейт Debug на всех типах.
- [x] Добавить возможность динамически добавлять/удалять устройства в комнату. - [x] Добавить возможность динамически добавлять/удалять устройства в комнату.
- [x] Добавить возможность динамически добавлять/удалять комнату в дом. - [x] Добавить возможность динамически добавлять/удалять комнату в дом.
- [ ] Добавить в тип умного дома метод, позволяющий сразу получить ссылку на умное устройство. Метод принимает имя комнаты - [x] Добавить в тип умного дома метод, позволяющий сразу получить ссылку на умное устройство. Метод принимает имя комнаты
и имя устройства. В случае, если устройство или комната не найдены, возвращать тип ошибки, сообщающий, что именно и имя устройства. В случае, если устройство или комната не найдены, возвращать тип ошибки, сообщающий, что именно
произошло. Тип ошибки должен реализовывать трейт `std::error::Error`. произошло. Тип ошибки должен реализовывать трейт `std::error::Error`.
- [ ] Добавить реализации трейта `From`, позволяющие преобразовывать объекты умной розетки и умного термометра в объект - [x] Добавить реализации трейта `From`, позволяющие преобразовывать объекты умной розетки и умного термометра в объект
умного устройства. умного устройства.
- [ ] Написать макрос для упрощенного создания комнаты, принимающий пары вида (ключ, объект умной розетки) или (ключ, - [ ] Написать макрос для упрощенного создания комнаты, принимающий пары вида (ключ, объект умной розетки) или (ключ,
объект умного термометра) и возвращающий объект комнаты, содержащей все перечисленные устройства с объект умного термометра) и возвращающий объект комнаты, содержащей все перечисленные устройства с

View File

@@ -30,6 +30,18 @@ impl Device {
} }
} }
impl From<super::Thermometer> for Device {
fn from(value: super::Thermometer) -> Self {
Device::Thermometer(value)
}
}
impl From<super::PowerSocket> for Device {
fn from(value: super::PowerSocket) -> Self {
Device::PowerSocket(value)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

23
smart-house/src/error.rs Normal file
View File

@@ -0,0 +1,23 @@
use std::fmt::{Display, Formatter};
#[derive(Debug)]
pub struct Error {
message: String,
}
impl Error {
pub fn new(message: impl AsRef<str>) -> Self {
Self {
message: message.as_ref().to_string(),
}
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.message))?;
Ok(())
}
}
impl std::error::Error for Error {}

View File

@@ -1,4 +1,4 @@
use crate::Room; use crate::{Device, Error, Room};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
@@ -36,6 +36,16 @@ impl House {
self.rooms.remove(key) self.rooms.remove(key)
} }
pub fn get_device(&self, room: &str, device: &str) -> Result<&Device, Error> {
let Some(room) = self.get_room(room) else {
return Err(Error::new(format!("no room named '{}' found", room)));
};
let Some(device) = room.get_device(device) else {
return Err(Error::new(format!("no device named '{}' found in room '{}'", device, room.get_name())));
};
Ok(device)
}
pub fn print_status(&self) { pub fn print_status(&self) {
println!("HOUSE '{}':", self.address); println!("HOUSE '{}':", self.address);
println!("{}", "=".repeat(32)); println!("{}", "=".repeat(32));
@@ -58,17 +68,14 @@ mod tests {
Room::new( Room::new(
"main", "main",
Box::new([ Box::new([
Device::Thermometer(Thermometer::new("ThermA", 20.0)), Thermometer::new("ThermA", 20.0).into(),
Device::PowerSocket(PowerSocket::new("PSocA", 12.34, false)), PowerSocket::new("PSocA", 12.34, false).into(),
Device::PowerSocket(PowerSocket::new("PSocB", 10.01, true)), PowerSocket::new("PSocB", 10.01, true).into(),
]), ]),
), ),
Room::new( Room::new(
"bedroom", "bedroom",
Box::new([ Box::new([PowerSocket::new("PSocC", 11.11, true).into(), Thermometer::new("ThermB", 17.99).into()]),
Device::PowerSocket(PowerSocket::new("PSocC", 11.11, true)),
Device::Thermometer(Thermometer::new("ThermB", 17.99)),
]),
), ),
]), ]),
) )
@@ -124,4 +131,18 @@ mod tests {
assert_eq!(result.get_name(), "bedroom"); assert_eq!(result.get_name(), "bedroom");
assert_eq!(house.rooms.len(), 2); assert_eq!(house.rooms.len(), 2);
} }
#[test]
fn test_get_device() {
let house = create_test_house();
let result = house.get_device("empty", "dummy");
assert_eq!(result.unwrap_err().to_string(), "no room named 'empty' found");
let result = house.get_device("main", "dummy");
assert_eq!(result.unwrap_err().to_string(), "no device named 'dummy' found in room 'main'");
let result = house.get_device("main", "ThermA");
assert_eq!(result.unwrap().get_name(), "ThermA");
}
} }

View File

@@ -1,10 +1,12 @@
mod device; mod device;
mod error;
mod house; mod house;
mod power_socket; mod power_socket;
mod room; mod room;
mod thermometer; mod thermometer;
pub use device::Device; pub use device::Device;
pub use error::Error;
pub use house::House; pub use house::House;
pub use power_socket::PowerSocket; pub use power_socket::PowerSocket;
pub use room::Room; pub use room::Room;