From 07c37c69938f5541658fb8d61372e2cb3e438431 Mon Sep 17 00:00:00 2001 From: BottlecapDave Date: Sat, 12 Oct 2024 07:01:31 +0100 Subject: [PATCH] fix: Fixed issue with target rate sensors when weighting was applied with finding latest rates --- .../octopus_energy/target_rates/__init__.py | 28 ++++++++++------- .../test_calculate_continuous_times.py | 31 +++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/custom_components/octopus_energy/target_rates/__init__.py b/custom_components/octopus_energy/target_rates/__init__.py index 442d9920..f6afef8c 100644 --- a/custom_components/octopus_energy/target_rates/__init__.py +++ b/custom_components/octopus_energy/target_rates/__init__.py @@ -117,7 +117,6 @@ def calculate_continuous_times( if (applicable_rates is None or target_hours <= 0): return [] - applicable_rates.sort(key=__get_valid_to, reverse=find_last_rates) applicable_rates_count = len(applicable_rates) total_required_rates = math.ceil(target_hours * 2) @@ -158,18 +157,23 @@ def calculate_continuous_times( current_continuous_rates_length = len(continuous_rates) best_continuous_rates_length = len(best_continuous_rates) if best_continuous_rates is not None else 0 + + is_best_continuous_rates = False + if best_continuous_rates is not None: + if search_for_highest_rate: + is_best_continuous_rates = (continuous_rates_total >= best_continuous_rates_total if find_last_rates else continuous_rates_total > best_continuous_rates_total) + else: + is_best_continuous_rates = (continuous_rates_total <= best_continuous_rates_total if find_last_rates else continuous_rates_total < best_continuous_rates_total) + + has_required_hours = False + if hours_mode == CONFIG_TARGET_HOURS_MODE_EXACT: + has_required_hours = current_continuous_rates_length == total_required_rates + elif hours_mode == CONFIG_TARGET_HOURS_MODE_MINIMUM: + has_required_hours = current_continuous_rates_length >= total_required_rates and current_continuous_rates_length >= best_continuous_rates_length + elif hours_mode == CONFIG_TARGET_HOURS_MODE_MAXIMUM: + has_required_hours = current_continuous_rates_length <= total_required_rates and current_continuous_rates_length >= best_continuous_rates_length - if ((best_continuous_rates is None or - (search_for_highest_rate == False and continuous_rates_total < best_continuous_rates_total) or - (search_for_highest_rate and continuous_rates_total > best_continuous_rates_total) - ) - and - ( - (hours_mode == CONFIG_TARGET_HOURS_MODE_EXACT and current_continuous_rates_length == total_required_rates) or - (hours_mode == CONFIG_TARGET_HOURS_MODE_MINIMUM and current_continuous_rates_length >= total_required_rates and current_continuous_rates_length >= best_continuous_rates_length) or - (hours_mode == CONFIG_TARGET_HOURS_MODE_MAXIMUM and current_continuous_rates_length <= total_required_rates and current_continuous_rates_length >= best_continuous_rates_length) - ) - ): + if ((best_continuous_rates is None or is_best_continuous_rates) and has_required_hours): best_continuous_rates = continuous_rates best_continuous_rates_total = continuous_rates_total _LOGGER.debug(f'New best block discovered {continuous_rates_total} ({continuous_rates[0]["start"] if len(continuous_rates) > 0 else None} - {continuous_rates[-1]["end"] if len(continuous_rates) > 0 else None})') diff --git a/tests/unit/target_rates/test_calculate_continuous_times.py b/tests/unit/target_rates/test_calculate_continuous_times.py index 2f35d44c..af9dd243 100644 --- a/tests/unit/target_rates/test_calculate_continuous_times.py +++ b/tests/unit/target_rates/test_calculate_continuous_times.py @@ -1176,6 +1176,37 @@ def test_when_multiple_blocks_have_same_value_then_earliest_is_picked(): assert len(result) == 6 current_start = datetime.strptime("2024-09-04T01:00:00+01:00", "%Y-%m-%dT%H:%M:%S%z") + for rate in result: + assert rate["start"] == current_start + current_start = current_start + timedelta(minutes=30) + assert rate["end"] == current_start + + +def test_when_weighting_present_with_find_latest_rate_then_latest_time_is_picked(): + applicable_rates = create_rate_data(datetime.strptime("2024-10-10T20:00:00+01:00", "%Y-%m-%dT%H:%M:%S%z"), + datetime.strptime("2024-10-10T23:30:00+01:00", "%Y-%m-%dT%H:%M:%S%z"), + [0.267159]) + applicable_rates.extend(create_rate_data(datetime.strptime("2024-10-10T23:30:00+01:00", "%Y-%m-%dT%H:%M:%S%z"), + datetime.strptime("2024-10-11T05:30:00+01:00", "%Y-%m-%dT%H:%M:%S%z"), + [0.070003])) + applicable_rates.extend(create_rate_data(datetime.strptime("2024-10-11T05:30:00+01:00", "%Y-%m-%dT%H:%M:%S%z"), + datetime.strptime("2024-10-11T23:30:00+01:00", "%Y-%m-%dT%H:%M:%S%z"), + [0.267159])) + + applicable_rates.sort(key=lambda x: x["start"]) + + result = calculate_continuous_times( + applicable_rates, + 7.5, + False, + True, + weighting=[2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + ) + + assert result is not None + assert len(result) == 15 + + current_start = datetime.strptime("2024-10-10T23:30:00+01:00", "%Y-%m-%dT%H:%M:%S%z") for rate in result: assert rate["start"] == current_start current_start = current_start + timedelta(minutes=30)