Have got a dictionary of words

This commit is contained in:
Leon Mika 2025-01-25 09:45:55 +11:00
parent 5cb44dd17e
commit d9fa154a01
15 changed files with 46459 additions and 39 deletions

2
.gitignore vendored
View file

@ -1,2 +1,4 @@
node_modules/
_site/
build/
.idea/

View file

@ -1,28 +0,0 @@
export class WordSource {
constructor() {
this._words = [
"MUNCH",
"HOUSE",
"MOON"
];
this._currentWord = 0;
}
isWord(word) {
return this._words.filter((x) => x == word).length > 0;
}
getCurrentWord() {
return this._words[this._currentWord];
}
nextWord() {
if (this._currentWord >= this._words.length - 1) {
return false;
}
this._currentWord += 1;
return true;
}
}

72
cmd/prep-words/main.go Normal file
View file

@ -0,0 +1,72 @@
package main
import (
"bufio"
"encoding/json"
"flag"
"log"
"os"
"sort"
)
type wordList struct {
Words map[int][]string `json:"words"`
}
func main() {
dictFile := flag.String("dict", "", "dictionary of word to prep")
flag.Parse()
words := wordList{
Words: make(map[int][]string),
}
if err := scanSuitableWords(*dictFile, func(word string) {
if len(word) >= 4 && len(word) <= 6 {
words.Words[len(word)] = append(words.Words[len(word)], word)
}
}); err != nil {
log.Fatal(err)
}
for _, word := range words.Words {
sort.Strings(word)
}
if err := json.NewEncoder(os.Stdout).Encode(words); err != nil {
log.Fatal(err)
}
}
func scanSuitableWords(dictFile string, withWord func(word string)) error {
f, err := os.Open(dictFile)
if err != nil {
return err
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
isSuitable := true
breakpoint := len(scanner.Text())
for i, r := range scanner.Text() {
if r == '/' {
breakpoint = i
break
}
if r < 'a' || r > 'z' {
isSuitable = false
break
}
}
if isSuitable {
word := scanner.Text()[:breakpoint]
withWord(word)
} else {
}
}
return scanner.Err()
}

2
dict/README.md Normal file
View file

@ -0,0 +1,2 @@
This is a Hunspell dictionary taken from this location:
https://archive.netbsd.org/pub/pkgsrc-archive/distfiles/2019Q4/hunspell-dictionaries/en_GB-20061130/en_GB.zip

46281
dict/en_GB.dic Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,12 @@
export default function(cfg) {
cfg.addPassthroughCopy("assets/styles/main.css");
cfg.addPassthroughCopy("assets/scripts/**/*.js");
cfg.addPassthroughCopy("site/assets/styles/main.css");
cfg.addPassthroughCopy("site/assets/scripts/**/*.js");
cfg.addPassthroughCopy("site/assets/data/*");
return {
dir: {
input: "site",
output: "build/site"
}
};
};

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module lmika.dev/lmika/wordle-clone
go 1.23.3

File diff suppressed because one or more lines are too long

View file

@ -7,10 +7,12 @@ import { WordSource } from "../models/words.js";
export default class extends Controller {
static targets = ["row"];
connect() {
async connect() {
this._wordSource = new WordSource();
this._gameController = new GameController(this._wordSource);
await this._gameController.start();
this._buildPlayfield();
}

View file

@ -13,29 +13,36 @@ export const MARKERS = {
export class GameController {
constructor(wordSource) {
this._wordSource = wordSource;
this._currentWord = wordSource.getCurrentWord();
}
async start() {
this._currentWord = await this._wordSource.getCurrentWord();
this._guesses = 5;
console.log("The current word: " + this._currentWord);
}
wordLength() {
this._checkHasStarted();
return this._currentWord.length;
}
guesses() {
this._checkHasStarted();
return this._guesses;
}
nextWord() {
if (!this._wordSource.nextWord()) {
return false;
}
this._currentWord = this._wordSource.getCurrentWord();
async nextWord() {
this._currentWord = await this._wordSource.getCurrentWord();
this._guesses = 5;
return true;
}
checkGuess(guess) {
this._checkHasStarted();
guess = guess.toLowerCase();
if (guess.length != this._currentWord.length) {
throw Error(`Expected length to be ${this._currentWord.length} but was ${guess.length}`);
}
@ -100,4 +107,10 @@ export class GameController {
markers: markers
};
}
_checkHasStarted() {
if (!this._currentWord) {
throw new Error("call start() first");
}
}
}

View file

@ -0,0 +1,64 @@
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._wordData = null;
this._currentWord = null;
}
isWord(word) {
let list = this._wordData.words[word.length.toString()];
if (!list) {
return false;
}
return binSearch(list, word);
}
async getCurrentWord() {
if (this._currentWord) {
return this._currentWord;
}
let words = await this._fetchAllWordsIfNecessary();
this._currentWord = words.words["4"][7];
return this._currentWord;
}
async nextWord() {
if (this._currentWord >= this._words.length - 1) {
return false;
}
this._currentWord += 1;
return true;
}
async _fetchAllWordsIfNecessary() {
if (this._wordData) {
return this._wordData;
}
let res = await fetch("/assets/data/words.json");
this._wordData = await res.json();
return this._wordData;
}
}