scrabble-cheater
Version:
A simple Scrabble cheating tool.
101 lines (100 loc) • 3.38 kB
JavaScript
import clipboard from 'clipboardy';
import fs from 'node:fs/promises';
import readline from 'node:readline';
const defaultOptions = {
letters: '',
maximum: 0,
quietMode: false,
singleMode: false,
};
export class ScrabbleCheater {
constructor(wordListPath, options) {
this.dictionary = [];
this.wordListPath = wordListPath;
this.options = { ...defaultOptions, ...options };
}
setLetters(letters) {
this.options.letters = letters;
return this;
}
async start() {
const length = await this.loadWords();
if (!length) {
throw new Error('No words loaded. Wordlist file corrupt?');
}
this.log(`${length} word${length > 1 ? 's' : ''} loaded.`);
const letters = this.options.letters ? this.formatLetters(this.options.letters) : await this.readLineAsync();
let matches = this.findMatches(letters);
this.log(`ScrabbleCheater: ${matches.length} matches found`, true);
if (this.options.maximum) {
this.log(`, ${this.options.singleMode ? 'sending' : 'displaying'} the first ${this.options.maximum}`, true);
matches = matches.slice(0, this.options.maximum);
}
this.log('.\n\n', true);
if (this.options.singleMode) {
this.singleOutput(matches);
}
return matches;
}
findMatches(letters) {
const regex = new RegExp(`^[${letters}]+$`);
return this.dictionary.filter(word => regex.test(word)).sort((wordA, wordB) => wordB.length - wordA.length);
}
formatLetters(letters) {
const regex = new RegExp('[^A-Za-z]');
return letters.replace(regex, '').toLowerCase();
}
async loadWords() {
const regex = new RegExp('^[A-Za-z]+$');
const wordList = await fs.readFile(this.wordListPath, 'utf-8');
this.dictionary = wordList.split('\n').filter(value => regex.test(value));
return this.dictionary.length;
}
log(message, raw = false) {
if (!this.options.quietMode) {
if (!raw) {
console.info(`ScrabbleCheater: ${message}`);
}
else {
process.stdout.write(message);
}
}
}
readLineAsync() {
return new Promise((resolve, reject) => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Letters? ', input => {
const letters = this.formatLetters(input);
if (letters) {
resolve(letters);
}
else {
reject(new Error('No letters entered.'));
}
rl.close();
});
});
}
singleOutput(matches) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let counter = 0;
const next = () => {
clipboard.writeSync(matches[counter]);
if (counter < matches.length - 1) {
this.log('Press Enter to copy the next word...');
counter++;
}
else {
return rl.close();
}
};
rl.on('line', next);
next();
}
}