From 4a311301e24871ea65f46fb3a46cef28f37fe550 Mon Sep 17 00:00:00 2001 From: poprhythm Date: Fri, 11 Sep 2026 21:50:39 +0000 Subject: [PATCH] subwave: fix matcher scoring for composite credits/subtitles, add 3 more 1995 shows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit score_candidate compared library tags verbatim against chart artist/title, so a reissue's composite artist credit (e.g. "Green Day • Billie Joe Armstrong, Mike Dirnt, & Tre Cool") or a dropped subtitle ("Sour Times" vs "Sour Times (Nobody Loves Me)") could push an otherwise-correct match just under the score threshold. Added whole-word substring containment as a scoring boost for both fields, which recovered several real misses. Also adds three more 1995 Tunecaster Rock Top 30 weeks (Jan 14, Jun 10, Dec 16) alongside the existing Oct 28 show, cross-checked against it for exact-track duplicates (swapped for a different real single by the same artist, or dropped where none existed in the library). Claude-Session: https://claude.ai/code/session_01L7Rwa6guD5wK8F8tWQwcJX --- subwave/.gitignore | 1 + .../tunecaster-rock-1995-01-14.json | 36 ++++ .../tunecaster-rock-1995-06-10.json | 156 ++++++++++++++++++ .../tunecaster-rock-1995-10-28.json | 36 ++++ .../tunecaster-rock-1995-12-16.json | 136 +++++++++++++++ subwave/recreate_broadcast.py | 22 ++- 6 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 subwave/.gitignore create mode 100644 subwave/broadcasts/tunecaster-rock-1995-01-14.json create mode 100644 subwave/broadcasts/tunecaster-rock-1995-06-10.json create mode 100644 subwave/broadcasts/tunecaster-rock-1995-10-28.json create mode 100644 subwave/broadcasts/tunecaster-rock-1995-12-16.json diff --git a/subwave/.gitignore b/subwave/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/subwave/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/subwave/broadcasts/tunecaster-rock-1995-01-14.json b/subwave/broadcasts/tunecaster-rock-1995-01-14.json new file mode 100644 index 0000000..a814f91 --- /dev/null +++ b/subwave/broadcasts/tunecaster-rock-1995-01-14.json @@ -0,0 +1,36 @@ +{ + "station": "Tunecaster Rock Top 30", + "date": "1995-01-14", + "tracks": [ + {"rank": 1, "artist": "Green Day", "title": "When I Come Around"}, + {"rank": 2, "artist": "Pearl Jam", "title": "Better Man"}, + {"rank": 3, "artist": "The Flaming Lips", "title": "She Don't Use Jelly"}, + {"rank": 4, "artist": "Weezer", "title": "Buddy Holly"}, + {"rank": 5, "artist": "Van Halen", "title": "Don't Tell Me (What Love Can Do)"}, + {"rank": 6, "artist": "The Offspring", "title": "Gotta Get Away"}, + {"rank": 7, "artist": "Bush", "title": "Everything Zen"}, + {"rank": 8, "artist": "Portishead", "title": "Sour Times (Nobody Loves Me)"}, + {"rank": 9, "artist": "Nine Inch Nails", "title": "Piggy"}, + {"rank": 10, "artist": "Alice In Chains", "title": "Got Me Wrong"}, + {"rank": 11, "artist": "Tom Petty", "title": "You Wreck Me"}, + {"rank": 12, "artist": "Queensryche", "title": "Bridge"}, + {"rank": 13, "artist": "Oasis", "title": "Live Forever"}, + {"rank": 14, "artist": "The Stone Roses", "title": "Love Spreads"}, + {"rank": 15, "artist": "Stone Temple Pilots", "title": "Unglued"}, + {"rank": 16, "artist": "Pearl Jam", "title": "Corduroy"}, + {"rank": 17, "artist": "Counting Crows", "title": "A Murder Of One"}, + {"rank": 18, "artist": "Tom Petty", "title": "You Don't Know How It Feels"}, + {"rank": 19, "artist": "R.E.M.", "title": "Bang And Blame"}, + {"rank": 20, "artist": "Jimmy Page & Robert Plant", "title": "Thank You"}, + {"rank": 21, "artist": "Aerosmith", "title": "Blind Man"}, + {"rank": 22, "artist": "Nirvana", "title": "The Man Who Sold The World"}, + {"rank": 23, "artist": "The Cranberries", "title": "Ode To My Family"}, + {"rank": 24, "artist": "Rancid", "title": "Roots Radical"}, + {"rank": 25, "artist": "Pete Droge", "title": "If You Don't Love Me (I'll Kill Myself)"}, + {"rank": 26, "artist": "Soundgarden", "title": "Fell On Black Days"}, + {"rank": 27, "artist": "Sponge", "title": "Plowed"}, + {"rank": 28, "artist": "The Cranberries", "title": "Zombie"}, + {"rank": 29, "artist": "Throwing Muses", "title": "Bright Yellow Gun"}, + {"rank": 30, "artist": "Hole", "title": "Doll Parts"} + ] +} diff --git a/subwave/broadcasts/tunecaster-rock-1995-06-10.json b/subwave/broadcasts/tunecaster-rock-1995-06-10.json new file mode 100644 index 0000000..9b16b03 --- /dev/null +++ b/subwave/broadcasts/tunecaster-rock-1995-06-10.json @@ -0,0 +1,156 @@ +{ + "station": "Tunecaster Rock Top 30", + "date": "1995-06-10", + "tracks": [ + { + "rank": 1, + "artist": "Soul Asylum", + "title": "Runaway Train" + }, + { + "rank": 2, + "artist": "Collective Soul", + "title": "December" + }, + { + "rank": 3, + "artist": "Live", + "title": "All Over You" + }, + { + "rank": 4, + "artist": "U2", + "title": "Hold Me, Thrill Me, Kiss Me, Kill Me" + }, + { + "rank": 5, + "artist": "Green Day", + "title": "She" + }, + { + "rank": 6, + "artist": "R.E.M.", + "title": "Strange Currencies" + }, + { + "rank": 7, + "artist": "Bush", + "title": "Little Things" + }, + { + "rank": 8, + "artist": "Nirvana", + "title": "Lake Of Fire" + }, + { + "rank": 9, + "artist": "White Zombie", + "title": "More Human Than Human" + }, + { + "rank": 10, + "artist": "Sponge", + "title": "Molly (Sixteen Candles)" + }, + { + "rank": 11, + "artist": "The Magnificent Bastards", + "title": "Mockingbird Girl" + }, + { + "rank": 12, + "artist": "Radiohead", + "title": "Fake Plastic Trees" + }, + { + "rank": 13, + "artist": "Blues Traveler", + "title": "Run-Around" + }, + { + "rank": 14, + "artist": "Nine Inch Nails", + "title": "Hurt" + }, + { + "rank": 15, + "artist": "Filter", + "title": "Hey Man, Nice Shot" + }, + { + "rank": 16, + "artist": "Catherine Wheel", + "title": "Waydown" + }, + { + "rank": 17, + "artist": "The Black Crowes", + "title": "Wiser Time" + }, + { + "rank": 18, + "artist": "Weezer", + "title": "Say It Ain't So" + }, + { + "rank": 19, + "artist": "Monster Magnet", + "title": "Negasonic Teenage Warhead" + }, + { + "rank": 20, + "artist": "The Rembrandts", + "title": "I'll Be There For You" + }, + { + "rank": 21, + "artist": "The Offspring", + "title": "Self Esteem" + }, + { + "rank": 22, + "artist": "Van Halen", + "title": "Amsterdam" + }, + { + "rank": 23, + "artist": "Hum", + "title": "Stars" + }, + { + "rank": 24, + "artist": "Mad Season", + "title": "River Of Deceit" + }, + { + "rank": 25, + "artist": "The Cranberries", + "title": "Ridiculous Thoughts" + }, + { + "rank": 26, + "artist": "Better Than Ezra", + "title": "Good" + }, + { + "rank": 27, + "artist": "Pink Floyd", + "title": "What Do You Want From Me" + }, + { + "rank": 28, + "artist": "Tom Petty", + "title": "It's Good To Be King" + }, + { + "rank": 29, + "artist": "Stone Temple Pilots", + "title": "Dancing Days" + }, + { + "rank": 30, + "artist": "Jill Sobule", + "title": "I Kissed A Girl" + } + ] +} \ No newline at end of file diff --git a/subwave/broadcasts/tunecaster-rock-1995-10-28.json b/subwave/broadcasts/tunecaster-rock-1995-10-28.json new file mode 100644 index 0000000..21da7bb --- /dev/null +++ b/subwave/broadcasts/tunecaster-rock-1995-10-28.json @@ -0,0 +1,36 @@ +{ + "station": "Tunecaster Rock Top 30", + "date": "1995-10-28", + "tracks": [ + {"rank": 1, "artist": "The Smashing Pumpkins", "title": "Bullet With Butterfly Wings"}, + {"rank": 2, "artist": "Foo Fighters", "title": "I'll Stick Around"}, + {"rank": 3, "artist": "Red Hot Chili Peppers", "title": "My Friends"}, + {"rank": 4, "artist": "Green Day", "title": "Geek Stink Breath"}, + {"rank": 5, "artist": "Alanis Morissette", "title": "Hand In My Pocket"}, + {"rank": 6, "artist": "Goo Goo Dolls", "title": "Name"}, + {"rank": 7, "artist": "Toadies", "title": "Possum Kingdom"}, + {"rank": 8, "artist": "Ozzy Osbourne", "title": "Perry Mason"}, + {"rank": 9, "artist": "Seven Mary Three", "title": "Cumbersome"}, + {"rank": 10, "artist": "Alice In Chains", "title": "Grind"}, + {"rank": 11, "artist": "The Presidents Of The United States Of America", "title": "Lump"}, + {"rank": 12, "artist": "Toad The Wet Sprocket", "title": "Good Intentions"}, + {"rank": 13, "artist": "Garbage", "title": "Queer"}, + {"rank": 14, "artist": "Melissa Etheridge", "title": "Your Little Secret"}, + {"rank": 15, "artist": "Oasis", "title": "Morning Glory"}, + {"rank": 16, "artist": "Edwyn Collins", "title": "A Girl Like You"}, + {"rank": 17, "artist": "AC/DC", "title": "Hard As A Rock"}, + {"rank": 18, "artist": "Blues Traveler", "title": "Hook"}, + {"rank": 19, "artist": "Folk Implosion", "title": "Natural One"}, + {"rank": 20, "artist": "The Rentals", "title": "Friends Of P."}, + {"rank": 21, "artist": "Candlebox", "title": "Simple Lessons"}, + {"rank": 22, "artist": "Joan Osborne", "title": "One Of Us"}, + {"rank": 23, "artist": "Rancid", "title": "Time Bomb"}, + {"rank": 24, "artist": "Civ", "title": "Can't Wait One Minute More"}, + {"rank": 25, "artist": "Heather Nova", "title": "Walk This World"}, + {"rank": 26, "artist": "Sponge", "title": "Rainin'"}, + {"rank": 27, "artist": "Lenny Kravitz", "title": "Rock And Roll Is Dead"}, + {"rank": 28, "artist": "Deep Blue Something", "title": "Breakfast At Tiffany's"}, + {"rank": 29, "artist": "Silverchair", "title": "Tomorrow"}, + {"rank": 30, "artist": "Lisa Loeb & Nine Stories", "title": "Do You Sleep?"} + ] +} diff --git a/subwave/broadcasts/tunecaster-rock-1995-12-16.json b/subwave/broadcasts/tunecaster-rock-1995-12-16.json new file mode 100644 index 0000000..b6afa80 --- /dev/null +++ b/subwave/broadcasts/tunecaster-rock-1995-12-16.json @@ -0,0 +1,136 @@ +{ + "station": "Tunecaster Rock Top 30", + "date": "1995-12-16", + "tracks": [ + { + "rank": 1, + "artist": "Bush", + "title": "Glycerine" + }, + { + "rank": 2, + "artist": "Oasis", + "title": "Wonderwall" + }, + { + "rank": 3, + "artist": "The Smashing Pumpkins", + "title": "1979" + }, + { + "rank": 4, + "artist": "Pearl Jam", + "title": "I Got ID" + }, + { + "rank": 6, + "artist": "Seven Mary Three", + "title": "Water's Edge" + }, + { + "rank": 7, + "artist": "Collective Soul", + "title": "The World I Know" + }, + { + "rank": 8, + "artist": "Alanis Morissette", + "title": "All I Really Want" + }, + { + "rank": 9, + "artist": "Red Hot Chili Peppers", + "title": "Give It Away" + }, + { + "rank": 10, + "artist": "The Presidents Of The United States Of America", + "title": "Kitty" + }, + { + "rank": 11, + "artist": "Everclear", + "title": "Santa Monica" + }, + { + "rank": 12, + "artist": "Silverchair", + "title": "Pure Massacre" + }, + { + "rank": 14, + "artist": "Alice In Chains", + "title": "Would?" + }, + { + "rank": 15, + "artist": "Foo Fighters", + "title": "This Is A Call" + }, + { + "rank": 17, + "artist": "No Doubt", + "title": "Just A Girl" + }, + { + "rank": 18, + "artist": "Better Than Ezra", + "title": "Circle of Friends" + }, + { + "rank": 19, + "artist": "Tom Petty And The Heartbreakers", + "title": "Waiting For Tonight" + }, + { + "rank": 20, + "artist": "Rancid", + "title": "Ruby Soho" + }, + { + "rank": 21, + "artist": "Green Day", + "title": "Brain Stew" + }, + { + "rank": 22, + "artist": "Candlebox", + "title": "Far Behind" + }, + { + "rank": 23, + "artist": "Spacehog", + "title": "In The Meantime" + }, + { + "rank": 24, + "artist": "Dave Matthews Band", + "title": "What Would You Say" + }, + { + "rank": 25, + "artist": "AC/DC", + "title": "Cover You In Oil" + }, + { + "rank": 26, + "artist": "Goo Goo Dolls", + "title": "Long Way Down" + }, + { + "rank": 27, + "artist": "Natalie Merchant", + "title": "Carnival" + }, + { + "rank": 28, + "artist": "Ruth Ruth", + "title": "Uninvited" + }, + { + "rank": 29, + "artist": "The Beatles", + "title": "Free As A Bird" + } + ] +} \ No newline at end of file diff --git a/subwave/recreate_broadcast.py b/subwave/recreate_broadcast.py index d367654..f629378 100755 --- a/subwave/recreate_broadcast.py +++ b/subwave/recreate_broadcast.py @@ -158,8 +158,28 @@ def similarity(a, b): return difflib.SequenceMatcher(None, normalize(a), normalize(b)).ratio() +def contains_normalized(a, b): + """True if the normalized forms of a/b contain one another as whole words. + + Handles library tags that carry extra baggage a chart title/artist won't -- + reissue composite credits ("Green Day • Billie Joe Armstrong, Mike Dirnt, + & Tre Cool") or a subtitle the library dropped ("Sour Times" vs "Sour Times + (Nobody Loves Me)") -- without this a correct match can score just under + the threshold on artist or title alone even though one string is clearly + the other plus extra text. + """ + na, nb = f" {normalize(a)} ", f" {normalize(b)} " + return bool(na.strip()) and bool(nb.strip()) and (na in nb or nb in na) + + def score_candidate(song, artist, title): - return similarity(song.get("title", ""), title) * 0.6 + similarity(song.get("artist", ""), artist) * 0.4 + title_score = similarity(song.get("title", ""), title) + if contains_normalized(song.get("title", ""), title): + title_score = max(title_score, 0.9) + artist_score = similarity(song.get("artist", ""), artist) + if contains_normalized(song.get("artist", ""), artist): + artist_score = 1.0 + return title_score * 0.6 + artist_score * 0.4 def match_track(nd_cfg, artist, title, min_score):