diff options
| author | Fuwn <[email protected]> | 2024-02-06 06:17:29 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2024-02-06 06:17:29 -0800 |
| commit | 1bcca367ef05082e23c3adbc345a3b481fc78852 (patch) | |
| tree | b2591caae71457f6ba683ebb23532d0f6fef03d6 /src/lib | |
| parent | feat(locale): localise debug settings (diff) | |
| download | due.moe-1bcca367ef05082e23c3adbc345a3b481fc78852.tar.xz due.moe-1bcca367ef05082e23c3adbc345a3b481fc78852.zip | |
fix(match): re-add schedule matcher
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/Media/Anime/Airing/Subtitled/match.ts | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/src/lib/Media/Anime/Airing/Subtitled/match.ts b/src/lib/Media/Anime/Airing/Subtitled/match.ts index c9e73e81..648b0af7 100644 --- a/src/lib/Media/Anime/Airing/Subtitled/match.ts +++ b/src/lib/Media/Anime/Airing/Subtitled/match.ts @@ -55,7 +55,7 @@ const calculateWeightedSimilarity = (title1: string, title2: string): number => return score / (Math.max(tokens1.length, tokens2.length) * 2); }; -const findClosestMatch = (times: Time[], titles: string[]): Time | null => { +export const findClosestMatch = (times: Time[], titles: string[]): Time | null => { let bestMatch: Time | null = null; let bestScore = 0; @@ -81,6 +81,44 @@ const findClosestMatch = (times: Time[], titles: string[]): Time | null => { return bestMatch; }; +const normalizeTitle = (title: string | null) => + (title || '') + .toLowerCase() + .replace(/\b(s|season|part|cour)\s*\d+/g, '') + .replace(/[\W_]+/g, ' ') + .trim(); + +export const findClosestMedia = (media: Media[], matchFor: string) => { + if (!matchFor) return null; + + let bestFitMedia: Media | null = null; + let smallestDistance = -Infinity; + + media.forEach((m) => { + const titles = [m.title.romaji, m.title.english, ...m.synonyms].filter(Boolean); + + titles.forEach((title) => { + const normalisedTitle = normalizeTitle(title); + const normalisedMatchFor = normalizeTitle(matchFor); + const distance = stringSimilarity.compareTwoStrings(normalisedMatchFor, normalisedTitle); + + if ( + distance > smallestDistance && + (normalisedMatchFor + .split(' ') + .filter((word) => titles.some((title) => normalizeTitle(title).includes(word))).length >= + normalisedMatchFor.split(' ').length || + titles.some((title) => normalizeTitle(title).includes(normalisedMatchFor))) + ) { + smallestDistance = distance; + bestFitMedia = m; + } + }); + }); + + return bestFitMedia as Media | null; +}; + export const injectAiringTime = (anime: Media, subsPlease: SubsPlease | null) => { const airingAt = anime.nextAiringEpisode?.airingAt; // const nativeUntilAiring = airingAt |