from typing import Callable, Union from collections.abc import Mapping from datatypes.epc.walls import EpcWallDescriptions from datatypes.epc.construction_age_band import EpcConstructionAgeBand from datatypes.epc.efficiency import EpcEfficiency # Unique combinations wall_map = { # Cavity walls ('Cavity', 'FilledCavity'): EpcWallDescriptions.cavity_filled_cavity, ('Cavity', 'Internal'): EpcWallDescriptions.cavity_internal_insulation, ('Cavity', 'External'): EpcWallDescriptions.cavity_external_insulation, ('Cavity', 'FilledCavityPlusInternal'): EpcWallDescriptions.cavity_filled_plus_internal, ('Cavity', 'FilledCavityPlusExternal'): EpcWallDescriptions.cavity_filled_plus_external, ('Cavity', 'AsBuilt'): None, # To be classified ('Cavity', 'Unknown'): None, # To be classified # System built walls ('System', 'External'): EpcWallDescriptions.system_external_insulation, ('System', 'Internal'): EpcWallDescriptions.system_internal_insulation, ('System', 'AsBuilt'): None, # To be classified ('System', 'Unknown'): None, # Timber Frame walls ('Timber Frame', 'Internal'): EpcWallDescriptions.timber_frame_internal_insulation, ('Timber Frame', 'External'): EpcWallDescriptions.timber_frame_external_insulation, ('Timber Frame', 'AsBuilt'): None, # To be classified ('Timber Frame', 'Unknown'): None, # Solid Brick walls ('Solid Brick', 'External'): EpcWallDescriptions.solid_brick_external_insulation, ('Solid Brick', 'Internal'): EpcWallDescriptions.solid_brick_internal_insulation, ('Solid Brick', 'AsBuilt'): None, # To be classified ('Solid Brick', 'Unknown'): None, # Granite walls ('Granite', 'External'): EpcWallDescriptions.granite_whinstone_external_insulation, ("Granite", 'Internal'): EpcWallDescriptions.granite_whinstone_internal_insulation, ('Granite', 'AsBuilt'): None, ('Granite', 'Unknown'): None, # Sandstone walls ('Sandstone', 'Internal'): EpcWallDescriptions.sandstone_limestone_internal_insulation, ('Sandstone', 'External'): EpcWallDescriptions.sandstone_limestone_external_insulation, ('Sandstone', 'Unknown'): None, ('Sandstone', 'AsBuilt'): None, # Cob walls ('Cob', 'AsBuilt'): None, } wall_unknown_age_fallback = { "Cavity": EpcWallDescriptions.cavity_as_built_unknown, "Solid Brick": EpcWallDescriptions.solid_brick_as_built_unknown, "Timber Frame": EpcWallDescriptions.timber_frame_as_built_unknown, "System": EpcWallDescriptions.system_as_built_unknown, "Granite": EpcWallDescriptions.granite_as_built_unknown, "Sandstone": EpcWallDescriptions.sandstone_as_built_unknown, "Cob": EpcWallDescriptions.cob_as_built_unknown, } def cavity_filled_efficiency(age_band: EpcConstructionAgeBand) -> EpcEfficiency: """" Maps cavity filled to efficiency based on construction age band. :param age_band: EpcConstructionAgeBand :return: EpcEfficiency """ if age_band in { EpcConstructionAgeBand.from_2023_onwards }: return EpcEfficiency.VERY_GOOD return EpcEfficiency.GOOD def internal_external_insulation_efficiency( age_band: EpcConstructionAgeBand, ) -> EpcEfficiency: """ Maps: - cavity unfilled with internal/external insulation to efficiency based on construction age band. We assumed based on 100mm insulation - solid brick with internal/external insulation to efficiency based on construction age band. We assumed based on 100mm insulation - system built with internal/external insulation to efficiency based on construction age band. We assumed based on 100mm insulation All of these wall types have the same behaviour in elmhurst :param age_band: EpcConstructionAgeBand :return: EpcEfficiency """ if age_band in { EpcConstructionAgeBand.from_1983_to_1990, EpcConstructionAgeBand.from_1991_to_1995, EpcConstructionAgeBand.from_1996_to_2002, EpcConstructionAgeBand.from_2003_to_2006, EpcConstructionAgeBand.from_2007_to_2011, EpcConstructionAgeBand.from_2012_to_2022, EpcConstructionAgeBand.from_2023_onwards, }: return EpcEfficiency.VERY_GOOD return EpcEfficiency.GOOD def timber_granite_sandstone_internal_external_efficiency(age_band: EpcConstructionAgeBand) -> EpcEfficiency: """" Maps: - timber frame with internal/external wall insulation to efficiency based on construction age band. - sandstone/limestone with internal/external wall insulation to efficiency based on construction age band. - granite/whinstone with internal/external wall insulation to efficiency based on construction age band. :param age_band: EpcConstructionAgeBand :return: EpcEfficiency """ if age_band in { EpcConstructionAgeBand.from_2023_onwards }: return EpcEfficiency.VERY_GOOD return EpcEfficiency.GOOD WallEfficiencyRule = Union[ EpcEfficiency, Callable[[EpcConstructionAgeBand, int | None], EpcEfficiency], ] WALL_DESCRIPTION_EFFICIENCIES: Mapping[EpcWallDescriptions, WallEfficiencyRule] = { # Note: all function mappings have been defined based on Elmhurst # Cavity # value mappings EpcWallDescriptions.cavity_no_insulation_assumed: EpcEfficiency.POOR, EpcWallDescriptions.cavity_partial_insulated_assumed: EpcEfficiency.AVERAGE, EpcWallDescriptions.cavity_insulated_assumed: EpcEfficiency.GOOD, EpcWallDescriptions.cavity_filled_plus_internal: EpcEfficiency.VERY_GOOD, EpcWallDescriptions.cavity_filled_plus_external: EpcEfficiency.VERY_GOOD, # function mappings EpcWallDescriptions.cavity_filled_cavity: cavity_filled_efficiency, EpcWallDescriptions.cavity_internal_insulation: internal_external_insulation_efficiency, EpcWallDescriptions.cavity_external_insulation: internal_external_insulation_efficiency, # Solid brick # value mappings EpcWallDescriptions.solid_brick_no_insulation_assumed: EpcEfficiency.POOR, EpcWallDescriptions.solid_brick_partial_insulated_assumed: EpcEfficiency.AVERAGE, EpcWallDescriptions.solid_brick_insulated_assumed: EpcEfficiency.GOOD, # function mappings EpcWallDescriptions.solid_brick_internal_insulation: internal_external_insulation_efficiency, EpcWallDescriptions.solid_brick_external_insulation: internal_external_insulation_efficiency, # System # value mappings EpcWallDescriptions.system_no_insulation_assumed: EpcEfficiency.POOR, EpcWallDescriptions.system_partial_insulated_assumed: EpcEfficiency.AVERAGE, EpcWallDescriptions.system_insulated_assumed: EpcEfficiency.GOOD, # function mappings EpcWallDescriptions.system_internal_insulation: internal_external_insulation_efficiency, EpcWallDescriptions.system_external_insulation: internal_external_insulation_efficiency, # Timber frame # value mappings EpcWallDescriptions.timber_frame_no_insulation_assumed: EpcEfficiency.POOR, EpcWallDescriptions.timber_frame_partial_insulated_assumed: EpcEfficiency.AVERAGE, EpcWallDescriptions.timber_frame_insulated_assumed: EpcEfficiency.GOOD, # function mappings EpcWallDescriptions.timber_frame_internal_insulation: timber_granite_sandstone_internal_external_efficiency, EpcWallDescriptions.timber_frame_external_insulation: timber_granite_sandstone_internal_external_efficiency, # Granite / whinstone EpcWallDescriptions.granite_whinstone_no_insulation_assumed: EpcEfficiency.VERY_POOR, EpcWallDescriptions.granite_whinstone_partial_insulated_assumed: EpcEfficiency.AVERAGE, EpcWallDescriptions.granite_whinestone_insulated_assumed: EpcEfficiency.GOOD, # function mappings EpcWallDescriptions.granite_whinstone_internal_insulation: timber_granite_sandstone_internal_external_efficiency, EpcWallDescriptions.granite_whinstone_external_insulation: timber_granite_sandstone_internal_external_efficiency, # Sandstone / limestone EpcWallDescriptions.sandstone_limestone_no_insulation_assumed: EpcEfficiency.VERY_POOR, EpcWallDescriptions.sandstone_limestone_partial_insulated_assumed: EpcEfficiency.AVERAGE, EpcWallDescriptions.sandstone_limestone_insulated_assumed: EpcEfficiency.GOOD, # function mappings EpcWallDescriptions.sandstone_limestone_internal_insulation: timber_granite_sandstone_internal_external_efficiency, EpcWallDescriptions.sandstone_limestone_external_insulation: timber_granite_sandstone_internal_external_efficiency, # Cob (special case) EpcWallDescriptions.cob_as_built_average: EpcEfficiency.AVERAGE, EpcWallDescriptions.cob_as_built_good: EpcEfficiency.GOOD, # Unknown mappings which are unhandled EpcWallDescriptions.cavity_as_built_unknown: EpcEfficiency.NA, EpcWallDescriptions.solid_brick_as_built_unknown: EpcEfficiency.NA, EpcWallDescriptions.system_as_built_unknown: EpcEfficiency.NA, EpcWallDescriptions.timber_frame_as_built_unknown: EpcEfficiency.NA, EpcWallDescriptions.granite_as_built_unknown: EpcEfficiency.NA, EpcWallDescriptions.sandstone_as_built_unknown: EpcEfficiency.NA, EpcWallDescriptions.cob_as_built_unknown: EpcEfficiency.NA, } def resolve_wall_efficiency( description: EpcWallDescriptions, age_band: EpcConstructionAgeBand, ) -> EpcEfficiency: rule = WALL_DESCRIPTION_EFFICIENCIES[description] if isinstance(rule, EpcEfficiency): return rule return rule(age_band)