From a7c34c85034eb35d5826ff118192194bd00a3218 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 2 Feb 2026 15:50:30 +0000 Subject: [PATCH] working on loft at rafters --- backend/onboarders/epc_descriptions.py | 181 +++++++++++++++++++++---- 1 file changed, 158 insertions(+), 23 deletions(-) diff --git a/backend/onboarders/epc_descriptions.py b/backend/onboarders/epc_descriptions.py index a92565d1..fc10ad70 100644 --- a/backend/onboarders/epc_descriptions.py +++ b/backend/onboarders/epc_descriptions.py @@ -364,10 +364,6 @@ RoofEfficiencyRule = Union[ ] -def flat_limited_insulation_efficiency(age_band: EpcConstructionAgeBand) -> EpcEfficiency: - pass - - def flat_insulated_efficiency_age_band(age_band: EpcConstructionAgeBand) -> EpcEfficiency: """ before 1900, 1900-1929, 1930-1949, 1950-1966, 1967-1975 -> Pitched, no insulation, Very Poor @@ -424,6 +420,19 @@ def flat_insulated_efficiency_thickness(insulation_thickness: int | None) -> Epc return EpcEfficiency.VERY_POOR +def flat_efficiency(insulation_thickness: int | None, age_band: EpcConstructionAgeBand) -> EpcEfficiency: + """ + Combines both age band and insulation thickness to determine flat roof efficiency. + :param insulation_thickness: Insulation thickness in mm + :param age_band: EpcConstructionAgeBand + :return: EpcEfficiency + """ + if insulation_thickness is not None: + return flat_insulated_efficiency_thickness(insulation_thickness) + + return flat_insulated_efficiency_age_band(age_band) + + def loft_insulated_efficiency(age_band: EpcConstructionAgeBand) -> EpcEfficiency: """ 2023 onwards -> Very Good @@ -451,39 +460,156 @@ def loft_insulated_efficiency(age_band: EpcConstructionAgeBand) -> EpcEfficiency return EpcEfficiency.AVERAGE -def flat_limited_efficiency( - age_band: EpcConstructionAgeBand, +def thatched_efficiency_age_band(age_band: EpcConstructionAgeBand) -> EpcEfficiency: + """ + Maps thatched roof efficiency based on construction age band. + :param age_band: EpcConstructionAgeBand + :return: EpcEfficiency + """ + year = age_band.start_year() + if year >= 2023: + return EpcEfficiency.VERY_GOOD + if year >= 2003: + return EpcEfficiency.GOOD + + return EpcEfficiency.AVERAGE + + +def thatched_efficiency_thickness(insulation_thickness: int | None) -> EpcEfficiency: + """ + Maps thatched roof efficiency based on insulation thickness. + :param insulation_thickness: Insulation thickness in mm + :return: EpcEfficiency + """ + if insulation_thickness is None: + raise ValueError("Insulation thickness is required for thatched efficiency calculation") + + if insulation_thickness >= 175: + return EpcEfficiency.VERY_GOOD + + if insulation_thickness >= 25: + return EpcEfficiency.GOOD + + return EpcEfficiency.AVERAGE + + +def thatched_efficiency( insulation_thickness: int | None, + age_band: EpcConstructionAgeBand, ) -> EpcEfficiency: """ - If we have an insulation thickness, 12mm results in a very poor rating. 25mm or above results in a poor rating. - If we don't have an insulation thickness, we fall back to age band, where - - 1976 - 1982 = Flat, limited insulation, poor efficiency - - 1967 - 1975 = Flat, limited insulation, Very Poor - :param age_band: - :param insulation_thickness: - :return: + Combines both age band and insulation thickness to determine thatched roof efficiency. + :param insulation_thickness: Insulation thickness in mm + :param age_band: EpcConstructionAgeBand + :return: EpcEfficiency """ - if insulation_thickness is not None: - if insulation_thickness >= 25: - return EpcEfficiency.POOR - return EpcEfficiency.VERY_POOR + return thatched_efficiency_thickness(insulation_thickness) - if age_band == EpcConstructionAgeBand.from_1976_to_1982: + return thatched_efficiency_age_band(age_band) + + +def sloping_ceiling_efficiency_age_band(age_band: EpcConstructionAgeBand) -> EpcEfficiency: + """ + Maps sloping ceiling roof efficiency based on construction age band. + :param age_band: EpcConstructionAgeBand + :return: EpcEfficiency + """ + year = age_band.start_year() + if year >= 2023: + return EpcEfficiency.VERY_GOOD + if year >= 2003: + return EpcEfficiency.GOOD + if year >= 1983: + return EpcEfficiency.AVERAGE + if year >= 1976: return EpcEfficiency.POOR - if age_band == EpcConstructionAgeBand.from_1967_to_1975: - return EpcEfficiency.VERY_POOR + return EpcEfficiency.VERY_POOR - raise ValueError("Cannot determine flat limited insulation efficiency without insulation thickness or age band") + +def sloping_ceiling_efficiency_thickness(insulation_thickness: int | None) -> EpcEfficiency: + """ + Maps sloping ceiling roof efficiency based on insulation thickness. + :param insulation_thickness: Insulation thickness in mm + :return: EpcEfficiency + """ + if insulation_thickness is None: + raise ValueError("Insulation thickness is required for sloping ceiling efficiency calculation") + + if insulation_thickness >= 270: + return EpcEfficiency.VERY_GOOD + + if insulation_thickness >= 150: + return EpcEfficiency.GOOD + + if insulation_thickness >= 75: + return EpcEfficiency.AVERAGE + + if insulation_thickness >= 25: + return EpcEfficiency.POOR + + return EpcEfficiency.VERY_POOR + + +def sloping_ceiling_efficiency( + insulation_thickness: int | None, + age_band: EpcConstructionAgeBand, +) -> EpcEfficiency: + """ + Combines both age band and insulation thickness to determine sloping ceiling roof efficiency. + :param insulation_thickness: Insulation thickness in mm + :param age_band: EpcConstructionAgeBand + :return: EpcEfficiency + """ + if insulation_thickness is not None: + return sloping_ceiling_efficiency_thickness(insulation_thickness) + + return sloping_ceiling_efficiency_age_band(age_band) + + +def loft_insulated_at_rafters_efficiency_thickness(insulation_thickness: int | None) -> EpcEfficiency: + """ + 400mm, 350mm = very good + 200-300mm = good + 125-175 = average + 50-100 = poor + 25 and below= very poor + :return: + """ + if insulation_thickness is None: + raise ValueError("Insulation thickness is required for loft insulated at rafters efficiency calculation") + + if insulation_thickness >= 350: + return EpcEfficiency.VERY_GOOD + + if insulation_thickness >= 200: + return EpcEfficiency.GOOD + + if insulation_thickness >= 125: + return EpcEfficiency.AVERAGE + + if insulation_thickness >= 50: + return EpcEfficiency.POOR + + return EpcEfficiency.VERY_POOR + + +def loft_insulated_at_rafters_efficiency_age_band(age_band: EpcConstructionAgeBand) -> EpcEfficiency: + """ + # 2023 onwards -> Very Good + # 2012-2022 -> Good + Before 1900 -> Very Poor + :param age_band: + :return: + """ ROOF_DESCRIPTION_EFFICIENCIES: Mapping[EpcRoofDescriptions, RoofEfficiencyRule] = { # Flat roof EpcRoofDescriptions.flat_no_insulation: EpcEfficiency.VERY_POOR, - EpcRoofDescriptions.flat_limited_insulation: flat_limited_insulation_efficiency, - EpcRoofDescriptions.flat_insulated: flat_insulated_efficiency, + EpcRoofDescriptions.flat_limited_insulation: flat_efficiency, + EpcRoofDescriptions.flat_insulated: flat_efficiency, # Loft: # value mappings @@ -511,4 +637,13 @@ ROOF_DESCRIPTION_EFFICIENCIES: Mapping[EpcRoofDescriptions, RoofEfficiencyRule] # Another dwelling above EpcRoofDescriptions.another_dwelling_above: EpcEfficiency.NA, + # Thatched + EpcRoofDescriptions.thatched: thatched_efficiency, + EpcRoofDescriptions.thatched_with_additional_insulation: thatched_efficiency, + + # Sloping ceiling + EpcRoofDescriptions.sloping_pitched_insulated: sloping_ceiling_efficiency, + EpcRoofDescriptions.sloping_pitched_limited_insulation: sloping_ceiling_efficiency, + EpcRoofDescriptions.sloping_pitched_no_insulation: EpcEfficiency.VERY_POOR, + }