Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import re
from typing import Sequence
from .property_floor_area_types import FloorArea, FloorAreaUnit, RoomDimensions
from .units_convert import convert_units ← from units.convert ^1.0.0 · built alongside by fune
_DIMENSION = re.compile(r"[0-9]{1,3}(\.[0-9]{1,3})?")
_MAX_ROOMS = 1000
def _thousandths(room: str, field: str, text: str) -> int:
"""A dimension as an integer number of thousandths."""
if not isinstance(text, str) or not _DIMENSION.fullmatch(text):
raise ValueError(
'room "%s": %s must be a decimal below 1000 with at most 3 decimal places, received "%s"'
% (room, field, text)
)
whole, _, fraction = text.partition(".")
value = int(whole) * 1000 + int(fraction.ljust(3, "0"))
if value == 0:
raise ValueError('room "%s": %s must be greater than zero' % (room, field))
return value
def _decimal(millionths: int) -> str:
"""An integer number of millionths as the shortest exact decimal."""
whole, rest = divmod(millionths, 1_000_000)
fraction = str(rest).rjust(6, "0").rstrip("0")
return str(whole) if fraction == "" else "%d.%s" % (whole, fraction)
def floor_area(rooms: Sequence[RoomDimensions], length_unit: FloorAreaUnit, decimals: int) -> FloorArea:
"""Room areas and their total, exact, from length x width of each room,
and the total in square metres and square feet rounded once at the end."""
if length_unit not in ("m", "ft"):
raise ValueError('unknown length unit "%s": use m or ft' % (length_unit,))
if len(rooms) == 0:
raise ValueError("rooms must not be empty")
if len(rooms) > _MAX_ROOMS:
raise ValueError("at most %d rooms, received %d" % (_MAX_ROOMS, len(rooms)))
areas = [_thousandths(r.name, "length", r.length) * _thousandths(r.name, "width", r.width) for r in rooms]
total = _decimal(sum(areas))
source = "m2" if length_unit == "m" else "ft2"
return FloorArea(
room_areas=[_decimal(a) for a in areas],
total=total,
square_metres=convert_units(total, source, "m2", decimals),
square_feet=convert_units(total, source, "ft2", decimals),
)