Have got a dictionary of words
This commit is contained in:
		
							parent
							
								
									5cb44dd17e
								
							
						
					
					
						commit
						d9fa154a01
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -1,2 +1,4 @@ | ||||||
| node_modules/ | node_modules/ | ||||||
| _site/ | _site/ | ||||||
|  | build/ | ||||||
|  | .idea/ | ||||||
|  | @ -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
									
								
							
							
						
						
									
										72
									
								
								cmd/prep-words/main.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										2
									
								
								dict/README.md
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										46281
									
								
								dict/en_GB.dic
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,4 +1,12 @@ | ||||||
| export default function(cfg) { | export default function(cfg) { | ||||||
|   cfg.addPassthroughCopy("assets/styles/main.css"); |   cfg.addPassthroughCopy("site/assets/styles/main.css"); | ||||||
|   cfg.addPassthroughCopy("assets/scripts/**/*.js"); |   cfg.addPassthroughCopy("site/assets/scripts/**/*.js"); | ||||||
|  |   cfg.addPassthroughCopy("site/assets/data/*"); | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     dir: { | ||||||
|  |       input: "site", | ||||||
|  |       output: "build/site" | ||||||
|  |     } | ||||||
|  |   }; | ||||||
| }; | }; | ||||||
							
								
								
									
										1
									
								
								site/assets/data/words.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								site/assets/data/words.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -7,10 +7,12 @@ import { WordSource } from "../models/words.js"; | ||||||
| export default class extends Controller { | export default class extends Controller { | ||||||
|   static targets = ["row"]; |   static targets = ["row"]; | ||||||
|    |    | ||||||
|   connect() {  |   async connect() { | ||||||
|     this._wordSource = new WordSource(); |     this._wordSource = new WordSource(); | ||||||
|     this._gameController = new GameController(this._wordSource); |     this._gameController = new GameController(this._wordSource); | ||||||
| 
 | 
 | ||||||
|  |     await this._gameController.start(); | ||||||
|  | 
 | ||||||
|     this._buildPlayfield(); |     this._buildPlayfield(); | ||||||
|   } |   } | ||||||
|    |    | ||||||
|  | @ -13,29 +13,36 @@ export const MARKERS = { | ||||||
| export class GameController { | export class GameController { | ||||||
|   constructor(wordSource) { |   constructor(wordSource) { | ||||||
|     this._wordSource = wordSource; |     this._wordSource = wordSource; | ||||||
|     this._currentWord = wordSource.getCurrentWord(); |   } | ||||||
|  | 
 | ||||||
|  |   async start() { | ||||||
|  |     this._currentWord = await this._wordSource.getCurrentWord(); | ||||||
|     this._guesses = 5; |     this._guesses = 5; | ||||||
|  | 
 | ||||||
|  |     console.log("The current word: " + this._currentWord); | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   wordLength() { |   wordLength() { | ||||||
|  |     this._checkHasStarted(); | ||||||
|     return this._currentWord.length; |     return this._currentWord.length; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   guesses() { |   guesses() { | ||||||
|  |     this._checkHasStarted(); | ||||||
|     return this._guesses; |     return this._guesses; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   nextWord() { |   async nextWord() { | ||||||
|     if (!this._wordSource.nextWord()) { |     this._currentWord = await this._wordSource.getCurrentWord(); | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     this._currentWord = this._wordSource.getCurrentWord(); |  | ||||||
|     this._guesses = 5; |     this._guesses = 5; | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   checkGuess(guess) { |   checkGuess(guess) { | ||||||
|  |     this._checkHasStarted(); | ||||||
|  | 
 | ||||||
|  |     guess = guess.toLowerCase(); | ||||||
|  | 
 | ||||||
|     if (guess.length != this._currentWord.length) { |     if (guess.length != this._currentWord.length) { | ||||||
|       throw Error(`Expected length to be ${this._currentWord.length} but was ${guess.length}`); |       throw Error(`Expected length to be ${this._currentWord.length} but was ${guess.length}`); | ||||||
|     } |     } | ||||||
|  | @ -100,4 +107,10 @@ export class GameController { | ||||||
|       markers: markers |       markers: markers | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   _checkHasStarted() { | ||||||
|  |     if (!this._currentWord) { | ||||||
|  |       throw new Error("call start() first"); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
							
								
								
									
										64
									
								
								site/assets/scripts/models/words.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								site/assets/scripts/models/words.js
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in a new issue