// Package dict loads the English test dictionary as a DAWG, preferring the serialized // cache under testdata and falling back to building from the dictionaries submodule. // Paths are resolved relative to the repository root so it works both from the repo root // (commands) and from a package directory (tests). package dict import ( "os" "path/filepath" "github.com/iliadenisov/alphabet" dawg "github.com/iliadenisov/dafsa" "scrabble-solver/internal/dictdawg" "scrabble-solver/internal/wordlist" ) // MinLen and MaxLen bound playable word lengths (a 15x15 board holds at most 15). const ( MinLen = 2 MaxLen = 15 ) func exists(p string) bool { _, err := os.Stat(p); return err == nil } // Root returns the repository root by walking up from the working directory to the // directory containing go.mod, or "." if none is found. func Root() string { dir, err := os.Getwd() if err != nil { return "." } for { if exists(filepath.Join(dir, "go.mod")) { return dir } parent := filepath.Dir(dir) if parent == dir { return "." } dir = parent } } // DAWGCache and WordlistPath locate the English cache file and source word list, // relative to the repository root. func DAWGCache() string { return filepath.Join(Root(), "testdata", "sowpods.dawg") } func WordlistPath() string { return filepath.Join(Root(), "dictionaries", "english", "sowpods.txt") } // EnglishAvailable reports whether the English dictionary can be loaded (cache or source). func EnglishAvailable() bool { return exists(DAWGCache()) || exists(WordlistPath()) } // EnglishWords returns the encoded English word list (from the submodule source). func EnglishWords() ([][]byte, error) { return wordlist.Read(WordlistPath(), alphabet.Latin(), MinLen, MaxLen) } // EnglishDAWG returns the English DAWG, loading the cache if present, otherwise building // it from the word list and caching it (best effort). func EnglishDAWG() (dawg.Finder, error) { if exists(DAWGCache()) { return dictdawg.Load(DAWGCache()) } words, err := EnglishWords() if err != nil { return nil, err } f, err := dictdawg.Build(alphabet.Latin(), words) if err != nil { return nil, err } _ = dictdawg.Save(f, DAWGCache()) return f, nil }