aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-02-06 06:17:29 -0800
committerFuwn <[email protected]>2024-02-06 06:17:29 -0800
commit1bcca367ef05082e23c3adbc345a3b481fc78852 (patch)
treeb2591caae71457f6ba683ebb23532d0f6fef03d6 /src/lib
parentfeat(locale): localise debug settings (diff)
downloaddue.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.ts40
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