Array of words from the manga title
Array of words from the search query
Word match score (0.75-1) or -1 if below threshold
export function calculateWordMatchScore(
titleWords: string[],
searchWords: string[],
): number {
const matchableTitleWords = filterMatchableWords(titleWords);
const matchableSearchWords = filterMatchableWords(searchWords);
if (matchableTitleWords.length === 0 || matchableSearchWords.length === 0) {
return -1;
}
let matchingWords = 0;
const matchedSearchWords = new Set<string>();
for (const word of matchableTitleWords) {
for (const searchWord of matchableSearchWords) {
if (matchedSearchWords.has(searchWord)) continue;
if (word === searchWord) {
matchingWords += 1;
matchedSearchWords.add(searchWord);
break;
}
if (isPartialWordMatch(word, searchWord)) {
matchingWords += 0.5;
matchedSearchWords.add(searchWord);
break;
}
}
}
const denominator = Math.max(
2,
Math.min(matchableTitleWords.length, matchableSearchWords.length),
);
const matchRatio = matchingWords / denominator;
const adjustedMatchRatio = applyDensityPenalty(
matchRatio,
matchingWords,
matchableTitleWords.length,
matchableSearchWords.length,
);
if (adjustedMatchRatio >= WORD_MATCH_BASE_RATIO) {
return (
WORD_MATCH_BASE_RATIO + (adjustedMatchRatio - WORD_MATCH_BASE_RATIO) * 0.6
);
}
const fallbackScore = getWordMatchFallbackScore(
adjustedMatchRatio,
matchableTitleWords.length,
matchableSearchWords.length,
matchingWords,
);
if (fallbackScore !== null) {
return fallbackScore;
}
return -1;
}
Calculate word matching score between title and search words. Counts exact word matches and partial matches (prefix/suffix) of length >= 4. Requires minimum 75% match ratio to return a score.