mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Merge pull request #490 from Hestia-Homes/funding-engine
Funding engine - handling EPC C properties
This commit is contained in:
commit
a90a0f97cc
3 changed files with 47 additions and 4 deletions
|
|
@ -566,6 +566,10 @@ class Funding:
|
||||||
measure_code = "LI_lessequal100" if existing_li_thickness <= 100 else "LI_greater100"
|
measure_code = "LI_lessequal100" if existing_li_thickness <= 100 else "LI_greater100"
|
||||||
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == measure_code]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == measure_code]
|
||||||
|
|
||||||
|
# There's no funding for EPC C or above
|
||||||
|
if self.starting_sap_band in ["Low_C", "High_C", "Low_B", "High_B", "Low_A", "High_A"]:
|
||||||
|
return 0
|
||||||
|
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError(f"Invalid LI category: {measure_code}")
|
raise ValueError(f"Invalid LI category: {measure_code}")
|
||||||
return pps.squeeze()["Cost Savings"]
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
@ -597,6 +601,10 @@ class Funding:
|
||||||
return pps.squeeze()["Cost Savings"]
|
return pps.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
if measure_type == "solid_floor_insulation":
|
if measure_type == "solid_floor_insulation":
|
||||||
|
if self.starting_sap_band in ["Low_C", "High_C", "Low_B", "High_B", "Low_A", "High_A"]:
|
||||||
|
# We don't fund SFI for properties starting at C or above
|
||||||
|
return 0
|
||||||
|
|
||||||
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == "SFI"]
|
pps = filtered_pps_matrix[filtered_pps_matrix["Measure_Type"] == "SFI"]
|
||||||
if pps.shape[0] != 1:
|
if pps.shape[0] != 1:
|
||||||
raise ValueError("Invalid SFI category")
|
raise ValueError("Invalid SFI category")
|
||||||
|
|
@ -607,9 +615,20 @@ class Funding:
|
||||||
(filtered_pps_matrix["Measure_Type"] == "Solar_PV") &
|
(filtered_pps_matrix["Measure_Type"] == "Solar_PV") &
|
||||||
(filtered_pps_matrix["Pre_Main_Heating_Source"] == pre_heating_system)
|
(filtered_pps_matrix["Pre_Main_Heating_Source"] == pre_heating_system)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if solar_pps_df.empty and self.starting_sap_band in [
|
||||||
|
"Low_C", "High_C", "Low_B", "High_B", "Low_B", "High_A"
|
||||||
|
]:
|
||||||
|
# No funding for EPC C or above
|
||||||
|
return 0
|
||||||
return solar_pps_df.squeeze()["Cost Savings"]
|
return solar_pps_df.squeeze()["Cost Savings"]
|
||||||
|
|
||||||
if measure_type == "air_source_heat_pump":
|
if measure_type == "air_source_heat_pump":
|
||||||
|
|
||||||
|
# No funding for EPC C or above
|
||||||
|
if self.starting_sap_band in ["Low_C", "High_C", "Low_B", "High_B", "Low_A", "High_A"]:
|
||||||
|
return 0
|
||||||
|
|
||||||
pps = filtered_pps_matrix[
|
pps = filtered_pps_matrix[
|
||||||
(filtered_pps_matrix["Pre_Main_Heating_Source"] == pre_heating_system) &
|
(filtered_pps_matrix["Pre_Main_Heating_Source"] == pre_heating_system) &
|
||||||
(filtered_pps_matrix["Post_Main_Heating_Source"] == "Air to Water ASHP") &
|
(filtered_pps_matrix["Post_Main_Heating_Source"] == "Air to Water ASHP") &
|
||||||
|
|
|
||||||
|
|
@ -900,8 +900,7 @@ class GoogleSolarApi:
|
||||||
|
|
||||||
return input_properties
|
return input_properties
|
||||||
|
|
||||||
@classmethod
|
def default_panel_performance(self, property_instance):
|
||||||
def default_panel_performance(cls, property_instance):
|
|
||||||
"""
|
"""
|
||||||
In a small number of cases, where properties have simulated uprns, we do not have a longitude and latitude
|
In a small number of cases, where properties have simulated uprns, we do not have a longitude and latitude
|
||||||
value and therefore we just return a default panel performance
|
value and therefore we just return a default panel performance
|
||||||
|
|
@ -911,6 +910,20 @@ class GoogleSolarApi:
|
||||||
|
|
||||||
cost_instance = Costs(property_instance=property_instance)
|
cost_instance = Costs(property_instance=property_instance)
|
||||||
|
|
||||||
|
material_1_6 = next(
|
||||||
|
(m for m in self.solar_materials if m["type"] == "solar_pv" and
|
||||||
|
abs(m["size"] - 1.6) < 0.1 and not m["includes_battery"]),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
material_3_2 = next(
|
||||||
|
(m for m in self.solar_materials if m["type"] == "solar_pv" and
|
||||||
|
abs(m["size"] - 3.2) < 0.1 and not m["includes_battery"]),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
||||||
|
if material_1_6 is None or material_3_2 is None:
|
||||||
|
raise ValueError("No suitable solar product found for the default configuration.")
|
||||||
|
|
||||||
# We return a 1.6 and 3.2 kwp system
|
# We return a 1.6 and 3.2 kwp system
|
||||||
panel_performance = pd.DataFrame(
|
panel_performance = pd.DataFrame(
|
||||||
[
|
[
|
||||||
|
|
@ -918,7 +931,12 @@ class GoogleSolarApi:
|
||||||
'n_panels': 8,
|
'n_panels': 8,
|
||||||
'yearly_dc_energy': 3200 * assumptions.MEDIAN_WATTAGE_TO_DC,
|
'yearly_dc_energy': 3200 * assumptions.MEDIAN_WATTAGE_TO_DC,
|
||||||
'total_cost': cost_instance.solar_pv(
|
'total_cost': cost_instance.solar_pv(
|
||||||
n_panels=8, has_battery=False, n_floors=property_instance.number_of_floors
|
solar_product=material_1_6,
|
||||||
|
scaffolding_options=[
|
||||||
|
{"total_cost": 1000, "size": property_instance.number_of_floors},
|
||||||
|
{"total_cost": 1000, "size": 3}
|
||||||
|
],
|
||||||
|
n_floors=property_instance.number_of_floors
|
||||||
)["total"],
|
)["total"],
|
||||||
'weighted_ratio': None,
|
'weighted_ratio': None,
|
||||||
'panneled_roof_area': 8 * assumptions.RDSAP_AREA_PER_PANEL,
|
'panneled_roof_area': 8 * assumptions.RDSAP_AREA_PER_PANEL,
|
||||||
|
|
@ -938,7 +956,12 @@ class GoogleSolarApi:
|
||||||
'n_panels': 4,
|
'n_panels': 4,
|
||||||
'yearly_dc_energy': 1600 * assumptions.MEDIAN_WATTAGE_TO_DC,
|
'yearly_dc_energy': 1600 * assumptions.MEDIAN_WATTAGE_TO_DC,
|
||||||
'total_cost': cost_instance.solar_pv(
|
'total_cost': cost_instance.solar_pv(
|
||||||
n_panels=6, has_battery=False, n_floors=property_instance.number_of_floors
|
solar_product=material_3_2,
|
||||||
|
scaffolding_options=[
|
||||||
|
{"total_cost": 1000, "size": property_instance.number_of_floors},
|
||||||
|
{"total_cost": 1000, "size": 3}
|
||||||
|
],
|
||||||
|
n_floors=property_instance.number_of_floors
|
||||||
)["total"],
|
)["total"],
|
||||||
'weighted_ratio': None,
|
'weighted_ratio': None,
|
||||||
'panneled_roof_area': 4 * assumptions.RDSAP_AREA_PER_PANEL,
|
'panneled_roof_area': 4 * assumptions.RDSAP_AREA_PER_PANEL,
|
||||||
|
|
|
||||||
|
|
@ -894,6 +894,7 @@ async def model_engine(body: PlanTriggerRequest):
|
||||||
0, 0, 0, 0
|
0, 0, 0, 0
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
(
|
(
|
||||||
r["partial_project_score"], r["partial_project_funding"], r["innovation_uplift"],
|
r["partial_project_score"], r["partial_project_funding"], r["innovation_uplift"],
|
||||||
r["uplift_project_score"]
|
r["uplift_project_score"]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue