From 93a74190060ecb250aff86ff0155480ddf1cd701 Mon Sep 17 00:00:00 2001 From: en Date: Mon, 3 Feb 2025 19:53:48 +0100 Subject: [PATCH] feat(games): improve search for games --- src/pages/search.tsx | 7 +++-- src/utils/utils.ts | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/pages/search.tsx b/src/pages/search.tsx index b294ce9..8b365dc 100644 --- a/src/pages/search.tsx +++ b/src/pages/search.tsx @@ -36,6 +36,7 @@ import { DEFAULT_FILTER_OPTIONS, extractModData, isModDataComplete, + memoizedNormalizeSearchString, scrollIntoView } from 'utils' import { useCuratedSet } from 'hooks/useCuratedSet' @@ -502,10 +503,12 @@ const GamesResult = ({ searchTerm }: GamesResultProps) => { const filteredGames = useMemo(() => { if (searchTerm === '') return [] - const lowerCaseSearchTerm = searchTerm.toLowerCase() + const normalizedSearchTerm = memoizedNormalizeSearchString(searchTerm) return games.filter((game) => - game['Game Name'].toLowerCase().includes(lowerCaseSearchTerm) + memoizedNormalizeSearchString(game['Game Name']).includes( + normalizedSearchTerm + ) ) }, [searchTerm, games]) diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 7cc8a73..19fc9bb 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -198,3 +198,65 @@ export function adjustTextareaHeight(textarea: HTMLTextAreaElement) { textarea.style.height = 'auto' textarea.style.height = `${textarea.scrollHeight}px` } + +// Normalizing search terms +const removeAccents = (str: string): string => { + return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '') +} + +const removeSpecialCharacters = (str: string): string => { + return str.replace(/[.,/#!$%^&*;:{}=\-_`~()&\s]/g, '') +} + +// Replace Roman numerals with their Arabic counterparts +const ROMAN_TO_ARABIC_MAP: { [key: string]: string } = { + i: '1', + ii: '2', + iii: '3', + iv: '4', + v: '5', + vi: '6', + vii: '7', + viii: '8', + ix: '9', + x: '10', + xi: '11', + xii: '12', + xiii: '13', + xiv: '14', + xv: '15', + xvi: '16', + xvii: '17', + xviii: '18', + xix: '19', + xx: '20' +} + +const romanRegex = new RegExp( + `\\b(${Object.keys(ROMAN_TO_ARABIC_MAP).join('|')})\\b`, + 'g' +) + +export const normalizeSearchString = (str: string): string => { + str = str.toLowerCase() + str = removeAccents(str) + str = removeSpecialCharacters(str) + return str.replace(romanRegex, (match) => ROMAN_TO_ARABIC_MAP[match]) +} + +// Memoization function to cache normalized results +const memoizeNormalize = (func: (str: string) => string) => { + const cache: { [key: string]: string } = {} + return (str: string): string => { + if (cache[str] !== undefined) { + return cache[str] + } + const result = func(str) + cache[str] = result + return result + } +} + +export const memoizedNormalizeSearchString = memoizeNormalize( + normalizeSearchString +)