mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
preparing partiy class
This commit is contained in:
parent
f4f9fc5b19
commit
ae02561cd0
17 changed files with 859 additions and 825 deletions
|
|
@ -3,7 +3,39 @@ from utils.s3 import read_from_s3
|
|||
|
||||
|
||||
class OnboarderBase:
|
||||
# Input dataset to be transformed
|
||||
data: pd.DataFrame | None = None
|
||||
# Description columns
|
||||
landlord_wall_construction: str = "landlord_wall_construction"
|
||||
landlord_roof_construction: str = "landlord_roof_construction"
|
||||
landlord_floor_construction: str = "landlord_floor_construction"
|
||||
landlord_windows_construction: str = "landlord_windows_construction"
|
||||
landlord_heating_construction: str = "landlord_heating_construction"
|
||||
landlord_fuel_construction: str = "landlord_fuel_construction"
|
||||
landlord_heating_controls_construction: str = "landlord_heating_controls_construction"
|
||||
landlord_hot_water_system_construction: str = "landlord_hot_water_system_construction"
|
||||
|
||||
# Efficiency columns
|
||||
landlord_roof_efficiency: str = "landlord_roof_efficiency"
|
||||
landlord_windows_efficiency: str = "landlord_windows_efficiency"
|
||||
landlord_heating_controls_efficiency: str = "landlord_heating_controls_efficiency"
|
||||
landlord_heating_efficiency: str = "landlord_heating_efficiency"
|
||||
landlord_hot_water_efficiency: str = "landlord_hot_water_efficiency"
|
||||
landlord_wall_efficiency: str = "landlord_wall_efficiency"
|
||||
|
||||
# Additional windows features
|
||||
landlord_multi_glaze_proportion: str = "landlord_multi_glaze_proportion"
|
||||
landlord_glazed_type: str = "landlord_glazed_type"
|
||||
landlord_glazed_area: str = "landlord_glazed_area"
|
||||
|
||||
# Additional roof features
|
||||
landlord_has_sloping_ceiling: str = "landlord_has_sloping_ceiling"
|
||||
|
||||
# Shape, dimensions, age
|
||||
landlord_total_floor_area_m2: str = "landlord_total_floor_area_m2"
|
||||
landlord_construction_age_band: str = "landlord_construction_age_band"
|
||||
landlord_property_type: str = "landlord_property_type"
|
||||
landlord_built_form: str = "landlord_built_form"
|
||||
|
||||
def read_s3(self, bucket_name: str, file_name: str):
|
||||
self.data = read_from_s3(bucket_name=bucket_name, s3_file_name=file_name)
|
||||
|
|
@ -27,4 +59,6 @@ class OnboarderBase:
|
|||
assert pd.isnull(data[column]).sum() == 0, f"column {column} contains null values, but should not"
|
||||
|
||||
def map_construction_age_band(self):
|
||||
pass
|
||||
raise NotImplementedError(
|
||||
"This method should be implemented by subclasses to map construction age bands to descriptions"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -511,19 +511,3 @@ def resolve_roof_efficiency(
|
|||
except TypeError:
|
||||
# Fallback to (age_band)
|
||||
return rule(age_band)
|
||||
|
||||
|
||||
class EpcFloorDescriptions(Enum):
|
||||
# Solid floor
|
||||
solid_insulated = "Solid, insulated"
|
||||
solid_insulated_assumed = "Solid, insulated (assumed)"
|
||||
solid_no_insulation_assumed = "Solid, no insulation (assumed)"
|
||||
solid_limited_insulation_assumed = "Solid, limited insulation (assumed)"
|
||||
|
||||
# Suspended floor
|
||||
suspended_insulated = "Suspended, insulated"
|
||||
suspended_insulated_assumed = "Suspended, insulated (assumed)"
|
||||
suspended_no_insulation_assumed = "Suspended, no insulation (assumed)"
|
||||
suspended_limited_insulation_assumed = "Suspended, limited insulation (assumed)"
|
||||
|
||||
unknown = None # We don't resolve anything
|
||||
|
|
|
|||
0
backend/onboarders/handler.py
Normal file
0
backend/onboarders/handler.py
Normal file
26
backend/onboarders/mappings/parity/floor.py
Normal file
26
backend/onboarders/mappings/parity/floor.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
from numpy import nan
|
||||
from datatypes.epc.floor import EpcFloorDescriptions
|
||||
|
||||
floor_map = {
|
||||
# Solid floor
|
||||
('Solid', 'AsBuilt'): None, # Mapped
|
||||
('Solid', 'Unknown'): None, # Mapped
|
||||
('Solid', nan): None, # Mapped
|
||||
('Solid', 'RetroFitted'): EpcFloorDescriptions.solid_insulated,
|
||||
|
||||
# Suspended floor
|
||||
('SuspendedTimber', nan): None, # Mapped suspended_floor_as_built
|
||||
('SuspendedTimber', 'AsBuilt'): None, # Mapped suspended_floor_as_built
|
||||
('SuspendedTimber', 'RetroFitted'): EpcFloorDescriptions.suspended_insulated,
|
||||
('SuspendedTimber', 'Unknown'): None, # Mapped suspended_floor_as_built
|
||||
('SuspendedNotTimber', 'RetroFitted'): EpcFloorDescriptions.suspended_insulated,
|
||||
('SuspendedNotTimber', nan): None, # Mapped suspended_floor_as_built
|
||||
('SuspendedNotTimber', 'Unknown'): None, # Mapped suspended_floor_as_built
|
||||
('SuspendedNotTimber', 'AsBuilt'): None, # Mapped suspended_floor_as_built
|
||||
|
||||
# Unknown type - mapped on age
|
||||
('Unknown', 'Unknown'): None, # Mapped unknown_floor_as_built
|
||||
('Unknown', 'RetroFitted'): None, # Mapped unknown_floor_retrofitted
|
||||
(nan, nan): None, # No actual information!
|
||||
('Unknown', 'AsBuilt'): None, # Mapped unknown_floor_as_built
|
||||
}
|
||||
20
backend/onboarders/mappings/parity/glazing.py
Normal file
20
backend/onboarders/mappings/parity/glazing.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from datatypes.epc.efficiency import EpcEfficiency
|
||||
|
||||
glazing_map = {
|
||||
# (description, energy efficiency, multi_glaze_proportion, glazed_type, glazed_area
|
||||
# For SAP 10 assessments, The glazed type and glazed area are not populated in the EPC API data any more
|
||||
"Double 2002 or later": ("Fully double glazed", EpcEfficiency.AVERAGE, 1, None, None),
|
||||
"Double before 2002": ("Fully double glazed", EpcEfficiency.POOR, 1, None, None),
|
||||
"Double but age unknown": ("Fully double glazed", EpcEfficiency.POOR, 1, None, None),
|
||||
"Single": ("Single glazed", EpcEfficiency.VERY_POOR, 0, None, None),
|
||||
# For triple glazing, with age unknown, the performance is only average, whereas if it's a post 2022
|
||||
# installation, it's classed as high performance glazing with good efficiency. We'll need to be considerate as to
|
||||
# how we make updates to the windows data.
|
||||
# Triple known data is high performance glazing with Good efficiency (at least)
|
||||
"Triple": ("Fully triple glazed", EpcEfficiency.AVERAGE, 1, None, None),
|
||||
# This is also classed as high performance glazing
|
||||
"DoubleKnownData": ("High performance glazing", EpcEfficiency.GOOD, 1, None, None),
|
||||
# Under SAP 10, secondary glazing is classed as poor efficiency (whereas under SAP 2012 it was generally good)
|
||||
"Secondary": ("Full secondary glazing", EpcEfficiency.POOR, 1, None, None),
|
||||
"TripleKnownData": ("High performance glazing", EpcEfficiency.GOOD, 1, None, None),
|
||||
}
|
||||
330
backend/onboarders/mappings/parity/heating.py
Normal file
330
backend/onboarders/mappings/parity/heating.py
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
from datatypes.epc.main_heating import EpcHeatingSystems
|
||||
from datatypes.epc.efficiency import EpcEfficiency
|
||||
from datatypes.epc.fuel import EpcFuel
|
||||
from datatypes.epc.heating_controls import EpcHeatingControls
|
||||
from datatypes.epc.hotwater import EpcHotWaterSystems
|
||||
|
||||
heating_map = {
|
||||
# 0
|
||||
('Boilers', 'A', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_electric, EpcEfficiency.VERY_POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 1
|
||||
('Boilers', 'A', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_electric, EpcEfficiency.VERY_POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 2
|
||||
('Boilers', 'A', 'ElectricityNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_electric, EpcEfficiency.VERY_POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 3
|
||||
('Boilers', 'A', 'LPGNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_lpg, EpcEfficiency.POOR, EpcFuel.lpg_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 4
|
||||
('Boilers', 'A', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.VERY_GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 5
|
||||
('Boilers', 'A', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.VERY_GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 6
|
||||
('Boilers', 'A', 'MainsGasNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.VERY_GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 7
|
||||
('Boilers', 'B', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 8
|
||||
('Boilers', 'B', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 9
|
||||
('Boilers', 'B', 'MainsGasNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 10
|
||||
('Boilers', 'C', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_electric, EpcEfficiency.VERY_POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 11
|
||||
('Boilers', 'C', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_electric, EpcEfficiency.VERY_POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 12
|
||||
('Boilers', 'C', 'ElectricityNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_electric, EpcEfficiency.VERY_POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 13
|
||||
('Boilers', 'C', 'LPGNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_lpg, EpcEfficiency.POOR, EpcFuel.lpg_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 14
|
||||
('Boilers', 'C', 'LPGNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_lpg, EpcEfficiency.POOR, EpcFuel.lpg_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 15
|
||||
('Boilers', 'C', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 16
|
||||
('Boilers', 'C', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 17
|
||||
('Boilers', 'C', 'MainsGasNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Boilers', 'C', 'OilNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_oil, EpcEfficiency.AVERAGE, EpcFuel.oil_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 19
|
||||
('Boilers', 'C', 'OilNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_oil, EpcEfficiency.AVERAGE, EpcFuel.oil_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 20
|
||||
('Boilers', 'C', 'OilNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_oil, EpcEfficiency.AVERAGE, EpcFuel.oil_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 21
|
||||
('Boilers', 'D', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 22
|
||||
('Boilers', 'D', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 23
|
||||
('Boilers', 'D', 'MainsGasNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 24
|
||||
('Boilers', 'E', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_and_radiators_electric, EpcEfficiency.VERY_POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 25
|
||||
('Boilers', 'E', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 26
|
||||
('Boilers', 'E', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 27
|
||||
('Boilers', 'E', 'MainsGasNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 28
|
||||
('Boilers', 'E', 'OilNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_oil, EpcEfficiency.AVERAGE, EpcFuel.oil_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 29
|
||||
('Boilers', 'E', 'OilNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_oil, EpcEfficiency.AVERAGE, EpcFuel.oil_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 30
|
||||
('Boilers', 'F', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 31
|
||||
('Boilers', 'F', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 32
|
||||
('Boilers', 'F', 'MainsGasNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 33
|
||||
('Boilers', 'G', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 34
|
||||
('Boilers', 'G', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 35
|
||||
('Boilers', 'G', 'MainsGasNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.boiler_radiators_mains_gas, EpcEfficiency.AVERAGE, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 36
|
||||
('Electric underfloor', 'A', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.electric_underfloor_heating, EpcEfficiency.AVERAGE, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 37
|
||||
('Electric underfloor', 'A', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.electric_underfloor_heating, EpcEfficiency.AVERAGE, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 38
|
||||
('Electric underfloor', 'A', 'ElectricityNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.electric_underfloor_heating, EpcEfficiency.AVERAGE, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 39
|
||||
('Heat pumps (warm air)', 'A', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.air_to_air_ashp, EpcEfficiency.AVERAGE, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 40
|
||||
('Heat pumps (warm air)', 'A', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.air_to_air_ashp, EpcEfficiency.AVERAGE, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 41
|
||||
('Heat pumps (wet)', 'A', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.ashp_radiators_electric, EpcEfficiency.GOOD, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_room_thermostat_trvs, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 42
|
||||
('Heat pumps (wet)', 'A', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.ashp_radiators_electric, EpcEfficiency.GOOD, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmers_trvs_bypass, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 43
|
||||
('Heat pumps (wet)', 'A', 'ElectricityNotCommunity', 'Top Spec'): (
|
||||
EpcHeatingSystems.ashp_radiators_electric, EpcEfficiency.GOOD, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.time_and_temperature_zone_control, EpcEfficiency.VERY_GOOD,
|
||||
EpcHotWaterSystems.from_main_system, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 44
|
||||
('Room heaters', 'A', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.room_heaters_electric, EpcEfficiency.POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_and_appliance_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 45
|
||||
('Room heaters', 'A', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.room_heaters_electric, EpcEfficiency.POOR, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.appliance_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 46
|
||||
('Room heaters', 'C', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.room_heaters_mains_gas, EpcEfficiency.AVERAGE, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.appliance_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
# 47 - water done from here
|
||||
('Room heaters', 'F', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.room_heaters_mains_gas, EpcEfficiency.POOR, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.appliance_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Room heaters', 'G', 'MainsGasNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.room_heaters_mains_gas, EpcEfficiency.POOR, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_and_appliance_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Room heaters', 'G', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.room_heaters_mains_gas, EpcEfficiency.POOR, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.appliance_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Room heaters', 'G', 'SmokelessCoal', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.room_heaters_smokeless_fuel, EpcEfficiency.VERY_POOR, EpcFuel.smokeless_coal,
|
||||
EpcHeatingControls.appliance_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Storage heaters', 'A', 'ElectricityNotCommunity', 'Optimal'): (
|
||||
EpcHeatingSystems.electric_storage_heaters, EpcEfficiency.AVERAGE, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.automatic_charge_control, EpcEfficiency.AVERAGE,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Storage heaters', 'A', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.electric_storage_heaters, EpcEfficiency.AVERAGE, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.manual_charge_control, EpcEfficiency.POOR,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Warm Air (not heat pump)', 'G', 'ElectricityNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.warm_air_electricaire, EpcEfficiency.GOOD, EpcFuel.electricity_not_community,
|
||||
EpcHeatingControls.programmer_and_atleast_two_room_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
),
|
||||
('Warm Air (not heat pump)', 'G', 'MainsGasNotCommunity', 'Sub Optimal'): (
|
||||
EpcHeatingSystems.warm_air_mains_gas, EpcEfficiency.GOOD, EpcFuel.mains_gas_not_community,
|
||||
EpcHeatingControls.programmer_and_atleast_two_room_thermostats, EpcEfficiency.GOOD,
|
||||
EpcHotWaterSystems.electric_immersion_off_peak, EpcEfficiency.AVERAGE
|
||||
)
|
||||
}
|
||||
103
backend/onboarders/mappings/parity/roof.py
Normal file
103
backend/onboarders/mappings/parity/roof.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
from numpy import nan
|
||||
from datatypes.epc.roof import EpcRoofDescriptions
|
||||
|
||||
roof_map = {
|
||||
# Dwelling above
|
||||
('AnotherDwellingAbove', 'Another Dwelling Above'): EpcRoofDescriptions.another_dwelling_above,
|
||||
('SameDwellingAbove', 'Same Dwelling Above'): EpcRoofDescriptions.another_dwelling_above,
|
||||
# Pitched, normal loft access, with a loft thickness
|
||||
('PitchedNormalLoftAccess', 'mm25'): EpcRoofDescriptions.loft_25mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm50'): EpcRoofDescriptions.loft_50mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm75'): EpcRoofDescriptions.loft_75mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm100'): EpcRoofDescriptions.loft_100mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm150'): EpcRoofDescriptions.loft_150mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm200'): EpcRoofDescriptions.loft_200mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm250'): EpcRoofDescriptions.loft_250mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm270'): EpcRoofDescriptions.loft_270mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm300'): EpcRoofDescriptions.loft_300mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm350'): EpcRoofDescriptions.loft_350mm_insulation,
|
||||
('PitchedNormalLoftAccess', 'mm400'): EpcRoofDescriptions.loft_400mm_plus_insulation,
|
||||
|
||||
# Pitched, no loft access, with a loft thickness
|
||||
('PitchedNormalNoLoftAccess', 'mm25'): EpcRoofDescriptions.loft_25mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm50'): EpcRoofDescriptions.loft_50mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm75'): EpcRoofDescriptions.loft_75mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm100'): EpcRoofDescriptions.loft_100mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm150'): EpcRoofDescriptions.loft_150mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm200'): EpcRoofDescriptions.loft_200mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm250'): EpcRoofDescriptions.loft_250mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm270'): EpcRoofDescriptions.loft_270mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm300'): EpcRoofDescriptions.loft_300mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm350'): EpcRoofDescriptions.loft_350mm_insulation,
|
||||
('PitchedNormalNoLoftAccess', 'mm400'): EpcRoofDescriptions.loft_400mm_plus_insulation,
|
||||
|
||||
# All pitched options with asbuilt or unknown got to EpcRoofDescriptions.pitched_insulated_assumed
|
||||
# With access
|
||||
('PitchedNormalLoftAccess', nan): EpcRoofDescriptions.pitched_insulated_assumed,
|
||||
('PitchedNormalLoftAccess', 'AsBuilt'): EpcRoofDescriptions.pitched_insulated_assumed,
|
||||
('PitchedNormalLoftAccess', 'Unknown'): EpcRoofDescriptions.pitched_insulated_assumed,
|
||||
# No access
|
||||
('PitchedNormalNoLoftAccess', nan): EpcRoofDescriptions.pitched_insulated_assumed,
|
||||
('PitchedNormalNoLoftAccess', 'AsBuilt'): EpcRoofDescriptions.pitched_insulated_assumed,
|
||||
('PitchedNormalNoLoftAccess', 'Unknown'): EpcRoofDescriptions.pitched_insulated_assumed,
|
||||
|
||||
# Flat
|
||||
('Flat', 'NoInsulation'): EpcRoofDescriptions.flat_no_insulation,
|
||||
# Flat - limited insulation
|
||||
('Flat', '12mm'): EpcRoofDescriptions.flat_limited_insulation,
|
||||
('Flat', 'mm25'): EpcRoofDescriptions.flat_limited_insulation,
|
||||
('Flat', 'mm50'): EpcRoofDescriptions.flat_limited_insulation,
|
||||
# Flat insulated
|
||||
('Flat', 'mm75'): EpcRoofDescriptions.flat_insulated,
|
||||
('Flat', 'mm100'): EpcRoofDescriptions.flat_insulated,
|
||||
('Flat', 'mm150'): EpcRoofDescriptions.flat_insulated,
|
||||
('Flat', 'mm200'): EpcRoofDescriptions.flat_insulated,
|
||||
('Flat', 'mm250'): EpcRoofDescriptions.flat_insulated,
|
||||
('Flat', 'mm300'): EpcRoofDescriptions.flat_insulated,
|
||||
('Flat', 'mm350'): EpcRoofDescriptions.flat_insulated,
|
||||
('Flat', 'mm400'): EpcRoofDescriptions.flat_insulated,
|
||||
# Flat - as built or unknown
|
||||
('Flat', 'AsBuilt'): None, # To be classified
|
||||
('Flat', nan): None, # To be classified
|
||||
('Flat', 'Unknown'): None, # To be classified
|
||||
|
||||
# 12mm = very poor & has limited insulation description
|
||||
# 25, 50 = poor & has limited insulation description
|
||||
# 75, 100, 125mm = average (Flat, insulated)
|
||||
# 150, 175, 200, 225, 250mm = good (Flat, insulated)
|
||||
# 270mm+ = very good (Flat, insulated)
|
||||
|
||||
# Thatched
|
||||
('PitchedThatched', 'mm50'): EpcRoofDescriptions.thatched_with_additional_insulation,
|
||||
('PitchedThatched', 'mm150'): EpcRoofDescriptions.thatched_with_additional_insulation,
|
||||
('PitchedThatched', 'mm300'): EpcRoofDescriptions.thatched_with_additional_insulation,
|
||||
('PitchedThatched', 'Unknown'): EpcRoofDescriptions.thatched, # efficiency classified based on age
|
||||
|
||||
# Sloping:
|
||||
# Limited (12 very poor, 25-50 poor)
|
||||
('PitchedWithSlopingCeiling', 'mm12'): EpcRoofDescriptions.sloping_pitched_limited_insulation,
|
||||
('PitchedWithSlopingCeiling', 'mm25'): EpcRoofDescriptions.sloping_pitched_limited_insulation,
|
||||
('PitchedWithSlopingCeiling', 'mm50'): EpcRoofDescriptions.sloping_pitched_limited_insulation,
|
||||
# Insulated 75mm+ (75 - 125 average, 150 - 250 good, 270+ very good)
|
||||
('PitchedWithSlopingCeiling', 'mm75'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm100'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm150'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm200'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm250'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm270'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm300'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm350'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
('PitchedWithSlopingCeiling', 'mm400'): EpcRoofDescriptions.sloping_pitched_insulated,
|
||||
# As built/unknown
|
||||
('PitchedWithSlopingCeiling', 'AsBuilt'): None, # To be classified
|
||||
('PitchedWithSlopingCeiling', nan): None, # To be classified
|
||||
('PitchedWithSlopingCeiling', 'Unknown'): None, #
|
||||
}
|
||||
|
||||
roof_unknown_age_fallback = {
|
||||
"Flat": EpcRoofDescriptions.flat_as_built_unknown,
|
||||
"PitchedWithSlopingCeiling": EpcRoofDescriptions.sloping_pitched_as_built_unknown,
|
||||
"PitchedThatched": EpcRoofDescriptions.thatched_as_built_unknown,
|
||||
"PitchedNormalLoftAccess": EpcRoofDescriptions.loft_as_built_unknown,
|
||||
"PitchedNormalNoLoftAccess": EpcRoofDescriptions.loft_as_built_unknown,
|
||||
}
|
||||
56
backend/onboarders/mappings/parity/walls.py
Normal file
56
backend/onboarders/mappings/parity/walls.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
from datatypes.epc.walls import EpcWallDescriptions
|
||||
|
||||
# Unique combinations
|
||||
wall_map = {
|
||||
# Cavity walls
|
||||
('Cavity', 'FilledCavity'): EpcWallDescriptions.cavity_filled_cavity,
|
||||
('Cavity', 'Internal'): EpcWallDescriptions.cavity_internal_insulation,
|
||||
('Cavity', 'External'): EpcWallDescriptions.cavity_external_insulation,
|
||||
('Cavity', 'FilledCavityPlusInternal'): EpcWallDescriptions.cavity_filled_plus_internal,
|
||||
('Cavity', 'FilledCavityPlusExternal'): EpcWallDescriptions.cavity_filled_plus_external,
|
||||
('Cavity', 'AsBuilt'): None, # To be classified
|
||||
('Cavity', 'Unknown'): None, # To be classified
|
||||
|
||||
# System built walls
|
||||
('System', 'External'): EpcWallDescriptions.system_external_insulation,
|
||||
('System', 'Internal'): EpcWallDescriptions.system_internal_insulation,
|
||||
('System', 'AsBuilt'): None, # To be classified
|
||||
('System', 'Unknown'): None,
|
||||
|
||||
# Timber Frame walls
|
||||
('Timber Frame', 'Internal'): EpcWallDescriptions.timber_frame_internal_insulation,
|
||||
('Timber Frame', 'External'): EpcWallDescriptions.timber_frame_external_insulation,
|
||||
('Timber Frame', 'AsBuilt'): None, # To be classified
|
||||
('Timber Frame', 'Unknown'): None,
|
||||
|
||||
# Solid Brick walls
|
||||
('Solid Brick', 'External'): EpcWallDescriptions.solid_brick_external_insulation,
|
||||
('Solid Brick', 'Internal'): EpcWallDescriptions.solid_brick_internal_insulation,
|
||||
('Solid Brick', 'AsBuilt'): None, # To be classified
|
||||
('Solid Brick', 'Unknown'): None,
|
||||
|
||||
# Granite walls
|
||||
('Granite', 'External'): EpcWallDescriptions.granite_whinstone_external_insulation,
|
||||
("Granite", 'Internal'): EpcWallDescriptions.granite_whinstone_internal_insulation,
|
||||
('Granite', 'AsBuilt'): None,
|
||||
('Granite', 'Unknown'): None,
|
||||
|
||||
# Sandstone walls
|
||||
('Sandstone', 'Internal'): EpcWallDescriptions.sandstone_limestone_internal_insulation,
|
||||
('Sandstone', 'External'): EpcWallDescriptions.sandstone_limestone_external_insulation,
|
||||
('Sandstone', 'Unknown'): None,
|
||||
('Sandstone', 'AsBuilt'): None,
|
||||
|
||||
# Cob walls
|
||||
('Cob', 'AsBuilt'): None,
|
||||
}
|
||||
|
||||
wall_unknown_age_fallback = {
|
||||
"Cavity": EpcWallDescriptions.cavity_as_built_unknown,
|
||||
"Solid Brick": EpcWallDescriptions.solid_brick_as_built_unknown,
|
||||
"Timber Frame": EpcWallDescriptions.timber_frame_as_built_unknown,
|
||||
"System": EpcWallDescriptions.system_as_built_unknown,
|
||||
"Granite": EpcWallDescriptions.granite_as_built_unknown,
|
||||
"Sandstone": EpcWallDescriptions.sandstone_as_built_unknown,
|
||||
"Cob": EpcWallDescriptions.cob_as_built_unknown,
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
parity_map = {
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
17
datatypes/epc/floor.py
Normal file
17
datatypes/epc/floor.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
from enum import Enum
|
||||
|
||||
|
||||
class EpcFloorDescriptions(Enum):
|
||||
# Solid floor
|
||||
solid_insulated = "Solid, insulated"
|
||||
solid_insulated_assumed = "Solid, insulated (assumed)"
|
||||
solid_no_insulation_assumed = "Solid, no insulation (assumed)"
|
||||
solid_limited_insulation_assumed = "Solid, limited insulation (assumed)"
|
||||
|
||||
# Suspended floor
|
||||
suspended_insulated = "Suspended, insulated"
|
||||
suspended_insulated_assumed = "Suspended, insulated (assumed)"
|
||||
suspended_no_insulation_assumed = "Suspended, no insulation (assumed)"
|
||||
suspended_limited_insulation_assumed = "Suspended, limited insulation (assumed)"
|
||||
|
||||
unknown = None # We don't resolve anything
|
||||
Loading…
Add table
Reference in a new issue