scrabble-solver 2.12.5 → 2.13.1
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.
- package/README.md +12 -10
- package/lerna.json +1 -1
- package/package.json +1 -1
- package/packages/configs/build/locales/index.d.ts +1 -0
- package/packages/configs/build/locales/index.js +3 -1
- package/packages/configs/build/locales/roRo.d.ts +3 -0
- package/packages/configs/build/locales/roRo.js +38 -0
- package/packages/configs/dictionaries/build/Dictionaries.d.ts +13 -0
- package/packages/configs/dictionaries/build/Dictionaries.js +46 -0
- package/packages/configs/dictionaries/build/constants/index.d.ts +3 -0
- package/packages/configs/dictionaries/build/constants/index.js +11 -0
- package/packages/configs/dictionaries/build/index.d.ts +3 -0
- package/packages/configs/dictionaries/build/index.js +23 -0
- package/packages/configs/dictionaries/build/lib/DiskCache.d.ts +11 -0
- package/packages/configs/dictionaries/build/lib/DiskCache.js +48 -0
- package/packages/configs/dictionaries/build/lib/LayeredCache.d.ts +13 -0
- package/packages/configs/dictionaries/build/lib/LayeredCache.js +55 -0
- package/packages/configs/dictionaries/build/lib/MemoryCache.d.ts +13 -0
- package/packages/configs/dictionaries/build/lib/MemoryCache.js +32 -0
- package/packages/configs/dictionaries/build/lib/createAsyncProxy.d.ts +3 -0
- package/packages/configs/dictionaries/build/lib/createAsyncProxy.js +18 -0
- package/packages/configs/dictionaries/build/lib/createCacheTimestampComparator.d.ts +5 -0
- package/packages/configs/dictionaries/build/lib/createCacheTimestampComparator.js +19 -0
- package/packages/configs/dictionaries/build/lib/downloadDictionary.d.ts +4 -0
- package/packages/configs/dictionaries/build/lib/downloadDictionary.js +16 -0
- package/packages/configs/dictionaries/build/lib/getDictionaryFilepath.d.ts +3 -0
- package/packages/configs/dictionaries/build/lib/getDictionaryFilepath.js +11 -0
- package/packages/configs/dictionaries/build/lib/index.d.ts +7 -0
- package/packages/configs/dictionaries/build/lib/index.js +20 -0
- package/packages/configs/dictionaries/build/types/Cache.d.ts +8 -0
- package/packages/configs/dictionaries/build/types/Cache.js +2 -0
- package/packages/configs/dictionaries/build/types/index.d.ts +1 -0
- package/packages/configs/dictionaries/build/types/index.js +2 -0
- package/packages/configs/package.json +3 -3
- package/packages/configs/src/locales/index.ts +1 -0
- package/packages/configs/src/locales/roRo.ts +39 -0
- package/packages/constants/package.json +1 -1
- package/packages/dictionaries/package-lock.json +2 -2
- package/packages/dictionaries/package.json +4 -4
- package/packages/logger/package-lock.json +2 -2
- package/packages/logger/package.json +1 -1
- package/packages/scrabble-solver/.next/BUILD_ID +1 -1
- package/packages/scrabble-solver/.next/build-manifest.json +4 -4
- package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
- package/packages/scrabble-solver/.next/cache/eslint/.cache_8dgz12 +1 -1
- package/packages/scrabble-solver/.next/cache/next-server.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/next-server.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/prerender-manifest.json +1 -1
- package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
- package/packages/scrabble-solver/.next/server/chunks/277.js +129 -39
- package/packages/scrabble-solver/.next/server/chunks/44.js +75 -31
- package/packages/scrabble-solver/.next/server/chunks/865.js +16 -4
- package/packages/scrabble-solver/.next/server/chunks/{131.js → 907.js} +924 -2
- package/packages/scrabble-solver/.next/server/chunks/911.js +48 -1
- package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/404.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/_document.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js +49 -2
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/solve.js +9 -5
- package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/verify.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/verify.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.js +9 -9
- package/packages/scrabble-solver/.next/server/pages/index.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
- package/packages/scrabble-solver/.next/static/{aKRf05U1XHnDU2-82b9mQ → RJ5_dKU0dHcryeTVO6SSX}/_buildManifest.js +1 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-b92880dde164b954.js +32 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/{index-82b2939158c7729f.js → index-f56eaa969a831c70.js} +1 -1
- package/packages/scrabble-solver/.next/trace +51 -51
- package/packages/scrabble-solver/package-lock.json +2 -2
- package/packages/scrabble-solver/package.json +8 -8
- package/packages/scrabble-solver/src/i18n/constants.ts +12 -1
- package/packages/scrabble-solver/src/i18n/i18n.ts +2 -0
- package/packages/scrabble-solver/src/i18n/ro.json +70 -0
- package/packages/scrabble-solver/src/icons/FlagRo.svg +5 -0
- package/packages/scrabble-solver/src/icons/index.ts +1 -0
- package/packages/scrabble-solver/src/lib/detectLocale.ts +10 -4
- package/packages/solver/package-lock.json +2 -2
- package/packages/solver/package.json +5 -5
- package/packages/types/build/Locale.d.ts +2 -1
- package/packages/types/build/Locale.js +1 -0
- package/packages/types/package.json +2 -2
- package/packages/types/src/Locale.ts +1 -0
- package/packages/word-definitions/build/crawl/crawl.js +2 -0
- package/packages/word-definitions/build/crawl/crawlRomanian.d.ts +2 -0
- package/packages/word-definitions/build/crawl/crawlRomanian.js +11 -0
- package/packages/word-definitions/build/parse/index.d.ts +1 -0
- package/packages/word-definitions/build/parse/index.js +3 -1
- package/packages/word-definitions/build/parse/parse.js +2 -0
- package/packages/word-definitions/build/parse/parseRomanian.d.ts +3 -0
- package/packages/word-definitions/build/parse/parseRomanian.js +16 -0
- package/packages/word-definitions/package-lock.json +20 -161
- package/packages/word-definitions/package.json +2 -2
- package/packages/word-definitions/src/crawl/crawl.ts +2 -0
- package/packages/word-definitions/src/crawl/crawlRomanian.ts +11 -0
- package/packages/word-definitions/src/parse/__tests__/expected/ro-RO.aciua.json +7 -0
- package/packages/word-definitions/src/parse/__tests__/input/ro-RO.aciua.html +33 -0
- package/packages/word-definitions/src/parse/index.ts +1 -0
- package/packages/word-definitions/src/parse/parse.test.ts +1 -0
- package/packages/word-definitions/src/parse/parse.ts +2 -0
- package/packages/word-definitions/src/parse/parseRomanian.ts +20 -0
- package/packages/word-lists/build/getEsEsWordList.js +10 -6
- package/packages/word-lists/build/getFrFrWordList.js +5 -5
- package/packages/word-lists/build/getPlPlWordList.js +1 -17
- package/packages/word-lists/build/getRoRoWordList.d.ts +2 -0
- package/packages/word-lists/build/getRoRoWordList.js +14 -0
- package/packages/word-lists/build/getWordList.js +2 -0
- package/packages/word-lists/build/lib/index.d.ts +1 -0
- package/packages/word-lists/build/lib/index.js +3 -1
- package/packages/word-lists/build/lib/unzip.d.ts +2 -0
- package/packages/word-lists/build/lib/unzip.js +23 -0
- package/packages/word-lists/package-lock.json +15 -2
- package/packages/word-lists/package.json +4 -2
- package/packages/word-lists/src/getEsEsWordList.ts +7 -6
- package/packages/word-lists/src/getFrFrWordList.ts +2 -6
- package/packages/word-lists/src/getPlPlWordList.ts +2 -19
- package/packages/word-lists/src/getRoRoWordList.ts +13 -0
- package/packages/word-lists/src/getWordList.ts +2 -0
- package/packages/word-lists/src/lib/index.ts +1 -0
- package/packages/word-lists/src/lib/unzip.ts +20 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-e7f3d1c9c09c8f91.js +0 -32
- /package/packages/scrabble-solver/.next/static/{aKRf05U1XHnDU2-82b9mQ → RJ5_dKU0dHcryeTVO6SSX}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
16
|
<p>
|
|
17
|
-
Available at <a href="https://scrabble-solver.org">https://scrabble-solver.org</a> in
|
|
17
|
+
Available at <a href="https://scrabble-solver.org">https://scrabble-solver.org</a> in 8 languages.
|
|
18
18
|
</p>
|
|
19
19
|
|
|
20
20
|
<p>
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
<img height="32" src="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f1e9-1f1ea.svg" alt="Flag of Germany" title="German" />
|
|
25
25
|
<img height="32" src="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f1ee-1f1f7.svg" alt="Flag of Iran" title="Persian" />
|
|
26
26
|
<img height="32" src="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f1f5-1f1f1.svg" alt="Flag of Poland" title="Polish" />
|
|
27
|
+
<img height="32" src="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f1f7-1f1f4.svg" alt="Flag of Romania" title="Romanian" />
|
|
27
28
|
<img height="32" src="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f1ea-1f1f8.svg" alt="Flag of Spain" title="Spanish" />
|
|
28
29
|
</p>
|
|
29
30
|
|
|
@@ -61,15 +62,16 @@
|
|
|
61
62
|
|
|
62
63
|
## Dictionaries
|
|
63
64
|
|
|
64
|
-
| Language
|
|
65
|
-
|
|
66
|
-
| 🇬🇧 English
|
|
67
|
-
| 🇺🇸 English
|
|
68
|
-
| 🇫🇷 French
|
|
69
|
-
| 🇩🇪 German
|
|
70
|
-
| 🇮🇷 Persian
|
|
71
|
-
| 🇵🇱 Polish
|
|
72
|
-
|
|
|
65
|
+
| Language | Word list | Word definitions | [Highest-scoring word](https://codesandbox.io/s/highest-scoring-words-in-scrabble-vbj1ns?file=/src/index.js) |
|
|
66
|
+
|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
|
|
67
|
+
| 🇬🇧 English | [💾](https://www.wordgamedictionary.com/sowpods/download/sowpods.txt) [SOWPODS](https://en.wikipedia.org/wiki/Collins_Scrabble_Words) | [Merriam-Webster](https://www.merriam-webster.com/) | oxyphenbutazone (1458) |
|
|
68
|
+
| 🇺🇸 English | [💾](https://www.wordgamedictionary.com/twl06/download/twl06.txt) [TWL06](https://en.wikipedia.org/wiki/NASPA_Word_List) | [Merriam-Webster](https://www.merriam-webster.com/) | oxyphenbutazone (1458) |
|
|
69
|
+
| 🇫🇷 French | [💾](https://raw.githubusercontent.com/Thecoolsim/French-Scrabble-ODS8/main/French%20ODS%20dictionary.txt) [ODS8](https://github.com/Thecoolsim/French-Scrabble-ODS8) | [CNRTL](https://www.cnrtl.fr/) | encyclopediques (1512) |
|
|
70
|
+
| 🇩🇪 German | [💾](https://raw.githubusercontent.com/hippler/german-wordlist/master/words.txt) [hippler/german-wordlist](https://github.com/hippler/german-wordlist) | [DWDS](https://www.dwds.de) | polytoxikomanem (1512) |
|
|
71
|
+
| 🇮🇷 Persian | [💾](https://raw.githubusercontent.com/MansourM/persian-to-persian-dictionary/main/moein/words.txt) [MansourM/persian-to-persian-dictionary](https://github.com/MansourM/persian-to-persian-dictionary) | [واژه یاب](https://vajehyab.com) | (756) اگزیستانسیالیست |
|
|
72
|
+
| 🇵🇱 Polish | [💾](https://sjp.pl/slownik/growy/) [SJP.PL](https://sjp.pl/slownik/dp.phtml) | [SJP.PL](https://sjp.pl) | współposiądźmyż (1512) |
|
|
73
|
+
| 🇷🇴 Romanian | [💾](https://dexonline.ro/static/download/scrabble/loc-flexiuni-5.0.zip) [LOC 5](https://dexonline.ro/scrabble) | [dexonline](https://dexonline.ro/) | luxemburghezele (1593) |
|
|
74
|
+
| 🇪🇸 Spanish | [💾](https://github.com/kamilmielnik/fise-2/blob/master/fise-2.txt) [FISE-2](https://fisescrabble.org/) | [Diccionarios.com](https://www.diccionarios.com/) | flexibilizabais (1323) |
|
|
73
75
|
|
|
74
76
|
## Run
|
|
75
77
|
|
package/lerna.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scrabble-solver",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.1",
|
|
4
4
|
"description": "Scrabble Solver 2 - Free, open-source, and cross-platform analysis tool for Scrabble, Super Scrabble & Literaki. Quickly find top scoring words using given letters and board state. Available in English, French, German, Polish & Spanish.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Scrabble",
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.plPl = exports.frFr = exports.faIr = exports.esEs = exports.enUs = exports.enGb = exports.deDe = void 0;
|
|
6
|
+
exports.roRo = exports.plPl = exports.frFr = exports.faIr = exports.esEs = exports.enUs = exports.enGb = exports.deDe = void 0;
|
|
7
7
|
var deDe_1 = require("./deDe");
|
|
8
8
|
Object.defineProperty(exports, "deDe", { enumerable: true, get: function () { return __importDefault(deDe_1).default; } });
|
|
9
9
|
var enGb_1 = require("./enGb");
|
|
@@ -18,3 +18,5 @@ var frFr_1 = require("./frFr");
|
|
|
18
18
|
Object.defineProperty(exports, "frFr", { enumerable: true, get: function () { return __importDefault(frFr_1).default; } });
|
|
19
19
|
var plPl_1 = require("./plPl");
|
|
20
20
|
Object.defineProperty(exports, "plPl", { enumerable: true, get: function () { return __importDefault(plPl_1).default; } });
|
|
21
|
+
var roRo_1 = require("./roRo");
|
|
22
|
+
Object.defineProperty(exports, "roRo", { enumerable: true, get: function () { return __importDefault(roRo_1).default; } });
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const types_1 = require("@scrabble-solver/types");
|
|
4
|
+
const games_1 = require("../games");
|
|
5
|
+
const roRo = [
|
|
6
|
+
new types_1.Config({
|
|
7
|
+
...games_1.scrabble,
|
|
8
|
+
locale: types_1.Locale.RO_RO,
|
|
9
|
+
/**
|
|
10
|
+
* @see https://frsc1.fortunecity.ws/reg6scr.htm#vallit
|
|
11
|
+
*/
|
|
12
|
+
tiles: [
|
|
13
|
+
{ character: 'a', count: 11, score: 1 },
|
|
14
|
+
{ character: 'b', count: 2, score: 9 },
|
|
15
|
+
{ character: 'c', count: 5, score: 1 },
|
|
16
|
+
{ character: 'd', count: 4, score: 2 },
|
|
17
|
+
{ character: 'e', count: 9, score: 1 },
|
|
18
|
+
{ character: 'f', count: 2, score: 8 },
|
|
19
|
+
{ character: 'g', count: 2, score: 9 },
|
|
20
|
+
{ character: 'h', count: 1, score: 10 },
|
|
21
|
+
{ character: 'i', count: 10, score: 1 },
|
|
22
|
+
{ character: 'j', count: 1, score: 10 },
|
|
23
|
+
{ character: 'l', count: 4, score: 1 },
|
|
24
|
+
{ character: 'm', count: 3, score: 4 },
|
|
25
|
+
{ character: 'n', count: 6, score: 1 },
|
|
26
|
+
{ character: 'o', count: 5, score: 1 },
|
|
27
|
+
{ character: 'p', count: 4, score: 2 },
|
|
28
|
+
{ character: 'r', count: 7, score: 1 },
|
|
29
|
+
{ character: 's', count: 5, score: 1 },
|
|
30
|
+
{ character: 't', count: 7, score: 1 },
|
|
31
|
+
{ character: 'u', count: 6, score: 1 },
|
|
32
|
+
{ character: 'v', count: 2, score: 8 },
|
|
33
|
+
{ character: 'x', count: 1, score: 10 },
|
|
34
|
+
{ character: 'z', count: 1, score: 10 },
|
|
35
|
+
],
|
|
36
|
+
}),
|
|
37
|
+
];
|
|
38
|
+
exports.default = roRo;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Trie } from '@kamilmielnik/trie';
|
|
2
|
+
import { Locale } from '@scrabble-solver/types';
|
|
3
|
+
declare class Dictionaries {
|
|
4
|
+
private readonly cache;
|
|
5
|
+
private readonly downloadDictionaryProxies;
|
|
6
|
+
constructor();
|
|
7
|
+
get(locale: Locale): Promise<Trie>;
|
|
8
|
+
remove(): void;
|
|
9
|
+
update(force?: boolean): Promise<void>;
|
|
10
|
+
private getLocalesToUpdate;
|
|
11
|
+
private updateDictionary;
|
|
12
|
+
}
|
|
13
|
+
export default Dictionaries;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const logger_1 = __importDefault(require("@scrabble-solver/logger"));
|
|
7
|
+
const types_1 = require("@scrabble-solver/types");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
const lib_1 = require("./lib");
|
|
11
|
+
class Dictionaries {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.cache = new lib_1.LayeredCache();
|
|
14
|
+
this.downloadDictionaryProxies = Object.fromEntries(Object.values(types_1.Locale).map((locale) => [locale, (0, lib_1.createAsyncProxy)(() => (0, lib_1.downloadDictionary)(locale))]));
|
|
15
|
+
}
|
|
16
|
+
async get(locale) {
|
|
17
|
+
if (this.cache.has(locale)) {
|
|
18
|
+
const trie = await this.cache.get(locale);
|
|
19
|
+
if (trie) {
|
|
20
|
+
return trie;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
logger_1.default.info('Dictionaries - cache miss', { locale });
|
|
24
|
+
return this.updateDictionary(locale);
|
|
25
|
+
}
|
|
26
|
+
remove() {
|
|
27
|
+
fs_1.default.rmdirSync(constants_1.OUTPUT_DIRECTORY, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
async update(force) {
|
|
30
|
+
const locales = force ? Object.values(types_1.Locale) : this.getLocalesToUpdate();
|
|
31
|
+
logger_1.default.info('Dictionaries - update', { force, locales });
|
|
32
|
+
await Promise.all(locales.map((locale) => this.updateDictionary(locale)));
|
|
33
|
+
}
|
|
34
|
+
getLocalesToUpdate() {
|
|
35
|
+
return Object.values(types_1.Locale).filter((locale) => this.cache.isStale(locale) !== false);
|
|
36
|
+
}
|
|
37
|
+
async updateDictionary(locale) {
|
|
38
|
+
logger_1.default.info('Dictionaries - updateDictionary', { locale });
|
|
39
|
+
fs_1.default.mkdirSync(constants_1.OUTPUT_DIRECTORY, { recursive: true });
|
|
40
|
+
const downloadDictionaryProxy = this.downloadDictionaryProxies[locale];
|
|
41
|
+
const trie = await downloadDictionaryProxy();
|
|
42
|
+
await this.cache.set(locale, trie);
|
|
43
|
+
return trie;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.default = Dictionaries;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OUTPUT_DIRECTORY = exports.CACHE_STALE_THRESHOLD = exports.DAY = void 0;
|
|
7
|
+
const os_1 = __importDefault(require("os"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
exports.DAY = 24 * 60 * 60 * 1000;
|
|
10
|
+
exports.CACHE_STALE_THRESHOLD = 1 * exports.DAY; // eslint-disable-line no-implicit-coercion
|
|
11
|
+
exports.OUTPUT_DIRECTORY = path_1.default.resolve(os_1.default.homedir(), '.scrabble-solver', 'dictionaries');
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.dictionaries = void 0;
|
|
21
|
+
const Dictionaries_1 = __importDefault(require("./Dictionaries"));
|
|
22
|
+
__exportStar(require("./lib"), exports);
|
|
23
|
+
exports.dictionaries = new Dictionaries_1.default();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Trie } from '@kamilmielnik/trie';
|
|
2
|
+
import { Locale } from '@scrabble-solver/types';
|
|
3
|
+
import { Cache } from '../types';
|
|
4
|
+
declare class DiskCache implements Cache<Locale, Trie> {
|
|
5
|
+
get(locale: Locale): Promise<Trie | undefined>;
|
|
6
|
+
getLastModifiedTimestamp(locale: Locale): number | undefined;
|
|
7
|
+
has(locale: Locale): boolean;
|
|
8
|
+
isStale(locale: Locale): boolean | undefined;
|
|
9
|
+
set(locale: Locale, trie: Trie): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export default DiskCache;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const trie_1 = require("@kamilmielnik/trie");
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const constants_1 = require("../constants");
|
|
9
|
+
const getDictionaryFilepath_1 = __importDefault(require("./getDictionaryFilepath"));
|
|
10
|
+
class DiskCache {
|
|
11
|
+
async get(locale) {
|
|
12
|
+
if (!this.has(locale)) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const filepath = (0, getDictionaryFilepath_1.default)(locale);
|
|
16
|
+
const serialized = await fs_1.default.promises.readFile(filepath, 'utf-8');
|
|
17
|
+
const trie = trie_1.Trie.deserialize(serialized);
|
|
18
|
+
return trie;
|
|
19
|
+
}
|
|
20
|
+
getLastModifiedTimestamp(locale) {
|
|
21
|
+
const filepath = (0, getDictionaryFilepath_1.default)(locale);
|
|
22
|
+
if (!fs_1.default.existsSync(filepath)) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const stats = fs_1.default.statSync(filepath);
|
|
26
|
+
return stats.mtimeMs;
|
|
27
|
+
}
|
|
28
|
+
has(locale) {
|
|
29
|
+
const filepath = (0, getDictionaryFilepath_1.default)(locale);
|
|
30
|
+
return fs_1.default.existsSync(filepath);
|
|
31
|
+
}
|
|
32
|
+
isStale(locale) {
|
|
33
|
+
if (!this.has(locale)) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
const lastModifiedTimestamp = this.getLastModifiedTimestamp(locale);
|
|
37
|
+
if (typeof lastModifiedTimestamp === 'undefined') {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const timeSinceModification = Math.abs(lastModifiedTimestamp - Date.now());
|
|
41
|
+
return timeSinceModification > constants_1.CACHE_STALE_THRESHOLD;
|
|
42
|
+
}
|
|
43
|
+
async set(locale, trie) {
|
|
44
|
+
const filepath = (0, getDictionaryFilepath_1.default)(locale);
|
|
45
|
+
await fs_1.default.promises.writeFile(filepath, trie.serialize());
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.default = DiskCache;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Trie } from '@kamilmielnik/trie';
|
|
2
|
+
import { Locale } from '@scrabble-solver/types';
|
|
3
|
+
import { Cache } from '../types';
|
|
4
|
+
declare class LayeredCache implements Cache<Locale, Trie> {
|
|
5
|
+
private readonly layers;
|
|
6
|
+
get(locale: Locale): Promise<Trie | undefined>;
|
|
7
|
+
getLastModifiedTimestamp(locale: Locale): number | undefined;
|
|
8
|
+
has(locale: Locale): boolean;
|
|
9
|
+
isStale(locale: Locale): boolean | undefined;
|
|
10
|
+
set(locale: Locale, trie: Trie): Promise<void>;
|
|
11
|
+
private getLastModifiedLayer;
|
|
12
|
+
}
|
|
13
|
+
export default LayeredCache;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const createCacheTimestampComparator_1 = __importDefault(require("./createCacheTimestampComparator"));
|
|
7
|
+
const DiskCache_1 = __importDefault(require("./DiskCache"));
|
|
8
|
+
const MemoryCache_1 = __importDefault(require("./MemoryCache"));
|
|
9
|
+
class LayeredCache {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.layers = [new MemoryCache_1.default(), new DiskCache_1.default()];
|
|
12
|
+
}
|
|
13
|
+
async get(locale) {
|
|
14
|
+
const cache = this.getLastModifiedLayer(locale);
|
|
15
|
+
if (!cache) {
|
|
16
|
+
return Promise.resolve(undefined);
|
|
17
|
+
}
|
|
18
|
+
const [memoryCache, diskCache] = this.layers;
|
|
19
|
+
const value = await cache.get(locale);
|
|
20
|
+
if (cache === diskCache && typeof value !== 'undefined') {
|
|
21
|
+
await memoryCache.set(locale, value);
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
getLastModifiedTimestamp(locale) {
|
|
26
|
+
const cache = this.getLastModifiedLayer(locale);
|
|
27
|
+
if (!cache) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
return cache.getLastModifiedTimestamp(locale);
|
|
31
|
+
}
|
|
32
|
+
has(locale) {
|
|
33
|
+
return this.layers.some((cache) => cache.has(locale));
|
|
34
|
+
}
|
|
35
|
+
isStale(locale) {
|
|
36
|
+
if (this.layers.some((cache) => cache.isStale(locale))) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (this.layers.every((cache) => typeof cache.isStale(locale) === 'undefined')) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
async set(locale, trie) {
|
|
45
|
+
const [memoryCache, diskCache] = this.layers;
|
|
46
|
+
await diskCache.set(locale, trie);
|
|
47
|
+
await memoryCache.set(locale, trie);
|
|
48
|
+
}
|
|
49
|
+
getLastModifiedLayer(locale) {
|
|
50
|
+
const layers = this.layers.filter((cache) => cache.has(locale));
|
|
51
|
+
const [cached] = [...layers].sort((0, createCacheTimestampComparator_1.default)(locale));
|
|
52
|
+
return cached;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.default = LayeredCache;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Trie } from '@kamilmielnik/trie';
|
|
2
|
+
import { Locale } from '@scrabble-solver/types';
|
|
3
|
+
import { Cache } from '../types';
|
|
4
|
+
declare class MemoryCache implements Cache<Locale, Trie> {
|
|
5
|
+
private readonly cache;
|
|
6
|
+
private readonly cacheTimestamps;
|
|
7
|
+
get(locale: Locale): Promise<Trie | undefined>;
|
|
8
|
+
getLastModifiedTimestamp(locale: Locale): number | undefined;
|
|
9
|
+
has(locale: Locale): boolean;
|
|
10
|
+
isStale(locale: Locale): boolean | undefined;
|
|
11
|
+
set(locale: Locale, trie: Trie): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export default MemoryCache;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const constants_1 = require("../constants");
|
|
4
|
+
class MemoryCache {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.cache = {};
|
|
7
|
+
this.cacheTimestamps = {};
|
|
8
|
+
}
|
|
9
|
+
get(locale) {
|
|
10
|
+
return Promise.resolve(this.cache[locale]);
|
|
11
|
+
}
|
|
12
|
+
getLastModifiedTimestamp(locale) {
|
|
13
|
+
return this.cacheTimestamps[locale];
|
|
14
|
+
}
|
|
15
|
+
has(locale) {
|
|
16
|
+
return typeof this.cache[locale] !== 'undefined';
|
|
17
|
+
}
|
|
18
|
+
isStale(locale) {
|
|
19
|
+
const timestamp = this.getLastModifiedTimestamp(locale);
|
|
20
|
+
if (!this.has(locale) || typeof timestamp === 'undefined') {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
const timeSinceModification = Math.abs(timestamp - Date.now());
|
|
24
|
+
return timeSinceModification > constants_1.CACHE_STALE_THRESHOLD;
|
|
25
|
+
}
|
|
26
|
+
set(locale, trie) {
|
|
27
|
+
this.cacheTimestamps[locale] = Date.now();
|
|
28
|
+
this.cache[locale] = trie;
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.default = MemoryCache;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createAsyncProxy = (asyncCallback) => {
|
|
4
|
+
let promise = null;
|
|
5
|
+
return async () => {
|
|
6
|
+
if (promise) {
|
|
7
|
+
return promise;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
promise = asyncCallback();
|
|
11
|
+
return await promise;
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
promise = null;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
exports.default = createAsyncProxy;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Trie } from '@kamilmielnik/trie';
|
|
2
|
+
import { Locale } from '@scrabble-solver/types';
|
|
3
|
+
import { Cache } from '../types';
|
|
4
|
+
declare const createCacheTimestampComparator: (locale: Locale) => (a: Cache<Locale, Trie>, b: Cache<Locale, Trie>) => number;
|
|
5
|
+
export default createCacheTimestampComparator;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createCacheTimestampComparator = (locale) => {
|
|
4
|
+
return (a, b) => {
|
|
5
|
+
const aTimestamp = a.getLastModifiedTimestamp(locale);
|
|
6
|
+
const bTimestamp = b.getLastModifiedTimestamp(locale);
|
|
7
|
+
if (aTimestamp === bTimestamp) {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
if (typeof aTimestamp === 'undefined') {
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
if (typeof bTimestamp === 'undefined') {
|
|
14
|
+
return -1;
|
|
15
|
+
}
|
|
16
|
+
return bTimestamp - aTimestamp;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
exports.default = createCacheTimestampComparator;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const trie_1 = require("@kamilmielnik/trie");
|
|
7
|
+
const logger_1 = __importDefault(require("@scrabble-solver/logger"));
|
|
8
|
+
const word_lists_1 = require("@scrabble-solver/word-lists");
|
|
9
|
+
const downloadDictionary = async (locale) => {
|
|
10
|
+
logger_1.default.info('downloadDictionary', { locale });
|
|
11
|
+
const words = await (0, word_lists_1.getWordList)(locale);
|
|
12
|
+
logger_1.default.info('downloadDictionary - success', { locale });
|
|
13
|
+
const trie = trie_1.Trie.fromArray(words);
|
|
14
|
+
return trie;
|
|
15
|
+
};
|
|
16
|
+
exports.default = downloadDictionary;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const constants_1 = require("../constants");
|
|
8
|
+
const getDictionaryFilepath = (locale) => {
|
|
9
|
+
return path_1.default.resolve(constants_1.OUTPUT_DIRECTORY, `${locale}.txt`);
|
|
10
|
+
};
|
|
11
|
+
exports.default = getDictionaryFilepath;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as createAsyncProxy } from './createAsyncProxy';
|
|
2
|
+
export { default as createCacheTimestampComparator } from './createCacheTimestampComparator';
|
|
3
|
+
export { default as DiskCache } from './DiskCache';
|
|
4
|
+
export { default as downloadDictionary } from './downloadDictionary';
|
|
5
|
+
export { default as getDictionaryFilepath } from './getDictionaryFilepath';
|
|
6
|
+
export { default as LayeredCache } from './LayeredCache';
|
|
7
|
+
export { default as MemoryCache } from './MemoryCache';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MemoryCache = exports.LayeredCache = exports.getDictionaryFilepath = exports.downloadDictionary = exports.DiskCache = exports.createCacheTimestampComparator = exports.createAsyncProxy = void 0;
|
|
7
|
+
var createAsyncProxy_1 = require("./createAsyncProxy");
|
|
8
|
+
Object.defineProperty(exports, "createAsyncProxy", { enumerable: true, get: function () { return __importDefault(createAsyncProxy_1).default; } });
|
|
9
|
+
var createCacheTimestampComparator_1 = require("./createCacheTimestampComparator");
|
|
10
|
+
Object.defineProperty(exports, "createCacheTimestampComparator", { enumerable: true, get: function () { return __importDefault(createCacheTimestampComparator_1).default; } });
|
|
11
|
+
var DiskCache_1 = require("./DiskCache");
|
|
12
|
+
Object.defineProperty(exports, "DiskCache", { enumerable: true, get: function () { return __importDefault(DiskCache_1).default; } });
|
|
13
|
+
var downloadDictionary_1 = require("./downloadDictionary");
|
|
14
|
+
Object.defineProperty(exports, "downloadDictionary", { enumerable: true, get: function () { return __importDefault(downloadDictionary_1).default; } });
|
|
15
|
+
var getDictionaryFilepath_1 = require("./getDictionaryFilepath");
|
|
16
|
+
Object.defineProperty(exports, "getDictionaryFilepath", { enumerable: true, get: function () { return __importDefault(getDictionaryFilepath_1).default; } });
|
|
17
|
+
var LayeredCache_1 = require("./LayeredCache");
|
|
18
|
+
Object.defineProperty(exports, "LayeredCache", { enumerable: true, get: function () { return __importDefault(LayeredCache_1).default; } });
|
|
19
|
+
var MemoryCache_1 = require("./MemoryCache");
|
|
20
|
+
Object.defineProperty(exports, "MemoryCache", { enumerable: true, get: function () { return __importDefault(MemoryCache_1).default; } });
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface Cache<Key extends string, Value> {
|
|
2
|
+
get(key: Key): Promise<Value | undefined>;
|
|
3
|
+
getLastModifiedTimestamp(key: Key): number | undefined;
|
|
4
|
+
has(key: Key): boolean;
|
|
5
|
+
isStale(key: Key): boolean | undefined;
|
|
6
|
+
set(key: Key, value: Value): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export default Cache;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Cache } from './Cache';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scrabble-solver/configs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.1",
|
|
4
4
|
"description": "Scrabble Solver 2 - Configs",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"clean:force": "npm run clean && rimraf package-lock.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@scrabble-solver/constants": "^2.
|
|
28
|
-
"@scrabble-solver/types": "^2.
|
|
27
|
+
"@scrabble-solver/constants": "^2.13.1",
|
|
28
|
+
"@scrabble-solver/types": "^2.13.1"
|
|
29
29
|
},
|
|
30
30
|
"gitHead": "1e2d1ad49a288d4a44196d8e3336740da132c637"
|
|
31
31
|
}
|