mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
completed estimate windows function, though it needs more testing
This commit is contained in:
parent
c6c8de6dcf
commit
57f92e6060
4 changed files with 154 additions and 2 deletions
2
.idea/Model.iml
generated
2
.idea/Model.iml
generated
|
|
@ -7,7 +7,7 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/open_uprn" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/open_uprn" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/recommendations" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/recommendations" isTestSource="false" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.10 (backend)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.10 (model_data)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PyNamespacePackagesService">
|
<component name="PyNamespacePackagesService">
|
||||||
|
|
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
|
|
@ -3,7 +3,7 @@
|
||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.10 (backend)" />
|
<option name="sdkName" value="Python 3.10 (backend)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (backend)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (model_data)" project-jdk-type="Python SDK" />
|
||||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||||
<option name="version" value="3" />
|
<option name="version" value="3" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
|
|
@ -652,3 +652,64 @@ def esimtate_pitched_roof_area(floor_area: float, floor_height: float) -> float:
|
||||||
area = 2 * (slope * wall_width)
|
area = 2 * (slope * wall_width)
|
||||||
|
|
||||||
return area
|
return area
|
||||||
|
|
||||||
|
|
||||||
|
def estimate_windows(
|
||||||
|
property_type, built_form, construction_age_band, floor_area, number_habitable_rooms, extension_count
|
||||||
|
):
|
||||||
|
# Base window count based on habitable rooms
|
||||||
|
window_count = number_habitable_rooms
|
||||||
|
|
||||||
|
# Additional windows for non-habitable rooms (e.g., kitchen, bathroom)
|
||||||
|
# Assuming most houses will have at least one kitchen and one bathroom
|
||||||
|
# Scale non-habitable windows with the number of habitable rooms
|
||||||
|
non_habitable_base = 2 # Base for kitchen and bathroom
|
||||||
|
extra_non_habitable = max(0, (number_habitable_rooms - 3) // 2) # Extra for large houses
|
||||||
|
window_count += non_habitable_base + extra_non_habitable
|
||||||
|
|
||||||
|
# Adjustments based on built form and property type
|
||||||
|
if property_type in ["House", "Bungalow"] and built_form in ["Semi-Detached", "Detached"]:
|
||||||
|
built_form_lookup = {
|
||||||
|
"Semi-Detached": 3,
|
||||||
|
"Detached": 4,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
# For Flats and Maisonettes, adjustments might be less
|
||||||
|
built_form_lookup = {
|
||||||
|
"Mid-Terrace": 0,
|
||||||
|
"End-Terrace": 1,
|
||||||
|
"Semi-Detached": 1,
|
||||||
|
"Detached": 2,
|
||||||
|
}
|
||||||
|
window_count += built_form_lookup.get(built_form, 0)
|
||||||
|
|
||||||
|
# Adjust for floor area (larger floor area might indicate more rooms/windows)
|
||||||
|
if floor_area < 85: # Small to medium properties
|
||||||
|
# Standard window count likely sufficient
|
||||||
|
pass
|
||||||
|
elif 85 <= floor_area <= 120: # Medium to large properties
|
||||||
|
# More rooms or larger rooms likely, potentially more windows
|
||||||
|
window_count += 1
|
||||||
|
elif floor_area > 120: # Very large properties
|
||||||
|
# Likely to have significantly more or larger rooms
|
||||||
|
window_count += 2
|
||||||
|
|
||||||
|
# Adjust for construction age band
|
||||||
|
if construction_age_band in ["England and Wales: before 1900", "England and Wales: 1900-1929"]:
|
||||||
|
# Older houses with smaller, more numerous windows
|
||||||
|
window_count += 1
|
||||||
|
|
||||||
|
# Adjust for extensions (each extension might add windows)
|
||||||
|
window_count += extension_count
|
||||||
|
|
||||||
|
# Adjustments for specific property types
|
||||||
|
if property_type in ["Flat", "Maisontte"]:
|
||||||
|
# Flats might have fewer windows due to shared walls
|
||||||
|
# Maisonettes might follow a similar pattern to flats or small houses
|
||||||
|
window_count -= 1
|
||||||
|
|
||||||
|
# Ensure window count is not negative
|
||||||
|
if window_count < 0:
|
||||||
|
raise ValueError("Window count cannot be negative.")
|
||||||
|
|
||||||
|
return window_count
|
||||||
|
|
|
||||||
|
|
@ -427,3 +427,94 @@ def test_external_wall_area():
|
||||||
for num_floors, floor_height, perimeter, built_form, expected in test_cases:
|
for num_floors, floor_height, perimeter, built_form, expected in test_cases:
|
||||||
result = recommendation_utils.estimate_external_wall_area(num_floors, floor_height, perimeter, built_form)
|
result = recommendation_utils.estimate_external_wall_area(num_floors, floor_height, perimeter, built_form)
|
||||||
assert result == expected, f"Test failed for {built_form}: Expected {expected}, got {result}"
|
assert result == expected, f"Test failed for {built_form}: Expected {expected}, got {result}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_estimate_windows():
|
||||||
|
# Based on data from an EPR that has 4 windows
|
||||||
|
windows_case_1 = recommendation_utils.estimate_windows(
|
||||||
|
property_type="Flat",
|
||||||
|
built_form="Semi-Detached",
|
||||||
|
construction_age_band="England and Wales: 1976-1982",
|
||||||
|
floor_area=37,
|
||||||
|
number_habitable_rooms=2,
|
||||||
|
extension_count=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert windows_case_1 == 4, f"Expected 4 windows, got {windows_case_1}"
|
||||||
|
|
||||||
|
# Based on data from an EPR that has 7 winows, however two of the windows were very small, having areas of
|
||||||
|
# 0.21m^2 and 0.3m^2 respectively. We see 6 as a reasonable estimate for the number of windows
|
||||||
|
windows_case_2 = recommendation_utils.estimate_windows(
|
||||||
|
property_type="House",
|
||||||
|
built_form="Mid-Terrace",
|
||||||
|
construction_age_band="England and Wales: 1950-1966",
|
||||||
|
floor_area=69,
|
||||||
|
number_habitable_rooms=4,
|
||||||
|
extension_count=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert windows_case_2 == 6, f"Expected 6 windows, got {windows_case_2}"
|
||||||
|
|
||||||
|
# Based on data from an EPR on a bungalow, that has 6 windows. Two of the windows are small, both have a 0.4m^2 area
|
||||||
|
# and so 5 windows is an acceptable estimate
|
||||||
|
windows_case_3 = recommendation_utils.estimate_windows(
|
||||||
|
property_type="Bungalow",
|
||||||
|
built_form="Mid-Terrace",
|
||||||
|
construction_age_band="England and Wales: 1967-1975",
|
||||||
|
floor_area=56,
|
||||||
|
number_habitable_rooms=3,
|
||||||
|
extension_count=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert windows_case_3 == 5, f"Expected 5 windows, got {windows_case_3}"
|
||||||
|
|
||||||
|
# Based on data from an EPR on a end terrace house that has 8 windows. One of the windows is very small, with an
|
||||||
|
# area of 0.25 m^2 and so 7 windows is an acceptable estimate
|
||||||
|
windows_case_4 = recommendation_utils.estimate_windows(
|
||||||
|
property_type="House",
|
||||||
|
built_form="End-Terrace",
|
||||||
|
construction_age_band="England and Wales: 1967-1975",
|
||||||
|
floor_area=77.28,
|
||||||
|
number_habitable_rooms=4,
|
||||||
|
extension_count=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert windows_case_4 == 7, f"Expected 7 windows, got {windows_case_4}"
|
||||||
|
|
||||||
|
# Based on data from an EPR on a Semi-detatched house that has 11 windows based on the associated condition report
|
||||||
|
# Right now, we estimate 12 windows for this property
|
||||||
|
windows_case_5 = recommendation_utils.estimate_windows(
|
||||||
|
property_type="House",
|
||||||
|
built_form="Semi-Detached",
|
||||||
|
construction_age_band="England and Wales: 1950-1966",
|
||||||
|
floor_area=88.4,
|
||||||
|
number_habitable_rooms=5,
|
||||||
|
extension_count=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert windows_case_5 == 12, f"Expected 12 windows, got {windows_case_5}"
|
||||||
|
|
||||||
|
# Based on Khalim's flat which has 3 windows. There is no construction age band on the EPC. The windows are large
|
||||||
|
# so an estimate of 5 windows is a reasonable estimate
|
||||||
|
windows_case_6 = recommendation_utils.estimate_windows(
|
||||||
|
property_type="Flat",
|
||||||
|
built_form="",
|
||||||
|
construction_age_band="",
|
||||||
|
floor_area=100,
|
||||||
|
number_habitable_rooms=3,
|
||||||
|
extension_count=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert windows_case_6 == 5, f"Expected 5 windows, got {windows_case_6}"
|
||||||
|
|
||||||
|
# Based on an EPR semi detatched house though we don't have the exact number of windows. We estimate 10
|
||||||
|
windows_case_7 = recommendation_utils.estimate_windows(
|
||||||
|
property_type="House",
|
||||||
|
built_form="Semi-Detached",
|
||||||
|
construction_age_band="England and Wales: 1967-1975",
|
||||||
|
floor_area=85,
|
||||||
|
number_habitable_rooms=4,
|
||||||
|
extension_count=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert windows_case_7 == 10, f"Expected 10 windows, got {windows_case_7}"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue