Sub-Ladder rungs fill from the highest-yield segment first 🟥

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-07 22:06:10 +00:00
parent 1a34e788d1
commit 0b33f7dc65

View file

@ -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),
}