diff --git a/backend/onboarders/epc_descriptions.py b/backend/onboarders/epc_descriptions.py index 7f1d04e9..36e9a4f8 100644 --- a/backend/onboarders/epc_descriptions.py +++ b/backend/onboarders/epc_descriptions.py @@ -122,8 +122,8 @@ class EpcRoofDescriptions(Enum): # Loft # Assumed options pitched_insulated_assumed = "Pitched, insulated (assumed)" - # Known insulation at joists - we have 12, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 270, 300, 350, - # 400+ as options + pitched_no_insulation = "Pitched, no insulation" + # Insulation thickness options loft_12mm_insulation: str = "Pitched, 12 mm loft insulation" loft_25mm_insulation: str = "Pitched, 25 mm loft insulation" loft_50mm_insulation: str = "Pitched, 50 mm loft insulation" @@ -182,7 +182,7 @@ class EpcRoofDescriptions(Enum): # Sloping ceiling # For sloping ceiling tags, we don't use any (assumed) tags so that it's unambiguous that the roof is sloped - sloping_pitched_no_insulation: str = "Pithced, no insulation" + sloping_pitched_no_insulation: str = "Pitched, no insulation" sloping_pitched_limited_insulation: str = "Pitched, limited insulation" sloping_pitched_insulated: str = "Pitched, insulated" @@ -372,6 +372,33 @@ def flat_insulated_efficiency(age_band: EpcConstructionAgeBand) -> EpcEfficiency pass +def loft_insulated_efficiency(age_band: EpcConstructionAgeBand) -> EpcEfficiency: + """ + 2023 onwards -> Very Good + 2012-2022 -> Very Good + 2007-2011 -> Very Good + 2003-2006 -> Very Good + 1996-2002 -> Good + 1991-1995 -> Good + 1983-1990 -> Average + 1976-1982 -> Average + 1967-1975 -> Average + 1950-1966 -> Average + 1930-1949 -> Average + 1900-1929 -> Average + before 1900 -> Average + :param age_band: Input age band, EpcConstructionAgeBand + :return: EpcEfficiency + """ + year = age_band.start_year() + if year >= 2003: + return EpcEfficiency.VERY_GOOD + if year >= 1991: + return EpcEfficiency.GOOD + + return EpcEfficiency.AVERAGE + + def flat_limited_efficiency( age_band: EpcConstructionAgeBand, insulation_thickness: int | None, @@ -407,6 +434,7 @@ ROOF_DESCRIPTION_EFFICIENCIES: Mapping[EpcRoofDescriptions, RoofEfficiencyRule] EpcRoofDescriptions.flat_insulated: flat_insulated_efficiency, # Loft: + # value mappings EpcRoofDescriptions.loft_12mm_insulation: EpcEfficiency.VERY_POOR, EpcRoofDescriptions.loft_25mm_insulation: EpcEfficiency.POOR, EpcRoofDescriptions.loft_50mm_insulation: EpcEfficiency.POOR, @@ -421,4 +449,8 @@ ROOF_DESCRIPTION_EFFICIENCIES: Mapping[EpcRoofDescriptions, RoofEfficiencyRule] EpcRoofDescriptions.loft_300mm_insulation: EpcEfficiency.VERY_GOOD, EpcRoofDescriptions.loft_350mm_insulation: EpcEfficiency.VERY_GOOD, EpcRoofDescriptions.loft_400mm_plus_insulation: EpcEfficiency.VERY_GOOD, + EpcRoofDescriptions.pitched_no_insulation: EpcEfficiency.VERY_POOR, + # function mappings + EpcRoofDescriptions.pitched_insulated_assumed: loft_insulated_efficiency, + } diff --git a/backend/onboarders/parity.py b/backend/onboarders/parity.py index f7553617..c3b4184d 100644 --- a/backend/onboarders/parity.py +++ b/backend/onboarders/parity.py @@ -438,7 +438,6 @@ ROOF_UNKNOWN_AGE_FALLBACK = { "PitchedThatched": EpcRoofDescriptions.thatched_as_built_unknown, "PitchedNormalLoftAccess": EpcRoofDescriptions.loft_as_built_unknown, "PitchedNormalNoLoftAccess": EpcRoofDescriptions.loft_as_built_unknown, - } @@ -454,9 +453,7 @@ def fill_roof_as_built(row): raise NotImplementedError(f"No roof classifier for roof type '{roof_type}'") if pd.isnull(row.construction_age_band): - raise NotImplementedError( - f"Missing age band for roof classification ({roof_type})" - ) + return ROOF_UNKNOWN_AGE_FALLBACK.get(roof_type) output = classifier(row.construction_age_band) if output is None: @@ -477,9 +474,12 @@ data["landlord_roof_description"] = data.progress_apply( fill_roof_as_built, axis=1, ) - -for _, row in data.iterrows(): - fill_roof_as_built(row) +# Sanity check +assert data["landlord_roof_description"].isnull().sum() == 0, ( + "Some roof descriptions could not be resolved" +) +# TODO: 1) Map energy efficiency +# TODO: 2) Flag sloped ceilings # Variables we want to map # 'Org Ref', 'Address 1', 'Address 2', 'Address 3', 'Postcode', 'Type',