mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
86 lines
3.5 KiB
Python
86 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from openpyxl.cell.rich_text import CellRichText, TextBlock
|
|
from openpyxl.cell.text import InlineFont
|
|
from openpyxl.formatting.rule import CellIsRule # type: ignore[reportUnknownVariableType]
|
|
from openpyxl.styles import Color, Font
|
|
|
|
from domain.magicplan.models import Door, Plan, Room, Window
|
|
|
|
_DATA_START_ROW = 6
|
|
_MAX_ROWS = 50
|
|
_DOOR_AREA_COL = "U"
|
|
_DOOR_AREA_CF_RANGE = f"{_DOOR_AREA_COL}{_DATA_START_ROW}:{_DOOR_AREA_COL}{_DATA_START_ROW + _MAX_ROWS - 1}"
|
|
_Y_THRESHOLD = 7600
|
|
_DOOR_AREA_HEADER = CellRichText(
|
|
TextBlock(InlineFont(b=True, sz=11, rFont="Aptos Narrow"), "Area (mm2)\n"),
|
|
TextBlock(InlineFont(b=True, sz=11, color=Color(rgb="FF0000"), rFont="Aptos Narrow"), "<"),
|
|
TextBlock(InlineFont(b=True, sz=11, rFont="Aptos Narrow"), " 7600 "),
|
|
TextBlock(InlineFont(b=True, sz=11, color=Color(rgb="196B24"), rFont="Aptos Narrow"), "<"),
|
|
)
|
|
|
|
|
|
def _apply_column_y_formatting(sheet: Any) -> None:
|
|
sheet.conditional_formatting.add(
|
|
_DOOR_AREA_CF_RANGE,
|
|
CellIsRule(operator="lessThan", formula=[str(_Y_THRESHOLD)], font=Font(color=Color(rgb="FF0000"))),
|
|
)
|
|
sheet.conditional_formatting.add(
|
|
_DOOR_AREA_CF_RANGE,
|
|
CellIsRule(operator="greaterThan", formula=[str(_Y_THRESHOLD)], font=Font(color=Color(rgb="196B24"))),
|
|
)
|
|
sheet[f"{_DOOR_AREA_COL}3"] = _DOOR_AREA_HEADER
|
|
|
|
|
|
def _write_cell(sheet: Any, row: int, col: str, value: Any) -> None:
|
|
sheet[f"{col}{row}"] = value
|
|
|
|
|
|
def populate_sheet(sheet: Any, plan: Plan) -> None:
|
|
rooms: list[Room] = [room for floor in plan.floors for room in floor.rooms]
|
|
windows: list[tuple[str, Window]] = [
|
|
(room.name, w) for room in rooms for w in room.windows
|
|
]
|
|
doors: list[tuple[str, Door]] = [
|
|
(room.name, d) for room in rooms for d in room.doors
|
|
]
|
|
|
|
if len(rooms) > _MAX_ROWS:
|
|
raise ValueError(f"Room series exceeds {_MAX_ROWS} rows ({len(rooms)} rooms)")
|
|
if len(windows) > _MAX_ROWS:
|
|
raise ValueError(f"Window series exceeds {_MAX_ROWS} rows ({len(windows)} windows)")
|
|
if len(doors) > _MAX_ROWS:
|
|
raise ValueError(f"Door series exceeds {_MAX_ROWS} rows ({len(doors)} doors)")
|
|
|
|
for i, room in enumerate(rooms):
|
|
row = _DATA_START_ROW + i
|
|
_write_cell(sheet, row, "B", room.name)
|
|
_write_cell(sheet, row, "D", room.area_m2)
|
|
|
|
for i, (room_name, window) in enumerate(windows):
|
|
row = _DATA_START_ROW + i
|
|
vent = window.ventilation
|
|
_write_cell(sheet, row, "F", room_name)
|
|
_write_cell(sheet, row, "G", window.width_m)
|
|
_write_cell(sheet, row, "H", window.height_m)
|
|
# I = formula =G*H — do not write
|
|
_write_cell(sheet, row, "J", vent.opening_type if vent else 0)
|
|
_write_cell(sheet, row, "K", vent.num_openings if vent else 0)
|
|
pct = vent.pct_openable if vent else None
|
|
_write_cell(sheet, row, "L", (pct / 100) if pct is not None else 0)
|
|
# M = formula =I*L — do not write
|
|
_write_cell(sheet, row, "N", vent.trickle_vent_area_mm2 if vent else 0)
|
|
_write_cell(sheet, row, "O", vent.num_trickle_vents if vent else 0)
|
|
# P = formula =N*O — do not write
|
|
|
|
for i, (room_name, door) in enumerate(doors):
|
|
row = _DATA_START_ROW + i
|
|
vent = door.ventilation
|
|
_write_cell(sheet, row, "R", room_name)
|
|
_write_cell(sheet, row, "S", door.width_mm)
|
|
_write_cell(sheet, row, "T", vent.undercut_mm if vent else 0)
|
|
# U = formula =S*T — do not write
|
|
|
|
_apply_column_y_formatting(sheet)
|