mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
129 lines
4.9 KiB
Python
129 lines
4.9 KiB
Python
import pandas as pd
|
|
from BaseUtility import Definitions
|
|
from backend.Property import Property
|
|
|
|
|
|
class VentilationRecommendations(Definitions):
|
|
"""
|
|
For properties that do not have ventilation, we recommend installing ventilaion
|
|
This is particularly important for properties that have insulated walls and is also
|
|
crucial for prevent overheating risks in warmer months
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
property_instance: Property,
|
|
materials
|
|
):
|
|
self.property = property_instance
|
|
|
|
self.recommendation = None
|
|
self.mechanical_ventilation_materials = [part for part in materials if part["type"] == "mechanical_ventilation"]
|
|
self.trickle_vent_materials = [part for part in materials if part["type"] == "trickle_vent"]
|
|
|
|
def recommend(self, phase):
|
|
"""
|
|
If there is no ventilation, we recommend installing ventilation
|
|
|
|
Generally, best practice is to install controlled ventilation for insulated walls so we still recommend
|
|
ventilation if there is natural ventilation
|
|
:return:
|
|
"""
|
|
|
|
self.property.identify_ventilation()
|
|
if self.property.has_ventilation:
|
|
return
|
|
|
|
# We recommend installing 2 units
|
|
n_units = 2
|
|
|
|
parts = self.mechanical_ventilation_materials.copy()
|
|
|
|
already_installed = "mechanical_ventilation" in self.property.already_installed
|
|
|
|
# TODO: We now have multiple ventilation options - we default to selecting the cheapest option
|
|
part = min(parts, key=lambda x: x['total_cost'])
|
|
|
|
estimated_cost = n_units * part["total_cost"] if not already_installed else 0
|
|
labour_hours = 4 * n_units if not already_installed else 0
|
|
labour_days = 4 * n_units / 8.0 if not already_installed else 0
|
|
|
|
part["total"] = estimated_cost
|
|
part["quantity"] = n_units
|
|
part["quantity_unit"] = "part"
|
|
|
|
# We recommend installing two mechanical ventilation systems
|
|
self.recommendation = [
|
|
{
|
|
"phase": phase,
|
|
"parts": [part],
|
|
"type": part["type"],
|
|
"measure_type": "mechanical_ventilation",
|
|
"description": f"Install {n_units} {part['description']} units",
|
|
"starting_u_value": None,
|
|
"new_u_value": None,
|
|
"already_installed": already_installed,
|
|
"sap_points": 0,
|
|
"heat_demand": 0,
|
|
"kwh_savings": 0,
|
|
"co2_equivalent_savings": 0,
|
|
"energy_cost_savings": 0,
|
|
"total": estimated_cost,
|
|
# We use a very simple and rough estimate of 4 hours per unit
|
|
"labour_hours": labour_hours,
|
|
"labour_days": labour_days, # Assume 8 hour day
|
|
"simulation_config": {
|
|
"mechanical_ventilation_ending": "mechanical, extract only",
|
|
},
|
|
"description_simulation": {
|
|
"mechanical-ventilation": "mechanical, extract only"
|
|
},
|
|
"innovation_rate": part["innovation_rate"],
|
|
}
|
|
]
|
|
|
|
def recommend_trickle_vents(self):
|
|
"""
|
|
This is not something that we can identify completely non-invasively, however a recommendation which may come
|
|
about as a result of an energy assessment is the installation of trickle vents. This function handles that
|
|
"""
|
|
|
|
trickle_vents_recommendation_config = next(
|
|
(r for r in self.property.non_invasive_recommendations if r["type"] == "trickle_vents"), {}
|
|
)
|
|
|
|
if not trickle_vents_recommendation_config:
|
|
return
|
|
|
|
description = (
|
|
"Install trickle vents on your windows" if
|
|
not trickle_vents_recommendation_config.get("description")
|
|
else trickle_vents_recommendation_config["description"]
|
|
)
|
|
|
|
cheapest_trickle_vent = min(
|
|
self.trickle_vent_materials, key=lambda x: x["total_cost"]
|
|
)
|
|
|
|
return [
|
|
{
|
|
"phase": None,
|
|
"parts": [],
|
|
"type": "trickle_vents",
|
|
"measure_type": "trickle_vents",
|
|
"description": description,
|
|
"starting_u_value": None,
|
|
"new_u_value": None,
|
|
"already_installed": False,
|
|
"sap_points": 0,
|
|
"heat_demand": 0,
|
|
"kwh_savings": 0,
|
|
"co2_equivalent_savings": 0,
|
|
"energy_cost_savings": 0,
|
|
"total": cheapest_trickle_vent["total_cost"] * self.property.number_of_windows,
|
|
# We use a very simple and rough estimate of 4 hours per unit
|
|
"labour_hours": trickle_vents_recommendation_config.get("labour_hours", 8),
|
|
"labour_days": trickle_vents_recommendation_config.get("labour_days", 1), # Assume 8 hour day
|
|
"survey": True
|
|
}
|
|
]
|