mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
222 lines
9 KiB
Python
222 lines
9 KiB
Python
from backend.Property import Property
|
|
from recommendations.Costs import Costs
|
|
from recommendations.recommendation_utils import override_costs, check_simulation_difference
|
|
from etl.epc_clean.epc_attributes.HotWaterAttributes import HotWaterAttributes
|
|
|
|
|
|
class HotwaterRecommendations:
|
|
def __init__(self, property_instance: Property):
|
|
self.property = property_instance
|
|
self.costs = Costs(self.property)
|
|
|
|
self.recommendations = []
|
|
|
|
def recommend(self, phase):
|
|
"""
|
|
There are maybe a number of recommendations that are simultaneously applicable to the property.
|
|
If this is true then the phase may need to be incrememnted from within this recommendation
|
|
|
|
:param phase:
|
|
:return:
|
|
"""
|
|
# Reset the recommendations
|
|
self.recommendations = []
|
|
non_invasive_recommendations = self.property.non_invasive_recommendations
|
|
if non_invasive_recommendations:
|
|
measures = [
|
|
r["type"] for r in non_invasive_recommendations if
|
|
r["type"] in ["hot_water_tank_insulation", "cylinder_thermostat"]
|
|
]
|
|
|
|
recommendations_phase = phase
|
|
for m in measures:
|
|
non_invasive_rec = [
|
|
r for r in non_invasive_recommendations if r["type"] == m
|
|
][0]
|
|
if m == "hot_water_tank_insulation":
|
|
# We need to be able to stack these recommendations
|
|
self.recommend_tank_insulation(
|
|
phase=recommendations_phase,
|
|
sap_points=non_invasive_rec["sap_points"],
|
|
survey=non_invasive_rec["survey"],
|
|
)
|
|
|
|
recommendations_phase += 1
|
|
elif m == "cylinder_thermostat":
|
|
self.recommend_cylinder_thermostat(
|
|
phase=recommendations_phase,
|
|
sap_points=non_invasive_rec["sap_points"],
|
|
survey=non_invasive_rec["survey"],
|
|
)
|
|
recommendations_phase += 1
|
|
|
|
# This first iteration of the recommender will provide very basic recommendation
|
|
# We recommend heating controls based on the main heating system
|
|
|
|
if self.property.hotwater["clean_description"] == "Gas boiler/circulator, no cylinder thermostat":
|
|
# Handle this case specifically:
|
|
self.recommend_cylinder_thermostat_gas_boiler_circulator(phase=phase)
|
|
return
|
|
|
|
# If there is no system present, but access to the mains, we
|
|
|
|
if (
|
|
(self.property.hotwater["heater_type"] in ["electric immersion"]) &
|
|
(self.property.data["hot-water-energy-eff"] == "Very Poor") &
|
|
(self.property.hotwater["no_system_present"] is None)
|
|
):
|
|
self.recommend_tank_insulation(phase=phase)
|
|
return
|
|
|
|
if self.property.hotwater["clean_description"] == "From main system, no cylinder thermostat":
|
|
self.recommend_cylinder_thermostat(phase=phase)
|
|
return
|
|
|
|
def recommend_tank_insulation(self, phase, sap_points=None, survey=False, _return=False):
|
|
"""
|
|
If the home has a very poor hot water system, this is often indicative of a lack of insulation on the hot water
|
|
tank. This is a very simple and cost effective improvement that can be made to the home. It will likely
|
|
take the efficiency from very poor to poor.
|
|
"""
|
|
|
|
recommendation_cost = self.costs.hot_water_tank_insulation()
|
|
|
|
already_installed = "hot_water_tank_insulation" in self.property.already_installed
|
|
if already_installed:
|
|
recommendation_cost = override_costs(recommendation_cost)
|
|
description = "Insulation tank has already been insulated, no further action required"
|
|
else:
|
|
description = "Insulate hot water tank"
|
|
|
|
to_append = {
|
|
"phase": phase,
|
|
"parts": [],
|
|
"type": "hot_water_tank_insulation",
|
|
"measure_type": "hot_water_tank_insulation",
|
|
"description": description,
|
|
"starting_u_value": None,
|
|
"new_u_value": None,
|
|
"sap_points": sap_points,
|
|
"already_installed": already_installed,
|
|
**recommendation_cost,
|
|
"simulation_config": {"hot_water_energy_eff_ending": "Poor"},
|
|
"description_simulation": {
|
|
"hot-water-energy-eff": "Poor"
|
|
},
|
|
"survey": survey
|
|
}
|
|
if _return:
|
|
return to_append
|
|
|
|
self.recommendations.append(to_append)
|
|
return
|
|
|
|
def recommend_cylinder_thermostat(self, phase, sap_points=None, survey=False, _return=False):
|
|
"""
|
|
If the home has a very poor hot water system, this is often indicative of a lack of insulation on the hot water
|
|
tank. This is a very simple and cost effective improvement that can be made to the home.
|
|
"""
|
|
|
|
recommendation_cost = self.costs.cylinder_thermostat()
|
|
|
|
already_installed = "cylinder_thermostat" in self.property.already_installed
|
|
if already_installed:
|
|
recommendation_cost = override_costs(recommendation_cost)
|
|
description = "Cylinder thermostat has already been installed, no further action required"
|
|
else:
|
|
description = "Install a smart cylinder thermostat on the hot water tank"
|
|
|
|
new_epc_description = "From main system"
|
|
hotwater_ending_config = HotWaterAttributes(new_epc_description).process()
|
|
hotwater_simulation_config = check_simulation_difference(
|
|
new_config=hotwater_ending_config, old_config=self.property.hotwater
|
|
)
|
|
|
|
simulation_config = {
|
|
"hot_water_energy_eff_ending": self.property.data["hot-water-energy-eff"],
|
|
**hotwater_simulation_config
|
|
}
|
|
|
|
to_append = {
|
|
"phase": phase,
|
|
"parts": [],
|
|
"type": "cylinder_thermostat",
|
|
"measure_type": "cylinder_thermostat",
|
|
"description": description,
|
|
"starting_u_value": None,
|
|
"new_u_value": None,
|
|
"sap_points": sap_points,
|
|
"already_installed": already_installed,
|
|
**recommendation_cost,
|
|
"simulation_config": simulation_config,
|
|
"description_simulation": {
|
|
"hot-water-energy-eff": self.property.data["hot-water-energy-eff"],
|
|
"hotwater-description": new_epc_description,
|
|
},
|
|
"survey": survey
|
|
}
|
|
if _return:
|
|
return to_append
|
|
|
|
self.recommendations.append(to_append)
|
|
return
|
|
|
|
def recommend_cylinder_thermostat_gas_boiler_circulator(self, phase):
|
|
"""
|
|
If the home has a very poor hot water system, this is often indicative of a lack of insulation on the
|
|
hot water
|
|
tank. This is a very simple and cost effective improvement that can be made to the home.
|
|
"""
|
|
|
|
thermostat_recommendation_cost = self.costs.cylinder_thermostat()
|
|
cylinder_recommendation_cost = self.costs.hot_water_tank_insulation()
|
|
# Add them
|
|
total_cost = {
|
|
k: thermostat_recommendation_cost[k] + cylinder_recommendation_cost[k] for k in
|
|
thermostat_recommendation_cost.keys()
|
|
}
|
|
|
|
already_installed = "cylinder_thermostat" in self.property.already_installed
|
|
if already_installed:
|
|
total_cost = override_costs(total_cost)
|
|
description = "Cylinder thermostat & insulation has already been installed, no further action required"
|
|
else:
|
|
description = "Install a smart cylinder thermostat and insulate the hot water tank with 80mm insulation"
|
|
|
|
new_epc_description = "From main system"
|
|
hotwater_ending_config = HotWaterAttributes(new_epc_description).process()
|
|
hotwater_simulation_config = check_simulation_difference(
|
|
new_config=hotwater_ending_config, old_config=self.property.hotwater
|
|
)
|
|
|
|
if self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor", "Average"]:
|
|
new_efficiency = "Good"
|
|
else:
|
|
new_efficiency = self.property.data["hot-water-energy-eff"]
|
|
|
|
simulation_config = {
|
|
"hot_water_energy_eff_ending": new_efficiency,
|
|
**hotwater_simulation_config
|
|
}
|
|
|
|
to_append = {
|
|
"phase": phase,
|
|
"parts": [],
|
|
"type": "cylinder_thermostat",
|
|
"measure_type": "cylinder_thermostat",
|
|
"description": description,
|
|
"starting_u_value": None,
|
|
"new_u_value": None,
|
|
"sap_points": None,
|
|
"already_installed": already_installed,
|
|
**total_cost,
|
|
"simulation_config": simulation_config,
|
|
"description_simulation": {
|
|
"hot-water-energy-eff": simulation_config["hot_water_energy_eff_ending"],
|
|
"hotwater-description": new_epc_description,
|
|
},
|
|
"survey": False
|
|
}
|
|
|
|
self.recommendations.append(to_append)
|
|
return
|