Hardened the lookups

This commit is contained in:
Connor Johnstone
2026-03-02 23:54:28 -05:00
parent 34977ea54b
commit 09d562fabb
7 changed files with 222 additions and 66 deletions

View File

@@ -37,6 +37,38 @@ def get_similar(db_path, mbid):
return rows
def get_top_tracks(db_path, mbid):
conn = sqlite3.connect(db_path)
rows = conn.execute(
"SELECT t.path, tt.playcount FROM tracks t "
"JOIN top_tracks tt ON tt.artist_mbid = t.artist_mbid "
" AND (LOWER(t.title) = tt.name_lower "
" OR t.recording_mbid = tt.recording_mbid) "
"WHERE t.artist_mbid = ?1 "
"ORDER BY tt.playcount DESC",
(mbid,),
).fetchall()
conn.close()
return rows
def get_local_track_count(db_path, mbid):
conn = sqlite3.connect(db_path)
total = conn.execute(
"SELECT COUNT(*) FROM tracks WHERE artist_mbid = ?1", (mbid,)
).fetchone()[0]
matched = conn.execute(
"SELECT COUNT(*) FROM tracks t "
"JOIN top_tracks tt ON tt.artist_mbid = t.artist_mbid "
" AND (LOWER(t.title) = tt.name_lower "
" OR t.recording_mbid = tt.recording_mbid) "
"WHERE t.artist_mbid = ?1",
(mbid,),
).fetchone()[0]
conn.close()
return total, matched
def fuzzy_match(query, name):
"""Simple fuzzy: all query chars appear in order in name."""
name_lower = name.lower()
@@ -124,28 +156,48 @@ def run_tui(stdscr, db_path):
def show_similar(stdscr, db_path, artist):
mbid, name = artist
similar = get_similar(db_path, mbid)
top = get_top_tracks(db_path, mbid)
total_local, matched_local = get_local_track_count(db_path, mbid)
curses.curs_set(0)
stdscr.erase()
h, w = stdscr.getmaxyx()
title = f" Similar to {name}"
stdscr.addnstr(0, 0, title, w, curses.color_pair(2) | curses.A_BOLD)
mid = w // 2
title_l = f" Similar to {name}"
title_r = f" Top tracks ({matched_local}/{total_local} matched)"
stdscr.addnstr(0, 0, title_l, mid, curses.color_pair(2) | curses.A_BOLD)
stdscr.addnstr(0, mid, title_r, w - mid, curses.color_pair(2) | curses.A_BOLD)
stdscr.addnstr(h - 1, 0, " [q] back", w, curses.color_pair(3))
scroll = 0
scroll_l = 0
scroll_r = 0
list_h = h - 2
while True:
# Left pane: similar artists
for i in range(list_h):
stdscr.move(i + 1, 0)
stdscr.clrtoeol()
idx = scroll + i
if idx >= len(similar):
continue
sname, score = similar[idx]
line = f" {score:5.2f} {sname}"
stdscr.addnstr(i + 1, 0, line, w)
idx = scroll_l + i
if idx < len(similar):
sname, score = similar[idx]
line = f" {score:5.2f} {sname}"
stdscr.addnstr(i + 1, 0, line, mid)
# Right pane: top tracks
for i in range(list_h):
idx = scroll_r + i
if idx < len(top):
path, playcount = top[idx]
# Show just the filename without extension
fname = Path(path).stem
# Strip "Artist - " prefix if present
if " - " in fname:
fname = fname.split(" - ", 1)[1]
line = f" {playcount:>8} {fname}"
stdscr.addnstr(i + 1, mid, line, w - mid)
stdscr.refresh()
key = stdscr.get_wch()
@@ -153,10 +205,13 @@ def show_similar(stdscr, db_path, artist):
if key in ("q", "Q", "\x1b"):
return
elif key == curses.KEY_UP or key == "\x10":
scroll = max(0, scroll - 1)
scroll_l = max(0, scroll_l - 1)
scroll_r = max(0, scroll_r - 1)
elif key == curses.KEY_DOWN or key == "\x0e":
if scroll + list_h < len(similar):
scroll += 1
if scroll_l + list_h < len(similar):
scroll_l += 1
if scroll_r + list_h < len(top):
scroll_r += 1
def main():