Source code for genplanner.zones.territory_zones

from dataclasses import dataclass
from enum import Enum

from genplanner.zones.abc_zone import Zone
from genplanner import config


[docs] class TerritoryZoneKind(str, Enum): """ Enumeration of supported territorial zone kinds. Values are stable string identifiers used in outputs and configuration. """ RESIDENTIAL = "residential" INDUSTRIAL = "industrial" BUSINESS = "business" RECREATION = "recreation" TRANSPORT = "transport" AGRICULTURE = "agriculture" SPECIAL = "special"
minimum_block_area = config.minimum_block_area
[docs] @dataclass(frozen=True, slots=True) class TerritoryZone(Zone): """ A concrete territorial zone definition. `TerritoryZone` represents a specific zone within a territory plan. It has: - a `kind` (from :class:`TerritoryZoneKind`), - a human-readable `name`, - a minimum block area constraint (`min_block_area`). The zone's `min_area` is defined as `min_block_area`, making it compatible with generic area constraints used elsewhere in the pipeline. Attributes: kind: Zone kind (Enum or a value convertible to it). name: Non-empty zone name. min_block_area: Minimum allowed area for generated blocks for this zone. Must be > 0. Raises: ValueError: If `kind` is invalid, `name` is empty, or `min_block_area` <= 0. """ kind: "TerritoryZoneKind" name: str min_block_area: float = minimum_block_area @property def min_area(self) -> float: """ Minimum area constraint for this zone. Returns: float: Minimum block area. """ return self.min_block_area def __post_init__(self): """ Validate and normalize fields after initialization. Raises: ValueError: If any field violates validation rules. """ self.validate() def validate(self) -> None: """ Validate and normalize zone fields. Ensures: - `kind` is a `TerritoryZoneKind` (attempts coercion from string/other), - `name` is a non-empty string, - `min_block_area` is a positive number. Raises: ValueError: If `kind` cannot be coerced, `name` is empty, or `min_block_area` <= 0. """ if not isinstance(self.kind, TerritoryZoneKind): try: object.__setattr__(self, "kind", TerritoryZoneKind(str(self.kind))) except Exception as e: raise ValueError( f"Invalid TerritoryZone kind: {self.kind!r}. " f"Allowed: {[k.value for k in TerritoryZoneKind]}" ) from e if not isinstance(self.name, str) or not self.name.strip(): raise ValueError("Zone name must be non-empty string") if not isinstance(self.min_block_area, (int, float)) or self.min_block_area <= 0: raise ValueError("min_block_area must be > 0") def __str__(self) -> str: """ Return a human-readable representation. Returns: str: String representation. """ return f'Territory zone "{self.name}" ({self.kind.value})'
residential_terr = TerritoryZone( kind=TerritoryZoneKind.RESIDENTIAL, name="residential", min_block_area=minimum_block_area, ) industrial_terr = TerritoryZone( kind=TerritoryZoneKind.INDUSTRIAL, name="industrial", min_block_area=minimum_block_area * 10, ) business_terr = TerritoryZone( kind=TerritoryZoneKind.BUSINESS, name="business", min_block_area=minimum_block_area * 2, ) recreation_terr = TerritoryZone( kind=TerritoryZoneKind.RECREATION, name="recreation", min_block_area=minimum_block_area * 8, ) transport_terr = TerritoryZone( kind=TerritoryZoneKind.TRANSPORT, name="transport", min_block_area=minimum_block_area * 8, ) agriculture_terr = TerritoryZone( kind=TerritoryZoneKind.AGRICULTURE, name="agriculture", min_block_area=minimum_block_area * 12, ) special_terr = TerritoryZone( kind=TerritoryZoneKind.SPECIAL, name="special", min_block_area=minimum_block_area * 4, )