diff --git a/backend/engine/engine.py b/backend/engine/engine.py index 276444e1..58203da7 100644 --- a/backend/engine/engine.py +++ b/backend/engine/engine.py @@ -980,12 +980,12 @@ async def model_engine(body: PlanTriggerRequest): logger.info("Preparing data for scoring in sap change api") recommendations_scoring_data = pd.DataFrame(recommendations_scoring_data) + # Temp putting this here + recommendations_scoring_data["is_post_sap10_ending"] = True recommendations_scoring_data = recommendations_scoring_data.drop( - columns=[ - "rdsap_change", "heat_demand_change", "carbon_change", "sap_ending", "heat_demand_ending", - "carbon_ending" - ] + columns=["rdsap_change", "heat_demand_change", "carbon_change", "sap_ending", "heat_demand_ending", + "carbon_ending"] ) all_predictions = await model_api.async_paginated_predictions( diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py index f984acc3..0b3d1635 100644 --- a/recommendations/Recommendations.py +++ b/recommendations/Recommendations.py @@ -615,7 +615,7 @@ class Recommendations: if metric == "sap": property_phase_impact[metric] = round(property_phase_impact[metric], 2) else: - # We prevent these from being positive + # We prevent mechanical ventilation from being positive property_phase_impact[metric] = ( 0 if property_phase_impact[metric] > 0 else property_phase_impact[metric] ) @@ -632,6 +632,38 @@ class Recommendations: property_phase_impact["carbon"], rec["co2_equivalent_savings"] ) + # Update the current phase values + current_phase_values["sap"] = previous_phase_values["sap"] + property_phase_impact["sap"] + current_phase_values["carbon"] = previous_phase_values["carbon"] - property_phase_impact["carbon"] + + # We also ensure that mechanical ventilation doesn't have an ovely strong negative SAP impact + if rec["type"] == "mechanical_ventilation": + # ventilation is capped by having no greater and a -4 impact + ventilation_sap_limit = -4 + + def _check_veniltation_out_of_bounds(sap_impact): + return (sap_impact < ventilation_sap_limit) or (sap_impact >= 0) + + def _adjust_ventilation_sap(sap_impact): + if sap_impact >= 0: + return -1 + if sap_impact < ventilation_sap_limit: + return ventilation_sap_limit + + ventilation_out_of_bounds = _check_veniltation_out_of_bounds(property_phase_impact["sap"]) + + if ventilation_out_of_bounds: + previous_modelled_sap = previous_phase_values.get("sap_prediction", 0) + proposed_sap_impact = current_phase_sap - previous_modelled_sap + proposal_out_of_bounds = _check_veniltation_out_of_bounds(proposed_sap_impact) + if proposal_out_of_bounds: + property_phase_impact["sap"] = _adjust_ventilation_sap(proposed_sap_impact) + else: + property_phase_impact["sap"] = proposed_sap_impact + + # Update the current phase values + current_phase_values["sap"] = previous_phase_values["sap"] + property_phase_impact["sap"] + if rec["type"] == "loft_insulation": # When we have a loft insulation recommendation, where there is an extension and the existing # amount of loft insulation is already good, we limit the SAP points @@ -642,6 +674,8 @@ class Recommendations: ) if li_sap_limit is not None: property_phase_impact["sap"] = min(property_phase_impact["sap"], li_sap_limit) + # Update the current phase values + current_phase_values["sap"] = previous_phase_values["sap"] + property_phase_impact["sap"] if rec["type"] == "solar_pv": # We use the SAP points in the recommendation as a minimum @@ -649,6 +683,8 @@ class Recommendations: rec["sap_points"] if property_phase_impact["sap"] < rec["sap_points"] else property_phase_impact["sap"] ) + # Update the current phase values + current_phase_values["sap"] = previous_phase_values["sap"] + property_phase_impact["sap"] # Insert this information into the recommendation. if not rec.get("survey", False): @@ -669,7 +705,8 @@ class Recommendations: "representative": rec["recommendation_id"] in representative_ids, "recommendation_id": rec["recommendation_id"], "measure_type": rec["measure_type"], - **current_phase_values + **current_phase_values, + "sap_prediction": phase_energy_efficiency_metrics["sap_change"] } )