adding simulation config to windows recommendation

This commit is contained in:
Khalim Conn-Kowlessar 2024-10-01 11:56:03 +01:00
parent 126232d5a5
commit 643bfb5d1d
2 changed files with 133 additions and 43 deletions

View file

@ -48,6 +48,15 @@ class WindowsRecommendations:
if not any(x in measures for x in MEASURE_MAP["windows"]): if not any(x in measures for x in MEASURE_MAP["windows"]):
return return
if self.property.windows["glazing_type"] in ["triple", "high performance"]:
# We don't make any recommendations in this case. The property already has outstanding glazing
return
if self.property.windows["has_glazing"] & (
self.property.windows["glazing_coverage"] == "full"
):
return
# If the property is in a conservation area or is a listed building, it becomes more difficult to install # If the property is in a conservation area or is a listed building, it becomes more difficult to install
# double glazing. Therefore, we don't recommend it. It is still possible but is not practical as it # double glazing. Therefore, we don't recommend it. It is still possible but is not practical as it
# requires planning permission and might require a more expensive window type, such as timber. # requires planning permission and might require a more expensive window type, such as timber.
@ -67,11 +76,6 @@ class WindowsRecommendations:
if not number_of_windows: if not number_of_windows:
raise ValueError("Number of windows not specified") raise ValueError("Number of windows not specified")
if self.property.windows["has_glazing"] & (
self.property.windows["glazing_coverage"] == "full"
):
return
if windows_area is not None: if windows_area is not None:
# TODO - we don't have a price for this so we can't recommend it # TODO - we don't have a price for this so we can't recommend it
print("We have windows area, we should use this data for our recommendations!!!") print("We have windows area, we should use this data for our recommendations!!!")
@ -122,6 +126,95 @@ class WindowsRecommendations:
". Secondary glazing recommended due to conservation area status" ". Secondary glazing recommended due to conservation area status"
) )
# Set up the simulation config
if self.property.windows["glazing_type"] == "multiple":
glazing_type_ending = "multiple"
glazed_type_ending = (
"secondary glazing" if is_secondary_glazing else "double glazing installed during or after 2002"
)
windows_energy_eff = "Good"
new_windows_description = "Multiple glazing throughout"
elif self.property.windows["glazing_type"] == "single":
# We will only recommend either secondary or double glazing
glazing_type_ending = (
"secondary" if is_secondary_glazing else "double"
)
glazed_type_ending = (
"secondary glazing" if is_secondary_glazing else "double glazing installed during or after 2002"
)
if is_secondary_glazing:
windows_energy_eff = "Good"
new_windows_description = "Full secondary glazing"
else:
windows_energy_eff = "Average"
new_windows_description = "Fully double glazed"
elif self.property.windows["glazing_type"] == "double":
glazing_type_ending = (
"multiple" if is_secondary_glazing else "double"
)
# We set glazed type depending on which window type is more prevalent. Since there is already double
# glazing in place, if we're recommending more double glazing, we set the glazed type to double glazing
# otherwise, if we're recommending secondary glazing and the proportion of glazing in place already that
# is double is less than 50% we set the glazed type to secondary glazing
if not is_secondary_glazing:
glazed_type_ending = "double glazing installed during or after 2002"
new_windows_description = "Fully double glazed"
windows_energy_eff = "Average"
else:
if self.property.data["multi-glaze-proportion"] < 50:
glazed_type_ending = "secondary glazing"
else:
glazed_type_ending = "double glazing installed during or after 2002"
new_windows_description = "Multiple glazing throughout"
windows_energy_eff = "Good"
elif self.property.windows["glazing_type"] == "secondary":
glazing_type_ending = (
"secondary" if is_secondary_glazing else "multiple"
)
windows_energy_eff = "Good"
# This is the opposite. If there is secondary glazing in place, and we're recommending double
# we set glazed_type_ending, depending on the proportion of glazing in place
if is_secondary_glazing:
glazed_type_ending = "secondary glazing"
new_windows_description = "Full secondary glazing"
else:
if self.property.data["multi-glaze-proportion"] < 50:
glazed_type_ending = "double glazing installed during or after 2002"
else:
glazed_type_ending = "secondary glazing"
new_windows_description = "Multiple glazing throughout"
else:
raise ValueError("Invalid glazing type - implement me")
windows_ending_config = WindowAttributes(new_windows_description).process()
windows_simulation_config = check_simulation_difference(
new_config=windows_ending_config, old_config=self.property.windows, prefix="windows_"
)
simulation_config = {
**windows_simulation_config,
"multi_glaze_proportion_ending": 100,
"windows_energy_eff_ending": windows_energy_eff,
"glazing_type_ending": glazing_type_ending,
"glazed_type_ending": glazed_type_ending,
}
description_simulation = {
"multi-glaze-proportion": 100,
"windows-energy-eff": windows_energy_eff,
"windows-description": new_windows_description,
"glazed-type": glazed_type_ending,
}
self.recommendation = [ self.recommendation = [
{ {
"phase": phase, "phase": phase,
@ -134,13 +227,8 @@ class WindowsRecommendations:
"already_installed": already_installed, "already_installed": already_installed,
**cost_result, **cost_result,
"is_secondary_glazing": is_secondary_glazing, "is_secondary_glazing": is_secondary_glazing,
# TODO: Make this condition on is_secondary_glazing "description_simulation": description_simulation,
"description_simulation": { "simulation_config": simulation_config,
"multi-glaze-proportion": 100,
"windows-energy-eff": "Average",
"windows-description": "Fully double glazed",
"glazed-type": "double glazing installed during or after 2002",
}
} }
] ]

