From b41cc4bf6201e0d0be677d269170303060d97318 Mon Sep 17 00:00:00 2001 From: alistairjcbrown <635903+alistairjcbrown@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:40:13 +0000 Subject: [PATCH] Update title normalization test --- common/get-movie-data.js | 1 + common/is-non-film-event.js | 31 +++++ common/is-sport-showing.js | 1 + common/known-removable-phrases.js | 4 + common/normalize-title.js | 12 +- common/source-only/transform.js | 7 +- common/tests/is-non-film-event.test.js | 56 +++++++++ common/tests/test-titles.json | 164 ++++++++++++++++++++++++- scripts/transform/index.js | 4 + 9 files changed, 271 insertions(+), 9 deletions(-) create mode 100644 common/is-non-film-event.js create mode 100644 common/tests/is-non-film-event.test.js diff --git a/common/get-movie-data.js b/common/get-movie-data.js index 69468acb..e8aa9afe 100644 --- a/common/get-movie-data.js +++ b/common/get-movie-data.js @@ -64,6 +64,7 @@ const ignoredIds = [ 858680, // World CUP -- https://www.themoviedb.org/movie/858680-world-cup 1254413, // RiffTrax Live: Point Break -- https://www.themoviedb.org/movie/1254413-rifftrax-live-point-break 1308510, // Hard Days Night -- https://www.themoviedb.org/movie/1308510-hard-days-night + 1234194, // Test Screening -- https://www.themoviedb.org/movie/1234194-test-screening ]; /** diff --git a/common/is-non-film-event.js b/common/is-non-film-event.js new file mode 100644 index 00000000..67531027 --- /dev/null +++ b/common/is-non-film-event.js @@ -0,0 +1,31 @@ +const { basicNormalize } = require("./utils"); + +const nonFilmEvents = [ + /Community Pilates/i, + /Bearpit Karaoke/i, + /Paint your own/i, + /WEEKND FANPARK/i, + /Bioimage Analysis/i, + /Business Networking/i, + /Healthcare & Wellness/i, + /Performance Networking/i, + /Networking Night/i, + /Networking Reception/i, + /Medtech Innovation/i, + /Fashion Business/i, + /Thursday Third Space/i, + /Free Salsa/i, + /Cabin Air Conference/i, + /Connected Intelligence/i, + /Annual Meeting/i, +]; + +const isNonFilmEvent = ({ title }) => + nonFilmEvents.some((pattern) => basicNormalize(title).match(pattern)); + +const isNotNonFilmEvent = (event) => !isNonFilmEvent(event); + +module.exports = { + isNonFilmEvent, + isNotNonFilmEvent, +}; diff --git a/common/is-sport-showing.js b/common/is-sport-showing.js index 1741fb13..b334d323 100644 --- a/common/is-sport-showing.js +++ b/common/is-sport-showing.js @@ -41,6 +41,7 @@ const sportShowings = [ /^England v\/?s?\.? /i, /^France v\/?s?\.? /i, /^Spain v\/?s?\.? /i, + /Sports Day/i, ]; const isSportShowing = ({ title }) => diff --git a/common/known-removable-phrases.js b/common/known-removable-phrases.js index 4626f708..144e42da 100644 --- a/common/known-removable-phrases.js +++ b/common/known-removable-phrases.js @@ -321,7 +321,9 @@ const knownRemovablePhrases = [ "with a Talk by Paul Merton", "With Bonus Footage", "w/ Bonus Footage", + "W/ Bonus Features", "w/Bonus Footage", + "W/Bonus Features", "with subtitles for the D/deaf", "with intro and post-film discussion", "with introduction and post-film discussion", @@ -1139,6 +1141,7 @@ const knownRemovablePhrases = [ "SUBTITLED:", "Sudanese Cinema:", "Summer Festival Film Night:", + "Summer Festival Film Night & Closing Party!", "Summer Nights in Brazil:", "Summer by the River:", "Summer Screenings at Greenford Quay:", @@ -1232,6 +1235,7 @@ const knownRemovablePhrases = [ // Weirdly specific fixes "愛殺", "老虎出更", + "Alumni Awards", "Afronauts & ", "Cockroach & ", " D.C.", diff --git a/common/normalize-title.js b/common/normalize-title.js index 859bf946..f26eb4b5 100644 --- a/common/normalize-title.js +++ b/common/normalize-title.js @@ -881,7 +881,14 @@ function normalizeTitle(title, options) { 'Sapphic Cinema + BFI "Rip it Up" - ', 'Sapphic Cinema & BFI "Rip it Up": ', ], - [/(? { diff --git a/common/source-only/transform.js b/common/source-only/transform.js index 7f829293..23109d06 100644 --- a/common/source-only/transform.js +++ b/common/source-only/transform.js @@ -1,10 +1,5 @@ const { isNotSportShowing } = require("../../common/is-sport-showing"); -const { basicNormalize } = require("../utils"); - -const nonFilmEvents = [/Community Pilates/i, /Bearpit Karaoke/i]; - -const isNotNonFilmEvent = ({ title }) => - !nonFilmEvents.some((nonFilm) => basicNormalize(title).match(nonFilm)); +const { isNotNonFilmEvent } = require("../../common/is-non-film-event"); async function transform(data, sourcedEvents) { // Return the sourced events for this venue diff --git a/common/tests/is-non-film-event.test.js b/common/tests/is-non-film-event.test.js new file mode 100644 index 00000000..b85bccac --- /dev/null +++ b/common/tests/is-non-film-event.test.js @@ -0,0 +1,56 @@ +const { isNonFilmEvent, isNotNonFilmEvent } = require("../is-non-film-event"); + +describe("isNonFilmEvent", () => { + test.each([ + ["Community Pilates"], + ["Bearpit Karaoke"], + ["Paint your own Carafe or Shot Glasses"], + ["THE WEEKND FANPARK"], + ["Crick Bioimage Analysis Symposium 2026"], + ["Business Networking | Healthcare & Wellness Industry"], + ["Media, PR & Communications | London Business Networking Evening"], + ["Clinical, Care & Performance Networking Reception – London"], + ["Fashion Business, Startups Industry Leaders Networking Night"], + ["Visionary Collective Artists & Industry Pros Networking Night"], + ["Medtech Innovation: Shaping the Future of Digital Health in London"], + ["WHAT HAPPENS NEXT - Thursday Third Space & Games for Singles 21+"], + ["Free Salsa & Bachata Outdoor Party - SABOR"], + ["Aircraft Cabin Air Conference 2026"], + [ + "one6G Summit 2026: Connected Intelligence for 6G (Sept. 10-11, London, UK)", + ], + ["BSNM Annual Meeting 2026"], + ])("flags '%s' as a non-film event", (title) => { + expect(isNonFilmEvent({ title })).toBe(true); + }); + + test.each([ + ["Community Cinema at UCL East – Pride"], + ["Big Screen Karaoke"], + ["War Paint: Women at War"], + ["ENGLAND FANPARK: ENGLAND V SERBIA"], + ["Introduction to Film Analysis and Filmmaking"], + ["Risky Business"], + ["Unfinished Business"], + ["Women in Film & TV networking - LIFF 2025"], + ["CLASSIC MATINEE: PERFORMANCE"], + ["Mambar Pierrette - Fashion in Film Festival 2025"], + ["Official Selection: La Salsa Vive (Salsa Lives)"], + ["The Cabinet of Dr. Caligari (1920) + Live Organ"], + ["A.I. Artificial Intelligence"], + ["The 23rd Annual Animation Show of Shows: UK screening"], + ["The Blinking Buzzards – Quarterly Meeting"], + ])("does not flag '%s' as a non-film event", (title) => { + expect(isNonFilmEvent({ title })).toBe(false); + }); +}); + +describe("isNotNonFilmEvent", () => { + test("returns true for film events", () => { + expect(isNotNonFilmEvent({ title: "The Wild Robot" })).toBe(true); + }); + + test("returns false for non-film events", () => { + expect(isNotNonFilmEvent({ title: "Bearpit Karaoke" })).toBe(false); + }); +}); diff --git a/common/tests/test-titles.json b/common/tests/test-titles.json index 49b4caa1..00e43a35 100644 --- a/common/tests/test-titles.json +++ b/common/tests/test-titles.json @@ -82109,7 +82109,7 @@ }, { "input": "Shaun the Sheep: The Beast of the Mossy Bottom", - "output": "a shaun the sheep movie the beast of the mossy bottom" + "output": "shaun the sheep the beast of mossy bottom" }, { "input": "Babymother + Q&A", @@ -84781,7 +84781,7 @@ }, { "input": "Madness: Take It Or Leave It (4K Restoration)", - "output": "madness take it or leave it" + "output": "take it or leave it" }, { "input": "Big Night Out: Legally Blonde", @@ -85318,5 +85318,165 @@ { "input": "The NeverEnding Story: The Directors Cut", "output": "neverending story" + }, + { + "input": "CARERS & BABIES: TONY", + "output": "tony" + }, + { + "input": "SEND FRIENDLY SCREENING: WALLACE & GROMIT: A GRAND DAY OUT + THE WRONG TROUSERS", + "output": "wallace gromit a grand day out the wrong trousers" + }, + { + "input": "THE END OF OAK STREET", + "output": "end of oak street" + }, + { + "input": "TONY", + "output": "tony" + }, + { + "input": "Zeteo UK LAUNCH EVENT - Live at the Barbican", + "output": "zeteo uk launch event" + }, + { + "input": "Challenging The Crown: The Conversation", + "output": "challenging the crown the conversation" + }, + { + "input": "Ballet Nights 012", + "output": "ballet nights 012" + }, + { + "input": "Femme Fatale", + "output": "femme fatale" + }, + { + "input": "Madness: Take It or Leave It", + "output": "take it or leave it" + }, + { + "input": "Insidious: Out Of The Further", + "output": "insidious out of the further" + }, + { + "input": "NFT: Cursed Images - London Screening", + "output": "nft cursed images" + }, + { + "input": "Open Season", + "output": "open season" + }, + { + "input": "Parent and Baby: Minions and Monsters", + "output": "minions monsters" + }, + { + "input": "Surf's Up", + "output": "surfs up" + }, + { + "input": "Tonight: Tangerine (2015)", + "output": "tangerine (2015)" + }, + { + "input": "Ice cream man", + "output": "ice cream man" + }, + { + "input": "Freud's Afternoon Session - Freud and Moses: What's in a name?", + "output": "freud moses whats in a name" + }, + { + "input": "IN-HOUSE – Analysis Everywhere, with Susana Caló and Godofredo Enes Pereira", + "output": "inhouse analysis everywhere with susana calo godofredo enes pereira" + }, + { + "input": "Aleto at 15: Documentary Premiere, Alumni Awards & Celebration", + "output": "aleto at 15" + }, + { + "input": "Naked Mondays", + "output": "naked mondays" + }, + { + "input": "Hammersmith Summer Festival Final Film Night and Closing Party!", + "output": "hammersmith summer festival final film night closing party" + }, + { + "input": "Summer Festival Film Night & Closing Party! 10 Things I Hate About You", + "output": "10 things i hate about you" + }, + { + "input": "Scratch Festival", + "output": "scratch festival" + }, + { + "input": "Frame by Frame Presents: Wasteman", + "output": "wasteman" + }, + { + "input": "Practical Magic (Re release)", + "output": "practical magic" + }, + { + "input": "Original Flava x Hackney Picturehouse Launch Party. (FREE EVENT)", + "output": "original flava x hackney picturehouse launch party" + }, + { + "input": "In the Soup", + "output": "in the soup" + }, + { + "input": "Trees Lounge", + "output": "trees lounge" + }, + { + "input": "At Sea: An Evening with Yassmin Abdel-Magied", + "output": "at sea an evening with yassmin abdelmagied" + }, + { + "input": "Pitchblack Playback: Outkast 'ATLiens' (30th Anniversary)", + "output": "outkast atliens" + }, + { + "input": "Anja Ngozi 'Context' : Album Listening", + "output": "anja ngozi context album listening" + }, + { + "input": "BSL tour of Encantados and Sacred Groves", + "output": "bsl tour of encantados sacred groves" + }, + { + "input": "Test Screening", + "output": "test screening" + }, + { + "input": "Sapphic Cinema + BFI \"Rip it Up\" - Stud Life + live performance", + "output": "stud life" + }, + { + "input": "A 'Brunch' of SISTEMS - When Life Gives You Lemons", + "output": "a brunch of sistems" + }, + { + "input": "Backrooms: Everything Must Go Edition W/ Bonus Features", + "output": "backrooms" + }, + { + "input": "Shaun the Sheep: The Beast of Mossy Bottom", + "output": "shaun the sheep the beast of mossy bottom" + }, + { + "input": "The Video Catalogue: Making and Re-making in Palestine, 2018-2026", + "output": "video catalogue making remaking in palestine 2018-2026" + }, + { + "input": "Lexi Seniors' Film Club: Bhaji On The Beach", + "output": "bhaji on the beach" + }, + { + "input": "Community Cinema at UCL East - Film_k presents: Go Fish (1994)", + "output": "go fish (1994)" } ] diff --git a/scripts/transform/index.js b/scripts/transform/index.js index bf4cfbef..0c07f19c 100644 --- a/scripts/transform/index.js +++ b/scripts/transform/index.js @@ -8,6 +8,7 @@ const { isOnline, } = require("../../common/utils"); const { isSportShowing } = require("../../common/is-sport-showing"); +const { isNonFilmEvent } = require("../../common/is-non-film-event"); const { getCinema } = require("../../cinemas"); const findMatchesOnTheMovieDb = require("./find-matches-on-the-movie-db"); const getSourcedEventsFor = require("./get-sourced-events-for"); @@ -129,6 +130,9 @@ async function transform( // Don't bring sports showings back in if (isSportShowing(movie)) continue; + // Don't bring non-film events back in + if (isNonFilmEvent(movie)) continue; + // The movie data from the previous release contains future performances. // If there's no future performances, it's a past movie; continue const now = new Date();