Merge pull request #349 from Hestia-Homes/renewables-recommendations

Renewables recommendations
This commit is contained in:
KhalimCK 2024-10-08 18:45:55 +01:00 committed by GitHub
commit eadd015308
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 337 additions and 272 deletions

View file

@ -69,7 +69,7 @@ class GoogleSolarApi:
self.floor_area = None
self.roof_area = None
self.roof_segment_indexes = None
self.panel_area = None
self.panel_area = assumptions.RDSAP_AREA_PER_PANEL
self.panel_wattage = None
self.panel_performance = None
@ -166,10 +166,6 @@ class GoogleSolarApi:
self.roof_area = self.insights_data["solarPotential"]["wholeRoofStats"]['areaMeters2']
self.floor_area = self.insights_data["solarPotential"]["wholeRoofStats"]['groundAreaMeters2']
self.panel_area = (
self.insights_data["solarPotential"]["panelHeightMeters"] *
self.insights_data["solarPotential"]["panelWidthMeters"]
)
self.panel_wattage = self.insights_data["solarPotential"]["panelCapacityWatts"]
if self.panel_wattage != 400:
# In the API documentation, it claims that the default output is 250W, however we've only seen 400W, so if
@ -450,8 +446,8 @@ class GoogleSolarApi:
# We want max roi, minimal generation deficit, and max generation value - we create a ranking score
# Assign equal weights to each metric
weights = {'roi': 0.6, 'generation_value': 0.2, 'generation_deficit': 0.2}
metrics = panel_performance[['roi', 'generation_value', 'generation_deficit']]
weights = {'roi': 0.8, 'generation_value': 0.2}
metrics = panel_performance[['roi', 'generation_value']].copy()
# Normalize the columns (0 to 1 scale)
scaler = MinMaxScaler()
@ -459,12 +455,11 @@ class GoogleSolarApi:
# Convert normalized metrics back to a dataframe
normalized_metrics_df = pd.DataFrame(
normalized_metrics, columns=['roi', 'generation_value', 'generation_deficit']
normalized_metrics, columns=['roi', 'generation_value']
)
normalized_metrics_df['combined_score'] = (
normalized_metrics_df['roi'] * weights['roi'] +
normalized_metrics_df['generation_value'] * weights['generation_value'] +
(1 - normalized_metrics_df['generation_deficit']) * weights['generation_deficit']
normalized_metrics_df['generation_value'] * weights['generation_value']
)
panel_performance['combined_score'] = normalized_metrics_df['combined_score'].values
@ -799,7 +794,6 @@ class GoogleSolarApi:
"panel_performance": solar_api_client.panel_performance,
"unit_share_of_energy": 1
},
roof_area=solar_api_client.roof_area
)
return input_properties
@ -825,7 +819,7 @@ class GoogleSolarApi:
n_panels=10, has_battery=False, n_floors=property_instance.number_of_floors
)["total"],
'weighted_ratio': None,
'panneled_roof_area': 10 * 1.8,
'panneled_roof_area': 10 * assumptions.RDSAP_AREA_PER_PANEL,
'array_wattage': 4000,
'initial_ac_kwh_per_year': 4000 * 0.95, # Assumed 95% efficient wattage -> ac
'lifetime_ac_kwh': None,
@ -845,7 +839,7 @@ class GoogleSolarApi:
n_panels=6, has_battery=False, n_floors=property_instance.number_of_floors
)["total"],
'weighted_ratio': None,
'panneled_roof_area': 6 * 1.8,
'panneled_roof_area': 6 * assumptions.RDSAP_AREA_PER_PANEL,
'array_wattage': 2400,
'initial_ac_kwh_per_year': 2400 * 0.95, # Assumed 95% efficient wattage -> ac
'lifetime_ac_kwh': None,

View file

