function binSearch(list, word) { let first = 0; let last = list.length; for (;;) { let ptr = (first + (last - first) / 2) | 0; if (list[ptr] === word) { return true; } else if (last - first <= 1) { return false; } else if (list[ptr] > word) { last = ptr; } else if (list[ptr] < word) { first = ptr; } } } export class WordSource { constructor() { this._dataVersion = null; this._wordData = null; this._otherWords = null; this._pattern = null; } isWord(word) { if (!this._wordData || !this._otherWords) { return false; } return binSearch(this._wordData[word.length.toString()], word) || binSearch(this._otherWords[word.length.toString()], word); } async needToResetProgression(prog) { await this._fetchAllWordsIfNecessary(); return !prog || !prog.shuffleId || this._dataVersion !== prog.shuffleId; } async getPattenShuffleID() { return this._dataVersion; } async getCurrentWord(prog) { await this._fetchAllWordsIfNecessary(); let wordLengthKey = prog.wordLength + ""; let wordIndex = prog.wordIndex[wordLengthKey]; let idx = this._pattern[wordLengthKey][wordIndex]; return this._wordData[wordLengthKey][idx]; } async _fetchAllWordsIfNecessary() { if (this._wordData) { return this._wordData; } let data = await (await fetch("/assets/data/data.json")).json(); this._dataVersion = data["versionId"]; this._wordData = data["guessWords"]; this._otherWords = data["otherWords"]; this._pattern = data["shufflePattern"]; } }