scrabble-solver 2.16.7 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/.nx/workspace-data/d/server-process.json +2 -2
  2. package/.nx/workspace-data/file-map.json +548 -572
  3. package/.nx/workspace-data/lockfile-dependencies.hash +1 -1
  4. package/.nx/workspace-data/lockfile-nodes.hash +1 -1
  5. package/.nx/workspace-data/nx_files.nxt +0 -0
  6. package/.nx/workspace-data/parsed-lock-file.dependencies.json +185 -160
  7. package/.nx/workspace-data/parsed-lock-file.nodes.json +406 -370
  8. package/.nx/workspace-data/project-graph.json +656 -552
  9. package/.nx/workspace-data/source-maps.json +96 -0
  10. package/.oxlintrc.json +6 -0
  11. package/CLAUDE.md +22 -17
  12. package/README.md +9 -0
  13. package/bun.lock +107 -133
  14. package/cypress/e2e/app.spec.cy.ts +4 -4
  15. package/cypress/e2e/features/solver-paths.ts +66 -0
  16. package/cypress/e2e/features.spec.cy.ts +1 -0
  17. package/cypress/support/lib/actions.ts +28 -9
  18. package/lerna.json +1 -1
  19. package/package.json +8 -7
  20. package/packages/configs/package.json +3 -3
  21. package/packages/constants/package.json +1 -1
  22. package/packages/dictionaries/README.md +1 -1
  23. package/packages/dictionaries/build/Dictionaries.d.ts +2 -2
  24. package/packages/dictionaries/build/Dictionaries.js +6 -6
  25. package/packages/dictionaries/build/lib/DiskCache.d.ts +11 -4
  26. package/packages/dictionaries/build/lib/DiskCache.js +27 -10
  27. package/packages/dictionaries/build/lib/LayeredCache.d.ts +4 -4
  28. package/packages/dictionaries/build/lib/LayeredCache.js +3 -3
  29. package/packages/dictionaries/build/lib/MemoryCache.d.ts +4 -4
  30. package/packages/dictionaries/build/lib/MemoryCache.js +2 -2
  31. package/packages/dictionaries/build/lib/createCacheTimestampComparator.d.ts +2 -2
  32. package/packages/dictionaries/build/lib/downloadDictionary.d.ts +2 -2
  33. package/packages/dictionaries/build/lib/downloadDictionary.js +4 -3
  34. package/packages/dictionaries/build/lib/getDictionaryFilepath.d.ts +3 -1
  35. package/packages/dictionaries/build/lib/getDictionaryFilepath.js +8 -3
  36. package/packages/dictionaries/package.json +7 -6
  37. package/packages/dictionaries/src/Dictionaries.ts +12 -12
  38. package/packages/dictionaries/src/lib/DiskCache.test.ts +85 -0
  39. package/packages/dictionaries/src/lib/DiskCache.ts +34 -14
  40. package/packages/dictionaries/src/lib/LayeredCache.ts +7 -7
  41. package/packages/dictionaries/src/lib/MemoryCache.ts +6 -6
  42. package/packages/dictionaries/src/lib/createCacheTimestampComparator.ts +2 -2
  43. package/packages/dictionaries/src/lib/downloadDictionary.ts +5 -4
  44. package/packages/dictionaries/src/lib/getDictionaryFilepath.ts +7 -2
  45. package/packages/gaddag/build/Gaddag.d.ts +39 -0
  46. package/packages/gaddag/build/Gaddag.js +128 -0
  47. package/packages/gaddag/build/buildGaddag.d.ts +10 -0
  48. package/packages/gaddag/build/buildGaddag.js +360 -0
  49. package/packages/gaddag/build/constants.d.ts +12 -0
  50. package/packages/gaddag/build/constants.js +15 -0
  51. package/packages/gaddag/build/index.d.ts +3 -0
  52. package/packages/gaddag/build/index.js +13 -0
  53. package/packages/logger/package.json +1 -1
  54. package/packages/scrabble-solver/.next/BUILD_ID +1 -1
  55. package/packages/scrabble-solver/.next/build-manifest.json +13 -13
  56. package/packages/scrabble-solver/.next/cache/.previewinfo +1 -1
  57. package/packages/scrabble-solver/.next/cache/.rscinfo +1 -1
  58. package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
  59. package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
  60. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
  61. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack.old +0 -0
  62. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
  63. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  64. package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
  65. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
  66. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack.old +0 -0
  67. package/packages/scrabble-solver/.next/diagnostics/framework.json +1 -1
  68. package/packages/scrabble-solver/.next/next-server.js.nft.json +1 -1
  69. package/packages/scrabble-solver/.next/prerender-manifest.json +4 -4
  70. package/packages/scrabble-solver/.next/required-server-files.js +3 -2
  71. package/packages/scrabble-solver/.next/required-server-files.json +3 -2
  72. package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
  73. package/packages/scrabble-solver/.next/server/chunks/129.js +1 -0
  74. package/packages/scrabble-solver/.next/server/chunks/30.js +1 -1
  75. package/packages/scrabble-solver/.next/server/chunks/392.js +1 -1
  76. package/packages/scrabble-solver/.next/server/chunks/671.js +1 -1
  77. package/packages/scrabble-solver/.next/server/chunks/712.js +1 -1
  78. package/packages/scrabble-solver/.next/server/chunks/785.js +1 -0
  79. package/packages/scrabble-solver/.next/server/chunks/791.js +1 -1
  80. package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
  81. package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
  82. package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
  83. package/packages/scrabble-solver/.next/server/pages/_app.js +1 -1
  84. package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
  85. package/packages/scrabble-solver/.next/server/pages/_error.js +1 -1
  86. package/packages/scrabble-solver/.next/server/pages/_error.js.nft.json +1 -1
  87. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js +1 -1
  88. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  89. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js +1 -1
  90. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  91. package/packages/scrabble-solver/.next/server/pages/api/solve.js +1 -1
  92. package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
  93. package/packages/scrabble-solver/.next/server/pages/api/verify.js +1 -1
  94. package/packages/scrabble-solver/.next/server/pages/api/verify.js.nft.json +1 -1
  95. package/packages/scrabble-solver/.next/server/pages/index.html +1 -1
  96. package/packages/scrabble-solver/.next/server/pages/index.js +1 -1
  97. package/packages/scrabble-solver/.next/server/pages/index.js.nft.json +1 -1
  98. package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
  99. package/packages/scrabble-solver/.next/server/pages/not-found.html +1 -1
  100. package/packages/scrabble-solver/.next/server/pages/not-found.js.nft.json +1 -1
  101. package/packages/scrabble-solver/.next/server/pages-manifest.json +1 -1
  102. package/packages/scrabble-solver/.next/server/webpack-runtime.js +1 -1
  103. package/packages/scrabble-solver/.next/static/{vYpMmuC_yEurZGcyGVnLf → OLE8_ZInlGH7ENU0NIOpf}/_buildManifest.js +1 -1
  104. package/packages/scrabble-solver/.next/static/chunks/583.7a46807be14c377e.js +1 -0
  105. package/packages/scrabble-solver/.next/static/chunks/830.661816bf0de8c2f1.js +1 -0
  106. package/packages/scrabble-solver/.next/static/chunks/{main-852475ca502b4e49.js → main-5b999f3f24ebfa84.js} +2 -2
  107. package/packages/scrabble-solver/.next/static/chunks/pages/_app-7024e7a27ffbb2fa.js +7 -0
  108. package/packages/scrabble-solver/.next/static/chunks/pages/{index-ec0f6aeeaf7be227.js → index-8b398b0a5d870773.js} +1 -1
  109. package/packages/scrabble-solver/.next/static/chunks/webpack-3943d624bbb47a64.js +1 -0
  110. package/packages/scrabble-solver/.next/static/css/aedeaada218d7280.css +2 -0
  111. package/packages/scrabble-solver/.next/trace +21 -21
  112. package/packages/scrabble-solver/.next/trace-build +1 -1
  113. package/packages/scrabble-solver/next.config.js +0 -6
  114. package/packages/scrabble-solver/package.json +10 -10
  115. package/packages/scrabble-solver/public/service-worker.js +2 -2
  116. package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.tsx +4 -1
  117. package/packages/scrabble-solver/src/components/Board/hooks/useGrid.ts +17 -6
  118. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss +7 -22
  119. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.tsx +1 -8
  120. package/packages/scrabble-solver/src/components/Results/Result.tsx +0 -3
  121. package/packages/scrabble-solver/src/components/Results/Results.module.scss +0 -1
  122. package/packages/scrabble-solver/src/components/Results/Results.tsx +10 -2
  123. package/packages/scrabble-solver/src/components/Results/types.ts +3 -3
  124. package/packages/scrabble-solver/src/components/Solver/Solver.tsx +4 -3
  125. package/packages/scrabble-solver/src/components/Tooltip/useTooltip.ts +1 -1
  126. package/packages/scrabble-solver/src/pages/api/dictionary/[locale]/[word].ts +2 -2
  127. package/packages/scrabble-solver/src/pages/api/dictionary/[locale]/index.ts +80 -3
  128. package/packages/scrabble-solver/src/pages/api/solve.ts +2 -2
  129. package/packages/scrabble-solver/src/pages/api/verify.ts +12 -3
  130. package/packages/scrabble-solver/src/sdk/solve.ts +13 -7
  131. package/packages/scrabble-solver/src/sdk/verify.ts +12 -6
  132. package/packages/scrabble-solver/src/service-worker/appShell.test.ts +86 -0
  133. package/packages/scrabble-solver/src/service-worker/appShell.ts +39 -0
  134. package/packages/scrabble-solver/src/service-worker/index.ts +4 -5
  135. package/packages/scrabble-solver/src/serviceWorkerManager.ts +1 -18
  136. package/packages/scrabble-solver/src/solver-worker/client.test.ts +151 -0
  137. package/packages/scrabble-solver/src/solver-worker/client.ts +106 -0
  138. package/packages/scrabble-solver/src/solver-worker/dictionaries/constants.ts +9 -0
  139. package/packages/scrabble-solver/src/solver-worker/dictionaries/getDictionary.ts +21 -0
  140. package/packages/scrabble-solver/src/solver-worker/dictionaries/index.ts +2 -0
  141. package/packages/scrabble-solver/src/solver-worker/dictionaries/revalidateDictionary.test.ts +199 -0
  142. package/packages/scrabble-solver/src/solver-worker/dictionaries/revalidateDictionary.ts +86 -0
  143. package/packages/scrabble-solver/src/solver-worker/dictionaries/revalidatedAt.ts +43 -0
  144. package/packages/scrabble-solver/src/solver-worker/getGaddag.test.ts +109 -0
  145. package/packages/scrabble-solver/src/solver-worker/getGaddag.ts +62 -0
  146. package/packages/scrabble-solver/src/solver-worker/index.ts +1 -0
  147. package/packages/scrabble-solver/src/solver-worker/index.worker.ts +124 -0
  148. package/packages/scrabble-solver/src/solver-worker/messages.ts +20 -0
  149. package/packages/scrabble-solver/src/state/index.ts +1 -0
  150. package/packages/scrabble-solver/src/state/sagas.ts +19 -9
  151. package/packages/scrabble-solver/src/state/useTypedStore.ts +6 -0
  152. package/packages/scrabble-solver/src/types/api.ts +1 -2
  153. package/packages/scrabble-solver/tsconfig.json +4 -0
  154. package/packages/scrabble-solver/tsconfig.tsbuildinfo +1 -1
  155. package/packages/solver/README.md +24 -0
  156. package/packages/solver/benchmarks/index.ts +15 -0
  157. package/packages/solver/benchmarks/lib.ts +31 -0
  158. package/packages/solver/benchmarks/renderChart.ts +165 -0
  159. package/packages/solver/benchmarks/results/chart.svg +65 -0
  160. package/packages/solver/benchmarks/runBenchmarks.ts +66 -0
  161. package/packages/solver/benchmarks/scenarios.ts +64 -0
  162. package/packages/solver/benchmarks/types.ts +16 -0
  163. package/packages/solver/benchmarks/updateReadme.ts +53 -0
  164. package/packages/solver/build/MoveGenerator.d.ts +116 -0
  165. package/packages/solver/build/MoveGenerator.js +686 -0
  166. package/packages/solver/build/index.d.ts +0 -13
  167. package/packages/solver/build/index.js +1 -27
  168. package/packages/solver/build/solve.d.ts +2 -2
  169. package/packages/solver/build/solve.js +3 -19
  170. package/packages/solver/package.json +7 -6
  171. package/packages/solver/src/MoveGenerator.test.ts +1009 -0
  172. package/packages/solver/src/MoveGenerator.ts +926 -0
  173. package/packages/solver/src/ReferenceSolver.ts +401 -0
  174. package/packages/solver/src/index.ts +0 -13
  175. package/packages/solver/src/solve.test.ts +21 -21
  176. package/packages/solver/src/solve.ts +4 -22
  177. package/packages/solver/tsconfig.json +1 -1
  178. package/packages/types/build/Cell.d.ts +1 -0
  179. package/packages/types/build/Cell.js +3 -0
  180. package/packages/types/build/Result.d.ts +3 -2
  181. package/packages/types/build/Result.js +11 -6
  182. package/packages/types/build/ResultJson.d.ts +5 -4
  183. package/packages/types/build/index.d.ts +0 -6
  184. package/packages/types/build/index.js +1 -9
  185. package/packages/types/build/readResultCells.d.ts +5 -0
  186. package/packages/types/build/readResultCells.js +75 -0
  187. package/packages/types/package.json +4 -3
  188. package/packages/types/src/Cell.ts +4 -0
  189. package/packages/types/src/Result.ts +15 -6
  190. package/packages/types/src/ResultJson.ts +5 -5
  191. package/packages/types/src/index.ts +0 -6
  192. package/packages/types/src/readResultCells.test.ts +140 -0
  193. package/packages/types/src/readResultCells.ts +90 -0
  194. package/packages/word-definitions/package.json +2 -2
  195. package/packages/word-lists/package.json +2 -2
  196. package/packages/scrabble-solver/.next/static/chunks/pages/_app-a5bbe02710f13d05.js +0 -7
  197. package/packages/scrabble-solver/.next/static/chunks/webpack-1a7a166b34ed8d24.js +0 -1
  198. package/packages/scrabble-solver/.next/static/css/0af35adb4bab56f0.css +0 -2
  199. package/packages/scrabble-solver/src/sdk/getDictionary.ts +0 -9
  200. package/packages/scrabble-solver/src/service-worker/average.ts +0 -7
  201. package/packages/scrabble-solver/src/service-worker/dictionaries/constants.ts +0 -5
  202. package/packages/scrabble-solver/src/service-worker/dictionaries/getDictionary.ts +0 -20
  203. package/packages/scrabble-solver/src/service-worker/dictionaries/index.ts +0 -2
  204. package/packages/scrabble-solver/src/service-worker/dictionaries/revalidateDictionary.ts +0 -33
  205. package/packages/scrabble-solver/src/service-worker/getTrie.ts +0 -24
  206. package/packages/scrabble-solver/src/service-worker/routeSolveRequests.ts +0 -91
  207. package/packages/scrabble-solver/src/service-worker/routeVerifyRequests.ts +0 -37
  208. package/packages/solver/build/areDigraphsValid.d.ts +0 -2
  209. package/packages/solver/build/areDigraphsValid.js +0 -17
  210. package/packages/solver/build/fillPattern.d.ts +0 -6
  211. package/packages/solver/build/fillPattern.js +0 -52
  212. package/packages/solver/build/generateEndIndices.d.ts +0 -2
  213. package/packages/solver/build/generateEndIndices.js +0 -17
  214. package/packages/solver/build/generateHorizontalPatterns.d.ts +0 -2
  215. package/packages/solver/build/generateHorizontalPatterns.js +0 -16
  216. package/packages/solver/build/generatePattern.d.ts +0 -7
  217. package/packages/solver/build/generatePattern.js +0 -20
  218. package/packages/solver/build/generatePatterns.d.ts +0 -2
  219. package/packages/solver/build/generatePatterns.js +0 -11
  220. package/packages/solver/build/generateStartIndices.d.ts +0 -2
  221. package/packages/solver/build/generateStartIndices.js +0 -16
  222. package/packages/solver/build/generateVectors.d.ts +0 -7
  223. package/packages/solver/build/generateVectors.js +0 -7
  224. package/packages/solver/build/generateVerticalPatterns.d.ts +0 -2
  225. package/packages/solver/build/generateVerticalPatterns.js +0 -16
  226. package/packages/solver/build/getCellsScore.d.ts +0 -2
  227. package/packages/solver/build/getCellsScore.js +0 -18
  228. package/packages/solver/build/getPatternHash.d.ts +0 -2
  229. package/packages/solver/build/getPatternHash.js +0 -14
  230. package/packages/solver/build/getPatternScore.d.ts +0 -2
  231. package/packages/solver/build/getPatternScore.js +0 -22
  232. package/packages/solver/build/getUniquePatterns.d.ts +0 -2
  233. package/packages/solver/build/getUniquePatterns.js +0 -17
  234. package/packages/solver/src/areDigraphsValid.ts +0 -18
  235. package/packages/solver/src/fillPattern.test.ts +0 -107
  236. package/packages/solver/src/fillPattern.ts +0 -68
  237. package/packages/solver/src/generateEndIndices.test.ts +0 -23
  238. package/packages/solver/src/generateEndIndices.ts +0 -19
  239. package/packages/solver/src/generateHorizontalPatterns.test.ts +0 -31
  240. package/packages/solver/src/generateHorizontalPatterns.ts +0 -15
  241. package/packages/solver/src/generatePattern.ts +0 -33
  242. package/packages/solver/src/generatePatterns.test.ts +0 -13
  243. package/packages/solver/src/generatePatterns.ts +0 -11
  244. package/packages/solver/src/generateStartIndices.test.ts +0 -19
  245. package/packages/solver/src/generateStartIndices.ts +0 -17
  246. package/packages/solver/src/generateVectors.test.ts +0 -12
  247. package/packages/solver/src/generateVectors.ts +0 -10
  248. package/packages/solver/src/generateVerticalPatterns.test.ts +0 -32
  249. package/packages/solver/src/generateVerticalPatterns.ts +0 -15
  250. package/packages/solver/src/getCellsScore.ts +0 -21
  251. package/packages/solver/src/getPatternHash.test.ts +0 -17
  252. package/packages/solver/src/getPatternHash.ts +0 -12
  253. package/packages/solver/src/getPatternScore.test.ts +0 -204
  254. package/packages/solver/src/getPatternScore.ts +0 -23
  255. package/packages/solver/src/getUniquePatterns.ts +0 -19
  256. package/packages/types/build/CollisionJson.d.ts +0 -2
  257. package/packages/types/build/CollisionJson.js +0 -2
  258. package/packages/types/build/FinalPattern.d.ts +0 -6
  259. package/packages/types/build/FinalPattern.js +0 -14
  260. package/packages/types/build/HorizontalPattern.d.ts +0 -5
  261. package/packages/types/build/HorizontalPattern.js +0 -34
  262. package/packages/types/build/Pattern.d.ts +0 -20
  263. package/packages/types/build/Pattern.js +0 -50
  264. package/packages/types/build/PatternJson.d.ts +0 -6
  265. package/packages/types/build/PatternJson.js +0 -2
  266. package/packages/types/build/VerticalPattern.d.ts +0 -5
  267. package/packages/types/build/VerticalPattern.js +0 -34
  268. package/packages/types/src/CollisionJson.ts +0 -3
  269. package/packages/types/src/FinalPattern.ts +0 -14
  270. package/packages/types/src/HorizontalPattern.ts +0 -37
  271. package/packages/types/src/Pattern.ts +0 -71
  272. package/packages/types/src/PatternJson.ts +0 -7
  273. package/packages/types/src/VerticalPattern.ts +0 -37
  274. /package/packages/scrabble-solver/.next/static/{vYpMmuC_yEurZGcyGVnLf → OLE8_ZInlGH7ENU0NIOpf}/_ssgManifest.js +0 -0
  275. /package/packages/scrabble-solver/src/{service-worker → solver-worker}/dictionaries/expirationManager.ts +0 -0
  276. /package/packages/scrabble-solver/src/{service-worker → solver-worker}/dictionaries/getDictionaryUrl.ts +0 -0
