mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-09-12 22:38:33 +00:00
feat(v3): sort the library by mastery (needs-practice / most-mastered)
Adds two sort options to the Songs library: "Needs practice first" (weakest
measured accuracy first) and "Most mastered first". Mastery = MAX(best_accuracy)
across a song's arrangements, from song_stats; because that's a separate table
it's a correlated subquery in the ORDER BY, so these sorts use OFFSET paging like
tuning/year. Unscored ("not started") songs always sort to the bottom in both
directions, so a large unpracticed library doesn't bury the songs you're
actually working on. Never the default.
Verified against a running server: scored songs at 0.90 / 0.30 plus unscored ->
ascending orders 0.30, 0.90, unscored; descending 0.90, 0.30, unscored.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbexxfTt8q2tAn436MqGWF
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f9607c5c94
commit
eba20b39fb
@@ -2153,6 +2153,20 @@ class MetadataDB:
|
|||||||
# '2005' rather than alphabetic.
|
# '2005' rather than alphabetic.
|
||||||
"year": "(year = '') ASC, CAST(year AS INTEGER) ASC",
|
"year": "(year = '') ASC, CAST(year AS INTEGER) ASC",
|
||||||
"year-desc": "(year = '') ASC, CAST(year AS INTEGER) DESC",
|
"year-desc": "(year = '') ASC, CAST(year AS INTEGER) DESC",
|
||||||
|
# Mastery = best accuracy across a song's arrangements, from the
|
||||||
|
# separate song_stats table (so via a correlated subquery — this sort
|
||||||
|
# drops to OFFSET paging, like tuning/year). Unscored ("not started")
|
||||||
|
# songs push to the BOTTOM in both directions (the IS NULL term);
|
||||||
|
# ascending is "needs practice first" (weakest measured first),
|
||||||
|
# descending is "most mastered first".
|
||||||
|
"mastery": (
|
||||||
|
"((SELECT MAX(best_accuracy) FROM song_stats s WHERE s.filename = songs.filename) IS NULL) ASC, "
|
||||||
|
"(SELECT MAX(best_accuracy) FROM song_stats s WHERE s.filename = songs.filename) ASC"
|
||||||
|
),
|
||||||
|
"mastery-desc": (
|
||||||
|
"((SELECT MAX(best_accuracy) FROM song_stats s WHERE s.filename = songs.filename) IS NULL) ASC, "
|
||||||
|
"(SELECT MAX(best_accuracy) FROM song_stats s WHERE s.filename = songs.filename) DESC"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
order = sort_map.get(sort, "artist COLLATE NOCASE")
|
order = sort_map.get(sort, "artist COLLATE NOCASE")
|
||||||
# Legacy `dir=desc` toggle: only safe to append on simple sort
|
# Legacy `dir=desc` toggle: only safe to append on simple sort
|
||||||
|
|||||||
@@ -35,6 +35,9 @@
|
|||||||
['title', 'Title A–Z'], ['title-desc', 'Title Z–A'],
|
['title', 'Title A–Z'], ['title-desc', 'Title Z–A'],
|
||||||
['recent', 'Recently Added'], ['year-desc', 'Year (newest)'],
|
['recent', 'Recently Added'], ['year-desc', 'Year (newest)'],
|
||||||
['year', 'Year (oldest)'], ['tuning', 'Tuning'],
|
['year', 'Year (oldest)'], ['tuning', 'Tuning'],
|
||||||
|
// Mastery = best accuracy across arrangements (song_stats); unscored songs
|
||||||
|
// sort last either way. Ascending surfaces what needs work; never default.
|
||||||
|
['mastery', 'Needs practice first'], ['mastery-desc', 'Most mastered first'],
|
||||||
];
|
];
|
||||||
const FORMATS = [['', 'All formats'], ['sloppak', 'Feedpak'], ['loose', 'Folder']];
|
const FORMATS = [['', 'All formats'], ['sloppak', 'Feedpak'], ['loose', 'Folder']];
|
||||||
const ARRANGEMENTS = ['Lead', 'Rhythm', 'Bass', 'Combo', 'Vocals'];
|
const ARRANGEMENTS = ['Lead', 'Rhythm', 'Bass', 'Combo', 'Vocals'];
|
||||||
|
|||||||
Reference in New Issue
Block a user