@ -7,6 +7,11 @@ AVERAGE_ASHP_EFFICIENCY = 250
# be exported
SOLAR_CONSUMPTION_PROPORTION = 0.5
# Typically, each solar panel takes up around 3.4 m2 of roof space under RdSAP. This was been verified in Elmhurst
RDSAP_AREA_PER_PANEL = 3.4
SOCIAL_TENURES = ["Rented (social)", "rental (social)"]
DESCRIPTIONS_TO_FUEL_TYPES = {
"Air source heat pump, radiators, electric": {
"fuel": "Electricity", "cop": AVERAGE_ASHP_EFFICIENCY / 100

View file

@ -631,27 +631,38 @@ async def trigger_plan(body: PlanTriggerRequest):
for p in input_properties:
if not recommendations.get(p.id):
continue
input_measures = prepare_input_measures(recommendations[p.id], body.goal)
current_sap_points = int(p.data["current-energy-efficiency"])
target_sap_points = epc_to_sap_lower_bound(body.goal_value)
sap_gain = CostOptimiser.calculate_sap_gain_with_slack(target_sap_points - current_sap_points)
if body.budget:
optimiser = GainOptimiser(
input_measures, max_cost=body.budget, max_gain=sap_gain if sap_gain > 0 else 0
)
if not body.optimise:
if body.goal != "Increasing EPC":
raise NotImplementedError("Only EPC optimisation is currently supported")
solution = []
for sub_list in input_measures:
# Select the entry with the highest gain, and if tied, choose the one with the lowest cost
best_measure = max(sub_list, key=lambda x: (x['gain'], -x['cost']))
solution.append(best_measure)
else:
# The minimum gain is the minimum number of SAP points required to get to the target SAP band
# If the gain is negative, the optimiser will return an empty solution
optimiser = CostOptimiser(
input_measures,
min_gain=sap_gain
)
optimiser.setup()
optimiser.solve()
solution = optimiser.solution
if body.budget:
optimiser = GainOptimiser(
input_measures, max_cost=body.budget, max_gain=sap_gain if sap_gain > 0 else 0
)
else:
# The minimum gain is the minimum number of SAP points required to get to the target SAP band
# If the gain is negative, the optimiser will return an empty solution
optimiser = CostOptimiser(
input_measures,
min_gain=sap_gain
)
optimiser.setup()
optimiser.solve()
solution = optimiser.solution
selected_recommendations = {r["id"] for r in solution}

View file

@ -86,6 +86,9 @@ class PlanTriggerRequest(BaseModel):
# exists in the portfolio, it will be ignored
multi_plan: Optional[bool] = False
# if False, allows optimisation to be switched off
optimise: Optional[bool] = False
_allowed_goals = {"Increasing EPC"}
_allowed_housing_types = {"Social", "Private"}

View file

@ -841,7 +841,7 @@ class Costs:
"labour_days": labour_days,
}
def high_heat_electric_storage_heaters(self, number_heated_rooms):
def high_heat_electric_storage_heaters(self, number_heated_rooms, needs_cylinder):
"""
We base the estimates for the cost of electric storage heaters on the cost per room as estimated by the
@ -852,7 +852,12 @@ class Costs:
:param number_heated_rooms: int, number of rooms to be heated
"""
total_cost = 1500 * number_heated_rooms
if needs_cylinder:
# 1000 is the cost of a new hot water cylinder
total_cost = 1200 * number_heated_rooms + 1000
else:
# 500 is the cost of a dual immersion heater - a rough estimate
total_cost = 1200 * number_heated_rooms + 500
subtotal_before_vat = total_cost / (1 + self.VAT_RATE)
vat = total_cost - subtotal_before_vat
@ -1143,7 +1148,7 @@ class Costs:
"labour_days": labour_days,
}
def air_source_heat_pump(self):
def air_source_heat_pump(self, ashp_size):
"""
Based on the region and type of property, this function will produce a cost estimation for an air source heat
pump. This cost will include the boiler upgrade scheme grant
@ -1151,14 +1156,19 @@ class Costs:
"""
# This is the average cost of a project, we'll add some additional contingency
regional_cost = MCS_AIR_SOURCE_HEAT_PUMP_COST_DATA[self.region]
total_cost = regional_cost * (1 + self.CONTINGENCY) - BOILER_UPGRADE_SCHEME_ASHP_VALUE
if ashp_size is None:
cost = [x for x in INSTALLER_ASHP_COSTS if x["capacity_kw"] is None][0]["cost"]
else:
cost = [x for x in INSTALLER_ASHP_COSTS if x][0]["cost"]
# We add some contingency since there are additional costs such as resizing radiators, that could be required
total_cost = cost * (1 + self.CONTINGENCY)
subtotal_before_vat = total_cost / (1 + self.VAT_RATE)
vat = total_cost - subtotal_before_vat
# We assume 3 days installation
labour_days = 3
# We assume 5 days installation
labour_days = 5
labour_hours = labour_days * 8
return {

View file

@ -1,3 +1,5 @@
import re
import backend.app.assumptions as assumptions
from recommendations.Costs import Costs, BOILER_UPGRADE_SCHEME_ASHP_VALUE
from recommendations.recommendation_utils import (
check_simulation_difference, override_costs, combine_recommendation_configs
@ -368,6 +370,75 @@ class HeatingRecommender:
description = ("Replace the existing boiler and cylinder without a thermostat with a new electric combi "
"boiler")
def size_heat_pump(self):
"""
Given the methodology by installers (SCIS) this function will perform a basic heat loss calculation and
produce a recommendation for the size of the heat pump
:return:
"""
floor_area = self.property.floor_area
# We use the default heat loss W/m2 values are specified by the insaller, depending on the property type
def remap_to_heat_loss(construction_age_band):
if "before 1900" in construction_age_band:
return "Pre 1900 (solid stone)"
elif "1900-1929" in construction_age_band:
return "Early 1900s (solid brick)"
elif re.search(r'1930|1949|1950|1966|1967|1975', construction_age_band):
return "1950-1980 (cavity void)"
elif re.search(r'1976|1982|1983|1990', construction_age_band):
return "Post 1980 (cavity wall construction)"
elif re.search(r'1991|1995|1996|2002|2003|2011', construction_age_band):
return "2000-2018"
elif "2012 onwards" in construction_age_band:
return "New build (2018+)"
else:
return None
def select_heatpump_size(heat_loss_calculation):
"""
This function calculates the size of the heat pump based on the heat loss calculation, mapping
the heat loss calculation to the size of the heat pump in KW
:param heat_loss_calculation: This is calcualted as the floor area multipled by the heat loss constant,
divided by 1000
"""
if heat_loss_calculation < 5:
return 5
elif 5 <= heat_loss_calculation < 6:
return 6
elif 6 <= heat_loss_calculation < 8.5:
return 8.5
elif 8.5 <= heat_loss_calculation < 11.2:
return 11.2
elif 11.2 <= heat_loss_calculation < 14:
return 14
elif 14 <= heat_loss_calculation < 17:
return 17
elif 17 <= heat_loss_calculation < 20:
return 20
else:
return None
heat_loss_constants = {
"New build (2018+)": 35,
"2000-2018": 50,
"Post 1980 (cavity wall construction)": 60,
"1950-1980 (cavity void)": 70,
"Early 1900s (solid brick)": 80,
"Pre 1900 (solid stone)": 90
}
heat_loss_group = remap_to_heat_loss(self.property.construction_age_band)
heat_loss_constant = heat_loss_constants[heat_loss_group]
heat_loss_calculation = floor_area * heat_loss_constant / 1000
heat_pump_size = select_heatpump_size(heat_loss_calculation)
return heat_pump_size
def recommend_air_source_heat_pump(self, phase, has_cavity_or_loft_recommendations, _return=False):
"""
This method will implement the recommendation for an air source heat pump
@ -383,8 +454,9 @@ class HeatingRecommender:
controls_recommender = HeatingControlRecommender(self.property)
controls_recommender.recommend(heating_description="Air source heat pump, radiators, electric")
ashp_size = self.size_heat_pump()
ashp_costs = self.costs.air_source_heat_pump()
ashp_costs = self.costs.air_source_heat_pump(ashp_size)
if non_intrusive_recommendation:
# Update with non-intrusive recommendation
if non_intrusive_recommendation.get("cost"):
@ -413,11 +485,13 @@ class HeatingRecommender:
# This is a map from the heating controls description to the description of the air source heat pump set up
ashp_descriptions = {
"Time and temperature zone control": (
"Install an air source heat pump, and upgrade heating controls to Smart Thermostats, "
"room sensors and smart radiator valves (time & temperature zone control)."
f"Install a {ashp_size}KW air source heat pump, and upgrade heating controls to Smart Thermostats, "
"room sensors and smart radiator valves (time & temperature zone control). Ensure you have an 18 or "
"24 hour tariff"
),
"Programmer, TRVs and bypass": (
"Install an air source heat pump, with programmer, TRVs and a Bypass valve."
f"Install a {ashp_size}KW air source heat pump, with programmer, TRVs and a Bypass valve. Ensure you "
"have an 18 or 24 hour tariff"
),
}
@ -434,7 +508,7 @@ class HeatingRecommender:
ashp_costs_with_controls[key] += controls_rec[key]
if controls_rec is None:
description = "Install a Mitsubish air source heat pump."
description = f"Install a {ashp_size}KW Air source heat pump. Ensure you have an 18 or 24 hour tariff"
elif already_installed:
description = "The property already has an air source heat pump, no further action needed."
else:
@ -443,17 +517,16 @@ class HeatingRecommender:
# If the property does not have existing cavity and loft insulation, we include a note that the cost
# includes the boiler upgrade scheme and that the cavity and loft need to be treated, to ensure access
# to the funding
if not non_intrusive_recommendation:
if not non_intrusive_recommendation and self.property.data["tenure"] not in assumptions.SOCIAL_TENURES:
if has_cavity_or_loft_recommendations:
description = description + (
f" The cost includes the £"
f"{BOILER_UPGRADE_SCHEME_ASHP_VALUE} boiler upgrade scheme grant. "
f"You must ensure that the property has an insulated cavity and "
f"270mm+ loft insulation to qualify for the grant"
f" You must ensure that the property has an insulated cavity and "
f"270mm+ loft insulation to qualify for the grant, to claim £"
f"{BOILER_UPGRADE_SCHEME_ASHP_VALUE} of funding from the boiler upgrade scheme grant. "
)
else:
description = description + (
f" The cost includes the £{BOILER_UPGRADE_SCHEME_ASHP_VALUE} boiler upgrade scheme grant"
f" £{BOILER_UPGRADE_SCHEME_ASHP_VALUE} of funding can be claimed from the boiler upgrade scheme"
)
simulation_config = {
@ -739,20 +812,37 @@ class HeatingRecommender:
new_heating_description = self.DUAL_HEATING_DESCRIPTIONS[
self.property.main_heating["clean_description"]
]["hhr"]["mainheating_description"]
new_hot_water_description = self.property.hotwater["clean_description"] # We keep the hot water system
else:
new_heating_description = "Electric storage heaters"
new_hot_water_description = "Electric immersion, off-peak"
# Set up artefacts, suitable for the simulation and regardless of controls
heating_ending_config = MainHeatAttributes(new_heating_description).process()
heating_simulation_config = check_simulation_difference(
new_config=heating_ending_config, old_config=self.property.main_heating
)
hot_water_end_config = HotWaterAttributes(new_hot_water_description).process()
hot_water_simulation_config = check_simulation_difference(
new_config=hot_water_end_config, old_config=self.property.hotwater
)
heating_simulation_config = {
**heating_simulation_config,
**hot_water_simulation_config
}
# This upgrade will only take the heating system to average energy efficiency
if self.property.data["mainheat-energy-eff"] in ["Very Poor", "Poor"]:
if self.property.data["mainheat-energy-eff"] in ["Very Poor", "Poor"] and not self.dual_heating:
heating_simulation_config["mainheat_energy_eff_ending"] = "Average"
else:
heating_simulation_config["mainheat_energy_eff_ending"] = self.property.data["mainheat-energy-eff"]
if self.property.data["hot-water-energy-eff"] in ["Very Poor", "Poor"]:
heating_simulation_config["hot_water_energy_eff_ending"] = "Average"
else:
heating_simulation_config["hot_water_energy_eff_ending"] = self.property.data["hot-water-energy-eff"]
# If the property is off-gas and has no heating system in place, the number of heated rooms will actually
# be 0, so we use the number of rooms as the figure
number_heated_rooms = (
@ -768,7 +858,8 @@ class HeatingRecommender:
# Upgrade to electric storage heaters
costs = self.costs.high_heat_electric_storage_heaters(
number_heated_rooms=number_heated_rooms
number_heated_rooms=number_heated_rooms,
needs_cylinder=self.property.hotwater["system_type"] == "from main system"
)
if self.dual_heating:
description = self.DUAL_HEATING_DESCRIPTIONS[
@ -776,7 +867,7 @@ class HeatingRecommender:
]["hhr"]["recommendation_description"]
else:
description = "Install high heat retention electric storage heaters."
description = "Install high heat retention electric storage heaters with an appropriate off-peak tariff."
# We check the existing heating system and controls
if (
@ -790,6 +881,8 @@ class HeatingRecommender:
heating_description_simulation = {
"mainheat-description": new_heating_description,
"mainheat-energy-eff": heating_simulation_config["mainheat_energy_eff_ending"],
"hotwater-description": new_hot_water_description,
"hot-water-energy-eff": heating_simulation_config["hot_water_energy_eff_ending"]
}
recommendations = self.combine_heating_and_controls(

View file

@ -337,7 +337,7 @@ class RoofRecommendations:
if proposed_depth >= 300:
new_efficiency = "Very Good"
else:
if self.property.data["walls-energy-eff"] not in ["Good", "Very Good"]:
if self.property.data["roof-energy-eff"] not in ["Good", "Very Good"]:
new_efficiency = "Good"
else:
new_efficiency = "Very Good"
@ -416,7 +416,7 @@ class RoofRecommendations:
self.recommendations = recommendations
def recommend_room_roof_insulation(self, u_value, phase):
def recommend_room_roof_insulation(self, u_value, phase, default_u_values):
"""
This method recommends room in roof insulation for properties that have been identified
to possess a room in roof.
@ -455,6 +455,8 @@ class RoofRecommendations:
- Flat ceilings can be insulated like a standard loft.
:param u_value: Current u-value of the roof
:param phase: Phase of the recommendation
:param default_u_values: Use default u-values
:return:
"""
@ -495,7 +497,7 @@ class RoofRecommendations:
sap_points = rir_non_invasive_recommendation.get("sap_points", None)
# Could also be Roof room(s), ceiling insulated
new_descriptin = "Pitched, insulated at rafters"
new_descriptin = "Roof room(s), insulated"
roof_ending_config = RoofAttributes(new_descriptin).process()
roof_simulation_config = check_simulation_difference(
new_config=roof_ending_config, old_config=self.property.roof, prefix="roof_"
@ -505,6 +507,19 @@ class RoofRecommendations:
else:
new_efficiency = self.property.data["roof-energy-eff"]
if default_u_values:
new_u_value = get_roof_u_value(
insulation_thickness="average",
has_dwelling_above=self.property.roof["has_dwelling_above"],
is_loft=self.property.roof["is_loft"],
is_roof_room=self.property.roof["is_roof_room"],
is_thatched=self.property.roof["is_thatched"],
age_band=self.property.age_band,
is_flat=self.property.roof["is_flat"],
is_pitched=self.property.roof["is_pitched"],
is_at_rafters=self.property.roof["is_at_rafters"],
)
simulation_config = {
**roof_simulation_config,
"roof_thermal_transmittance_ending": new_u_value,

View file

@ -17,6 +17,8 @@ class SolarPvRecommendations:
MAX_SYSTEM_WATTAGE = 6000
MIN_SYSTEM_WATTAGE = 1000
MAX_ROOF_AREA_PERCENTAGE = 0.7
def __init__(self, property_instance):
"""
:param property_instance: Instance of the Property class, for the home associated to property_id
@ -187,15 +189,20 @@ class SolarPvRecommendations:
)
else:
# TODO: There may be some instances where we don't want to use the solar API so we should cover for them
panel_performance = self.property.solar_panel_configuration["panel_performance"]
panel_performance = self.property.solar_panel_configuration["panel_performance"].copy()
# We don't allow for more than 70% of the roof to be covered
panel_performance = panel_performance[
panel_performance["panneled_roof_area"] / self.property.roof_area <= self.MAX_ROOF_AREA_PERCENTAGE
]
roof_area = self.property.roof_area
solar_configurations = panel_performance.head(3).reset_index(drop=True)
# We combine each of these configurations with estimates with and without a battery
for rank, recommendation_config in solar_configurations.iterrows():
roof_coverage_percent = round(recommendation_config["panneled_roof_area"] / roof_area * 100)
# We round up to the nearest 10
roof_coverage_percent = np.ceil(roof_coverage_percent / 10) * 10
# We round up to the nearest 5
roof_coverage_percent = np.ceil(roof_coverage_percent / 5) * 5
for has_battery in [False, True]:
cost_result = self.costs.solar_pv(
has_battery=has_battery,

View file

@ -282,11 +282,14 @@ def get_u_value_from_s9(
):
"""Get the U-value from table S9 based on the insulation thickness."""
if thickness in ["below average", "average", "above average", "none", None, "0", 0] or (
if thickness in ["below average", "average", "above average", "none", None] or (
not is_loft and not is_roof_room and not is_at_rafters
):
return None
if thickness in [0, "0"] and is_loft:
return None
# Determine the column to refer based on the roof type
column = (
"Thatched_roof_U_value_W_m2K"
@ -294,8 +297,11 @@ def get_u_value_from_s9(
else "Slates_or_tiles_U_value_W_m2K"
)
# Get the correct U-value based on the insulation thickness
return s9[s9["Insulation_thickness_mm"] >= thickness][column].iloc[0]
if thickness in [0, "0"] and is_roof_room:
return s9[pd.isnull(s9["Insulation_thickness_mm"])][column].iloc[0]
else:
# Get the correct U-value based on the insulation thickness
return s9[s9["Insulation_thickness_mm"] >= thickness][column].iloc[0]
def get_roof_u_value(

View file

@ -39,15 +39,8 @@ testing_examples = [
'fixed-lighting-outlets-count': 10.0, 'low-energy-fixed-light-count': 7.0, 'uprn': 100110195416.0,
'uprn-source': 'Address Matched'
},
"heating_recommendation_descriptions": [
"Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and "
"smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade "
"scheme grant",
],
"heating_controls_recommendation_descriptions": [
"Upgrade heating controls to Smart Thermostats, room sensors and smart radiator valves (time & "
"temperature zone control)"
],
"heating_measure_types": ["air_source_heat_pump"],
"heating_controls_measure_types": ["time_temperature_zone_control"],
"notes": "This property has a boiler, radiators & mains gas with good efficiency so the only recommendation"
"we expect here is for an air source heat pump. The heating controls are a programmer, room thermostat"
"and TRVs and so we should expect a TTZC recommendation"
@ -93,11 +86,10 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 10012342725.0,
'uprn-source': 'Address Matched',
},
"heating_recommendation_descriptions": [
"Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention "
"Storage Heater Controls"
"heating_measure_types": [
"high_heat_retention_storage_heater",
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has electric room heaters and is off gas so a boiler recommendation is not appropriate."
"We would expect a high heat retention storage recommendation. The property is a flat and therefore"
"we don't expect an air source heat pump recommendation. We also wouldn't expect a specific heating"
@ -144,16 +136,8 @@ testing_examples = [
'tenure': 'owner-occupied', 'fixed-lighting-outlets-count': 6.0, 'low-energy-fixed-light-count': 4.0,
'uprn': 100090311351.0, 'uprn-source': 'Address Matched', 'property-type_y': None, 'built-form_y': None,
},
"heating_recommendation_descriptions": [
'Install high heat retention electric storage heaters. The current electric heaters may be retrofit with '
'high heat retention storage controls however this is dependent on the existing system and may not be '
'possible. Upgrade heating controls to High Heat Retention Storage Heater Controls',
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant'
],
"heating_controls_recommendation_descriptions": [],
"heating_measure_types": ['high_heat_retention_storage_heater', 'air_source_heat_pump'],
"heating_controls_measure_types": [],
"notes": "This test has electric storage heaters with automatic charge control - we recommend hhr storage"
"heaters in this case, but because there are already electic storage heaters in place, we "
"note, in the description of the recommendation, that this upgrade may be possible by retrofitting"
@ -197,13 +181,10 @@ testing_examples = [
'tenure': 'owner-occupied', 'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None,
'uprn': 100021560521.0, 'uprn-source': 'Address Matched',
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler.'
],
"heating_controls_recommendation_descriptions": [
'Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade heating controls to Smart Thermostats, room sensors and smart radiator valves (time & '
'temperature zone control)'
"heating_measure_types": ['boiler_upgrade'],
"heating_controls_measure_types": [
'roomstat_programmer_trvs',
'time_temperature_zone_control',
],
"notes": "Because of this property is a maisonette, which already has a boiler (but an inefficient one due to "
"the current water heating efficiency) the only recommendation we expect is for "
@ -250,12 +231,10 @@ testing_examples = [
'tenure': 'owner-occupied', 'fixed-lighting-outlets-count': 9.0, 'low-energy-fixed-light-count': 5.0,
'uprn': 100021936225.0, 'uprn-source': 'Address Matched',
},
"heating_recommendation_descriptions": [
],
"heating_controls_recommendation_descriptions": [
'Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade heating controls to Smart Thermostats, room sensors and smart radiator valves (time & '
'temperature zone control)'
"heating_measure_types": [],
"heating_controls_measure_types": [
'roomstat_programmer_trvs',
'time_temperature_zone_control',
],
"notes": "Because this property already has a boiler, we don't recommend HHR. We don't recommend an ashp "
"because the home is mid-terraced. Because the heating controls are "
@ -302,11 +281,10 @@ testing_examples = [
'tenure': 'rental (private)', 'fixed-lighting-outlets-count': 7.0, 'low-energy-fixed-light-count': 6.0,
'uprn': 43088770.0, 'uprn-source': 'Address Matched',
},
"heating_recommendation_descriptions": [
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property is a flat so we don't have an ASHP recommendation. It also doesn't have access to the "
"mains and so it can't have a gas boiler. We don't expect any controls recommendations"
},
@ -348,16 +326,10 @@ testing_examples = [
'tenure': 'owner-occupied', 'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None,
'uprn': 100080513604.0, 'uprn-source': 'Address Matched'
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant'
],
"heating_controls_recommendation_descriptions": [
'Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade heating controls to Smart Thermostats, room sensors and smart radiator valves (time & '
'temperature zone control)'
"heating_measure_types": ['air_source_heat_pump'],
"heating_controls_measure_types": [
'roomstat_programmer_trvs',
'time_temperature_zone_control',
],
"notes": "This has a very efficient boiler and is a detached bungalow, but only has "
"Programmer and room thermostat for heating controls so we'd expect an ASHP heating recommendation"
@ -404,14 +376,12 @@ testing_examples = [
'fixed-lighting-outlets-count': 10.0, 'low-energy-fixed-light-count': 9.0, 'uprn': 100070358594,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and smart '
'radiator valves (time & temperature zone control)'
"heating_measure_types": [
'boiler_upgrade',
'high_heat_retention_storage_heater',
'boiler_upgrade'
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has assumed electric heating and is mid-terrace house. It has a mains gas connection."
"We can recommend a boiler upgrade and high heat retention storage heaters"
},
@ -453,15 +423,11 @@ testing_examples = [
'fixed-lighting-outlets-count': 42.0, 'low-energy-fixed-light-count': 13.0, 'uprn': 100070985545,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has an oil boiler and doesn't have a mains gas connection so we can only recommend"
"an air source heat pump and HHR (since if the home has a non-gas boiler, we recommend HHR)"
},
@ -505,17 +471,13 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 2465031849,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls',
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control)'
"heating_measure_types": [
'boiler_upgrade',
'high_heat_retention_storage_heater',
'air_source_heat_pump',
'boiler_upgrade' # TTZs
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has room heaters, from the mains gas supply. We recommend a boiler upgrade as"
"well as an air source heat pump and HHR (since the home has a room heater set up)"
},
@ -558,14 +520,12 @@ testing_examples = [
'uprn-source': 'Energy Assessor', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and smart '
'radiator valves (time & temperature zone control)',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls',
"heating_measure_types": [
'boiler_upgrade',
'boiler_upgrade',
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has assumed electric heaters. Boiler upgrade, HHR are recommended. We don't recommend"
"an ASHP off of the bat because it's mid-terrace."
},
@ -607,14 +567,12 @@ testing_examples = [
'fixed-lighting-outlets-count': 10.0, 'low-energy-fixed-light-count': None, 'uprn': 100071089116,
'uprn-source': 'Energy Assessor', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control)'
"heating_measure_types": [
'boiler_upgrade',
'high_heat_retention_storage_heater',
'boiler_upgrade'
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This has a form of assumed electric heating and has a mains connection so we recommend HHR, boiler"
"upgrade and ASHP"
},
@ -657,15 +615,12 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 100030352255,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and smart '
'radiator valves (time & temperature zone control)',
'Install high heat retention electric storage heaters. The current electric heaters may be retrofit with '
'high heat retention storage controls however this is dependent on the existing system and may not be '
'possible. Upgrade heating controls to High Heat Retention Storage Heater Controls'
"heating_measure_types": [
'boiler_upgrade',
'boiler_upgrade',
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property already has storage heaters with manual charge control. The home is mid terrace so"
"the ashp is not suitable"
},
@ -709,14 +664,11 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 10009573249,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls',
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant'
"heating_measure_types": [
'high_heat_retention_storage_heater',
'air_source_heat_pump',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has an LFG boiler but it doesn't have a mains gas connection so we can only recommend"
"an air source heat pump and hhr storage"
},
@ -758,14 +710,11 @@ testing_examples = [
'fixed-lighting-outlets-count': 8.0, 'low-energy-fixed-light-count': None, 'uprn': 10013181470,
'uprn-source': 'Energy Assessor', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls',
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant'
"heating_measure_types": [
'high_heat_retention_storage_heater',
'air_source_heat_pump',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has electric boilers in place, but does not have a mains connection so we don't "
"recommend a boiler upgrade. We recommend HHR and ASHP"
},
@ -809,14 +758,11 @@ testing_examples = [
'fixed-lighting-outlets-count': 11.0, 'low-energy-fixed-light-count': 7.0, 'uprn': 452047507,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'high_heat_retention_storage_heater'
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has a dual fuel boiler and no mains gas connection. We recommend ASHP and HHR, but"
"no gas condensing boiler"
},
@ -857,14 +803,11 @@ testing_examples = [
'fixed-lighting-outlets-count': 16.0, 'low-energy-fixed-light-count': 4.0, 'uprn': 100030309413,
'uprn-source': 'Energy Assessor', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has a coal boiler and no mains gas connection. We recommend ASHP and HHR, but"
"no gas condensing boiler"
},
@ -908,15 +851,11 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 10007366417,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has a smokeless fuel boiler and no mains gas connection. We recommend ASHP and HHR, but"
"no gas condensing boiler"
},
@ -958,15 +897,11 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 100030256931,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has a wood pellets boiler and no mains gas connection. We recommend ASHP and HHR, but"
"no gas condensing boiler"
},
@ -1009,11 +944,10 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 10000460605,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'high_heat_retention_storage_heater',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This is an end-terrace house, without mains gas connection, so all we recommend is HHR"
},
{
@ -1054,8 +988,8 @@ testing_examples = [
'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None, 'uprn': 100031045596,
'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [],
"heating_controls_recommendation_descriptions": [],
"heating_measure_types": [],
"heating_controls_measure_types": [],
"notes": "This property already has an ashp. We don't recommend any heating upgrades"
},
{
@ -1095,17 +1029,12 @@ testing_examples = [
'tenure': 'Rented (social)', 'fixed-lighting-outlets-count': 11.0, 'low-energy-fixed-light-count': None,
'uprn': 90041166, 'uprn-source': 'Energy Assessor', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Install high heat retention electric storage heaters alongside the boiler. The current electric heaters '
'may be retrofit with high heat retention storage controls however this is dependent on the existing '
'system and may not be possible. Upgrade heating controls to High Heat Retention Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'high_heat_retention_storage_heater'
],
"heating_controls_recommendation_descriptions": [
'Upgrade heating controls to Smart Thermostats, room sensors and smart radiator valves (time & '
'temperature zone control)'
"heating_controls_measure_types": [
'time_temperature_zone_control',
],
"notes": "This property has dual heating. A boiler and electric storage heaters. The heating is efficient so"
"we recommend ASHP and HHR. We also recommend upgrading the heating controls for the boiler"
@ -1147,20 +1076,14 @@ testing_examples = [
'tenure': 'Rented (social)', 'fixed-lighting-outlets-count': 11.0, 'low-energy-fixed-light-count': None,
'uprn': 90041166, 'uprn-source': 'Energy Assessor', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Upgrade the existing boiler to a new, more efficient condensing boiler. ',
'Upgrade both the existing boiler to a new condensing boiler and upgrade storage heaters to high heat '
'retention storage heaters.',
'Install high heat retention electric storage heaters alongside the boiler. The current electric heaters '
'may be retrofit with high heat retention storage controls however this is dependent on the existing '
'system and may not be possible. Upgrade heating controls to High Heat Retention Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'boiler_upgrade',
'boiler_upgrade+high_heat_retention_storage_heater',
'high_heat_retention_storage_heater'
],
"heating_controls_recommendation_descriptions": [
'Upgrade heating controls to Smart Thermostats, room sensors and smart radiator valves (time & '
'temperature zone control)'
"heating_controls_measure_types": [
'time_temperature_zone_control'
],
"notes": "This property is a modified version of the previous dual heating property, where we lower the"
"starting heating efficiency so that we a combined heating upgrade to both the boiler and the electric"
@ -1204,14 +1127,11 @@ testing_examples = [
'tenure': 'rental (social)', 'fixed-lighting-outlets-count': None, 'low-energy-fixed-light-count': None,
'uprn': 10009574286, 'uprn-source': 'Address Matched', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'high_heat_retention_storage_heater'
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has anthracite heating without mains. "
"We recommend ASHP and HHR, but no gas condensing boiler"
},
@ -1254,14 +1174,12 @@ testing_examples = [
'fixed-lighting-outlets-count': 8.0, 'low-energy-fixed-light-count': None, 'uprn': 100031556691,
'uprn-source': 'Energy Assessor', 'sheating-energy-eff': None, 'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and smart '
'radiator valves (time & temperature zone control)',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'boiler_upgrade',
'boiler_upgrade',
'high_heat_retention_storage_heater'
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has room heaters with two different fuel sources, so we recommend HHR, ASHP, and a "
"boiler upgrade"
},
@ -1302,11 +1220,10 @@ testing_examples = [
'uprn': 100070685908, 'uprn-source': 'Address Matched', 'sheating-energy-eff': None,
'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'high_heat_retention_storage_heater'
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property is a flag, without mains gas connection. Currently has underfloor electric heating"
"so we recommend HHR"
},
@ -1348,17 +1265,13 @@ testing_examples = [
'uprn': 100071209105, 'uprn-source': 'Address Matched', 'sheating-energy-eff': None,
'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Install an air source heat pump, and upgrade heating controls to Smart Thermostats, room sensors and '
'smart radiator valves (time & temperature zone control). The cost includes the £7500 boiler upgrade '
'scheme grant',
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and smart '
'radiator valves (time & temperature zone control)',
'Install high heat retention electric storage heaters. Upgrade heating controls to High Heat Retention '
'Storage Heater Controls'
"heating_measure_types": [
'air_source_heat_pump',
'boiler_upgrade',
'boiler_upgrade',
'high_heat_retention_storage_heater'
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "The property has warm air electricaire heating, so we recommend ASHP and HHR. It also has a mains"
"connection so we recommend a gas condensing boiler"
},
@ -1402,12 +1315,11 @@ testing_examples = [
'uprn': 100070955137, 'uprn-source': 'Address Matched', 'sheating-energy-eff': None,
'sheating-env-eff': None
},
"heating_recommendation_descriptions": [
'Upgrade to a new condensing boiler. Upgrade heating controls to Room thermostat, programmer and TRVs',
'Upgrade to a new condensing boiler. Upgrade heating controls to Smart Thermostats, room sensors and smart '
'radiator valves (time & temperature zone control)'
"heating_measure_types": [
'boiler_upgrade',
'boiler_upgrade',
],
"heating_controls_recommendation_descriptions": [],
"heating_controls_measure_types": [],
"notes": "This property has warm air mains gas heating, so we recommend a gas condensing boiler"
}
]

View file

@ -96,19 +96,19 @@ class TestHeatingRecommendations:
recommender.recommend(has_cavity_or_loft_recommendations=False)
assert len(recommender.heating_recommendations) == len(test_case["heating_recommendation_descriptions"])
assert len(recommender.heating_recommendations) == len(test_case["heating_measure_types"])
assert (
len(recommender.heating_control_recommendations) ==
len(test_case["heating_controls_recommendation_descriptions"])
len(test_case["heating_controls_measure_types"])
)
# Check the exact descriptions
# Check the exact measure types
assert (
{x["description"] for x in recommender.heating_recommendations} ==
set(test_case["heating_recommendation_descriptions"])
{x["measure_type"] for x in recommender.heating_recommendations} ==
set(test_case["heating_measure_types"])
)
assert (
{x["description"] for x in recommender.heating_control_recommendations} ==
set(test_case["heating_controls_recommendation_descriptions"])
{x["measure_type"] for x in recommender.heating_control_recommendations} ==
set(test_case["heating_controls_measure_types"])
)

View file

@ -231,6 +231,15 @@ class TestRecommendationUtils:
expected_uvalue = test_case["uvalue"]
inputs = test_case.copy()
del inputs["uvalue"]
# insulation_thickness = inputs["insulation_thickness"]
# has_dwelling_above = inputs["has_dwelling_above"]
# is_loft = inputs["is_loft"]
# is_roof_room = inputs["is_roof_room"]
# is_thatched = inputs["is_thatched"]
# age_band = inputs["age_band"]
# is_flat = inputs["is_flat"]
# is_pitched = inputs["is_pitched"]
# is_at_rafters = inputs["is_at_rafters"]
uvalue = recommendation_utils.get_roof_u_value(**inputs)
assert expected_uvalue == uvalue, f"Expected u value {expected_uvalue}, recieved {uvalue}"

View file

@ -35,7 +35,7 @@ class TestRoofRecommendations:
def test_loft_insulation_recommendation_50mm_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Kent"}
epc_record.prepared_epc = {"county": "Kent", "roof-energy-eff": "Very Poor"}
property_instance2 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance2.age_band = "F"
property_instance2.insulation_floor_area = 100
@ -63,7 +63,7 @@ class TestRoofRecommendations:
assert roof_recommender2.recommendations[0]["parts"][0]["depth"] == 270
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Greater London Authority"}
epc_record.prepared_epc = {"county": "Greater London Authority", "roof-energy-eff": "Very Poor"}
property_instance3 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance3.age_band = "F"
property_instance3.insulation_floor_area = 100
@ -89,7 +89,7 @@ class TestRoofRecommendations:
def test_loft_insulation_recommendation_150mm_insulation(self):
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "North East Lincolnshire"}
epc_record.prepared_epc = {"county": "North East Lincolnshire", "roof-energy-eff": "Good"}
property_instance4 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance4.age_band = "F"
property_instance4.insulation_floor_area = 100
@ -117,7 +117,7 @@ class TestRoofRecommendations:
assert roof_recommender4.recommendations[0]["parts"][0]["depth"] == 200
epc_record = EPCRecord()
epc_record.prepared_epc = {"county": "Somerset"}
epc_record.prepared_epc = {"county": "Somerset", "roof-energy-eff": "Good"}
property_instance5 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
property_instance5.age_band = "F"
property_instance5.insulation_floor_area = 100
@ -189,8 +189,8 @@ class TestRoofRecommendations:
roof_recommender7.recommend(phase=0)
assert len(roof_recommender7.recommendations) == 1
assert roof_recommender7.recommendations[0]["new_u_value"] == 0.23
assert roof_recommender7.recommendations[0]["starting_u_value"] == 1.5
assert roof_recommender7.recommendations[0]["new_u_value"] == 0.24
assert roof_recommender7.recommendations[0]["starting_u_value"] == 2.3
assert roof_recommender7.recommendations[0]["description"] == "Insulate room in roof at rafters and re-decorate"
def test_ceiling_insulated_room_in_roof(self):