@@ -0,0 +1,360 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildGaddag = void 0;
4
+ /* eslint-disable max-depth, max-lines, max-statements, no-bitwise */
5
+ const constants_1 = require("./constants");
6
+ const Gaddag_1 = require("./Gaddag");
7
+ /**
8
+ * Builds a minimal GADDAG from a word list.
9
+ *
10
+ * The construction generates every GADDAG sequence (`reverse(prefix) [+ ◇ + suffix]`)
11
+ * as a compact `(wordIndex << 6) | splitIndex` integer, orders them with an in-place
12
+ * MSD radix sort, and feeds them to an incremental minimal-automaton builder
13
+ * (Daciuk et al., 2000) backed by typed arrays and an open-addressing state registry.
14
+ */
15
+ const buildGaddag = (words) => {
16
+ const { charCodes, letterByCharCode } = buildAlphabet(words);
17
+ const { itemsCount, wordBytes, wordOffsets, wordsCount } = encodeWords(words, letterByCharCode);
18
+ const items = generateItems(wordsCount, wordOffsets, itemsCount);
19
+ sortItems(items, wordBytes, wordOffsets);
20
+ return insertItems(items, wordBytes, wordOffsets, charCodes);
21
+ };
22
+ exports.buildGaddag = buildGaddag;
23
+ const buildAlphabet = (words) => {
24
+ const codes = new Set();
25
+ for (const word of words) {
26
+ if (word.length > constants_1.MAX_WORD_LENGTH) {
27
+ continue;
28
+ }
29
+ for (let index = 0; index < word.length; ++index) {
30
+ codes.add(word.charCodeAt(index));
31
+ }
32
+ }
33
+ if (codes.size > constants_1.MAX_LETTERS) {
34
+ throw new Error(`Gaddag supports up to ${constants_1.MAX_LETTERS} distinct characters, got ${codes.size}`);
35
+ }
36
+ const charCodes = Int32Array.from([...codes].sort((a, b) => a - b));
37
+ const letterByCharCode = new Map();
38
+ for (let index = 0; index < charCodes.length; ++index) {
39
+ letterByCharCode.set(charCodes[index], index + 1);
40
+ }
41
+ return { charCodes, letterByCharCode };
42
+ };
43
+ const encodeWords = (words, letterByCharCode) => {
44
+ let totalLength = 0;
45
+ let wordsCount = 0;
46
+ for (const word of words) {
47
+ if (word.length === 0 || word.length > constants_1.MAX_WORD_LENGTH) {
48
+ continue;
49
+ }
50
+ totalLength += word.length;
51
+ ++wordsCount;
52
+ }
53
+ if (wordsCount >= 1 << 25) {
54
+ throw new Error('Gaddag supports up to 33M words');
55
+ }
56
+ const wordBytes = new Uint8Array(totalLength);
57
+ const wordOffsets = new Int32Array(wordsCount + 1);
58
+ let offset = 0;
59
+ let wordIndex = 0;
60
+ for (const word of words) {
61
+ if (word.length === 0 || word.length > constants_1.MAX_WORD_LENGTH) {
62
+ continue;
63
+ }
64
+ wordOffsets[wordIndex] = offset;
65
+ for (let index = 0; index < word.length; ++index) {
66
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
+ wordBytes[offset] = letterByCharCode.get(word.charCodeAt(index));
68
+ ++offset;
69
+ }
70
+ ++wordIndex;
71
+ }
72
+ wordOffsets[wordsCount] = offset;
73
+ return { itemsCount: totalLength, wordBytes, wordOffsets, wordsCount };
74
+ };
75
+ const generateItems = (wordsCount, wordOffsets, itemsCount) => {
76
+ const items = new Int32Array(itemsCount);
77
+ let itemIndex = 0;
78
+ for (let wordIndex = 0; wordIndex < wordsCount; ++wordIndex) {
79
+ const length = wordOffsets[wordIndex + 1] - wordOffsets[wordIndex];
80
+ for (let split = 1; split <= length; ++split) {
81
+ items[itemIndex] = (wordIndex << 6) | split;
82
+ ++itemIndex;
83
+ }
84
+ }
85
+ return items;
86
+ };
87
+ /**
88
+ * Radix character of sequence `item` at position `depth`:
89
+ * 0 = end of sequence, 1 = separator, letter + 1 otherwise.
90
+ */
91
+ const charAt = (item, depth, wordBytes, wordOffsets) => {
92
+ const wordIndex = item >>> 6;
93
+ const split = item & 63;
94
+ const offset = wordOffsets[wordIndex];
95
+ if (depth < split) {
96
+ return wordBytes[offset + split - 1 - depth] + 1;
97
+ }
98
+ if (depth === split) {
99
+ return split < wordOffsets[wordIndex + 1] - offset ? 1 : 0;
100
+ }
101
+ return depth <= wordOffsets[wordIndex + 1] - offset ? wordBytes[offset + depth - 1] + 1 : 0;
102
+ };
103
+ const RADIX = constants_1.MAX_LETTERS + 2;
104
+ const sortItems = (items, wordBytes, wordOffsets) => {
105
+ const auxiliary = new Int32Array(items.length);
106
+ const counts = new Int32Array(RADIX);
107
+ const starts = new Int32Array(RADIX);
108
+ // Manual stack of (low, high, depth) ranges to avoid recursion.
109
+ let stack = new Int32Array(3 * 64);
110
+ let stackTop = 0;
111
+ const push = (low, high, depth) => {
112
+ if (stackTop + 3 > stack.length) {
113
+ const grown = new Int32Array(stack.length * 2);
114
+ grown.set(stack);
115
+ stack = grown;
116
+ }
117
+ stack[stackTop] = low;
118
+ stack[stackTop + 1] = high;
119
+ stack[stackTop + 2] = depth;
120
+ stackTop += 3;
121
+ };
122
+ push(0, items.length, 0);
123
+ while (stackTop > 0) {
124
+ stackTop -= 3;
125
+ const low = stack[stackTop];
126
+ const high = stack[stackTop + 1];
127
+ let depth = stack[stackTop + 2];
128
+ if (high - low < 2) {
129
+ continue;
130
+ }
131
+ for (;;) {
132
+ counts.fill(0);
133
+ for (let index = low; index < high; ++index) {
134
+ ++counts[charAt(items[index], depth, wordBytes, wordOffsets)];
135
+ }
136
+ // Skip scatter when the whole range shares the character at this depth.
137
+ let singleBucket = -1;
138
+ for (let bucket = 0; bucket < RADIX; ++bucket) {
139
+ if (counts[bucket] === high - low) {
140
+ singleBucket = bucket;
141
+ break;
142
+ }
143
+ if (counts[bucket] > 0) {
144
+ break;
145
+ }
146
+ }
147
+ if (singleBucket > 0) {
148
+ ++depth;
149
+ continue;
150
+ }
151
+ if (singleBucket === 0) {
152
+ break;
153
+ }
154
+ let position = low;
155
+ for (let bucket = 0; bucket < RADIX; ++bucket) {
156
+ starts[bucket] = position;
157
+ position += counts[bucket];
158
+ }
159
+ for (let index = low; index < high; ++index) {
160
+ const item = items[index];
161
+ auxiliary[starts[charAt(item, depth, wordBytes, wordOffsets)]++] = item;
162
+ }
163
+ items.set(auxiliary.subarray(low, high), low);
164
+ // After the scatter, starts[bucket] holds the end position of each bucket.
165
+ for (let bucket = 1; bucket < RADIX; ++bucket) {
166
+ if (counts[bucket] > 1) {
167
+ push(starts[bucket] - counts[bucket], starts[bucket], depth + 1);
168
+ }
169
+ }
170
+ break;
171
+ }
172
+ }
173
+ };
174
+ const MAX_DEPTH = constants_1.MAX_WORD_LENGTH + 2;
175
+ const MAX_ARCS_PER_STATE = constants_1.MAX_LETTERS + 1;
176
+ class Builder {
177
+ constructor() {
178
+ // Frozen arcs (1-indexed; index 0 is a sentinel).
179
+ this.labels = new Uint8Array(1 << 20);
180
+ this.targets = new Int32Array(1 << 20);
181
+ this.arcTop = 1;
182
+ // Open-addressing registry of frozen states, storing first-arc indices (0 = empty slot).
183
+ this.table = new Int32Array(1 << 20);
184
+ this.tableCount = 0;
185
+ // Temporary (not yet minimized) states along the current insertion path.
186
+ this.pathLetters = new Uint8Array(MAX_DEPTH * MAX_ARCS_PER_STATE);
187
+ this.pathTargets = new Int32Array(MAX_DEPTH * MAX_ARCS_PER_STATE);
188
+ this.pathCounts = new Int32Array(MAX_DEPTH);
189
+ this.pathFinal = new Uint8Array(MAX_DEPTH);
190
+ this.previous = new Uint8Array(MAX_DEPTH);
191
+ this.previousLength = 0;
192
+ }
193
+ insert(sequence, length) {
194
+ const { previous, pathCounts, pathFinal } = this;
195
+ let commonPrefixLength = 0;
196
+ const maxCommon = Math.min(length, this.previousLength);
197
+ while (commonPrefixLength < maxCommon && sequence[commonPrefixLength] === previous[commonPrefixLength]) {
198
+ ++commonPrefixLength;
199
+ }
200
+ if (commonPrefixLength === length && commonPrefixLength === this.previousLength) {
201
+ return; // Duplicate sequence.
202
+ }
203
+ for (let depth = this.previousLength; depth > commonPrefixLength; --depth) {
204
+ this.freeze(depth);
205
+ }
206
+ for (let depth = commonPrefixLength; depth < length; ++depth) {
207
+ const base = depth * MAX_ARCS_PER_STATE;
208
+ this.pathLetters[base + pathCounts[depth]] = sequence[depth];
209
+ this.pathTargets[base + pathCounts[depth]] = 0;
210
+ ++pathCounts[depth];
211
+ pathCounts[depth + 1] = 0;
212
+ pathFinal[depth + 1] = 0;
213
+ }
214
+ pathFinal[length] = 1;
215
+ previous.set(sequence.subarray(0, length));
216
+ this.previousLength = length;
217
+ }
218
+ finish(charCodes) {
219
+ for (let depth = this.previousLength; depth > 0; --depth) {
220
+ this.freeze(depth);
221
+ }
222
+ const rootRef = this.registerState(0);
223
+ const labels = this.labels.slice(0, this.arcTop);
224
+ const targets = this.targets.slice(0, this.arcTop);
225
+ return new Gaddag_1.Gaddag(labels, targets, rootRef, charCodes);
226
+ }
227
+ /** Minimizes the state at `depth` and patches its parent's dangling arc. */
228
+ freeze(depth) {
229
+ const ref = this.registerState(depth);
230
+ const parentBase = (depth - 1) * MAX_ARCS_PER_STATE;
231
+ this.pathTargets[parentBase + this.pathCounts[depth - 1] - 1] = ref;
232
+ }
233
+ /** Returns the ref of a frozen state equivalent to the temporary state at `depth`. */
234
+ registerState(depth) {
235
+ const count = this.pathCounts[depth];
236
+ const final = this.pathFinal[depth];
237
+ if (count === 0) {
238
+ return final;
239
+ }
240
+ const base = depth * MAX_ARCS_PER_STATE;
241
+ const hash = this.hashPath(base, count);
242
+ const mask = this.table.length - 1;
243
+ let slot = hash & mask;
244
+ for (;;) {
245
+ const existing = this.table[slot];
246
+ if (existing === 0) {
247
+ break;
248
+ }
249
+ if (this.equalsPath(existing, base, count)) {
250
+ return (existing << 1) | final;
251
+ }
252
+ slot = (slot + 1) & mask;
253
+ }
254
+ const firstArc = this.appendArcs(base, count);
255
+ this.table[slot] = firstArc;
256
+ ++this.tableCount;
257
+ if (this.tableCount * 10 > this.table.length * 7) {
258
+ this.growTable();
259
+ }
260
+ return (firstArc << 1) | final;
261
+ }
262
+ hashPath(base, count) {
263
+ let hash = 0x811c9dc5 ^ count;
264
+ for (let index = 0; index < count; ++index) {
265
+ hash = Math.imul(hash ^ this.pathLetters[base + index], 16777619);
266
+ hash = Math.imul(hash ^ this.pathTargets[base + index], 16777619);
267
+ }
268
+ return hash >>> 0;
269
+ }
270
+ hashFrozen(firstArc) {
271
+ let count = 0;
272
+ for (let index = firstArc;; ++index) {
273
+ ++count;
274
+ if (this.labels[index] >= constants_1.LAST_ARC_FLAG) {
275
+ break;
276
+ }
277
+ }
278
+ let hash = 0x811c9dc5 ^ count;
279
+ for (let index = 0; index < count; ++index) {
280
+ hash = Math.imul(hash ^ (this.labels[firstArc + index] & constants_1.LETTER_MASK), 16777619);
281
+ hash = Math.imul(hash ^ this.targets[firstArc + index], 16777619);
282
+ }
283
+ return hash >>> 0;
284
+ }
285
+ equalsPath(firstArc, base, count) {
286
+ for (let index = 0; index < count; ++index) {
287
+ const label = this.labels[firstArc + index];
288
+ if ((label & constants_1.LETTER_MASK) !== this.pathLetters[base + index]) {
289
+ return false;
290
+ }
291
+ if (this.targets[firstArc + index] !== this.pathTargets[base + index]) {
292
+ return false;
293
+ }
294
+ const isLast = label >= constants_1.LAST_ARC_FLAG;
295
+ if (isLast !== (index === count - 1)) {
296
+ return false;
297
+ }
298
+ }
299
+ return true;
300
+ }
301
+ appendArcs(base, count) {
302
+ if (this.arcTop + count > this.labels.length) {
303
+ const capacity = Math.max(this.labels.length * 2, this.arcTop + count);
304
+ const labels = new Uint8Array(capacity);
305
+ labels.set(this.labels);
306
+ this.labels = labels;
307
+ const targets = new Int32Array(capacity);
308
+ targets.set(this.targets);
309
+ this.targets = targets;
310
+ }
311
+ const firstArc = this.arcTop;
312
+ for (let index = 0; index < count; ++index) {
313
+ this.labels[this.arcTop] = this.pathLetters[base + index] | (index === count - 1 ? constants_1.LAST_ARC_FLAG : 0);
314
+ this.targets[this.arcTop] = this.pathTargets[base + index];
315
+ ++this.arcTop;
316
+ }
317
+ return firstArc;
318
+ }
319
+ growTable() {
320
+ const previousTable = this.table;
321
+ this.table = new Int32Array(previousTable.length * 2);
322
+ const mask = this.table.length - 1;
323
+ for (const firstArc of previousTable) {
324
+ if (firstArc === 0) {
325
+ continue;
326
+ }
327
+ let slot = this.hashFrozen(firstArc) & mask;
328
+ while (this.table[slot] !== 0) {
329
+ slot = (slot + 1) & mask;
330
+ }
331
+ this.table[slot] = firstArc;
332
+ }
333
+ }
334
+ }
335
+ const insertItems = (items, wordBytes, wordOffsets, charCodes) => {
336
+ const builder = new Builder();
337
+ const sequence = new Uint8Array(MAX_DEPTH);
338
+ for (let index = 0; index < items.length; ++index) {
339
+ const item = items[index];
340
+ const wordIndex = item >>> 6;
341
+ const split = item & 63;
342
+ const offset = wordOffsets[wordIndex];
343
+ const length = wordOffsets[wordIndex + 1] - offset;
344
+ let sequenceLength = 0;
345
+ for (let position = split - 1; position >= 0; --position) {
346
+ sequence[sequenceLength] = wordBytes[offset + position];
347
+ ++sequenceLength;
348
+ }
349
+ if (split < length) {
350
+ sequence[sequenceLength] = 0;
351
+ ++sequenceLength;
352
+ for (let position = split; position < length; ++position) {
353
+ sequence[sequenceLength] = wordBytes[offset + position];
354
+ ++sequenceLength;
355
+ }
356
+ }
357
+ builder.insert(sequence, sequenceLength);
358
+ }
359
+ return builder.finish(charCodes);
360
+ };
@@ -0,0 +1,12 @@
1
+ /** Letter index reserved for the GADDAG separator (◇). */
2
+ export declare const SEPARATOR = 0;
3
+ /** Letters are stored on 6 bits (1..63); 0 is the separator. */
4
+ export declare const MAX_LETTERS = 63;
5
+ /** Words longer than this are skipped — they cannot fit on any board. */
6
+ export declare const MAX_WORD_LENGTH = 63;
7
+ /** Arc label bit marking the last arc of a state. */
8
+ export declare const LAST_ARC_FLAG = 128;
9
+ /** Mask extracting the letter from an arc label. */
10
+ export declare const LETTER_MASK = 63;
11
+ /** "GDG1" magic number opening the binary serialization format. */
12
+ export declare const MAGIC = 826754119;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAGIC = exports.LETTER_MASK = exports.LAST_ARC_FLAG = exports.MAX_WORD_LENGTH = exports.MAX_LETTERS = exports.SEPARATOR = void 0;
4
+ /** Letter index reserved for the GADDAG separator (◇). */
5
+ exports.SEPARATOR = 0;
6
+ /** Letters are stored on 6 bits (1..63); 0 is the separator. */
7
+ exports.MAX_LETTERS = 63;
8
+ /** Words longer than this are skipped — they cannot fit on any board. */
9
+ exports.MAX_WORD_LENGTH = 63;
10
+ /** Arc label bit marking the last arc of a state. */
11
+ exports.LAST_ARC_FLAG = 128;
12
+ /** Mask extracting the letter from an arc label. */
13
+ exports.LETTER_MASK = 63;
14
+ /** "GDG1" magic number opening the binary serialization format. */
15
+ exports.MAGIC = 0x31474447;
@@ -0,0 +1,3 @@
1
+ export { buildGaddag } from './buildGaddag';
2
+ export { LAST_ARC_FLAG, LETTER_MASK, MAX_LETTERS, MAX_WORD_LENGTH, SEPARATOR } from './constants';
3
+ export { Gaddag } from './Gaddag';
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Gaddag = exports.SEPARATOR = exports.MAX_WORD_LENGTH = exports.MAX_LETTERS = exports.LETTER_MASK = exports.LAST_ARC_FLAG = exports.buildGaddag = void 0;
4
+ var buildGaddag_1 = require("./buildGaddag");
5
+ Object.defineProperty(exports, "buildGaddag", { enumerable: true, get: function () { return buildGaddag_1.buildGaddag; } });
6
+ var constants_1 = require("./constants");
7
+ Object.defineProperty(exports, "LAST_ARC_FLAG", { enumerable: true, get: function () { return constants_1.LAST_ARC_FLAG; } });
8
+ Object.defineProperty(exports, "LETTER_MASK", { enumerable: true, get: function () { return constants_1.LETTER_MASK; } });
9
+ Object.defineProperty(exports, "MAX_LETTERS", { enumerable: true, get: function () { return constants_1.MAX_LETTERS; } });
10
+ Object.defineProperty(exports, "MAX_WORD_LENGTH", { enumerable: true, get: function () { return constants_1.MAX_WORD_LENGTH; } });
11
+ Object.defineProperty(exports, "SEPARATOR", { enumerable: true, get: function () { return constants_1.SEPARATOR; } });
12
+ var Gaddag_1 = require("./Gaddag");
13
+ Object.defineProperty(exports, "Gaddag", { enumerable: true, get: function () { return Gaddag_1.Gaddag; } });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/logger",
3
- "version": "2.16.7",
3
+ "version": "2.17.0",
4
4
  "description": "Scrabble Solver 2 - Logger",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -1 +1 @@
