attribution: a reissue is not the record it was built from
Radiohead's "No Surprises", "Karma Police" and "Let Down" attributed to "OK Computer OKNOTOK 1997 2017" rather than to OK Computer. Deezer carries both and dates BOTH 1997-05-21, so the EP test, the edition-keyword test and the date all tied, and the rule that breaks that tie — an original album over a truncated sampler of it, by track count — then picked the 23-track reissue over the 12-track record. `is_edition_title` could not catch it because "OKNOTOK 1997 2017" is a bespoke name carrying none of the edition keywords. So a candidate whose title is another candidate's title plus something loses to the one it was built from, ranked above the track-count rule and below the date so the measured Weezer ordering is untouched. Safe because it only ever fires when BOTH records contain the song. A sequel does not share its predecessor's tracklist, so "Greatest Hits II" is never in the running against "Greatest Hits" for the same track — and the numeral guard in `expands_on` refuses the relationship anyway, along with volume and part markers. Pinned both ways. Also: the recordings browse is filtered to `type=album&status=official`. Unfiltered, Radiohead has 1141 releases and the two-page window saw 18% of them, mostly singles and bootleg pressings; filtered it is 274, so the same two pages cover 73% of the releases that could actually own a popular song. Same cost, better sample. The tail is accepted rather than paged around. Queen still has 1119 official album pressings, but this map exists to place songs Deezer does NOT carry, and an artist with a thousand pressings is one Deezer carries exhaustively — measured, the relabel pass reports 0 for both Queen and Radiohead. Reaching them would cost eleven requests behind the 1 req/s gate to change nothing. Verified live: Radiohead's three rows move to OK Computer; Queen, My Bloody Valentine and Death Grips are unchanged. 77 Rust tests and 85 JS tests pass.
This commit is contained in:
1 parent
4cb2c4c1b3
commit
4d7fb7f72e
1 file changed
+100
-1
+100
-1
@@ -6025,8 +6025,22 @@ impl MetadataClient {
|
||||
let mut found: HashMap<String, MbRecording> = HashMap::new();
|
||||
for page in 0..MB_RECORDING_PAGES {
|
||||
let offset = page * MB_RECORDING_PAGE;
|
||||
// Filtered to official ALBUM releases, which is both cheaper and
|
||||
// more relevant: unfiltered, Radiohead has 1141 releases and the
|
||||
// two-page window saw 18% of them, mostly singles and bootleg
|
||||
// pressings. `type=album&status=official` leaves 274, so the same
|
||||
// two pages now cover 73% of the releases that could actually own a
|
||||
// popular song.
|
||||
//
|
||||
// It does not fix the tail — Queen still has 1119 official album
|
||||
// pressings — and that is accepted rather than paged around. This
|
||||
// map exists to place songs Deezer does not carry, and an artist
|
||||
// with a thousand pressings is one Deezer carries exhaustively:
|
||||
// measured, the relabel pass reports 0 for both Queen and
|
||||
// Radiohead. Paging to reach them would cost 11 requests behind the
|
||||
// 1 req/s gate to change nothing.
|
||||
let url = format!(
|
||||
"https://musicbrainz.org/ws/2/release?artist={mbid}\
|
||||
"https://musicbrainz.org/ws/2/release?artist={mbid}&type=album&status=official\
|
||||
&inc=recordings+release-groups&limit={MB_RECORDING_PAGE}&offset={offset}&fmt=json"
|
||||
);
|
||||
let Some(body) = self.musicbrainz_json(&url).await else {
|
||||
@@ -8420,6 +8434,26 @@ fn apply_original_album_attribution(
|
||||
.unwrap_or("9999")
|
||||
.cmp(right.release_date.as_deref().unwrap_or("9999"))
|
||||
})
|
||||
// A title one candidate BUILDS ON is the original of it.
|
||||
//
|
||||
// Above the track-count rule below, and Radiohead is why.
|
||||
// Deezer carries "OK Computer" (12 tracks) and "OK Computer
|
||||
// OKNOTOK 1997 2017" (23) and dates BOTH 1997-05-21, so EP,
|
||||
// edition-keyword and date all tie and the sampler rule
|
||||
// then picked the 23-track reissue for "No Surprises",
|
||||
// "Karma Police" and "Let Down". `is_edition_title` cannot
|
||||
// catch it because "OKNOTOK 1997 2017" is a bespoke name
|
||||
// with none of the usual keywords in it.
|
||||
//
|
||||
// Only ever fires when both records actually contain the
|
||||
// song, which is what makes it safe: a sequel does not
|
||||
// share its predecessor's tracklist, so "Greatest Hits II"
|
||||
// is never in the running against "Greatest Hits" for the
|
||||
// same track. The numeral guard is belt and braces.
|
||||
// `false` sorts before `true`, and the winner is the
|
||||
// SMALLEST, so the one that expands on the other loses.
|
||||
.then_with(|| expands_on(&left.title, &right.title)
|
||||
.cmp(&expands_on(&right.title, &left.title)))
|
||||
// An original album over a truncated sampler of it.
|
||||
.then_with(|| {
|
||||
right
|
||||
@@ -9150,6 +9184,29 @@ fn regex_lite_year_mix_tail(lower_title: &str) -> bool {
|
||||
/// ("OK Computer OKNOTOK 1997 2017") is built on an existing album ("OK
|
||||
/// Computer") despite carrying no edition keyword. Length-guarded so a very
|
||||
/// short album title cannot spuriously match.
|
||||
/// Does `title` look like `base` plus something — a reissue, an expansion, a
|
||||
/// bespoke anniversary name — rather than a different record?
|
||||
///
|
||||
/// Returns `false` when the extra part is only a sequel number, because
|
||||
/// "Greatest Hits II" builds on nothing: it is its own record that happens to
|
||||
/// share a prefix. Same rule the frontend uses when it decides whether a
|
||||
/// MusicBrainz row is already covered by a Deezer variant.
|
||||
fn expands_on(title: &str, base: &str) -> bool {
|
||||
let (title, base) = (normalize(title), normalize(base));
|
||||
if base.len() < 5 || title.len() <= base.len() || !title.starts_with(&base) {
|
||||
return false;
|
||||
}
|
||||
let tail = &title[base.len()..];
|
||||
// A bare numeral or volume marker is a SEQUEL, not an edition.
|
||||
!matches!(
|
||||
tail,
|
||||
"2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10"
|
||||
| "ii" | "iii" | "iv" | "v" | "vi" | "vii" | "viii" | "ix" | "x"
|
||||
) && !tail.starts_with("vol")
|
||||
&& !tail.starts_with("part")
|
||||
&& !tail.starts_with("pt")
|
||||
}
|
||||
|
||||
fn contains_other_album_title(title: &str, non_edition_titles: &[String]) -> bool {
|
||||
let n = normalize(title);
|
||||
non_edition_titles
|
||||
@@ -14965,6 +15022,48 @@ mod tests {
|
||||
assert_eq!(tracks[0].album, "Weezer (Blue Album)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attribution_prefers_the_record_a_reissue_was_built_from() {
|
||||
// Radiohead, measured live: Deezer carries "OK Computer" (12 tracks)
|
||||
// and "OK Computer OKNOTOK 1997 2017" (23) and dates BOTH 1997-05-21.
|
||||
// EP, edition-keyword and date all tie — "OKNOTOK 1997 2017" carries
|
||||
// none of the edition keywords — so the "original over a truncated
|
||||
// sampler" rule handed No Surprises, Karma Police and Let Down to the
|
||||
// 23-track reissue.
|
||||
let reissue = catalog_album(40, "OK Computer OKNOTOK 1997 2017", Some("1997-05-21"));
|
||||
let original = catalog_album(41, "OK Computer", Some("1997-05-21"));
|
||||
let songs: &[&str] = &["No Surprises", "Karma Police", "Let Down"];
|
||||
let (albums, containment, details) =
|
||||
attribution_fixture(&[(reissue, songs), (original, songs)]);
|
||||
let mut tracks = vec![licensed_track(999, "No Surprises", "Some Compilation", 77)];
|
||||
let mb = HashMap::from([
|
||||
(release_date_key(Some("Album"), "OK Computer"), mb_album("1997-05-21")),
|
||||
(
|
||||
release_date_key(Some("Album"), "OK Computer OKNOTOK 1997 2017"),
|
||||
mb_album("1997-05-21"),
|
||||
),
|
||||
]);
|
||||
|
||||
let moved =
|
||||
apply_original_album_attribution(&mut tracks, &albums, &containment, &details, &mb);
|
||||
assert_eq!(moved, 1);
|
||||
assert_eq!(tracks[0].album, "OK Computer");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_sequel_is_not_an_expansion_of_the_record_it_follows() {
|
||||
// The guard on the rule above. A sequel shares a prefix but not a
|
||||
// tracklist, so it must never be read as an edition of its predecessor.
|
||||
assert!(expands_on("OK Computer OKNOTOK 1997 2017", "OK Computer"));
|
||||
assert!(expands_on("Rumours (Super Deluxe)", "Rumours"));
|
||||
assert!(!expands_on("Greatest Hits II", "Greatest Hits"));
|
||||
assert!(!expands_on("Trap House 3", "Trap House"));
|
||||
assert!(!expands_on("Deep Cuts, Volume 2", "Deep Cuts"));
|
||||
// Not a prefix at all, and never itself.
|
||||
assert!(!expands_on("Kid A", "Amnesiac"));
|
||||
assert!(!expands_on("OK Computer", "OK Computer"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attribution_leaves_a_track_alone_when_nothing_contains_it() {
|
||||
// 3 of the 80 measured tracks match nothing — a remix, an "(Original)"
|
||||
|
||||
Reference in new issue
Block a user