From f732ce0be593b5ee7060da0637bc3c22e113e357 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 5 Aug 2024 18:30:07 +0100 Subject: [PATCH] Adding simulation_config convention to roof recommendations --- backend/Property.py | 66 ++++----------------- recommendations/RoofRecommendations.py | 81 ++++++++++++++++---------- 2 files changed, 60 insertions(+), 87 deletions(-) diff --git a/backend/Property.py b/backend/Property.py index cc392933..ba22ce60 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -494,61 +494,6 @@ class Property: if output["floor_insulation_thickness_ending"] is None: output["floor_insulation_thickness_ending"] = "none" - if recommendation["type"] in [ - "loft_insulation", - "room_roof_insulation", - "flat_roof_insulation", - ]: - output["roof_thermal_transmittance_ending"] = recommendation[ - "new_u_value" - ] - - parts = recommendation["parts"] - if len(parts) != 1: - raise ValueError( - "More than one part for roof insulation - investiage me" - ) - - # This is based on the values we have in the training data - valid_numeric_values = [ - 12, - 25, - 50, - 75, - 100, - 150, - 200, - 250, - 270, - 300, - 350, - 400, - ] - - proposed_depth = recommendation["new_thickness"] - if proposed_depth not in valid_numeric_values: - # Take the nearest value for scoring - proposed_depth = min( - valid_numeric_values, key=lambda x: abs(x - proposed_depth) - ) - - output["roof_insulation_thickness_ending"] = str(int(proposed_depth)) - if recommendation["type"] == "loft_insulation": - if proposed_depth >= 270: - output["roof_energy_eff_ending"] = "Very Good" - else: - if output["roof_energy_eff_ending"] not in ["Good", "Very Good"]: - output["roof_energy_eff_ending"] = "Good" - else: - output["roof_energy_eff_ending"] = "Very Good" - else: - # Fill missing roof u-values - this fill is not based on recommended upgrades - if output["roof_thermal_transmittance_ending"] is None: - raise ValueError("We should not have a None value for the u value") - - if output["roof_insulation_thickness_ending"] is None: - output["roof_insulation_thickness_ending"] = "none" - if recommendation["type"] == "sealing_open_fireplace": output["number_open_fireplaces_ending"] = 0 @@ -592,12 +537,21 @@ class Property: if recommendation["type"] in [ "heating", "hot_water_tank_insulation", "heating_control", "secondary_heating", "internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation", - "cylinder_thermostat" + "cylinder_thermostat", "loft_insulation", "room_roof_insulation", "flat_roof_insulation", ]: # We update the data, as defined in the recommendaton if output["walls_insulation_thickness_ending"] is None: output["walls_insulation_thickness_ending"] = "none" + if output["walls_thermal_transmittance_ending"] is None: + raise ValueError("We should not have a None value for the u value") + + if output["roof_insulation_thickness_ending"] is None: + output["roof_insulation_thickness_ending"] = "none" + + if output["roof_thermal_transmittance_ending"] is None: + raise ValueError("We should not have a None value for the u value") + simulation_config = recommendation["simulation_config"] # If any entries in simulation_config are None, we will set them to "Unknown" which is the cleaning # value diff --git a/recommendations/RoofRecommendations.py b/recommendations/RoofRecommendations.py index 56f3721a..fa2cb53c 100644 --- a/recommendations/RoofRecommendations.py +++ b/recommendations/RoofRecommendations.py @@ -5,9 +5,11 @@ from typing import List from datatypes.enums import QuantityUnits from recommendations.recommendation_utils import ( get_roof_u_value, r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns, - update_lowest_selected_u_value, get_recommended_part, convert_thickness_to_numeric, override_costs + update_lowest_selected_u_value, get_recommended_part, convert_thickness_to_numeric, override_costs, + check_simulation_difference ) from recommendations.Costs import Costs +from etl.epc_clean.epc_attributes.RoofAttributes import RoofAttributes class RoofRecommendations: @@ -274,6 +276,40 @@ class RoofRecommendations: if already_installed: cost_result = override_costs(cost_result) new_thickness = insulation_thickness + material["depth"] + + # This is based on the values we have in the training data + valid_numeric_values = [ + 12, + 25, + 50, + 75, + 100, + 150, + 200, + 250, + 270, + 300, + 350, + 400, + ] + + proposed_depth = new_thickness + if (new_thickness not in valid_numeric_values) and material["type"] == "loft_insulation": + # Take the nearest value for scoring + proposed_depth = min( + valid_numeric_values, key=lambda x: abs(x - proposed_depth) + ) + + if proposed_depth >= 270: + new_efficiency = "Very Good" + else: + if self.property.data["walls-energy-eff"] not in ["Good", "Very Good"]: + new_efficiency = "Good" + else: + new_efficiency = "Very Good" + + new_description = f"Pitched, {int(proposed_depth)}mm loft insulation" + elif material["type"] == "flat_roof_insulation": cost_result = self.costs.flat_roof_insulation( floor_area=self.property.insulation_floor_area, @@ -283,38 +319,21 @@ class RoofRecommendations: already_installed = "flat_roof_insulation" in self.property.already_installed if already_installed: cost_result = override_costs(cost_result) - new_thickness = None + new_description = "Flat, insulated" + new_efficiency = "Good" else: raise ValueError("Invalid material type") - # This is based on the values we have in the training data - valid_numeric_values = [ - 12, - 25, - 50, - 75, - 100, - 150, - 200, - 250, - 270, - 300, - 350, - 400, - ] + roof_ending_config = RoofAttributes(new_description).process() + roof_simulation_config = check_simulation_difference( + new_config=roof_ending_config, old_config=self.property.roof, prefix="roof_" + ) - proposed_depth = new_thickness - if new_thickness not in valid_numeric_values: - # Take the nearest value for scoring - proposed_depth = min( - valid_numeric_values, key=lambda x: abs(x - proposed_depth) - ) - - if proposed_depth >= 270: - new_efficiency = "Very Good" - else: - if self.property.data["walls-energy-eff"] not in ["Good", "Very Good"]: - new_efficiency = "Good" + simulation_config = { + **roof_simulation_config, + "roof_thermal_transmittance_ending": new_u_value, + "roof_energy_eff_ending": new_efficiency + } recommendations.append( { @@ -333,9 +352,9 @@ class RoofRecommendations: "new_u_value": new_u_value, "sap_points": None, "already_installed": already_installed, - "new_thickness": new_thickness, + "simulation_config": simulation_config, "description_simulation": { - "roof-description": f"Pitched, {int(proposed_depth)}mm loft insulation", + "roof-description": new_description, "roof-energy-eff": new_efficiency }, **cost_result