From 0b33f7dc65054116b5824c992b41a680c2136528 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 7 Jul 2026 22:06:10 +0000 Subject: [PATCH] =?UTF-8?q?Sub-Ladder=20rungs=20fill=20from=20the=20highes?= =?UTF-8?q?t-yield=20segment=20first=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../modelling/test_solar_config_selection.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tests/domain/modelling/test_solar_config_selection.py b/tests/domain/modelling/test_solar_config_selection.py index e24f54cd1..53b6dca18 100644 --- a/tests/domain/modelling/test_solar_config_selection.py +++ b/tests/domain/modelling/test_solar_config_selection.py @@ -256,3 +256,51 @@ def test_small_roof_derives_sub_ladder_rungs_below_googles_smallest_config() -> assert [c.panels_count for c in configs] == [2, 3] assert [c.yearly_energy_dc_kwh for c in configs] == [639.0, 958.5] assert [sum(s.panels_count for s in c.segments) for c in configs] == [2, 3] + + +def test_sub_ladder_rungs_fill_from_the_highest_yield_segment_first() -> None: + # ADR-0058 — filling follows the ADR-0038 "by generation" precedent: the + # derived rung takes panels from the better-yielding plane first, each + # kept segment scaled pro-rata, never biased by segment tuple order. + + # Arrange — smallest rung spans SE (2 panels, 250/panel) listed FIRST and + # SW (2 panels, 350/panel) listed second; max 5 → cap 3.5 → rungs 2 and 3. + south_east = SolarRoofSegment( + segment_index=0, + panels_count=2, + azimuth_degrees=135.0, + pitch_degrees=30.0, + yearly_energy_dc_kwh=500.0, + ) + south_west = SolarRoofSegment( + segment_index=1, + panels_count=2, + azimuth_degrees=225.0, + pitch_degrees=30.0, + yearly_energy_dc_kwh=700.0, + ) + potential = SolarPotential( + panel_capacity_watts=400.0, + max_array_panels_count=5, + configurations=( + SolarPanelConfiguration( + panels_count=4, + yearly_energy_dc_kwh=1200.0, + segments=(south_east, south_west), + ), + ), + ) + + # Act + configs = select_conservative_configs(potential) + + # Assert — rung 2 is the SW plane alone (700); rung 3 adds one SE panel + # pro-rata (700 + 250 = 950). + assert [c.panels_count for c in configs] == [2, 3] + assert [c.yearly_energy_dc_kwh for c in configs] == [700.0, 950.0] + rung_two, rung_three = configs + assert [s.azimuth_degrees for s in rung_two.segments] == [225.0] + assert {(s.azimuth_degrees, s.panels_count) for s in rung_three.segments} == { + (225.0, 2), + (135.0, 1), + }