mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
feat(modelling): Score carries the scored SapResult for billing
Score gains sap_result: Optional[SapResult], populated by PackageScorer with the calculator output its headline figures came from. This lets the Modelling stage price the post-package (and baseline) end-state via Bill Derivation reusing a SapResult already computed by the optimiser's re-score / the orchestrator's baseline score — no second calculate (ADR-0014 amendment). The optimiser reads only sap_continuous, so it stays domain-agnostic and the stub scorers (which omit sap_result) are unaffected — all optimiser tests pass unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ced6287baa
commit
2bbc401f0d
2 changed files with 27 additions and 2 deletions
|
|
@ -8,7 +8,7 @@ user-assembled plan.
|
|||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Sequence
|
||||
from typing import Optional, Sequence
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import EpcPropertyData
|
||||
from domain.modelling.scoring.overlay_applicator import apply_simulations
|
||||
|
|
@ -20,11 +20,18 @@ from domain.sap10_calculator.calculator import SapCalculator, SapResult
|
|||
class Score:
|
||||
"""The headline metrics of a scored package. `sap_continuous` is the
|
||||
un-rounded SAP rating (used for deltas); carbon and primary energy are the
|
||||
annual totals."""
|
||||
annual totals.
|
||||
|
||||
`sap_result` is the calculator output the headline figures were taken from,
|
||||
carried so Bill Derivation can price the scored end-state without a second
|
||||
`calculate` (ADR-0014 amendment). The optimiser never reads it — it works
|
||||
off `sap_continuous` only — so it stays domain-agnostic and a stub scorer
|
||||
may leave it `None`."""
|
||||
|
||||
sap_continuous: float
|
||||
co2_kg_per_yr: float
|
||||
primary_energy_kwh_per_yr: float
|
||||
sap_result: Optional[SapResult] = None
|
||||
|
||||
|
||||
class PackageScorer:
|
||||
|
|
@ -44,4 +51,5 @@ class PackageScorer:
|
|||
sap_continuous=result.sap_score_continuous,
|
||||
co2_kg_per_yr=result.co2_kg_per_yr,
|
||||
primary_energy_kwh_per_yr=result.primary_energy_kwh_per_yr,
|
||||
sap_result=result,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -52,3 +52,20 @@ def test_empty_package_scores_the_unmodified_baseline() -> None:
|
|||
abs(score.primary_energy_kwh_per_yr - direct.primary_energy_kwh_per_yr)
|
||||
<= 1e-9
|
||||
)
|
||||
|
||||
|
||||
def test_score_carries_the_scored_sap_result_for_billing() -> None:
|
||||
# Arrange — the post-package SapResult must ride on the Score so Bill
|
||||
# Derivation can price the simulated end-state without a second calculate
|
||||
# (ADR-0014 amendment).
|
||||
baseline: EpcPropertyData = build_epc()
|
||||
scorer = PackageScorer(Sap10Calculator())
|
||||
|
||||
# Act
|
||||
filled: Score = scorer.score(baseline, [_CAVITY_FILL])
|
||||
|
||||
# Assert — the SapResult is the one the Score's headline figures came from.
|
||||
assert filled.sap_result is not None
|
||||
assert (
|
||||
abs(filled.sap_result.sap_score_continuous - filled.sap_continuous) <= 1e-9
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue