mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Updated wall recommended partially for new costs
This commit is contained in:
parent
80b4d2390c
commit
cb52c9f7a3
1 changed files with 66 additions and 22 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
import math
|
import math
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
from datatypes.enums import QuantityUnits
|
from datatypes.enums import QuantityUnits
|
||||||
from backend.Property import Property
|
from backend.Property import Property
|
||||||
from BaseUtility import Definitions
|
from BaseUtility import Definitions
|
||||||
|
|
@ -9,6 +11,7 @@ from recommendations.recommendation_utils import (
|
||||||
get_recommended_part, get_wall_u_value
|
get_recommended_part, get_wall_u_value
|
||||||
)
|
)
|
||||||
from recommendations.config import PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION
|
from recommendations.config import PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION
|
||||||
|
from recommendations.Costs import Costs
|
||||||
from utils.logger import setup_logger
|
from utils.logger import setup_logger
|
||||||
|
|
||||||
logger = setup_logger()
|
logger = setup_logger()
|
||||||
|
|
@ -50,13 +53,36 @@ class WallRecommendations(Definitions):
|
||||||
materials: List
|
materials: List
|
||||||
):
|
):
|
||||||
self.property = property_instance
|
self.property = property_instance
|
||||||
|
self.costs = Costs(self.property)
|
||||||
# For audit purposes, when estimating u values we'll store it
|
# For audit purposes, when estimating u values we'll store it
|
||||||
self.estimated_u_value = None
|
self.estimated_u_value = None
|
||||||
|
|
||||||
# Will contains a list of recommended measures
|
# Will contains a list of recommended measures
|
||||||
self.recommendations = []
|
self.recommendations = []
|
||||||
|
|
||||||
self.materials = materials
|
self.cavity_wall_insulation_materials = [
|
||||||
|
part for part in materials if part["type"] == "cavity_wall_insulation"
|
||||||
|
]
|
||||||
|
|
||||||
|
self.internal_wall_insulation_materials = [
|
||||||
|
part for part in materials if part["type"] == "internal_wall_insulation"
|
||||||
|
]
|
||||||
|
|
||||||
|
self.internal_wall_non_insulation_materials = [
|
||||||
|
part for part in materials if part["type"] in [
|
||||||
|
"iwi_wall_demolition", "iwi_vapour_barrier", "iwi_redecoration"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
self.external_wall_insulation_materials = [
|
||||||
|
part for part in materials if part["type"] == "external_wall_insulation"
|
||||||
|
]
|
||||||
|
|
||||||
|
self.external_wall_non_insulation_materials = [
|
||||||
|
part for part in materials if part["type"] in [
|
||||||
|
"ewi_wall_demolition", "ewi_wall_preparation", "ewi_wall_redecoration"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ewi_valid(self):
|
def ewi_valid(self):
|
||||||
|
|
@ -200,15 +226,15 @@ class WallRecommendations(Definitions):
|
||||||
|
|
||||||
self.recommendations = recommendations
|
self.recommendations = recommendations
|
||||||
|
|
||||||
def _find_insulation(self, parts, u_value):
|
def _find_insulation(self, u_value, insulation_materials, non_insulation_materials):
|
||||||
|
|
||||||
lowest_selected_u_value = None
|
lowest_selected_u_value = None
|
||||||
recommendations = []
|
recommendations = []
|
||||||
for part in parts:
|
for _, insulation_material_group in insulation_materials.groupby("description"):
|
||||||
|
|
||||||
for depth, cost_per_unit in zip(part["depths"], part["cost"]):
|
for _, material in insulation_material_group.iterrows():
|
||||||
|
|
||||||
part_u_value = r_value_per_mm_to_u_value(depth, part["r_value_per_mm"])
|
|
||||||
|
|
||||||
|
part_u_value = r_value_per_mm_to_u_value(material["depth"], material["r_value_per_mm"])
|
||||||
_, new_u_value = calculate_u_value_uplift(u_value, part_u_value)
|
_, new_u_value = calculate_u_value_uplift(u_value, part_u_value)
|
||||||
new_u_value = math.ceil(new_u_value * 100.0) / 100.0
|
new_u_value = math.ceil(new_u_value * 100.0) / 100.0
|
||||||
|
|
||||||
|
|
@ -225,27 +251,40 @@ class WallRecommendations(Definitions):
|
||||||
|
|
||||||
# We allow a small tolerance for error so we don't discount the recommendation entirely
|
# We allow a small tolerance for error so we don't discount the recommendation entirely
|
||||||
if new_u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
if new_u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
||||||
|
|
||||||
lowest_selected_u_value = update_lowest_selected_u_value(lowest_selected_u_value, new_u_value)
|
lowest_selected_u_value = update_lowest_selected_u_value(lowest_selected_u_value, new_u_value)
|
||||||
|
|
||||||
estimated_cost = cost_per_unit * self.property.insulation_wall_area
|
if material["type"] == "internal_wall_insulation":
|
||||||
|
cost_result = self.costs.internal_wall_insulation(
|
||||||
|
wall_area=self.property.insulation_wall_area,
|
||||||
|
material=material.to_dict(),
|
||||||
|
non_insulation_materials=non_insulation_materials
|
||||||
|
)
|
||||||
|
elif material["type"] == "external_wall_insulation":
|
||||||
|
cost_result = self.costs.external_wall_insulation(
|
||||||
|
wall_area=self.property.insulation_wall_area,
|
||||||
|
material=material.to_dict(),
|
||||||
|
non_insulation_materials=non_insulation_materials
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid material type")
|
||||||
|
|
||||||
recommendations.append(
|
recommendations.append(
|
||||||
{
|
{
|
||||||
"parts": [
|
"parts": [
|
||||||
get_recommended_part(
|
get_recommended_part(
|
||||||
part=part,
|
part=material.to_dict(),
|
||||||
selected_depth=depth,
|
|
||||||
quantity=self.property.insulation_wall_area,
|
quantity=self.property.insulation_wall_area,
|
||||||
quantity_unit=QuantityUnits.m2.value,
|
quantity_unit=QuantityUnits.m2.value,
|
||||||
selected_total_cost=estimated_cost
|
cost_result=cost_result
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
"type": "wall_insulation",
|
"type": "wall_insulation",
|
||||||
"description": "Install " + self._make_description(part, depth),
|
"description": "Install " + self._make_description(material),
|
||||||
"starting_u_value": u_value,
|
"starting_u_value": u_value,
|
||||||
"new_u_value": new_u_value,
|
"new_u_value": new_u_value,
|
||||||
"sap_points": None,
|
"sap_points": None,
|
||||||
"cost": estimated_cost,
|
**cost_result
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -258,27 +297,32 @@ class WallRecommendations(Definitions):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ewi_parts = [
|
|
||||||
part for part in self.materials if part["type"] == "external_wall_insulation"
|
|
||||||
] if self.ewi_valid else []
|
|
||||||
|
|
||||||
iwi_parts = [part for part in self.materials if part["type"] == "internal_wall_insulation"]
|
|
||||||
|
|
||||||
# Recommend external and internal wall insulation separately
|
# Recommend external and internal wall insulation separately
|
||||||
# Since external and internal wall insulation are sufficiently different,
|
# Since external and internal wall insulation are sufficiently different,
|
||||||
# we separate the logic for for recommending them, therefore we don't
|
# we separate the logic for for recommending them, therefore we don't
|
||||||
# consider diminishing returns between the two
|
# consider diminishing returns between the two
|
||||||
|
|
||||||
ewi_recommendations = self._find_insulation(ewi_parts, u_value)
|
ewi_recommendations = []
|
||||||
iwi_recommendations = self._find_insulation(iwi_parts, u_value)
|
if self.ewi_valid:
|
||||||
|
ewi_recommendations = self._find_insulation(
|
||||||
|
u_value=u_value,
|
||||||
|
insulation_materials=pd.DataFrame(self.external_wall_insulation_materials),
|
||||||
|
non_insulation_materials=self.external_wall_non_insulation_materials
|
||||||
|
)
|
||||||
|
|
||||||
|
iwi_recommendations = self._find_insulation(
|
||||||
|
u_value=u_value,
|
||||||
|
insulation_materials=pd.DataFrame(self.internal_wall_insulation_materials),
|
||||||
|
non_insulation_materials=self.internal_wall_non_insulation_materials
|
||||||
|
)
|
||||||
|
|
||||||
self.recommendations += ewi_recommendations + iwi_recommendations
|
self.recommendations += ewi_recommendations + iwi_recommendations
|
||||||
|
|
||||||
self.prune_diminishing_recommendations()
|
self.prune_diminishing_recommendations()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _make_description(part, depth):
|
def _make_description(material):
|
||||||
return f"{depth}{part['depth_unit']} {part['description']}"
|
return f"{int(material['depth'])}{material['depth_unit']} {material['description']}"
|
||||||
|
|
||||||
def prune_diminishing_recommendations(self):
|
def prune_diminishing_recommendations(self):
|
||||||
# For any recommendations, if we have at least 1 reommendation that does not exhibit diminishing returns
|
# For any recommendations, if we have at least 1 reommendation that does not exhibit diminishing returns
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue