homework: remove names

This commit is contained in:
6 changed files with 133 additions and 163 deletions

View File

@@ -21,13 +21,6 @@ impl Device {
pub fn print_status(&self) {
println!("{}", self.display());
}
pub fn get_name(&self) -> &str {
match self {
Device::Thermometer(thermometer) => thermometer.get_name(),
Device::PowerSocket(power_socket) => power_socket.get_name(),
}
}
}
impl From<super::Thermometer> for Device {
@@ -49,8 +42,8 @@ mod tests {
#[test]
fn smoke_test() {
let dev_thermometer = Device::Thermometer(Thermometer::new("Therm", 20.1));
let dev_power_socket = Device::PowerSocket(PowerSocket::new("PSoc", 11.2, false));
let dev_thermometer = Device::Thermometer(Thermometer::new(20.1));
let dev_power_socket = Device::PowerSocket(PowerSocket::new(11.2, false));
dev_thermometer.print_status();
dev_power_socket.print_status();
@@ -60,16 +53,16 @@ mod tests {
unreachable!()
};
assert_eq!(format!("{}", thermometer.display()), "Therm[ 20.1 ]");
assert_eq!(format!("{}", power_socket.display()), "PSoc[ OFF : 0.0 ]");
assert_eq!(format!("{}", thermometer.display()), "Thermometer[ 20.1 ]");
assert_eq!(format!("{}", power_socket.display()), "PowerSocket[ OFF : 0.0 ]");
}
#[test]
fn display_test() {
let dev_thermometer = Device::Thermometer(Thermometer::new("Therm", 20.1));
let dev_power_socket = Device::PowerSocket(PowerSocket::new("PSoc", 11.2, false));
let dev_thermometer = Device::Thermometer(Thermometer::new(20.1));
let dev_power_socket = Device::PowerSocket(PowerSocket::new(11.2, false));
assert_eq!(format!("{}", dev_thermometer.display()), "DEV:Therm[ 20.1 ]");
assert_eq!(format!("{}", dev_power_socket.display()), "DEV:PSoc[ OFF : 0.0 ]");
assert_eq!(format!("{}", dev_thermometer.display()), "DEV:Thermometer[ 20.1 ]");
assert_eq!(format!("{}", dev_power_socket.display()), "DEV:PowerSocket[ OFF : 0.0 ]");
}
}

View File

@@ -3,21 +3,12 @@ use std::collections::HashMap;
#[derive(Debug)]
pub struct House {
address: String,
rooms: HashMap<String, Room>,
}
impl House {
pub fn new(address: impl AsRef<str>, rooms: Box<[Room]>) -> Self {
let rooms = rooms.into_iter().map(|r| (r.get_name().to_string(), r)).collect();
Self {
address: address.as_ref().to_string(),
rooms,
}
}
pub fn get_address(&self) -> &str {
&self.address
pub fn new(rooms: HashMap<String, Room>) -> Self {
Self { rooms }
}
pub fn get_room(&self, key: &str) -> Option<&Room> {
@@ -28,28 +19,28 @@ impl House {
self.rooms.get_mut(key)
}
pub fn insert_room(&mut self, room: Room) -> Option<Room> {
self.rooms.insert(room.get_name().to_string(), room)
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: &str, device: &str) -> Result<&Device, Error> {
let Some(room) = self.get_room(room) else {
return Err(Error::new(format!("no room named '{}' found", room)));
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) else {
return Err(Error::new(format!("no device named '{}' found in room '{}'", device, room.get_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)
}
pub fn print_status(&self) {
println!("HOUSE '{}':", self.address);
println!("{}", "=".repeat(32));
for (_, room) in self.rooms.iter() {
for (room_name, room) in self.rooms.iter() {
println!("{}:", room_name);
println!("{}", "-".repeat(32));
room.print_status();
println!();
}
@@ -63,42 +54,53 @@ mod tests {
fn create_test_house() -> House {
House::new(
"Best street, 777",
Box::new([
Room::new(
"main",
Box::new([
Thermometer::new("ThermA", 20.0).into(),
PowerSocket::new("PSocA", 12.34, false).into(),
PowerSocket::new("PSocB", 10.01, true).into(),
]),
[
(
"main".to_string(),
Room::new(
[
("ThermA".to_string(), Thermometer::new(20.0).into()),
("PSocA".to_string(), PowerSocket::new(12.34, false).into()),
("PSocB".to_string(), PowerSocket::new(10.01, true).into()),
]
.into_iter()
.collect(),
),
),
Room::new(
"bedroom",
Box::new([PowerSocket::new("PSocC", 11.11, true).into(), Thermometer::new("ThermB", 17.99).into()]),
(
"bedroom".to_string(),
Room::new(
[
("PSocC".to_string(), PowerSocket::new(11.11, true).into()),
("ThermB".to_string(), Thermometer::new(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!(house.address, "Best street, 777");
assert_eq!(house.get_address(), "Best street, 777");
assert_eq!(
format!("{}", house.get_room("main").unwrap().get_device("ThermA").unwrap().display()),
"DEV:ThermA[ 20.0 ]"
"DEV:Thermometer[ 20.0 ]"
);
assert_eq!(
format!("{}", house.get_room("main").unwrap().get_device("PSocA").unwrap().display()),
"DEV:PSocA[ OFF : 0.0 ]"
"DEV:PowerSocket[ OFF : 0.0 ]"
);
assert_eq!(
format!("{}", house.get_room("bedroom").unwrap().get_device("PSocC").unwrap().display()),
"DEV:PSocC[ ON : 11.1 ]"
"DEV:PowerSocket[ ON : 11.1 ]"
);
let Device::PowerSocket(powers_socket) = house.get_room_mut("main").unwrap().get_device_mut("PSocA").unwrap() else {
@@ -108,7 +110,7 @@ mod tests {
assert_eq!(
format!("{}", house.get_room("main").unwrap().get_device("PSocA").unwrap().display()),
"DEV:PSocA[ ON : 12.3 ]"
"DEV:PowerSocket[ ON : 12.3 ]"
);
}
@@ -121,15 +123,14 @@ mod tests {
#[test]
fn test_add_remove() {
let mut house = create_test_house();
let room = Room::new("empty", Box::new([]));
let room = Room::new(HashMap::new());
let result = house.insert_room(room);
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_name(), "bedroom");
assert_eq!(house.rooms.len(), 2);
assert_eq!(result.get_device("ThermB").unwrap().display().to_string(), "DEV:Thermometer[ 18.0 ]");
}
#[test]
@@ -143,6 +144,6 @@ mod tests {
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");
assert_eq!(result.unwrap().display().to_string(), "DEV:Thermometer[ 20.0 ]");
}
}

View File

@@ -2,31 +2,44 @@ use smart_house::{Device, House, PowerSocket, Room, Thermometer};
fn main() {
let mut house = House::new(
"A house of dream",
Box::new([
Room::new(
"Hall",
Box::new([
Device::PowerSocket(PowerSocket::new("PSocA", 9.5, true)),
Device::Thermometer(Thermometer::new("ThermA", 20.1)),
]),
[
(
"Hall".to_string(),
Room::new(
[
("PSocA".to_string(), PowerSocket::new(9.5, true).into()),
("ThermA".to_string(), Thermometer::new(20.1).into()),
]
.into_iter()
.collect(),
),
),
Room::new(
"Main",
Box::new([
Device::PowerSocket(PowerSocket::new("PSocB", 11.2, true)),
Device::Thermometer(Thermometer::new("ThermB", 24.5)),
Device::PowerSocket(PowerSocket::new("PSocC", 10.4, true)),
]),
(
"Main".to_string(),
Room::new(
[
("PSocB".to_string(), PowerSocket::new(11.2, true).into()),
("ThermB".to_string(), Thermometer::new(24.5).into()),
("PSocC".to_string(), PowerSocket::new(10.4, true).into()),
]
.into_iter()
.collect(),
),
),
Room::new(
"Bedroom",
Box::new([
Device::Thermometer(Thermometer::new("ThermC", 19.3)),
Device::PowerSocket(PowerSocket::new("PSocD", 12.1, true)),
]),
(
"Bedroom".to_string(),
Room::new(
[
("ThermC".to_string(), Thermometer::new(19.3).into()),
("PSocD".to_string(), PowerSocket::new(12.1, true).into()),
]
.into_iter()
.collect(),
),
),
]),
]
.into_iter()
.collect(),
);
house.print_status();

View File

@@ -2,22 +2,13 @@ use std::fmt::Display;
#[derive(Debug)]
pub struct PowerSocket {
name: String,
power_rate: f32,
on: bool,
}
impl PowerSocket {
pub fn new(name: impl AsRef<str>, power_rate: f32, on: bool) -> Self {
Self {
name: name.as_ref().to_string(),
power_rate,
on,
}
}
pub fn get_name(&self) -> &str {
&self.name
pub fn new(power_rate: f32, on: bool) -> Self {
Self { power_rate, on }
}
pub fn is_on(&self) -> bool {
@@ -34,7 +25,7 @@ impl PowerSocket {
pub fn display(&self) -> impl Display {
let state = if self.is_on() { "ON" } else { "OFF" };
format!("{}[ {} : {:02.1} ]", self.get_name(), state, self.get_power())
format!("PowerSocket[ {} : {:02.1} ]", state, self.get_power())
}
}
@@ -44,7 +35,7 @@ mod tests {
#[test]
fn smoke_test() {
let mut power_socket = PowerSocket::new("PowerSocket", 12.4, false);
let mut power_socket = PowerSocket::new(12.4, false);
assert_eq!(power_socket.power_rate, 12.4);
assert!(!power_socket.on);
assert!(!power_socket.is_on());
@@ -57,8 +48,8 @@ mod tests {
#[test]
fn display_test() {
assert_eq!(format!("{}", PowerSocket::new("PS_1", 11.549, false).display()), "PS_1[ OFF : 0.0 ]");
assert_eq!(format!("{}", PowerSocket::new("PS_2", 11.549, true).display()), "PS_2[ ON : 11.5 ]");
assert_eq!(format!("{}", PowerSocket::new("PS_3", 11.550, true).display()), "PS_3[ ON : 11.6 ]");
assert_eq!(format!("{}", PowerSocket::new(11.549, false).display()), "PowerSocket[ OFF : 0.0 ]");
assert_eq!(format!("{}", PowerSocket::new(11.549, true).display()), "PowerSocket[ ON : 11.5 ]");
assert_eq!(format!("{}", PowerSocket::new(11.550, true).display()), "PowerSocket[ ON : 11.6 ]");
}
}

View File

@@ -3,43 +3,33 @@ use std::collections::HashMap;
#[derive(Debug)]
pub struct Room {
name: String,
devices: HashMap<String, Device>,
}
impl Room {
pub fn new(name: impl AsRef<str>, devices: Box<[Device]>) -> Self {
let devices = devices.into_iter().map(|d| (d.get_name().to_string(), d)).collect();
Self {
name: name.as_ref().to_string(),
devices,
}
pub fn new(devices: HashMap<String, Device>) -> Self {
Self { devices }
}
pub fn get_name(&self) -> &str {
&self.name
pub fn get_device(&self, name: &str) -> Option<&Device> {
self.devices.get(name)
}
pub fn get_device(&self, key: &str) -> Option<&Device> {
self.devices.get(key)
pub fn get_device_mut(&mut self, name: &str) -> Option<&mut Device> {
self.devices.get_mut(name)
}
pub fn get_device_mut(&mut self, key: &str) -> Option<&mut Device> {
self.devices.get_mut(key)
pub fn insert_device(&mut self, name: &str, device: Device) -> Option<Device> {
self.devices.insert(name.to_string(), device)
}
pub fn insert_device(&mut self, device: Device) -> Option<Device> {
self.devices.insert(device.get_name().to_string(), device)
}
pub fn remove_device(&mut self, key: &str) -> Option<Device> {
self.devices.remove(key)
pub fn remove_device(&mut self, name: &str) -> Option<Device> {
self.devices.remove(name)
}
pub fn print_status(&self) {
println!("ROOM '{}':", self.name);
println!("{}", "-".repeat(24));
for (_, device) in self.devices.iter() {
for (name, device) in self.devices.iter() {
print!("{} => ", name);
device.print_status();
}
}
@@ -50,58 +40,50 @@ mod tests {
use super::*;
use crate::{PowerSocket, Thermometer};
fn create_test_room() -> Room {
let devices = [
("PSoc".to_string(), PowerSocket::new(12.34, false).into()),
("Therm".to_string(), Thermometer::new(21.56).into()),
]
.into_iter()
.collect::<HashMap<String, Device>>();
Room::new(devices)
}
#[test]
fn smoke_test() {
let devices = Box::new([
Device::PowerSocket(PowerSocket::new("PSoc", 12.34, false)),
Device::Thermometer(Thermometer::new("Therm", 21.56)),
]);
let mut room = Room::new("test_room", devices);
assert_eq!(room.name, "test_room");
assert_eq!(room.get_name(), "test_room");
let mut room = create_test_room();
assert_eq!(room.devices.len(), 2);
room.print_status();
assert_eq!(format!("{}", room.get_device("PSoc").unwrap().display()), "DEV:PSoc[ OFF : 0.0 ]");
assert_eq!(format!("{}", room.get_device("Therm").unwrap().display()), "DEV:Therm[ 21.6 ]");
assert_eq!(format!("{}", room.get_device("PSoc").unwrap().display()), "DEV:PowerSocket[ OFF : 0.0 ]");
assert_eq!(format!("{}", room.get_device("Therm").unwrap().display()), "DEV:Thermometer[ 21.6 ]");
let Device::PowerSocket(power_socket) = room.get_device_mut("PSoc").unwrap() else {
unreachable!()
};
power_socket.set_on(true);
assert_eq!(format!("{}", room.get_device("PSoc").unwrap().display()), "DEV:PSoc[ ON : 12.3 ]");
assert_eq!(format!("{}", room.get_device("Therm").unwrap().display()), "DEV:Therm[ 21.6 ]");
assert_eq!(format!("{}", room.get_device("PSoc").unwrap().display()), "DEV:PowerSocket[ ON : 12.3 ]");
assert_eq!(format!("{}", room.get_device("Therm").unwrap().display()), "DEV:Thermometer[ 21.6 ]");
}
#[test]
fn check_out_of_bounds() {
let room = Room::new(
"test_room",
Box::new([
Device::PowerSocket(PowerSocket::new("PSoc", 12.34, false)),
Device::Thermometer(Thermometer::new("Therm", 21.56)),
]),
);
let room = create_test_room();
assert!(room.get_device("dummy").is_none());
}
#[test]
fn test_add_remove() {
let mut room = Room::new(
"test_room",
Box::new([
Device::PowerSocket(PowerSocket::new("PSoc", 12.34, false)),
Device::Thermometer(Thermometer::new("Therm", 21.56)),
]),
);
let result = room.insert_device(Device::Thermometer(Thermometer::new("NewTerm", 20.0)));
let mut room = create_test_room();
let result = room.insert_device("NewTerm", Thermometer::new(20.0).into());
assert!(result.is_none());
assert_eq!(room.devices.len(), 3);
let Some(Device::Thermometer(removed)) = room.remove_device("Therm") else {
unreachable!()
};
assert_eq!(removed.get_name(), "Therm");
assert_eq!(removed.get_temperature(), 21.56);
assert_eq!(room.devices.len(), 2);
}

View File

@@ -2,20 +2,12 @@ use std::fmt::Display;
#[derive(Debug)]
pub struct Thermometer {
name: String,
temperature: f32,
}
impl Thermometer {
pub fn new(name: impl AsRef<str>, temperature: f32) -> Self {
Self {
name: name.as_ref().to_string(),
temperature,
}
}
pub fn get_name(&self) -> &str {
&self.name
pub fn new(temperature: f32) -> Self {
Self { temperature }
}
pub fn get_temperature(&self) -> f32 {
@@ -23,7 +15,7 @@ impl Thermometer {
}
pub fn display(&self) -> impl Display {
format!("{}[ {:02.1} ]", self.get_name(), self.get_temperature())
format!("Thermometer[ {:02.1} ]", self.get_temperature())
}
}
@@ -33,16 +25,14 @@ mod tests {
#[test]
fn smoke_test() {
let thermometer = Thermometer::new("TERM", 20.0);
let thermometer = Thermometer::new(20.0);
assert_eq!(thermometer.temperature, 20.0);
assert_eq!(thermometer.get_temperature(), 20.0);
assert_eq!(thermometer.name, "TERM");
assert_eq!(thermometer.get_name(), "TERM");
}
#[test]
fn display_test() {
assert_eq!(format!("{}", Thermometer::new("T1", 19.550).display()), "T1[ 19.5 ]");
assert_eq!(format!("{}", Thermometer::new("T2", 19.551).display()), "T2[ 19.6 ]");
assert_eq!(format!("{}", Thermometer::new(19.550).display()), "Thermometer[ 19.5 ]");
assert_eq!(format!("{}", Thermometer::new(19.551).display()), "Thermometer[ 19.6 ]");
}
}