Created
May 28, 2026 18:00
-
-
Save mnguyenngo/8e960f2c12d12174d5a03ce433d6e61b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from typing import List, Tuple, Dict, Any | |
| import math | |
| class Room: | |
| """ | |
| Represents a room as a logical constraint boundary. | |
| Supports composition of adjacent rooms (e.g., bathrooms and closets). | |
| """ | |
| def __init__(self, name: str, x: float, y: float, center: Tuple[float, float] = (0.0, 0.0)): | |
| if x <= 0 or y <= 0: | |
| raise ValueError("Dimensions must be positive.") | |
| self.name = name | |
| self.x = x # width (feet) | |
| self.y = y # depth (feet) | |
| self.center = center | |
| self.sub_rooms: List['Room'] = [] | |
| @property | |
| def calculated_area(self) -> float: | |
| return self.x * self.y | |
| @property | |
| def total_suite_area(self) -> float: | |
| """Returns the total area of the room and all its sub-rooms.""" | |
| return self.calculated_area + sum(r.total_suite_area for r in self.sub_rooms) | |
| def add_bathroom(self, target_area: float, bathroom_type: str = "standard") -> 'Room': | |
| """Attaches a bathroom to this room adjacent to its right side.""" | |
| # Standard width of 5.0 ft for standard layout, or 8.0 ft for custom | |
| width = 5.0 if bathroom_type == "standard" else 8.0 | |
| depth = target_area / width | |
| # Position bathroom adjacent to the right side of the main room | |
| bath_center = (self.center[0] + (self.x + width) / 2.0, self.center[1]) | |
| bath = Room(f"{self.name} Bathroom", x=width, y=depth, center=bath_center) | |
| self.sub_rooms.append(bath) | |
| return bath | |
| def add_closet(self, target_area: float, closet_type: str = "walk_in") -> 'Room': | |
| """Attaches a closet to this room adjacent to its top side.""" | |
| # Standard depth of 4.0 ft for walk-in layout, or 3.0 ft for reach-in | |
| depth = 4.0 if closet_type == "walk_in" else 3.0 | |
| width = target_area / depth | |
| # Position closet adjacent to the top side of the main room | |
| closet_center = (self.center[0], self.center[1] + (self.y + depth) / 2.0) | |
| closet = Room(f"{self.name} Closet", x=width, y=depth, center=closet_center) | |
| self.sub_rooms.append(closet) | |
| return closet | |
| def _calculate_vertices(self) -> List[Tuple[float, float]]: | |
| cx, cy = self.center | |
| x_min, x_max = cx - self.x / 2.0, cx + self.x / 2.0 | |
| y_min, y_max = cy - self.y / 2.0, cy + self.y / 2.0 | |
| return [ | |
| (x_min, y_min), | |
| (x_max, y_min), | |
| (x_max, y_max), | |
| (x_min, y_max) | |
| ] | |
| @property | |
| def vertices(self) -> List[Tuple[float, float]]: | |
| return self._calculate_vertices() | |
| def serialize(self) -> Dict[str, Any]: | |
| return { | |
| "name": self.name, | |
| "dimensions": (self.x, self.y), | |
| "center": self.center, | |
| "calculated_area": self.calculated_area, | |
| "vertices": self.vertices, | |
| "sub_rooms": [r.serialize() for r in self.sub_rooms] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment