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 """ VENTILATION_DESCRIPTIONS = [ 'mechanical, extract only', 'mechanical, supply and extract' ] def __init__( self, property_instance: Property, materials ): self.property = property_instance self.has_ventilaion = None self.recommendation = None self.materials = [part for part in materials if part["type"] == "mechanical_ventilation"] def identify_ventilation(self): self.has_ventilaion = self.property.data["mechanical-ventilation"] in self.VENTILATION_DESCRIPTIONS def recommend(self): """ 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.identify_ventilation() if self.has_ventilaion: return if len(self.materials) != 1: raise NotImplementedError("Only handled the case of having one venilation option") # We recommend installing 2 units n_units = 2 part = self.materials.copy() already_installed = "cavity_wall_insulation" in self.property.already_installed estimated_cost = n_units * part[0]["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[0]["total"] = estimated_cost part[0]["quantity"] = n_units part[0]["quantity_unit"] = "part" # We recommend installing two mechanical ventilation systems self.recommendation = [ { "phase": None, "parts": part, "type": part[0]["type"], "measure_type": "mechanical_ventilation", "description": f"Install {n_units} {part[0]['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 } ] 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"] ) 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": trickle_vents_recommendation_config["cost"], # 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 } ]