diff --git a/gates/pool.py b/gates/pool.py index a5865a1..5235941 100644 --- a/gates/pool.py +++ b/gates/pool.py @@ -61,6 +61,29 @@ def add_image(base_dir, pool_id, data, ts=0): return m +def _clamp_active(m): + n = len(m["slots"]) + if n == 0: + return 0 + return max(0, min(m.get("active", 0), n - 1)) + + +def set_active(base_dir, pool_id, index): + m = read_manifest(base_dir, pool_id) + m["active"] = index + m["active"] = _clamp_active(m) + write_manifest(base_dir, pool_id, m) + return m + + +def resolve_slot(manifest, index_widget): + n = len(manifest["slots"]) + if n == 0: + return -1 + idx = manifest.get("active", 0) if index_widget == -1 else index_widget + return max(0, min(idx, n - 1)) + + def rebuild_manifest(base_dir, pool_id): # Temporary stub — replaced in Task 7. return empty_manifest() diff --git a/tests/test_pool.py b/tests/test_pool.py index 8666d2c..723cdb5 100644 --- a/tests/test_pool.py +++ b/tests/test_pool.py @@ -49,3 +49,19 @@ def test_add_image_monotonic_after_growth(tmp_path): pool.add_image(str(tmp_path), "p1", b"a", ts=1) m = pool.add_image(str(tmp_path), "p1", b"b", ts=2) assert [s["image"] for s in m["slots"]] == ["img_0001.png", "img_0002.png"] + + +def test_set_active_clamps(tmp_path): + pool.add_image(str(tmp_path), "p1", b"a", ts=1) + pool.add_image(str(tmp_path), "p1", b"b", ts=2) + assert pool.set_active(str(tmp_path), "p1", 1)["active"] == 1 + assert pool.set_active(str(tmp_path), "p1", 9)["active"] == 1 # clamp high + assert pool.set_active(str(tmp_path), "p1", -5)["active"] == 0 # clamp low + + +def test_resolve_slot_rules(): + m = {"active": 1, "slots": [0, 1, 2], "next_seq": 4} # 3 slots + assert pool.resolve_slot(m, -1) == 1 # manual -> active + assert pool.resolve_slot(m, 0) == 0 # forced + assert pool.resolve_slot(m, 9) == 2 # clamp high + assert pool.resolve_slot({"active": 0, "slots": [], "next_seq": 1}, -1) == -1 # empty