UNPKG

scrabble-solver

Version:

Scrabble Solver 2 - Free, open-source, cross-platform, multi-language analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter League, Crossplay, Literaki, and Kelimelik. Quickly find the top-scoring words using the given board and tiles.

92 lines (76 loc) 3.04 kB
import { type Trie } from '@kamilmielnik/trie'; import { getConfig } from '@scrabble-solver/configs'; import { BLANK } from '@scrabble-solver/constants'; import { solve } from '@scrabble-solver/solver'; import { Board, Tile } from '@scrabble-solver/types'; import { registerRoute } from 'workbox-routing'; import { type SolveRequestPayload } from '@/types'; import { average } from './average'; import { revalidateDictionary } from './dictionaries'; import { getTrie } from './getTrie'; const headers = { 'Content-Type': 'application/json; charset=utf-8', }; const MIN_MEASUREMENTS = 5; const localDurations: number[] = []; const serverDurations: number[] = []; export const routeSolveRequests = () => { registerRoute( ({ url }) => url.origin === location.origin && url.pathname === '/api/solve', async ({ request }) => { const requestJson: SolveRequestPayload = await request.clone().json(); const { board, characters, game, locale } = requestJson; const solveLocal = async (trie: Trie): Promise<Response> => { const config = getConfig(game, locale); const tiles = characters.map((character: string) => new Tile({ character, isBlank: character === BLANK })); return new Promise((resolve) => { const resultsJson = solve(trie, config, Board.fromJson(board), tiles); const responseJson = JSON.stringify(resultsJson); resolve(new Response(responseJson, { headers })); }); }; const solveServer = () => fetch(request); const trie = await getTrie(locale); if (trie && typeof isSlowDevice() === 'undefined') { const response = await Promise.race([ (async () => { const start = Date.now(); const result = solveLocal(trie); localDurations.push(Date.now() - start); return result; })(), (async () => { const start = Date.now(); const result = await solveServer(); serverDurations.push(Date.now() - start); return result; })(), ]); // eslint-disable-next-line @typescript-eslint/no-floating-promises revalidateDictionary(locale); return response; } const handleSolve = trie && !isSlowDevice() ? () => solveLocal(trie) : () => solveServer(); const response = await handleSolve(); // eslint-disable-next-line @typescript-eslint/no-floating-promises revalidateDictionary(locale); return response; }, 'POST', ); }; const isSlowDevice = (): boolean | undefined => { if (localDurations.length < MIN_MEASUREMENTS || serverDurations.length < MIN_MEASUREMENTS) { return undefined; } const count = Math.min(localDurations.length, serverDurations.length); const local = localDurations .slice(0, count) .sort((a, b) => a - b) .slice(1, -1); const server = localDurations .slice(0, count) .sort((a, b) => a - b) .slice(1, -1); return average(local) > average(server); };