View file

@ -37,11 +37,13 @@ class TestWindowRecommendations:
recommender.recommend() recommender.recommend()
assert recommender.recommendation == [ assert recommender.recommendation == [
{'parts': [], 'type': 'windows_glazing', 'description': 'Install double glazing to all windows', {'phase': 0, 'parts': [], 'type': 'windows_glazing', 'description': 'Install double glazing to all windows',
'starting_u_value': None, 'new_u_value': None, 'sap_points': None, 'total': 5721.943248, 'starting_u_value': None, 'new_u_value': None, 'sap_points': None, 'already_installed': False,
'subtotal': 4768.28604, 'vat': 953.6572080000001, 'contingency': 340.59186, 'preliminaries': 340.59186, 'total': 7980.0, 'labour_hours': 0.0, 'labour_days': 0.0, 'is_secondary_glazing': False,
'material': 1275.75, 'profit': 681.18372, 'labour_hours': 45.5, 'labour_cost': 994.8624, 'description_simulation': {'multi-glaze-proportion': 100, 'windows-energy-eff': 'Average',
'labour_days': 2.84375, 'is_secondary_glazing': False}] 'windows-description': 'Fully double glazed',
'glazed-type': 'double glazing installed during or after 2002'}}
]
def test_partial_double_glazed(self): def test_partial_double_glazed(self):
""" """
@ -73,11 +75,14 @@ class TestWindowRecommendations:
recommender2.recommend() recommender2.recommend()
assert recommender2.recommendation == [ assert recommender2.recommendation == [
{'parts': [], 'type': 'windows_glazing', 'description': 'Install double glazing to the remaining windows', {'phase': 0, 'parts': [], 'type': 'windows_glazing',
'starting_u_value': None, 'new_u_value': None, 'sap_points': None, 'total': 4087.10232, 'description': 'Install double glazing to the remaining windows', 'starting_u_value': None,
'subtotal': 3405.9186, 'vat': 681.18372, 'contingency': 243.2799, 'preliminaries': 243.2799, 'new_u_value': None, 'sap_points': None, 'already_installed': False, 'total': 5700.0, 'labour_hours': 0.0,
'material': 911.25, 'profit': 486.5598, 'labour_hours': 32.5, 'labour_cost': 710.6160000000001, 'labour_days': 0.0, 'is_secondary_glazing': False,
'labour_days': 2.03125, 'is_secondary_glazing': False}] 'description_simulation': {'multi-glaze-proportion': 100, 'windows-energy-eff': 'Average',
'windows-description': 'Fully double glazed',
'glazed-type': 'double glazing installed during or after 2002'}}
]
def test_fully_double_glazed(self): def test_fully_double_glazed(self):
""" """
@ -160,12 +165,14 @@ class TestWindowRecommendations:
recommender5.recommend() recommender5.recommend()
assert recommender5.recommendation == [ assert recommender5.recommendation == [
{'parts': [], 'type': 'windows_glazing', {'phase': 0, 'parts': [], 'type': 'windows_glazing',
'description': 'Install secondary glazing to the remaining windows', 'description': 'Install secondary glazing to the remaining windows', 'starting_u_value': None,
'starting_u_value': None, 'new_u_value': None, 'sap_points': None, 'total': 1089.893952, 'new_u_value': None, 'sap_points': None, 'already_installed': False, 'total': 4560.0, 'labour_hours': 0.0,
'subtotal': 908.24496, 'vat': 181.64899200000002, 'contingency': 64.87464, 'preliminaries': 64.87464, 'labour_days': 0.0, 'is_secondary_glazing': True,
'material': 729.0, 'profit': 129.74928, 'labour_hours': 13.0, 'labour_cost': 568.4928, 'description_simulation': {'multi-glaze-proportion': 100, 'windows-energy-eff': 'Good',
'labour_days': 0.8125, 'is_secondary_glazing': True}] 'windows-description': 'Full secondary glazing',
'glazed-type': 'secondary glazing'}}
]
def test_single_glazed_restricted_measures(self): def test_single_glazed_restricted_measures(self):
epc_record = EPCRecord() epc_record = EPCRecord()
@ -195,14 +202,14 @@ class TestWindowRecommendations:
recommender6.recommend() recommender6.recommend()
assert recommender6.recommendation == [ assert recommender6.recommendation == [
{'parts': [], 'type': 'windows_glazing', {'phase': 0, 'parts': [], 'type': 'windows_glazing',
'description': 'Install secondary glazing to all windows. Secondary ' 'description': 'Install secondary glazing to all windows. Secondary glazing recommended due to herigate '
'glazing recommended due to herigate building status', 'building status',
'starting_u_value': None, 'new_u_value': None, 'sap_points': None, 'starting_u_value': None, 'new_u_value': None, 'sap_points': None, 'already_installed': False,
'total': 1907.314416, 'subtotal': 1589.42868, 'vat': 317.885736, 'total': 7980.0, 'labour_hours': 0.0, 'labour_days': 0.0, 'is_secondary_glazing': True,
'contingency': 113.53062, 'preliminaries': 113.53062, 'description_simulation': {'multi-glaze-proportion': 100, 'windows-energy-eff': 'Good',
'material': 1275.75, 'profit': 227.06124, 'labour_hours': 22.75, 'windows-description': 'Full secondary glazing',
'labour_cost': 994.8624, 'labour_days': 1.421875, 'is_secondary_glazing': True} 'glazed-type': 'secondary glazing'}}
] ]
def test_full_triple_glazed(self): def test_full_triple_glazed(self):
@ -233,7 +240,7 @@ class TestWindowRecommendations:
def test_partial_triple_glazed(self): def test_partial_triple_glazed(self):
""" """
We should just recommend double glazing to the remaining windows, since it's a cheaper option We don't recommend anything here
""" """
epc_record = EPCRecord() epc_record = EPCRecord()
epc_record.prepared_epc = { epc_record.prepared_epc = {
@ -258,9 +265,4 @@ class TestWindowRecommendations:
recommender8.recommend() recommender8.recommend()
assert recommender8.recommendation == [ assert not recommender8.recommendation
{'parts': [], 'type': 'windows_glazing', 'description': 'Install double glazing to the remaining windows',
'starting_u_value': None, 'new_u_value': None, 'sap_points': None, 'total': 1634.840928,
'subtotal': 1362.36744, 'vat': 272.47348800000003, 'contingency': 97.31196, 'preliminaries': 97.31196,
'material': 364.5, 'profit': 194.62392, 'labour_hours': 13.0, 'labour_cost': 284.2464,
'labour_days': 0.8125, 'is_secondary_glazing': False}]