1
- vYpMmuC_yEurZGcyGVnLf
1
+ OLE8_ZInlGH7ENU0NIOpf
@@ -4,36 +4,36 @@
4
4
  ],
5
5
  "devFiles": [],
6
6
  "lowPriorityFiles": [
7
- "static/vYpMmuC_yEurZGcyGVnLf/_buildManifest.js",
8
- "static/vYpMmuC_yEurZGcyGVnLf/_ssgManifest.js"
7
+ "static/OLE8_ZInlGH7ENU0NIOpf/_buildManifest.js",
8
+ "static/OLE8_ZInlGH7ENU0NIOpf/_ssgManifest.js"
9
9
  ],
10
10
  "rootMainFiles": [],
11
11
  "rootMainFilesTree": {},
12
12
  "pages": {
13
13
  "/": [
14
- "static/chunks/webpack-1a7a166b34ed8d24.js",
14
+ "static/chunks/webpack-3943d624bbb47a64.js",
15
15
  "static/chunks/framework-3cf15b8041c59dd3.js",
16
- "static/chunks/main-852475ca502b4e49.js",
16
+ "static/chunks/main-5b999f3f24ebfa84.js",
17
17
  "static/css/a78e04fe95452380.css",
18
- "static/chunks/pages/index-ec0f6aeeaf7be227.js"
18
+ "static/chunks/pages/index-8b398b0a5d870773.js"
19
19
  ],
20
20
  "/_app": [
21
- "static/chunks/webpack-1a7a166b34ed8d24.js",
21
+ "static/chunks/webpack-3943d624bbb47a64.js",
22
22
  "static/chunks/framework-3cf15b8041c59dd3.js",
23
- "static/chunks/main-852475ca502b4e49.js",
24
- "static/css/0af35adb4bab56f0.css",
25
- "static/chunks/pages/_app-a5bbe02710f13d05.js"
23
+ "static/chunks/main-5b999f3f24ebfa84.js",
24
+ "static/css/aedeaada218d7280.css",
25
+ "static/chunks/pages/_app-7024e7a27ffbb2fa.js"
26
26
  ],
27
27
  "/_error": [
28
- "static/chunks/webpack-1a7a166b34ed8d24.js",
28
+ "static/chunks/webpack-3943d624bbb47a64.js",
29
29
  "static/chunks/framework-3cf15b8041c59dd3.js",
30
- "static/chunks/main-852475ca502b4e49.js",
30
+ "static/chunks/main-5b999f3f24ebfa84.js",
31
31
  "static/chunks/pages/_error-afeda7c5231b6c3c.js"
32
32
  ],
33
33
  "/not-found": [
34
- "static/chunks/webpack-1a7a166b34ed8d24.js",
34
+ "static/chunks/webpack-3943d624bbb47a64.js",
35
35
  "static/chunks/framework-3cf15b8041c59dd3.js",
36
- "static/chunks/main-852475ca502b4e49.js",
36
+ "static/chunks/main-5b999f3f24ebfa84.js",
37
37
  "static/chunks/pages/not-found-9e076427bad69d90.js"
38
38
  ]
39
39
  }
@@ -1 +1 @@
1
- {"previewModeId":"a6c19cde59370e106894a193c20cd8a4","previewModeSigningKey":"9060e5ecf8e605d70100eb0672f230a6866343e531c51afc048bfc0c8c403919","previewModeEncryptionKey":"62d17ceeff4cc44fb11cc2c43e09f43b9e851a9a2ce563c8d17807a573072eff","expireAt":1786826991817}
1
+ {"previewModeId":"c85e6f8a4ff2deaa95f42e5c117c8c9a","previewModeSigningKey":"2c028e3be2a3b39a4bf0159d5697d0494bd393ea48a70bf384e74ca981f58bb7","previewModeEncryptionKey":"bb45fb12938370f5852a51404a032a492598a3961a990d340d6915d7f259d198","expireAt":1787264687438}
@@ -1 +1 @@
1
- {"encryption.key":"UCQyYhWSgZQMZYhNsOgppaCfZZpbJgyOn1/xnLZsT9s=","encryption.expire_at":1786826991813}
1
+ {"encryption.key":"/d/sez38cwQmbhvcO7v0mHeIc1/pH+xWoZ7JBA8xBbQ=","encryption.expire_at":1787264687435}