fix(career): exclude orphaned song_stats from star totals

Codex preflight: scans hide rather than delete stats of removed songs, so
stars now apply the same existing-song filter other stats surfaces use
(filename IN (SELECT filename FROM songs)).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
byrongamatos
2026-07-12 01:56:48 +02:00
co-authored by Claude Fable 5
parent 0cc08ebebf
commit 99b6d3c384
3 changed files with 20 additions and 2 deletions
+4 -1
View File
@@ -70,8 +70,11 @@ def _stars():
if db is None:
return 0, {}
thresholds = _state["content"]["star_accuracy_thresholds"]
# Existing-song filter: a scan hides (not deletes) stats of songs removed
# from the library, so orphaned rows must not keep counting toward stars.
rows = db.conn.execute(
"SELECT filename, MAX(best_accuracy) FROM song_stats GROUP BY filename"
"SELECT filename, MAX(best_accuracy) FROM song_stats "
"WHERE filename IN (SELECT filename FROM songs) GROUP BY filename"
).fetchall()
per_song = {}
for filename, acc in rows:
+6 -1
View File
@@ -23,10 +23,15 @@ class FakeMetaDb:
filename TEXT, arrangement TEXT, best_accuracy REAL
)"""
)
self.conn.execute("CREATE TABLE songs (filename TEXT)")
def add(self, filename, arrangement, best_accuracy):
def add(self, filename, arrangement, best_accuracy, in_library=True):
self.conn.execute("INSERT INTO song_stats VALUES (?, ?, ?)",
(filename, arrangement, best_accuracy))
if in_library:
self.conn.execute(
"INSERT INTO songs SELECT ? WHERE NOT EXISTS "
"(SELECT 1 FROM songs WHERE filename = ?)", (filename, filename))
self.conn.commit()
+10
View File
@@ -42,6 +42,16 @@ def test_unlock_flags_follow_thresholds(client, meta_db):
assert by_id["arena"]["unlocked"] is False
def test_orphaned_stats_do_not_count(client, meta_db):
# A song removed from the library (stats row survives the scan) must not
# keep contributing stars.
meta_db.add("gone.feedpak", "guitar", 0.99, in_library=False)
meta_db.add("here.feedpak", "guitar", 0.99)
state = client.get("/api/plugins/career/state").json()
assert state["stars_total"] == 3
assert "gone.feedpak" not in state["stars_per_song"]
def test_no_stats_still_serves_state(client):
state = client.get("/api/plugins/career/state").json()
assert state["stars_total"] == 0