fix(career): gig backfill offsets by qualifying taken, not picks length

CodeRabbit on #954: after the stakes loop appends near-bar songs,
qualifying[len(picks):] overshoots and skips eligible qualifying songs
— a stocked passport could still get a short set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
byrongamatos
2026-07-14 01:26:04 +02:00
co-authored by Claude Fable 5
parent c59883aac9
commit 72212e7bfd
2 changed files with 20 additions and 5 deletions
+6 -4
View File
@@ -722,17 +722,19 @@ def setup(app, context):
# first gig is how stubs start. random per call = free re-roll. # first gig is how stubs start. random per call = free re-roll.
random.shuffle(qualifying) random.shuffle(qualifying)
rest.sort(key=lambda s: -s["best_accuracy"]) rest.sort(key=lambda s: -s["best_accuracy"])
picks = qualifying[:max(1, size - cfg["stakes_songs"])] qtaken = max(1, size - cfg["stakes_songs"])
picks = qualifying[:qtaken]
for s in rest: for s in rest:
if len(picks) >= size: if len(picks) >= size:
break break
picks.append(s) picks.append(s)
# Surplus qualifying songs backfill a short set — a mature passport # Surplus qualifying songs backfill a short set — a mature passport
# with no near-bar songs left must still fill the bill. # with no near-bar songs left must still fill the bill. Offset by how
for s in qualifying[len(picks):] if len(picks) < size else []: # many QUALIFYING songs were taken, not len(picks): rest's stakes
# additions would otherwise skip eligible qualifying songs entirely.
for s in qualifying[qtaken:]:
if len(picks) >= size: if len(picks) >= size:
break break
if s not in picks:
picks.append(s) picks.append(s)
if len(picks) < size: if len(picks) < size:
exclude = {s["filename"] for s in picks} exclude = {s["filename"] for s in picks}
+13
View File
@@ -358,3 +358,16 @@ def test_gig_propose_backfills_from_surplus_qualifying(client, meta_db):
res = client.post("/api/plugins/career/gigs/propose", res = client.post("/api/plugins/career/gigs/propose",
json={"instrument": "guitar", "genre": "Ska", "size": 5}) json={"instrument": "guitar", "genre": "Ska", "size": 5})
assert len(res.json()["songs"]) == 5 assert len(res.json()["songs"]) == 5
def test_gig_propose_backfill_offset_survives_stakes(client, meta_db):
# 4 qualifying + 1 near-bar stake, size 5: the stake must not shift the
# qualifying backfill window past eligible songs.
for i in range(4):
meta_db.add(f"q{i}.feedpak", 0, 0.9, genre="Reggae", arrangements=LEAD)
meta_db.add("near.feedpak", 0, 0.7, genre="Reggae", arrangements=LEAD)
res = client.post("/api/plugins/career/gigs/propose",
json={"instrument": "guitar", "genre": "Reggae", "size": 5})
files = [s["filename"] for s in res.json()["songs"]]
assert len(files) == 5 and len(set(files)) == 5
assert "near.feedpak" in files