"""Stage 1c tests — ТЭП and financial model arithmetic. Pure-arithmetic unit tests against known footprint geometry: GFA, residential area, apartment count, FAR, parking, revenue/cost/margin and the IRR-proxy clamp. """ from __future__ import annotations from shapely.geometry import box from app.schemas.concept import TEAP from app.services.generative import financial, teap # Один прямоугольник 20 x 10 = 200 кв.м пятна. _FOOTPRINT = box(0, 0, 20, 10) def test_teap_basic_arithmetic() -> None: result = teap.compute_teap( footprints=[_FOOTPRINT], floors=10, site_area_sqm=1000.0, housing_class="comfort", ) assert result.built_area_sqm == 200.0 # GFA = пятно * этажность. assert result.total_floor_area_sqm == 2000.0 # FAR = GFA / участок. assert result.density == 2.0 # Жилая = GFA * efficiency(comfort=0.78). assert result.residential_area_sqm == 1560.0 # Квартир = floor(жилая / avg(comfort=55)). assert result.apartments_count == int(1560.0 // 55.0) # Парковка = ceil(квартир * 1.0). assert result.parking_spaces == result.apartments_count def test_teap_class_changes_efficiency_and_lot() -> None: econ = teap.compute_teap( footprints=[_FOOTPRINT], floors=10, site_area_sqm=1000.0, housing_class="econom" ) biz = teap.compute_teap( footprints=[_FOOTPRINT], floors=10, site_area_sqm=1000.0, housing_class="business" ) # Эконом эффективнее по площади -> больше жилой при той же GFA. assert econ.residential_area_sqm > biz.residential_area_sqm # Бизнес — крупнее лот -> меньше квартир. assert biz.apartments_count < econ.apartments_count # Бизнес — выше норма парковки на квартиру. assert biz.parking_spaces / max(1, biz.apartments_count) >= 1.4 def test_teap_zero_site_area_no_division_error() -> None: result = teap.compute_teap( footprints=[_FOOTPRINT], floors=5, site_area_sqm=0.0, housing_class="comfort" ) assert result.density == 0.0 def test_teap_empty_placement_is_zeroed() -> None: result = teap.compute_teap( footprints=[], floors=9, site_area_sqm=1000.0, housing_class="comfort" ) assert result.built_area_sqm == 0.0 assert result.total_floor_area_sqm == 0.0 assert result.apartments_count == 0 assert result.parking_spaces == 0 def _teap(residential: float, gfa: float) -> TEAP: return TEAP( built_area_sqm=100.0, total_floor_area_sqm=gfa, residential_area_sqm=residential, apartments_count=10, density=1.0, parking_spaces=10, ) def test_financial_revenue_cost_margin() -> None: t = _teap(residential=1000.0, gfa=1300.0) model = financial.compute_financial( teap=t, housing_class="comfort", land_cost_rub=50_000_000.0 ) # revenue = 1000 * 145_000. assert model.revenue_rub == 1000.0 * 145_000.0 # cost = 1300 * 88_000 + land. assert model.cost_rub == 1300.0 * 88_000.0 + 50_000_000.0 assert model.gross_margin_rub == model.revenue_rub - model.cost_rub def test_financial_land_cost_optional() -> None: t = _teap(residential=1000.0, gfa=1300.0) no_land = financial.compute_financial(teap=t, housing_class="comfort", land_cost_rub=None) with_land = financial.compute_financial( teap=t, housing_class="comfort", land_cost_rub=10_000_000.0 ) # Земля увеличивает затраты ровно на свою стоимость. assert with_land.cost_rub - no_land.cost_rub == 10_000_000.0 def test_financial_irr_proxy_clamped() -> None: # Огромная маржа -> irr-proxy зажат в [-1, 1]. t = _teap(residential=100_000.0, gfa=1.0) model = financial.compute_financial(teap=t, housing_class="business", land_cost_rub=None) assert -1.0 <= model.irr <= 1.0 def test_financial_zero_cost_no_division_error() -> None: t = _teap(residential=0.0, gfa=0.0) model = financial.compute_financial(teap=t, housing_class="comfort", land_cost_rub=None) assert model.irr == 0.0 assert model.cost_rub == 0.0