From d303db25577c19cd645badf36446934a32a74713 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 8 Jul 2024 20:41:51 +0100 Subject: [PATCH] Adding the recommendation scoring mechanisms --- backend/Property.py | 24 +++++++++++++++++++++++ recommendations/FloorRecommendations.py | 5 +++++ recommendations/Recommendations.py | 5 +++++ recommendations/SolarPvRecommendations.py | 7 ++++--- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/backend/Property.py b/backend/Property.py index 752a0868..106931d8 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -174,6 +174,7 @@ class Property: self.hot_water_energy_source = None self.recommendations_scoring_data = [] + self.simulation_epcs = {} self.parse_kwargs(kwargs) @@ -282,6 +283,7 @@ class Property: """ self.recommendations_scoring_data = [] + self.simulation_epcs = {} phases = sorted( [ r[0]["phase"] @@ -336,6 +338,28 @@ class Property: ) self.recommendations_scoring_data.append(scoring_dict) + # We also use the representative recommendations to produce transformed EPCs + represenative_recs_to_this_phase = [ + r for r in property_representative_recommendations + if r["phase"] <= phase + ] + epc_transformations = [x["description_simulation"] for x in represenative_recs_to_this_phase] + # It is possible that we could have two simulations applied to the same descriptions + # We extract these out + phase_epc_transformation = {} + for config in epc_transformations: + for k, v in config.items(): + if k in phase_epc_transformation: + raise NotImplementedError( + "Already have this key in the phase_epc_transformation - implement me") + phase_epc_transformation[k] = v + + simulation_epc = self.epc_record.prepared_epc.copy() + # Replace the understores with hyphens + simulation_epc = {k.replace("_", "-"): v for k, v in simulation_epc.items()} + simulation_epc.update(simulation_epc) + self.simulation_epcs = simulation_epc + @staticmethod def create_recommendation_scoring_data( property_id, diff --git a/recommendations/FloorRecommendations.py b/recommendations/FloorRecommendations.py index 3f764d83..9faedb89 100644 --- a/recommendations/FloorRecommendations.py +++ b/recommendations/FloorRecommendations.py @@ -227,6 +227,11 @@ class FloorRecommendations(Definitions): "new_u_value": new_u_value, "sap_points": None, "already_installed": already_installed, + "description_simulation": { + "floor-description": "Solid, insulated" if + material["type"] == "solid_floor_insulation" + else "Suspended, insulated" + }, **cost_result } ) diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py index 827ca928..1541246a 100644 --- a/recommendations/Recommendations.py +++ b/recommendations/Recommendations.py @@ -221,6 +221,7 @@ class Recommendations: has_u_value = recommendations_by_type[0].get("new_u_value") is not None has_sap_points = recommendations_by_type[0].get("sap_points") is not None + has_rank = recommendations_by_type[0].get("rank") is not None # When check if these recommendations have two different types, such as solid wall insulation # If we have multiple types, we group by type and then select the best recommendation for each type @@ -238,6 +239,10 @@ class Recommendations: # Sort the options by the cost per SAP point improvement - the lower the better for rec in recommendations: rec["efficiency"] = rec["total"] / rec["sap_points"] + elif has_rank: + # Sort the options by rank - the lower the better + for rec in recommendations: + rec["efficiency"] = rec["rank"] else: # Sort the options by cost - the lower the better for rec in recommendations: diff --git a/recommendations/SolarPvRecommendations.py b/recommendations/SolarPvRecommendations.py index 42bf03d4..18bfdced 100644 --- a/recommendations/SolarPvRecommendations.py +++ b/recommendations/SolarPvRecommendations.py @@ -109,9 +109,9 @@ class SolarPvRecommendations: ) n_units = self.property.solar_panel_configuration["n_units"] - best_configurations = panel_performance.head(3) + best_configurations = panel_performance.head(3).reset_index(drop=True) - for _, recommendation_config in best_configurations.iterrows(): + for rank, recommendation_config in best_configurations.iterrows(): roof_coverage_percent = round(recommendation_config["panneled_roof_area"] / total_roof_area * 100) # Spread the cost to the individual units total_cost = recommendation_config["total_cost"] / n_units @@ -135,7 +135,8 @@ class SolarPvRecommendations: # back up here "photo_supply": roof_coverage_percent, "has_battery": False, - "description_simulation": {"photo-supply": roof_coverage_percent} + "description_simulation": {"photo-supply": roof_coverage_percent}, + "rank": rank # Rank is used to get the representative recommendation - rank 0 will be chosen } )