wrap into workspace
This commit is contained in:
154
smart-house/house/src/house.rs
Normal file
154
smart-house/house/src/house.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
use crate::{Device, Error, PrintStatus, Room};
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct House {
|
||||
rooms: HashMap<String, Room>,
|
||||
}
|
||||
|
||||
impl House {
|
||||
pub fn new(rooms: HashMap<String, Room>) -> Self {
|
||||
Self { rooms }
|
||||
}
|
||||
|
||||
pub fn get_room(&self, key: &str) -> Option<&Room> {
|
||||
self.rooms.get(key)
|
||||
}
|
||||
|
||||
pub fn get_room_mut(&mut self, key: &str) -> Option<&mut Room> {
|
||||
self.rooms.get_mut(key)
|
||||
}
|
||||
|
||||
pub fn insert_room(&mut self, name: &str, room: Room) -> Option<Room> {
|
||||
self.rooms.insert(name.to_string(), room)
|
||||
}
|
||||
|
||||
pub fn remove_room(&mut self, key: &str) -> Option<Room> {
|
||||
self.rooms.remove(key)
|
||||
}
|
||||
|
||||
pub fn get_device(&self, room_name: &str, device_name: &str) -> Result<&Device, Error> {
|
||||
let Some(room) = self.get_room(room_name) else {
|
||||
return Err(Error::new(format!("no room named '{}' found", room_name)));
|
||||
};
|
||||
let Some(device) = room.get_device(device_name) else {
|
||||
return Err(Error::new(format!("no device named '{}' found in room '{}'", device_name, room_name)));
|
||||
};
|
||||
Ok(device)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintStatus for House {
|
||||
fn print_status_into(&self, out: &mut dyn Write) -> Result<(), std::io::Error> {
|
||||
for (room_name, room) in self.rooms.iter() {
|
||||
out.write_fmt(format_args!("{}:\n", room_name))?;
|
||||
out.write_fmt(format_args!("{}\n", "-".repeat(32)))?;
|
||||
room.print_status_into(out)?;
|
||||
out.write_fmt(format_args!("\n"))?;
|
||||
println!();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{Device, PowerSocket, Thermometer};
|
||||
|
||||
fn create_test_house() -> House {
|
||||
House::new(
|
||||
[
|
||||
(
|
||||
"main".to_string(),
|
||||
Room::new(
|
||||
[
|
||||
("ThermA".to_string(), Thermometer::stub(20.0).into()),
|
||||
("PSocA".to_string(), PowerSocket::stub(12.34, false).into()),
|
||||
("PSocB".to_string(), PowerSocket::stub(10.01, true).into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
),
|
||||
(
|
||||
"bedroom".to_string(),
|
||||
Room::new(
|
||||
[
|
||||
("PSocC".to_string(), PowerSocket::stub(11.11, true).into()),
|
||||
("ThermB".to_string(), Thermometer::stub(17.99).into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_test() {
|
||||
let mut house = create_test_house();
|
||||
assert_eq!(house.rooms.len(), 2);
|
||||
house.print_status();
|
||||
|
||||
assert_eq!(
|
||||
format!("{}", house.get_room("main").unwrap().get_device("ThermA").unwrap().display()),
|
||||
"DEV:Thermometer[ 20.0 ]"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{}", house.get_room("main").unwrap().get_device("PSocA").unwrap().display()),
|
||||
"DEV:PowerSocket[ OFF : 0.0 ]"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{}", house.get_room("bedroom").unwrap().get_device("PSocC").unwrap().display()),
|
||||
"DEV:PowerSocket[ ON : 11.1 ]"
|
||||
);
|
||||
|
||||
let Device::PowerSocket(powers_socket) = house.get_room_mut("main").unwrap().get_device_mut("PSocA").unwrap() else {
|
||||
unreachable!()
|
||||
};
|
||||
powers_socket.set_on(true).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
format!("{}", house.get_room("main").unwrap().get_device("PSocA").unwrap().display()),
|
||||
"DEV:PowerSocket[ ON : 12.3 ]"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_out_of_bounds() {
|
||||
let house = create_test_house();
|
||||
assert!(house.get_room("absent").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_remove() {
|
||||
let mut house = create_test_house();
|
||||
let room = Room::new(HashMap::new());
|
||||
|
||||
let result = house.insert_room("empty", room);
|
||||
assert!(result.is_none());
|
||||
assert_eq!(house.rooms.len(), 3);
|
||||
|
||||
let Some(result) = house.remove_room("bedroom") else { unreachable!() };
|
||||
assert_eq!(result.get_device("ThermB").unwrap().display().to_string(), "DEV:Thermometer[ 18.0 ]");
|
||||
}
|
||||
|
||||
#[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().display().to_string(), "DEV:Thermometer[ 20.0 ]");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user