from typing import Dict, Union from model_data.BaseUtility import Definitions from model_data.epc_attributes.attribute_utils import clean_description, find_keyword class MainheatControlAttributes(Definitions): # These systems allow for the automatic regulation of temperature THERMOSTATIC_CONTROL_KEYWORDS = [ 'room thermostats', 'appliance thermostats', 'room thermostat', 'temperature zone control', 'time and temperature zone control', 'celect-type control' # This is a specific type of thermostat controls # 'no thermostatic control', # 'no room thermostat' ] # TRVs stands for Thermostatic Radiator Valves which control the heating temperature of individual radiators # This is split out distinctly TRVS_KEYWORDS = [ 'trvs', ] # These systems provide a way to store and manage energy usage CHARGING_SYSTEM_KEYWORDS = [ 'charging system', 'automatic charge control', 'manual charge control', 'flat rate charging', 'high heat retention storage heaters' ] # These systems are mainly focused on on/off operations SWITCH_SYSTEM_KEYWORDS = [ 'programmer', ] # These systems enhance operation, efficiency, or safety. e.g. a boiler energy manager # manages the efficiency of boiler operation. There is an argument to separate 'boiler energy manager' and 'bypass' AUXILIARY_SYSTEM_KEYWORDS = [ 'boiler energy manager', 'bypass', 'flow switch', ] # These keywords indicate a lack of control system NO_CONTROL_SYSTEM_KEYWORDS = [ 'no time or thermostatic control', 'no thermostatic control', 'none', 'no room thermostat' ] # These systems provide control specifically for Domestic Hot Water DHW_CONTROL_KEYWORDS = [ 'dhw only' ] # This system indicates the use of community heating COMMUNITY_HEATING_KEYWORDS = [ 'use of community heating' ] MULTIPLE_ROOM_THERMOSTATS_PHRASES = [ 'at least two room stats', 'at least two room thermostats' ] RATE_CONTROL_KEYWORDS = [ 'single rate heating', ] # Sufficiently similar descriptions to be remapped TO_REMAP = { "celect control": 'celect-type control', "celect controls": 'celect-type control', } WELSH_TEXT = { "rhaglennydd, dim thermostat ystafell": "programmer, no room thermostat", "rhaglennydd a thermostat ystafell": "programmer and room thermostat", "rheoligçör t+ól +ó llaw": "manual charge control", "rheoli'r t+ól +ó llaw": "manual charge control", "rheolaeth amser a rheolaeth parthau tymheredd": "time and temperature zone control", "rhaglennydd a thermostatau ar y cyfarpar": "programmer, room thermostat", "rheolyddion i wresogyddion storio sygçön cadw llawer o wres": "controls for high heat retention storage " "heaters", "t+ól un gyfradd, rhaglennydd a thermostat ystafell": "single rate heating, programmer and room thermostat", "rhaglennydd ac o leiaf ddau thermostat ystafell": "programmer and at least two room thermostats", "thermostat ystafell yn unig": "room thermostat only", "dim rheolaeth amser na rheolaeth thermostatig ar dymheredd yr ystafell": "no time or thermostatic control of " "room temperature", "rheoli gwefr drydanol yn awtomatig": "automatic charge control", 'system dalu wedigçöi chysylltu +ó defnyddio gwres cymunedol, thermostat ystafell yn unig': "charging system " "linked to use of" " community " "heating, " "room thermostat " "only", "dim": "none", "dim rheolaeth thermostatig ar dymheredd yr ystafell": "no thermostatic control of room temperature", "thermostatau ar y cyfarpar": "appliance thermostats", "rhaglennydd a thermostatau ystafell": "programmer and room thermostats", "system dalu wedigçöi chysylltu +ó defnyddio gwres cymunedol, rhaglennydd a thermostat ystafell": ( "charging system linked to use of community heating, programmer and room thermostat" ), } def __init__(self, description: str): self.description: str = clean_description(description.lower()).strip() self.nodata = not self.description or description in self.DATA_ANOMALY_MATCHES translation = self.WELSH_TEXT.get(self.description) if translation: self.nodata = False self.description = translation # Remap remapped = self.TO_REMAP.get(self.description) if remapped: self.description = remapped if not self.nodata: if not any( self._keyword_in_description(keywords) for keywords in [ self.THERMOSTATIC_CONTROL_KEYWORDS, self.CHARGING_SYSTEM_KEYWORDS, self.SWITCH_SYSTEM_KEYWORDS, self.DHW_CONTROL_KEYWORDS, self.COMMUNITY_HEATING_KEYWORDS, self.TRVS_KEYWORDS, self.NO_CONTROL_SYSTEM_KEYWORDS, self.RATE_CONTROL_KEYWORDS ] ): raise ValueError('Invalid description') def _keyword_in_description(self, keywords): return any(keyword in self.description for keyword in keywords) def process(self) -> Dict[str, Union[str, bool, None]]: if self.nodata: result = { "thermostatic_control": False, "charging_system": False, "switch_system": False, "no_control": False, "dhw_control": False, "community_heating": False, "multiple_room_thermostats": False, "auxiliary_systems": False, "trvs": False, "rate_control": False } return result result: Dict[str, Union[str, bool, None]] = { "thermostatic_control": find_keyword(self.description, self.THERMOSTATIC_CONTROL_KEYWORDS), "charging_system": find_keyword(self.description, self.CHARGING_SYSTEM_KEYWORDS), "switch_system": find_keyword(self.description, self.SWITCH_SYSTEM_KEYWORDS), "no_control": find_keyword(self.description, self.NO_CONTROL_SYSTEM_KEYWORDS), "dhw_control": find_keyword(self.description, self.DHW_CONTROL_KEYWORDS), "community_heating": find_keyword(self.description, self.COMMUNITY_HEATING_KEYWORDS), "multiple_room_thermostats": any( phrase in self.description for phrase in self.MULTIPLE_ROOM_THERMOSTATS_PHRASES ), "auxiliary_systems": find_keyword(self.description, self.AUXILIARY_SYSTEM_KEYWORDS), "trvs": find_keyword(self.description, self.TRVS_KEYWORDS), "rate_control": find_keyword(self.description, self.RATE_CONTROL_KEYWORDS), } if result["no_control"] == 'no room thermostat': result["thermostatic_control"] = None return result