Genre priorities for album covers section

This commit is contained in:
2026-03-22 12:38:57 +00:00
parent 6c240b0dc9
commit aaa1580c49
2 changed files with 18 additions and 8 deletions

View File

@@ -594,8 +594,8 @@ pub fn top_genres(conn: &Connection, period: &str, limit: i64) -> Result<Vec<Top
// Deprioritised genres (e.g. "ambient") always rank below specific
// genres regardless of play count. They still appear in the list if
// they are the only genres present.
let a_dep = is_deprioritised(&a.genre);
let b_dep = is_deprioritised(&b.genre);
let a_dep = is_deprioritised_genre(&a.genre);
let b_dep = is_deprioritised_genre(&b.genre);
match (a_dep, b_dep) {
(true, false) => std::cmp::Ordering::Greater,
(false, true) => std::cmp::Ordering::Less,
@@ -743,7 +743,7 @@ pub fn uncached_albums(conn: &Connection) -> Result<Vec<UncachedAlbum>> {
/// Single-word genres ("rock", "electronic", "ambient") are broad descriptors
/// that appear as secondary tags on many artists. Multi-word genres ("prog
/// rock", "alternative metal") are more specific and should rank first.
fn is_deprioritised(genre: &str) -> bool {
pub fn is_deprioritised_genre(genre: &str) -> bool {
canonical_genre_key(genre).split_whitespace().count() < 2
}

View File

@@ -1539,16 +1539,23 @@ fn html_attr_escape(s: &str) -> String {
html_escape(s).replace('"', "&quot;")
}
/// Split a comma-separated genre list and keep only the first `max_labels`
/// cleaned labels.
/// Split a comma-separated genre list and return the top `max_labels` labels,
/// applying the same deprioritisation rule as `top_genres`: multi-word genres
/// rank before single-word broad descriptors ("rock", "electronic", etc.).
fn top_genre_labels(genre_csv: &str, max_labels: usize) -> Vec<String> {
genre_csv
let mut labels: Vec<String> = genre_csv
.split(',')
.map(str::trim)
.filter(|s| !s.is_empty())
.take(max_labels)
.map(|s| s.to_string())
.collect()
.collect();
// Stable sort so that multi-word genres always precede single-word ones,
// preserving the original MusicBrainz order within each group.
labels.sort_by_key(|g| db::is_deprioritised_genre(g));
labels.truncate(max_labels);
labels
}
// ---------------------------------------------------------------------------
@@ -1610,6 +1617,9 @@ mod tests {
#[test]
fn test_top_genre_labels_caps_to_three() {
// "alternative rock" and "industrial" are multi-word → rank first.
// "electronic" and "darkwave" are single-word → deprioritised.
// With limit 3 we get both multi-word genres + one single-word.
let labels = top_genre_labels("alternative rock, electronic, industrial, darkwave", 3);
assert_eq!(
labels,