diff --git a/recommendations/SolarPvRecommendations.py b/recommendations/SolarPvRecommendations.py index 3a89b213..744351be 100644 --- a/recommendations/SolarPvRecommendations.py +++ b/recommendations/SolarPvRecommendations.py @@ -8,6 +8,9 @@ class SolarPvRecommendations: # Wattage per panel - this is based on the average wattage of a solar panel being between 250w and 420w SOLAR_PANEL_WATTAGE = 250 + MAX_SYSTEM_WATTAGE = 4200 + MIN_SYSTEM_WATTAGE = 2500 + def __init__(self, property_instance): """ :param property_instance: Instance of the Property class, for the home associated to property_id @@ -18,6 +21,19 @@ class SolarPvRecommendations: self.recommendation = [] + @staticmethod + def trim_solar_wattage_options(scenarios_with_wattage): + # Initialize the list with the first element, assuming the list is not empty + trimmed_list = [scenarios_with_wattage[0]] + + # Iterate over the list starting from the second element + for scenario in scenarios_with_wattage[1:]: + # Compare the second element (index 1) of the current tuple with the last tuple in the trimmed list + if scenario[1] > trimmed_list[-1][1]: + trimmed_list.append(scenario) + + return trimmed_list + def recommend(self, phase): """ We check if a property is potentially suitable for solar PV based on the following criteria: @@ -46,26 +62,40 @@ class SolarPvRecommendations: self.property.solar_pv_percentage - 0.1, self.property.solar_pv_percentage, self.property.solar_pv_percentage + 0.1 ] - # We make sure we haven't gone too low or high - roof_coverage_scenarios = [v for v in roof_coverage_scenarios if 0 <= v <= 1] + # We make sure we haven't gone too low or high - we allow no more than 60% coverage + roof_coverage_scenarios = [v for v in roof_coverage_scenarios if 0 <= v <= 0.6] + # If we only have two scenarios, we add a coverage scenario 10% less than the smallest + if len(roof_coverage_scenarios) == 2: + roof_coverage_scenarios.insert(0, roof_coverage_scenarios[0] - 0.1) battery_scenarios = [False, True] - # I now produce the cross product of the scenarios - scenarios = [(roof, battery) for roof in roof_coverage_scenarios for battery in battery_scenarios] - - for roof_coverage, has_battery in scenarios: + scenarios_with_wattage = [] + for roof_coverage in roof_coverage_scenarios: # We now have a property which is potentially suitable for solar PV solar_pv_roof_area = self.property.get_solar_pv_roof_area(roof_coverage) number_solar_panels = np.floor(solar_pv_roof_area / self.SOLAR_PANEL_AREA) solar_panel_wattage = number_solar_panels * self.SOLAR_PANEL_WATTAGE + solar_panel_wattage = np.clip( + a=solar_panel_wattage, a_min=self.MIN_SYSTEM_WATTAGE, a_max=self.MAX_SYSTEM_WATTAGE + ) + scenarios_with_wattage.append((roof_coverage, solar_panel_wattage)) + # We trim the scenarios, so that we don't have duplicate wattages + scenarios_with_wattage = self.trim_solar_wattage_options(scenarios_with_wattage) + + # Produce the cross product of the scenarios + scenarios = [ + (roof, wattage, battery) for roof, wattage in scenarios_with_wattage for battery in battery_scenarios + ] + # We deduce the wattage of the solar panels based on the roof coverage + + for roof_coverage, solar_panel_wattage, has_battery in scenarios: + # We now have a property which is potentially suitable for solar PV roof_coverage_percent = round(roof_coverage * 100) - # Given the wattage, we estimate the cost of the solar PV system. This is based on the MCS database # of solar PV installations cost_result = self.costs.solar_pv(wattage=solar_panel_wattage, has_battery=has_battery) - kw = np.floor(solar_panel_wattage / 100) / 10 if has_battery: