Model/etl/epc_clean/epc_attributes/HotWaterAttributes.py
2026-01-02 17:39:48 +08:00

216 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import Dict, Union
from BaseUtility import Definitions
from etl.epc_clean.epc_attributes.attribute_utils import clean_description, find_keyword, handle_mixed_translation
class HotWaterAttributes(Definitions):
# HEATER_TYPES refer to the main devices used for heating water. These devices can be powered by different energy
# sources.
HEATER_TYPES = [
'gas instantaneous', # A water heater that provides hot water only as it is needed
'electric heat pump',
# A device that transfers heat from a source (like the ground or air) into a building to provide hot water
'electric immersion', # An electric device that heats water using electric resistance
'gas boiler', # A boiler that uses gas as fuel to heat water
'oil boiler', # A boiler that uses oil as fuel to heat water
'electric instantaneous', # Similar to gas instantaneous, but uses electricity as its energy source
'gas multipoint', # A gas water heater that can supply hot water to multiple points of use at once
'heat pump', # A general category for heat pumps, regardless of the energy source
'solid fuel boiler', # burns solid materials to generate heat for water heating and/or space heating
'solid fuel range cooker',
'room heaters', # Generic/unspecified category
'electric multipoint',
'single-point gas',
]
# SYSTEM_TYPES refer to the larger system within which the heater operates.
SYSTEM_TYPES = [
'from main system', # The hot water is provided by the main heating system of the building
'from secondary system',
# The hot water is provided by a secondary (or supplementary) heating system in the building
'from second main heating system', # Same as 'from secondary system'
'community scheme', # The hot water is provided by a community heating system
"water heater",
]
# THERMOSTAT_CHARACTERISTICS refer to features related to temperature control in the system.
THERMOSTAT_CHARACTERISTICS = [
'no cylinder thermostat', # Indicates that the hot water cylinder does not have a thermostat
]
# HEATING_SCOPE refers to the specific role of the heater in the heating system.
HEATING_SCOPE = [
'water heating only', # Indicates that the heater is used only for water heating, not space heating
]
# ENERGY_RECOVERY refers to systems or epc_attributes that recover and utilize waste energy.
ENERGY_RECOVERY = [
'waste water heat recovery',
# A system that recovers heat from waste hot water (e.g., from showers) to preheat incoming cold water
'flue gas heat recovery', # A system that recovers heat from the flue gases of a boiler or furnace
]
# TARIFF_TYPE relates to the energy pricing structure or tariff that applies to the system.
TARIFF_TYPE = [
'standard tariff', # The energy used by the system is billed at a standard rate
'off-peak', # The energy used by the system is primarily used during off-peak hours when rates are lower
]
# EXTRA_FEATURES are additional features or systems that enhance the efficiency or capability of the hot water
# system.
EXTRA_FEATURES = [
'plus solar', # Indicates that the system includes solar thermal panels to assist in water heating
]
# CHP_SYSTEMS is specifically for the Combined Heat and Power systems.
CHP_SYSTEMS = [
'chp',
# Combined Heat and Power system, a system that simultaneously produces heat and electricity from the same
# energy source
]
# NO_SYSTEM_PRESENT_KEYWORDS indicates there is no specific hot water system present.
NO_SYSTEM_PRESENT_KEYWORDS = [
'no system present',
]
# DISTRIBUTION_SYSTEM_KEYWORDS refers to components that assist in the distribution of the heated water.
DISTRIBUTION_SYSTEM_KEYWORDS = [
'circulator', # A pump used to circulate hot water in the system
]
# Indicate if the information is assumed
ASSUMED = [
'assumed'
]
# in some rare instances, especially in older homes, a range cooker can be part of a larger system that also
# includes a boiler for heating water. In these cases, the cooker may help to heat the water, but this setup is
# not common, especially in modern homes.
APPLIANCE_SYSTEMS = [
'gas range cooker', # A gas-powered range cooker
'oil range cooker'
]
# Descriptions which represent the same thing
SYNONYMS = {
'from second main heating system': 'from secondary system',
}
WELSH_TEXT = {
"ogçör brif system": "from main system",
"o r brif system": "from main system",
"or brif system": "from main system",
"ogçör brif system, adfer gwres nwyon ffliw": "from main system, flue gas heat recovery",
"bwyler/cylchredydd nwy": "gas boiler/circulator",
"ogçör brif system, dim thermostat ar y silindr": "from main system, no cylinder thermostat",
"o r brif system, dim thermostat ar y silindr": "from main system, no cylinder thermostat",
"twymwr tanddwr, an-frig": "electric immersion, off-peak",
"ogçör brif system, gydag ynnigçör haul": "from main system, plus solar",
"twymwr tanddwr, tarriff safonol": "electric immersion, standard tariff",
"trydan ar unwaith yn y fan lle maegçön cael ei ddefnyddio": 'electric instantaneous at point of use',
"o gynllun cymunedol": "community scheme",
"o'r brif system": "from main system",
"trydan ar unwaith yn y fan lle mae'n cael ei ddefnyddio": 'electric instantaneous at point of use',
"popty estynedig olew, dim thermostat ar y silindr": "oil range cooker, no cylinder thermostat",
"cynllun cymunedol": "community scheme",
"nwy wrth fwy nag un pwynt": "gas multipoint",
"popty estynedig olew": "oil range cooker",
"dim system ar gael rhagdybir bod twymwr tanddwr trydan": "no system present electric immersion assumed",
"o'r brif system, dim thermostat ar y silindr": "from main system, no cylinder thermostat",
"trydan ar unwaith yn y fan lle maegçön cael ei ddefnyddio, adfer gwres d+¦r gwastraff": "electric "
"instantaneous at "
"point of use, "
"waste water heat "
"recovery",
"ogçör brif system, adfer gwres d+¦r gwastraff": "from main system, waste water heat recovery",
"twymwr tanddwr, tarriff safonol, adfer gwres d+¦r gwastraff": "electric immersion, standard tariff, waste "
"water heat recovery",
"ogçör brif system, dim thermostat ar y silindr, adfer gwres nwyon ffliw": "from main system, no cylinder "
"thermostat, flue gas heat recovery",
"ogçör brif system, gydag ynnigçör haul, adfer gwres nwyon ffliw": "from main system, plus solar, flue gas "
"heat recovery",
"o r brif system, gydag ynni r haul, dim thermostat ar y silindr": "from main system, plus solar, no cylinder "
"thermostat",
"o r brif system, gydag ynni r haul": "from main system, plus solar",
"pwmp gwres": "heat pump"
}
NODATA_DESCRIPTIONS = [
"sap05 hot-water",
"sap hot-water"
]
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 or (
self.description in self.NODATA_DESCRIPTIONS
)
translation = self.WELSH_TEXT.get(self.description)
if translation:
self.nodata = False
self.description = translation
# We handle seemind occurances of mixed translations
self.description = handle_mixed_translation(self.description)
if not self.nodata and not any(
self._keyword_in_description(keywords)
for keywords in [
self.HEATER_TYPES,
self.SYSTEM_TYPES,
self.THERMOSTAT_CHARACTERISTICS,
self.HEATING_SCOPE,
self.ENERGY_RECOVERY,
self.TARIFF_TYPE,
self.EXTRA_FEATURES,
self.CHP_SYSTEMS,
self.NO_SYSTEM_PRESENT_KEYWORDS,
self.APPLIANCE_SYSTEMS,
self.DISTRIBUTION_SYSTEM_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]]:
if self.nodata:
return {
"heater_type": None,
"system_type": None,
"thermostat_characteristics": None,
"heating_scope": None,
"energy_recovery": None,
"tariff_type": None,
"extra_features": None,
"chp_systems": None,
"distribution_system": None,
"no_system_present": None,
"assumed": None,
"appliance": None,
}
result: Dict[str, Union[str, bool]] = {
"heater_type": find_keyword(self.description, self.HEATER_TYPES),
"system_type": find_keyword(self.description, self.SYSTEM_TYPES, self.SYNONYMS),
"thermostat_characteristics": find_keyword(self.description, self.THERMOSTAT_CHARACTERISTICS),
"heating_scope": find_keyword(self.description, self.HEATING_SCOPE),
"energy_recovery": find_keyword(self.description, self.ENERGY_RECOVERY),
"tariff_type": find_keyword(self.description, self.TARIFF_TYPE),
"extra_features": find_keyword(self.description, self.EXTRA_FEATURES),
"chp_systems": find_keyword(self.description, self.CHP_SYSTEMS),
"distribution_system": find_keyword(self.description, self.DISTRIBUTION_SYSTEM_KEYWORDS),
"no_system_present": find_keyword(self.description, self.NO_SYSTEM_PRESENT_KEYWORDS),
"appliance": find_keyword(self.description, self.APPLIANCE_SYSTEMS),
}
assumed_found = find_keyword(self.description, self.ASSUMED)
result["assumed"] = True if assumed_found else False
return result