mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
feat(modelling): Epc.sap_lower_bound() — band → minimum SAP (#1160)
Slice 3a. The inverse of Epc.from_sap_score: the minimum SAP rating in a band (C → 69, B → 81, …), used as the Optimiser's repair target for an INCREASING_EPC goal (goal_value "C" → target SAP 69). Keeps the band-target derivation in the domain rather than re-coupling to backend.app.utils.epc_to_sap_lower_bound. 8 tests incl. round-trip through from_sap_score; pyright strict clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
49e86344d2
commit
504f592a27
5 changed files with 41 additions and 0 deletions
|
|
@ -31,3 +31,18 @@ class Epc(Enum):
|
|||
if score >= 21:
|
||||
return cls.F
|
||||
return cls.G
|
||||
|
||||
def sap_lower_bound(self) -> int:
|
||||
"""The minimum SAP rating in this band — the inverse of
|
||||
`from_sap_score` (A → 92, B → 81, C → 69, D → 55, E → 39, F → 21,
|
||||
G → 1). Used as an optimisation target, e.g. "reach band C" → 69."""
|
||||
bounds: dict["Epc", int] = {
|
||||
Epc.A: 92,
|
||||
Epc.B: 81,
|
||||
Epc.C: 69,
|
||||
Epc.D: 55,
|
||||
Epc.E: 39,
|
||||
Epc.F: 21,
|
||||
Epc.G: 1,
|
||||
}
|
||||
return bounds[self]
|
||||
|
|
|
|||
0
tests/datatypes/__init__.py
Normal file
0
tests/datatypes/__init__.py
Normal file
0
tests/datatypes/epc/__init__.py
Normal file
0
tests/datatypes/epc/__init__.py
Normal file
0
tests/datatypes/epc/domain/__init__.py
Normal file
0
tests/datatypes/epc/domain/__init__.py
Normal file
26
tests/datatypes/epc/domain/test_epc.py
Normal file
26
tests/datatypes/epc/domain/test_epc.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
"""Behaviour of the Epc band enum's SAP mapping — the band a SAP rating falls
|
||||
in, and the minimum SAP rating of a band (the inverse, used as an optimisation
|
||||
target)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from datatypes.epc.domain.epc import Epc
|
||||
|
||||
|
||||
def test_sap_lower_bound_returns_the_band_floor() -> None:
|
||||
# Act / Assert — the standard SAP10 band floors.
|
||||
assert Epc.A.sap_lower_bound() == 92
|
||||
assert Epc.B.sap_lower_bound() == 81
|
||||
assert Epc.C.sap_lower_bound() == 69
|
||||
assert Epc.D.sap_lower_bound() == 55
|
||||
assert Epc.E.sap_lower_bound() == 39
|
||||
assert Epc.F.sap_lower_bound() == 21
|
||||
assert Epc.G.sap_lower_bound() == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("band", list(Epc))
|
||||
def test_band_floor_round_trips_through_from_sap_score(band: Epc) -> None:
|
||||
# Act / Assert — a band's floor scores back to that band.
|
||||
assert Epc.from_sap_score(band.sap_lower_bound()) is band
|
||||
Loading…
Add table
Reference in a new issue