from typing import Optional import datatypes.magicplan.api.response as api from datatypes.magicplan.api.response import MagicPlanPlan from domain.magicplan.models import Plan, Floor, Room, Window, Door def map_plan(mp: MagicPlanPlan) -> Plan: return Plan( uid=mp.plan.id, name=mp.plan.name, address=_map_address(mp.plan.address), postcode=mp.plan.address.postal_code if mp.plan.address else None, floors=[_map_floor(f) for f in mp.plan_detail.plan.floors], ) def _map_address(addr: Optional[api.Address]) -> Optional[str]: if addr is None: return None street = " ".join(p for p in [addr.street_number, addr.street] if p) or None parts = [p for p in [street, addr.city, addr.country] if p] return ", ".join(parts) if parts else None def _map_floor(f: api.Floor) -> Floor: return Floor( level=f.level, name=f.name, rooms=[_map_room(r) for r in f.rooms], ) def _map_room(r: api.Room) -> Room: width, length = _parse_dimensions(r.dimensions) return Room( name=r.name, width_m=width, length_m=length, area_m2=round(r.area, 2), windows=[ _map_window(wi) for wi in r.wall_items if wi.symbol.id.startswith("window") ], doors=[_map_door(wi) for wi in r.wall_items if wi.symbol.id.startswith("door")], ) def _parse_dimensions(dimensions: Optional[str]) -> tuple[float, float]: if not dimensions: return 0.0, 0.0 parts = dimensions.split(" x ") width = round(float(parts[0].split(" m")[0]), 2) length = round(float(parts[1].split(" m")[0]), 2) return width, length def _map_window(wi: api.WallItem) -> Window: return Window( width_m=round(wi.size.x, 2), height_m=round(wi.size.z, 2), area_m2=round(wi.size.x * wi.size.z, 2), opening_type=wi.symbol.id.removeprefix("window"), ) def _map_door(wi: api.WallItem) -> Door: return Door(width_mm=round(wi.size.x, 2))