diff --git a/backend/Property.py b/backend/Property.py index c4e2c6bc..704e4f0a 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -561,7 +561,7 @@ class Property: "loft_insulation", "room_roof_insulation", "flat_roof_insulation", "solid_floor_insulation", "suspended_floor_insulation", "windows_glazing", "solar_pv", "heating", "hot_water_tank_insulation", - "heating_control", "secondary_heating", "cylinder_thermostat" + "heating_control", "secondary_heating", "cylinder_thermostat", "mixed_glazing" ]: raise NotImplementedError( "Implement me, given type %s" % recommendation["type"] diff --git a/recommendations/DraughtProofingRecommendations.py b/recommendations/DraughtProofingRecommendations.py index 9ce9aa1b..197d80cc 100644 --- a/recommendations/DraughtProofingRecommendations.py +++ b/recommendations/DraughtProofingRecommendations.py @@ -8,16 +8,23 @@ class DraughtProofingRecommendations: self.recommendation = [] - def recommend(self, phase): + def recommend(self): """ In some cases, we can identify the need for draught proofing from the EPC recommendations, however the initial implementation of this class will just assume that we are picking up a non-invasive recommendation from the survey """ - draught_proofing_recommendation_config = [ - r for r in self.property.non_invasive_recommendations if r["type"] == "draught_proofing" - ][0] + # For the moment, draught proofing doesn't have a phase impact + + draught_proofing_recommendation_config = next( + (r for r in self.property.non_invasive_recommendations if + r["type"] == "draught_proofing"), + {} + ) + + if not draught_proofing_recommendation_config: + return description = ( "Draught proof doors and windows to improve energy efficiency" if @@ -28,7 +35,7 @@ class DraughtProofingRecommendations: # We recommend installing two mechanical ventilation systems self.recommendation = [ { - "phase": phase, + "phase": None, "parts": [], "type": "draught_proofing", "description": description, diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py index 44c6b4f2..ce8225a1 100644 --- a/recommendations/Recommendations.py +++ b/recommendations/Recommendations.py @@ -132,14 +132,16 @@ class Recommendations: if "trickle_vents" in measures: # This is a recommendatin that typically comes from an energy assessment - property_recommendations.append(self.ventilation_recomender.recommend_trickle_vents()) + trickle_vents_rec = self.ventilation_recomender.recommend_trickle_vents() + if trickle_vents_rec: + property_recommendations.append(trickle_vents_rec) if "draught_proofing" in measures: # This is a recommendation that in some instances we can recommend, by deducing it from the SAP # recommendations, however we will implement this later - self.draught_proofing_recommender.recommend(phase=phase) - property_recommendations.append(self.draught_proofing_recommender.recommendation) - phase += 1 + self.draught_proofing_recommender.recommend() + if self.draught_proofing_recommender.recommendation: + property_recommendations.append(self.draught_proofing_recommender.recommendation) if "floor_insulation" in measures: self.floor_recommender.recommend(phase=phase, measures=measures) @@ -155,8 +157,10 @@ class Recommendations: if "mixed_glazing" in measures: # This is a recommendation that comes exclusively from an energy assessment - property_recommendations.append(self.windows_recommender.recommend_mixed_glazing(phase=phase)) - phase += 1 + mixed_glazing_rec = self.windows_recommender.recommend_mixed_glazing(phase=phase) + if mixed_glazing_rec: + property_recommendations.append(mixed_glazing_rec) + phase += 1 if "fireplace" in measures: self.fireplace_recommender.recommend(phase=phase) @@ -442,8 +446,9 @@ class Recommendations: impact_summary = [] for recommendations_by_type in property_recommendations: for rec in recommendations_by_type: - if rec["type"] == "mechanical_ventilation": - # We don't have a percieved sap impact of mechanical ventilation + if rec["type"] in ["mechanical_ventilation", "trickle_vents", "draught_proofing"]: + # We don't have a percieved sap impact of mechanical ventilation or trickle vents, and we don't + # have the capacity to score draught proofing continue phase_energy_efficiency_metrics = { @@ -530,7 +535,9 @@ class Recommendations: ) # Insert this information into the recommendation - rec["sap_points"] = property_phase_impact["sap"] + if rec.get("survey", False): + rec["sap_points"] = property_phase_impact["sap"] + rec["co2_equivalent_savings"] = property_phase_impact["carbon"] rec["heat_demand"] = property_phase_impact["heat_demand"] @@ -704,18 +711,6 @@ class Recommendations: pd.isnull(kwh_impact_table["hotwater_fuel_type"]).sum()): raise Exception("Fuel type is missing") - # kwh_impact_table["heating_fuel_type"] = np.where( - # kwh_impact_table["id"] == STARTING_DUMMY_ID_VALUE, - # property_instance.heating_energy_source, - # kwh_impact_table["heating_fuel_type"] - # ) - # - # kwh_impact_table["hotwater_fuel_type"] = np.where( - # kwh_impact_table["id"] == STARTING_DUMMY_ID_VALUE, - # property_instance.hot_water_energy_source, - # kwh_impact_table["hotwater_fuel_type"] - # ) - # We now calculate the fuel cost for k in ["heating", "hotwater"]: kwh_impact_table[f"{k}_cost"] = kwh_impact_table.apply( @@ -727,7 +722,8 @@ class Recommendations: # We now deduce if any of the recommendations result in a change of fuel type for recs in property_recommendations: for rec in recs: - if rec["type"] == "mechanical_ventilation": + if rec["type"] in ["mechanical_ventilation", "trickle_vents", "draught_proofing"]: + # We cannot score the impact on draught proofing continue rec_impact = kwh_impact_table[kwh_impact_table["recommendation_id"] == rec["recommendation_id"]] diff --git a/recommendations/VentilationRecommendations.py b/recommendations/VentilationRecommendations.py index 163cdb8a..34439827 100644 --- a/recommendations/VentilationRecommendations.py +++ b/recommendations/VentilationRecommendations.py @@ -88,12 +88,15 @@ class VentilationRecommendations(Definitions): about as a result of an energy assessment is the installation of trickle vents. This function handles that """ - trickle_vents_recommendation_config = [ - r for r in self.property.non_invasive_recommendations if r["type"] == "trickle_vents" - ][0] + 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 to windows without them" if + "Install trickle vents on your windows" if not trickle_vents_recommendation_config.get("description") else trickle_vents_recommendation_config["description"] ) diff --git a/recommendations/WindowsRecommendations.py b/recommendations/WindowsRecommendations.py index d7643393..ae7f7057 100644 --- a/recommendations/WindowsRecommendations.py +++ b/recommendations/WindowsRecommendations.py @@ -137,9 +137,11 @@ class WindowsRecommendations: :return: """ - mixed_glazing_recommendation_config = [ - r for r in self.property.non_invasive_recommendations if r["type"] == "mixed_glazing" - ][0] + mixed_glazing_recommendation_config = next( + (r for r in self.property.non_invasive_recommendations if r["type"] == "mixed_glazing"), {} + ) + if not mixed_glazing_recommendation_config: + return description = ( "Install a combination of secondary and double glazing to single glazed windows" if @@ -147,7 +149,7 @@ class WindowsRecommendations: else mixed_glazing_recommendation_config["description"] ) - windows_ending_config = WindowAttributes("Multiple glazing throughout").process() + windows_ending_config = WindowAttributes("Full secondary glazing").process() windows_simulation_config = check_simulation_difference( new_config=windows_ending_config, old_config=self.property.windows, prefix="windows_"