From fa548b31e1ce27dd6b40f0c223191efae3d86ae6 Mon Sep 17 00:00:00 2001 From: kartikvirendrar Date: Sat, 20 Jul 2024 17:30:16 +0530 Subject: [PATCH] added caching mechanism for suggestions --- package.json | 2 +- src/index.tsx | 8 ++-- src/util/suggestions-util.ts | 88 ++++++++++++++++++++++++++++++++---- 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index c70ec92..ed2916f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ai4bharat/indic-transliterate", - "version": "1.3.3", + "version": "1.3.4", "description": "Transliterate component for React", "author": "AI4Bharat", "license": "MIT", diff --git a/src/index.tsx b/src/index.tsx index 8221e8a..e07594d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -135,12 +135,12 @@ export const IndicTransliterate = ({ // fetch suggestion from api // const url = `https://www.google.com/inputtools/request?ime=transliteration_en_${lang}&num=5&cp=0&cs=0&ie=utf-8&oe=utf-8&app=jsapi&text=${lastWord}`; - const numOptions = showCurrentWordAsLastSuggestion - ? maxOptions - 1 - : maxOptions; + // const numOptions = showCurrentWordAsLastSuggestion + // ? maxOptions - 1 + // : maxOptions; const data = await getTransliterateSuggestions(lastWord, customApiURL, { - numOptions, + // numOptions, showCurrentWordAsLastSuggestion, lang, }); diff --git a/src/util/suggestions-util.ts b/src/util/suggestions-util.ts index b22e483..c80e249 100644 --- a/src/util/suggestions-util.ts +++ b/src/util/suggestions-util.ts @@ -1,26 +1,70 @@ import { Language } from "../types/Language"; type Config = { - numOptions?: number; + // numOptions?: number; showCurrentWordAsLastSuggestion?: boolean; lang?: Language; }; +type CacheEntry = { + suggestions: string[]; + frequency: number; +}; + +const MAX_CACHE_SIZE = 1000; +const SAVE_THRESHOLD = 20; +const CACHE_KEY = 'transliterateCache'; + +const cache: Record> = loadCacheFromLocalStorage(); +let newEntriesCount = 0; + +function loadCacheFromLocalStorage(): Record> { + const cachedData = localStorage.getItem(CACHE_KEY); + return cachedData ? JSON.parse(cachedData) : {}; +} + +function saveCacheToLocalStorage() { + localStorage.setItem(CACHE_KEY, JSON.stringify(cache)); +} + +const getWordWithLowestFrequency = (dictionary: Record): string | null => { + let lowestFreqWord: string | null = null; + let lowestFreq = Infinity; + + for (const word in dictionary) { + if (dictionary[word].frequency < lowestFreq) { + lowestFreq = dictionary[word].frequency; + lowestFreqWord = word; + } + } + + return lowestFreqWord; +}; + export const getTransliterateSuggestions = async ( word: string, customApiURL: string, config?: Config, ): Promise => { - const { showCurrentWordAsLastSuggestion, lang } = config || { - numOptions: 5, - showCurrentWordAsLastSuggestion: true, - lang: "hi", - }; + const { + // numOptions = 5, + showCurrentWordAsLastSuggestion = true, + lang = "hi", + } = config || {}; // fetch suggestion from api // const url = `https://www.google.com/inputtools/request?ime=transliteration_en_${lang}&num=5&cp=0&cs=0&ie=utf-8&oe=utf-8&app=jsapi&text=${word}`; // let myHeaders = new Headers(); // myHeaders.append("Content-Type", "application/json"); + if (!cache[lang]) { + cache[lang] = {}; + } + + if (cache[lang][word]) { + cache[lang][word].frequency += 1; + return cache[lang][word].suggestions; + } + const requestOptions = { method: "GET", }; @@ -37,17 +81,41 @@ export const getTransliterateSuggestions = async ( ); let data = await res.json(); console.log("library data", data); - if(!customApiURL.includes("xlit-api")){ + if (!customApiURL.includes("xlit-api")) { data.result = data.output[0].target; } if (data && data.result.length > 0) { const found = showCurrentWordAsLastSuggestion ? [...data.result, word] : data.result; + + if (Object.keys(cache[lang]).length >= MAX_CACHE_SIZE) { + const lowestFreqWord = getWordWithLowestFrequency(cache[lang]); + if (lowestFreqWord) { + delete cache[lang][lowestFreqWord]; + } + } + + cache[lang][word] = { + suggestions: found, + frequency: 1, + }; + + newEntriesCount += 1; + if (newEntriesCount >= SAVE_THRESHOLD) { + saveCacheToLocalStorage(); + newEntriesCount = 0; + } + return found; } else { if (showCurrentWordAsLastSuggestion) { - return [word]; + const fallback = [word]; + cache[lang][word] = { + suggestions: fallback, + frequency: 1, + }; + return fallback; } return []; } @@ -56,4 +124,6 @@ export const getTransliterateSuggestions = async ( console.error("There was an error with transliteration", e); return []; } -}; \ No newline at end of file +}; + +window.addEventListener('beforeunload', saveCacheToLocalStorage); \ No newline at end of file