UNPKG

@logic-pad/core

Version:
72 lines (71 loc) 2.41 kB
import debounce from 'lodash/debounce.js'; import { Serializer } from './serializer/allSerializers.js'; import validateGrid from './validate.js'; const SYNC_VALIDATION_THRESHOLD = 10000; export class GridValidator { worker = null; stateListeners = new Set(); loadListeners = new Set(); validateGridDebounced = debounce((grid, solution) => { this.worker?.terminate(); this.worker = new Worker(new URL('./validateAsyncWorker.js', import.meta.url), { type: 'module' }); this.worker.onmessage = (event) => { if (event.data) { this.notifyState(event.data); } this.worker?.terminate(); this.worker = null; this.notifyLoad(); }; this.worker.onmessageerror = (error) => { console.error('Validation worker error:', error); this.worker?.terminate(); this.worker = null; this.notifyLoad(); }; this.worker.postMessage({ grid: Serializer.stringifyGrid(grid), solution: solution ? Serializer.stringifyGrid(solution) : null, }); this.notifyLoad(); }, 300, { leading: true, trailing: true }); validateGrid = (grid, solution) => { if (grid.width * grid.height <= SYNC_VALIDATION_THRESHOLD) { // Synchronous validation for small grids // to avoid the overhead of worker communication. const state = validateGrid(grid, solution); this.notifyState(state); } else { this.validateGridDebounced(grid, solution); } }; notifyState = (state) => { this.stateListeners.forEach(listener => listener(state)); }; subscribeToState = (listener) => { this.stateListeners.add(listener); return () => { this.stateListeners.delete(listener); }; }; notifyLoad = () => { this.loadListeners.forEach(listener => listener()); }; subscribeToLoad = (listener) => { this.loadListeners.add(listener); return () => { this.loadListeners.delete(listener); }; }; isLoading = () => { return this.worker !== null; }; delete = () => { if (this.worker) { this.worker.terminate(); this.worker = null; } this.stateListeners.clear(); }; }