from typing import override class Room: name: str length: float width: float def __init__(self, name: str, length: float, width: float): self.name = name self.length = length self.width = width @override def __repr__(self) -> str: return f"Room({self.length}'x{self.width}' {self.name})" def getArea(self) -> float: return self.length * self.width class Floor: name: str room_map: dict[str, Room] def __init__(self, name: str): self.name = name self.room_map = dict() @override def __repr__(self) -> str: return f"Floor({self.name} with {len(self.room_map)} room(s))" def addRoom(self, room: Room) -> None: if room.name in self.room_map: raise LookupError(f"{room.name} already exists on this floor") else: self.room_map[room.name] = room def getRoomCount(self) -> int: return len(self.room_map) def getRoom(self, name: str) -> Room | None: return self.room_map.get(name, None) def getRoomNames(self) -> list[str]: return sorted(self.room_map.keys()) def getArea(self) -> float: return sum([r.getArea() for r in self.room_map.values()]) class House: floors: dict[str, Floor] def __init__(self) -> None: self.floors = dict() @override def __repr__(self) -> str: return f"House({self.getFloorCount()} floor(s), {self.getRoomCount()} room(s), {self.getArea()} sq feet)" def addFloor(self, floor: Floor) -> None: if floor.name in self.floors: raise LookupError(f"{floor.name} already exists on this floor") else: self.floors[floor.name] = floor def getFloorCount(self) -> int: return len(self.floors) def getRoomCount(self) -> int: return sum([f.getRoomCount() for f in self.floors.values()]) def getArea(self) -> float: return sum([f.getArea() for f in self.floors.values()]) def getRoomFloor(self, room_name: str) -> Floor | None: for floor in self.floors.values(): if room_name in floor.getRoomNames(): return floor else: return None def getRoom(self, room_name: str) -> Room | None: floor = self.getRoomFloor(room_name) if floor == None: return None else: return floor.getRoom(room_name) def testLevel1(): print("Testing Level 1 (Core) material...", end="") # Note: a Room represents a room, on a Floor, in a House. room1 = Room("Living Room", 15, 15) # name, length, width assert str(room1) == "Room(15'x15' Living Room)" assert str([room1]) == "[Room(15'x15' Living Room)]" assert room1.getArea() == 225 # 15 * 15 room2 = Room("Kitchen", 10, 20) assert str(room2) == "Room(10'x20' Kitchen)" assert room2.getArea() == 200 # 10 * 20 # Notes: # * Each Floor can contain 0 or more rooms. # * Store the rooms in floor.roomMap, which is a dictionary # mapping the room name to the room instance. # * Do not store a floor's roomCount or roomNames separately. # Instead, compute these based on the keys in floor.roomMap. floor1 = Floor("1st Floor") assert str(floor1) == "Floor(1st Floor with 0 room(s))" assert floor1.getRoomCount() == 0 assert floor1.getRoomNames() == [] assert floor1.getArea() == 0 floor1.addRoom(room1) assert str(floor1) == "Floor(1st Floor with 1 room(s))" assert floor1.getRoomCount() == 1 assert floor1.getRoomNames() == ["Living Room"] assert floor1.getArea() == 225 floor1.addRoom(room2) assert str(floor1) == "Floor(1st Floor with 2 room(s))" assert floor1.getRoomCount() == 2 # Note that getRoomNames returns a *sorted* list of room names: assert floor1.getRoomNames() == ["Kitchen", "Living Room"] assert floor1.getArea() == 425 # We will try to add the Kitchen room again. # We are not allowed to add the same room twice, # nor even two rooms with the same name on any floor. error = None try: floor1.addRoom(room2) except Exception as e: error = str(e) assert error == "Kitchen already exists on this floor" assert floor1.getRoom("Living Room") == room1 assert floor1.getRoom("Kitchen") == room2 assert floor1.getRoom("Study") == None room3 = Room("Attic", 20, 30) assert str(room3) == "Room(20'x30' Attic)" assert room3.getArea() == 600 # 20 * 30 floor2 = Floor("2nd Floor") floor2.addRoom(room3) assert str(floor2) == "Floor(2nd Floor with 1 room(s))" assert floor2.getArea() == 600 # 20 * 30 print("Passed!") def testLevel2(): print("Testing Level 2+ (Not Core) material...", end="") room1 = Room("Living Room", 15, 15) room2 = Room("Kitchen", 10, 20) floor1 = Floor("1st Floor") floor1.addRoom(room1) floor1.addRoom(room2) room3 = Room("Attic", 20, 30) floor2 = Floor("2nd Floor") floor2.addRoom(room3) house = House() assert house.getFloorCount() == 0 assert house.getRoomCount() == 0 assert house.getArea() == 0 assert str(house) == "House(0 floor(s), 0 room(s), 0 sq feet)" house.addFloor(floor1) assert house.getFloorCount() == 1 assert house.getRoomCount() == 2 assert house.getArea() == 425 assert str(house) == "House(1 floor(s), 2 room(s), 425 sq feet)" house.addFloor(floor2) assert str(house) == "House(2 floor(s), 3 room(s), 1025 sq feet)" assert house.getFloorCount() == 2 assert house.getRoomCount() == 3 assert house.getArea() == 1025 assert house.getRoomFloor("Kitchen") == floor1 assert house.getRoomFloor("Attic") == floor2 assert house.getRoomFloor("Study") == None assert house.getRoom("Kitchen") == room2 assert house.getRoom("Attic") == room3 assert house.getRoom("Study") == None print("Passed!") def main(): testLevel1() testLevel2() main()