scrabble-solver 2.8.5 → 2.8.7
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 +31 -24
- package/lerna.json +1 -1
- package/package.json +2 -2
- package/packages/configs/build/literaki/literaki.js +2 -2
- package/packages/configs/build/scrabble/scrabble.js +2 -2
- package/packages/configs/package.json +3 -3
- package/packages/configs/src/literaki/literaki.ts +2 -2
- package/packages/configs/src/scrabble/scrabble.ts +2 -2
- 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 +9 -9
- 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/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/413.js +183 -94
- package/packages/scrabble-solver/.next/server/chunks/{206.js → 429.js} +2 -4137
- package/packages/scrabble-solver/.next/server/chunks/515.js +111 -78
- package/packages/scrabble-solver/.next/server/chunks/{907.js → 911.js} +134 -367
- package/packages/scrabble-solver/.next/server/chunks/939.js +218 -0
- package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/404.html +2 -2
- package/packages/scrabble-solver/.next/server/pages/404.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/500.html +2 -2
- package/packages/scrabble-solver/.next/server/pages/_app.js +3 -2
- 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/_error.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js +33 -17
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/solve.js +404 -58
- package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/visit.js +3 -2
- package/packages/scrabble-solver/.next/server/pages/api/visit.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.html +3 -7
- package/packages/scrabble-solver/.next/server/pages/index.js +12 -14
- 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/chunks/56-cf37c430261bbea5.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-0b12a65bea70a0df.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/index-fcb69802550afb81.js +1 -0
- package/packages/scrabble-solver/.next/static/css/1f39b55d50f5b30b.css +1 -0
- package/packages/scrabble-solver/.next/static/css/751e8a14776d05d8.css +1 -0
- package/packages/scrabble-solver/.next/static/z_0_lqfmiI_ISokr6NNRq/_buildManifest.js +1 -0
- package/packages/scrabble-solver/.next/static/{TzKQ3IntkvaYmHBkWpfoi → z_0_lqfmiI_ISokr6NNRq}/_ssgManifest.js +0 -0
- package/packages/scrabble-solver/.next/trace +40 -42
- package/packages/scrabble-solver/package-lock.json +2 -2
- package/packages/scrabble-solver/package.json +8 -8
- package/packages/scrabble-solver/src/api/index.ts +3 -9
- package/packages/scrabble-solver/src/api/isBoardValid.ts +43 -0
- package/packages/scrabble-solver/src/api/isCellValid.ts +26 -0
- package/packages/scrabble-solver/src/api/isRowValid.ts +19 -0
- package/packages/scrabble-solver/src/components/Board/Board.tsx +3 -1
- package/packages/scrabble-solver/src/components/Board/BoardPure.tsx +4 -1
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.module.scss +28 -11
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.tsx +12 -1
- package/packages/scrabble-solver/src/components/Board/components/Cell/CellPure.tsx +3 -1
- package/packages/scrabble-solver/src/components/Board/components/Cell/lib.ts +10 -2
- package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss +20 -0
- package/packages/scrabble-solver/src/components/Dictionary/Dictionary.tsx +40 -29
- package/packages/scrabble-solver/src/components/Results/Cell.tsx +3 -2
- package/packages/scrabble-solver/src/components/Results/Result.tsx +16 -6
- package/packages/scrabble-solver/src/components/ResultsInput/ResultsInput.tsx +11 -3
- package/packages/scrabble-solver/src/hooks/useIsTablet.ts +2 -2
- package/packages/scrabble-solver/src/lib/getRemainingTiles.ts +1 -1
- package/packages/scrabble-solver/src/lib/index.ts +2 -1
- package/packages/scrabble-solver/src/lib/isRegExp.ts +11 -0
- package/packages/scrabble-solver/src/lib/isStringArray.ts +5 -0
- package/packages/scrabble-solver/src/lib/sortResults.ts +5 -5
- package/packages/scrabble-solver/src/pages/_app.tsx +6 -3
- package/packages/scrabble-solver/src/pages/api/dictionary/[locale]/[word].ts +35 -11
- package/packages/scrabble-solver/src/pages/api/solve.ts +39 -19
- package/packages/scrabble-solver/src/pages/api/visit.ts +1 -0
- package/packages/scrabble-solver/src/pages/index.module.scss +5 -11
- package/packages/scrabble-solver/src/pages/index.tsx +5 -5
- package/packages/scrabble-solver/src/sdk/{findWordDefinition.ts → findWordDefinitions.ts} +3 -3
- package/packages/scrabble-solver/src/sdk/index.ts +1 -1
- package/packages/scrabble-solver/src/state/sagas.ts +11 -11
- package/packages/scrabble-solver/src/state/selectors.ts +6 -2
- package/packages/scrabble-solver/src/state/slices/dictionaryInitialState.ts +3 -3
- package/packages/scrabble-solver/src/state/slices/dictionarySlice.ts +4 -10
- package/packages/solver/build/PatternsFiller.js +1 -1
- package/packages/solver/build/PatternsGenerator.d.ts +4 -4
- package/packages/solver/build/PatternsGenerator.js +6 -6
- package/packages/solver/build/ScoresCalculator.js +1 -1
- package/packages/solver/build/Solver.js +3 -3
- package/packages/solver/build/getUniquePatterns.d.ts +3 -0
- package/packages/solver/build/getUniquePatterns.js +25 -0
- package/packages/solver/package-lock.json +3 -29
- package/packages/solver/package.json +5 -7
- package/packages/solver/src/PatternsFiller.ts +1 -1
- package/packages/solver/src/PatternsGenerator.test.ts +2 -2
- package/packages/solver/src/PatternsGenerator.ts +8 -8
- package/packages/solver/src/ScoresCalculator.ts +1 -1
- package/packages/solver/src/Solver.ts +3 -3
- package/packages/solver/src/getUniquePatterns.ts +30 -0
- package/packages/types/build/Board.d.ts +2 -2
- package/packages/types/build/Board.js +8 -8
- package/packages/types/build/BoardJson.d.ts +2 -1
- package/packages/types/build/BoardJson.js +19 -0
- package/packages/types/build/Cell.d.ts +2 -3
- package/packages/types/build/Cell.js +0 -15
- package/packages/types/build/CellJson.d.ts +1 -0
- package/packages/types/build/CellJson.js +14 -0
- package/packages/types/build/Collision.d.ts +3 -0
- package/packages/types/build/Collision.js +2 -0
- package/packages/types/build/CollisionJson.d.ts +3 -0
- package/packages/types/build/CollisionJson.js +2 -0
- package/packages/types/build/Config.d.ts +2 -2
- package/packages/types/build/Config.js +5 -5
- package/packages/types/build/ConfigJson.d.ts +2 -2
- package/packages/types/build/Locale.d.ts +1 -0
- package/packages/types/build/Locale.js +4 -0
- package/packages/types/build/Pattern.d.ts +1 -1
- package/packages/types/build/Pattern.js +4 -4
- package/packages/types/build/PatternJson.d.ts +1 -1
- package/packages/types/build/Result.d.ts +10 -8
- package/packages/types/build/Result.js +15 -10
- package/packages/types/build/ResultJson.d.ts +3 -2
- package/packages/types/build/TileJson.d.ts +1 -0
- package/packages/types/build/TileJson.js +9 -0
- package/packages/types/build/index.d.ts +7 -4
- package/packages/types/build/index.js +10 -1
- package/packages/types/build/isObject.d.ts +2 -0
- package/packages/types/build/isObject.js +6 -0
- package/packages/types/package.json +2 -2
- package/packages/types/src/Board.ts +11 -11
- package/packages/types/src/BoardJson.ts +22 -2
- package/packages/types/src/Cell.ts +2 -19
- package/packages/types/src/CellJson.ts +12 -1
- package/packages/types/src/Collision.ts +5 -0
- package/packages/types/src/CollisionJson.ts +5 -0
- package/packages/types/src/Config.ts +6 -6
- package/packages/types/src/ConfigJson.ts +2 -2
- package/packages/types/src/Locale.ts +4 -0
- package/packages/types/src/Pattern.ts +4 -5
- package/packages/types/src/PatternJson.ts +1 -1
- package/packages/types/src/Result.ts +33 -23
- package/packages/types/src/ResultJson.ts +3 -2
- package/packages/types/src/TileJson.ts +6 -0
- package/packages/types/src/index.ts +7 -4
- package/packages/types/src/isObject.ts +5 -0
- package/packages/word-definitions/package-lock.json +2 -2
- package/packages/word-definitions/package.json +2 -2
- package/packages/word-lists/build/getDeDeWordList.js +1 -1
- package/packages/word-lists/build/lib/extractWords.js +4 -1
- package/packages/word-lists/package-lock.json +2 -2
- package/packages/word-lists/package.json +2 -2
- package/packages/word-lists/src/getDeDeWordList.ts +1 -1
- package/packages/word-lists/src/lib/extractWords.ts +4 -1
- package/packages/scrabble-solver/.next/static/TzKQ3IntkvaYmHBkWpfoi/_buildManifest.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/56-2d34867599a0ac66.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-6ffa2ab900772b67.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/index-13ea7770a65c69ee.js +0 -1
- package/packages/scrabble-solver/.next/static/css/3159cfe62ff742a3.css +0 -1
- package/packages/scrabble-solver/.next/static/css/551d09cac435debb.css +0 -1
- package/packages/scrabble-solver/src/api/validateBoard.ts +0 -45
- package/packages/scrabble-solver/src/api/validateCell.ts +0 -40
- package/packages/scrabble-solver/src/api/validateCharacter.ts +0 -14
- package/packages/scrabble-solver/src/api/validateCharacters.ts +0 -24
- package/packages/scrabble-solver/src/api/validateConfigId.ts +0 -9
- package/packages/scrabble-solver/src/api/validateLocale.ts +0 -15
- package/packages/scrabble-solver/src/api/validateRow.ts +0 -17
- package/packages/scrabble-solver/src/api/validateTile.ts +0 -21
- package/packages/scrabble-solver/src/api/validateWord.ts +0 -11
- package/packages/scrabble-solver/src/lib/isLocale.ts +0 -7
|
@@ -15,8 +15,8 @@ class PatternsGenerator {
|
|
|
15
15
|
return this.generatePatterns({
|
|
16
16
|
board,
|
|
17
17
|
getNthVector: (index) => board.getRow(index),
|
|
18
|
-
numberOfVectors: this.config.boardHeight,
|
|
19
18
|
PatternModel: HorizontalPattern,
|
|
19
|
+
vectorsCount: this.config.boardHeight,
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -24,35 +24,35 @@ class PatternsGenerator {
|
|
|
24
24
|
return this.generatePatterns({
|
|
25
25
|
board,
|
|
26
26
|
getNthVector: (index) => board.getColumn(index),
|
|
27
|
-
numberOfVectors: this.config.boardWidth,
|
|
28
27
|
PatternModel: VerticalPattern,
|
|
28
|
+
vectorsCount: this.config.boardWidth,
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
public generatePatterns<P extends Pattern>({
|
|
33
33
|
board,
|
|
34
34
|
getNthVector,
|
|
35
|
-
|
|
35
|
+
vectorsCount,
|
|
36
36
|
PatternModel,
|
|
37
37
|
}: {
|
|
38
38
|
board: Board;
|
|
39
39
|
getNthVector: (index: number) => Cell[];
|
|
40
|
-
numberOfVectors: number;
|
|
41
40
|
PatternModel: new (parameters: { board: Board; cells: Cell[] }) => P;
|
|
41
|
+
vectorsCount: number;
|
|
42
42
|
}): P[] {
|
|
43
|
-
return this.generateVectors({ getNthVector,
|
|
43
|
+
return this.generateVectors({ getNthVector, vectorsCount }).reduce<P[]>((patterns, cells) => {
|
|
44
44
|
return patterns.concat(this.generateCellsPatterns<P>({ board, PatternModel, cells }));
|
|
45
45
|
}, []);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
public generateVectors({
|
|
49
49
|
getNthVector,
|
|
50
|
-
|
|
50
|
+
vectorsCount,
|
|
51
51
|
}: {
|
|
52
52
|
getNthVector: (index: number) => Cell[];
|
|
53
|
-
|
|
53
|
+
vectorsCount: number;
|
|
54
54
|
}): Cell[][] {
|
|
55
|
-
return Array(
|
|
55
|
+
return Array(vectorsCount)
|
|
56
56
|
.fill(0)
|
|
57
57
|
.map((_, index) => getNthVector(index));
|
|
58
58
|
}
|
|
@@ -13,7 +13,7 @@ class ScoresCalculator {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
public calculateBonusScore(pattern: Pattern): number {
|
|
16
|
-
const areAllTilesUsed = pattern.
|
|
16
|
+
const areAllTilesUsed = pattern.getEmptyCellsCount() === this.config.maximumCharactersCount;
|
|
17
17
|
return areAllTilesUsed ? this.config.allTilesBonusScore : 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Trie } from '@kamilmielnik/trie';
|
|
2
2
|
import { Board, Config, Result, Tile } from '@scrabble-solver/types';
|
|
3
|
-
import uniqBy from 'lodash/uniqBy';
|
|
4
3
|
|
|
4
|
+
import getUniquePatterns from './getUniquePatterns';
|
|
5
5
|
import PatternsFiller from './PatternsFiller';
|
|
6
6
|
import PatternsGenerator from './PatternsGenerator';
|
|
7
7
|
import ScoresCalculator from './ScoresCalculator';
|
|
@@ -22,13 +22,13 @@ class Solver {
|
|
|
22
22
|
public solve(board: Board, tiles: Tile[]): Result[] {
|
|
23
23
|
const patterns = this.patternsGenerator.generate(board);
|
|
24
24
|
const filledPatterns = patterns.flatMap((pattern) => this.patternsFiller.fill(pattern, tiles));
|
|
25
|
-
const uniquePatterns =
|
|
25
|
+
const uniquePatterns = getUniquePatterns(filledPatterns);
|
|
26
26
|
const results = uniquePatterns.map(
|
|
27
27
|
(pattern, index) =>
|
|
28
28
|
new Result({
|
|
29
29
|
cells: pattern.cells,
|
|
30
|
+
collisions: pattern.getCollisions().map((collision) => collision.cells),
|
|
30
31
|
id: index,
|
|
31
|
-
numberOfCollisions: pattern.getCollisions().length,
|
|
32
32
|
points: this.scoresCalculator.calculate(pattern),
|
|
33
33
|
}),
|
|
34
34
|
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Pattern } from '@scrabble-solver/types';
|
|
2
|
+
|
|
3
|
+
const getPatternHash = (pattern: Pattern): string => {
|
|
4
|
+
return pattern.cells
|
|
5
|
+
.map((cell) => {
|
|
6
|
+
const blank = cell.tile.isBlank ? '!' : '';
|
|
7
|
+
const tile = cell.tile.character + blank;
|
|
8
|
+
// eslint-disable-next-line prefer-template
|
|
9
|
+
return cell.x + ',' + cell.y + ',' + tile;
|
|
10
|
+
})
|
|
11
|
+
.join('-');
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const getUniquePatterns = (patterns: Pattern[]): Pattern[] => {
|
|
15
|
+
const hashes = new Set<string>();
|
|
16
|
+
const uniquePatterns: Pattern[] = [];
|
|
17
|
+
|
|
18
|
+
for (const pattern of patterns) {
|
|
19
|
+
const hash = getPatternHash(pattern);
|
|
20
|
+
|
|
21
|
+
if (!hashes.has(hash)) {
|
|
22
|
+
hashes.add(hash);
|
|
23
|
+
uniquePatterns.push(pattern);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return uniquePatterns;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default getUniquePatterns;
|
|
@@ -4,9 +4,9 @@ declare class Board {
|
|
|
4
4
|
static create(width: number, height: number): Board;
|
|
5
5
|
static fromJson(json: BoardJson): Board;
|
|
6
6
|
static fromStringArray(stringArray: string[]): Board;
|
|
7
|
+
readonly columnsCount: number;
|
|
7
8
|
readonly rows: Cell[][];
|
|
8
|
-
readonly
|
|
9
|
-
readonly numberOfRows: number;
|
|
9
|
+
readonly rowsCount: number;
|
|
10
10
|
constructor({ rows }: {
|
|
11
11
|
rows: Cell[][];
|
|
12
12
|
});
|
|
@@ -9,8 +9,8 @@ const Tile_1 = __importDefault(require("./Tile"));
|
|
|
9
9
|
class Board {
|
|
10
10
|
constructor({ rows }) {
|
|
11
11
|
this.rows = rows;
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
12
|
+
this.columnsCount = rows[0].length;
|
|
13
|
+
this.rowsCount = rows.length;
|
|
14
14
|
}
|
|
15
15
|
static create(width, height) {
|
|
16
16
|
return Board.fromStringArray(Array(height).fill(Array(width).fill(' ').join('')));
|
|
@@ -31,8 +31,8 @@ class Board {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
get center() {
|
|
34
|
-
const x = Math.floor(this.
|
|
35
|
-
const y = Math.floor(this.
|
|
34
|
+
const x = Math.floor(this.columnsCount / 2);
|
|
35
|
+
const y = Math.floor(this.rowsCount / 2);
|
|
36
36
|
return this.rows[y][x];
|
|
37
37
|
}
|
|
38
38
|
clone() {
|
|
@@ -43,20 +43,20 @@ class Board {
|
|
|
43
43
|
return this.collidesUp(cell) || this.collidesDown(cell) || this.collidesLeft(cell) || this.collidesRight(cell);
|
|
44
44
|
}
|
|
45
45
|
collidesDown({ x, y }) {
|
|
46
|
-
return y < this.
|
|
46
|
+
return y < this.rowsCount - 1 && !this.rows[y + 1][x].isEmpty;
|
|
47
47
|
}
|
|
48
48
|
collidesLeft({ x, y }) {
|
|
49
49
|
return x > 0 && !this.rows[y][x - 1].isEmpty;
|
|
50
50
|
}
|
|
51
51
|
collidesRight({ x, y }) {
|
|
52
|
-
return x < this.
|
|
52
|
+
return x < this.columnsCount - 1 && !this.rows[y][x + 1].isEmpty;
|
|
53
53
|
}
|
|
54
54
|
collidesUp({ x, y }) {
|
|
55
55
|
return y > 0 && !this.rows[y - 1][x].isEmpty;
|
|
56
56
|
}
|
|
57
57
|
equals(other) {
|
|
58
|
-
return (this.
|
|
59
|
-
this.
|
|
58
|
+
return (this.columnsCount === other.columnsCount &&
|
|
59
|
+
this.rowsCount === other.rowsCount &&
|
|
60
60
|
this.rows.every((row, rowIndex) => {
|
|
61
61
|
return row.every((cell, cellIndex) => {
|
|
62
62
|
return cell.equals(other.rows[rowIndex][cellIndex]);
|
|
@@ -1,2 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isBoardJson = void 0;
|
|
4
|
+
const CellJson_1 = require("./CellJson");
|
|
5
|
+
const isBoardJson = (value) => {
|
|
6
|
+
if (!Array.isArray(value)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
for (const row of value) {
|
|
10
|
+
if (!Array.isArray(value)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
for (const cell of row) {
|
|
14
|
+
if (!(0, CellJson_1.isCellJson)(cell)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
};
|
|
21
|
+
exports.isBoardJson = isBoardJson;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import CellJson from './CellJson';
|
|
2
2
|
import Tile from './Tile';
|
|
3
3
|
declare class Cell {
|
|
4
|
-
static fromJson(json: CellJson
|
|
5
|
-
static readonly Null: Cell;
|
|
4
|
+
static fromJson(json: CellJson): Cell;
|
|
6
5
|
readonly isEmpty: boolean;
|
|
7
6
|
tile: Tile;
|
|
8
7
|
readonly x: number;
|
|
@@ -17,7 +16,7 @@ declare class Cell {
|
|
|
17
16
|
equals(other: Cell): boolean;
|
|
18
17
|
hasTile(): boolean;
|
|
19
18
|
isCandidate(): boolean;
|
|
20
|
-
toJson(): CellJson
|
|
19
|
+
toJson(): CellJson;
|
|
21
20
|
toString(): string;
|
|
22
21
|
}
|
|
23
22
|
export default Cell;
|
|
@@ -13,9 +13,6 @@ class Cell {
|
|
|
13
13
|
this.y = y;
|
|
14
14
|
}
|
|
15
15
|
static fromJson(json) {
|
|
16
|
-
if (!json) {
|
|
17
|
-
return Cell.Null;
|
|
18
|
-
}
|
|
19
16
|
return new Cell({
|
|
20
17
|
isEmpty: json.isEmpty,
|
|
21
18
|
tile: Tile_1.default.fromJson(json.tile),
|
|
@@ -52,16 +49,4 @@ class Cell {
|
|
|
52
49
|
return this.tile.toString();
|
|
53
50
|
}
|
|
54
51
|
}
|
|
55
|
-
Cell.Null = Object.freeze({
|
|
56
|
-
isEmpty: true,
|
|
57
|
-
tile: Tile_1.default.Null,
|
|
58
|
-
x: 0,
|
|
59
|
-
y: 0,
|
|
60
|
-
clone: () => Cell.Null,
|
|
61
|
-
equals: (other) => other === Cell.Null,
|
|
62
|
-
hasTile: () => false,
|
|
63
|
-
isCandidate: () => false,
|
|
64
|
-
toString: () => '',
|
|
65
|
-
toJson: () => null,
|
|
66
|
-
});
|
|
67
52
|
exports.default = Cell;
|
|
@@ -1,2 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isCellJson = void 0;
|
|
7
|
+
const isObject_1 = __importDefault(require("./isObject"));
|
|
8
|
+
const TileJson_1 = require("./TileJson");
|
|
9
|
+
const isCellJson = (value) => {
|
|
10
|
+
return ((0, isObject_1.default)(value) &&
|
|
11
|
+
typeof value.isEmpty === 'boolean' &&
|
|
12
|
+
((0, TileJson_1.isTileJson)(value.tile) || value.tile === null) &&
|
|
13
|
+
typeof value.x === 'number' &&
|
|
14
|
+
typeof value.y === 'number');
|
|
15
|
+
};
|
|
16
|
+
exports.isCellJson = isCellJson;
|
|
@@ -13,6 +13,7 @@ declare class Config {
|
|
|
13
13
|
get allTilesBonusScore(): number;
|
|
14
14
|
get alphabet(): string[];
|
|
15
15
|
get blankScore(): number;
|
|
16
|
+
get blanksCount(): number;
|
|
16
17
|
get boardHeight(): number;
|
|
17
18
|
get boardWidth(): number;
|
|
18
19
|
get twoCharacterTiles(): string[];
|
|
@@ -23,8 +24,7 @@ declare class Config {
|
|
|
23
24
|
getTilePoints(tile: Tile | null): number | undefined;
|
|
24
25
|
hasCharacter(character: string): boolean;
|
|
25
26
|
isTwoCharacterTilePrefix(character: string): boolean;
|
|
26
|
-
get
|
|
27
|
-
get numberOfBlanks(): number;
|
|
27
|
+
get maximumCharactersCount(): number;
|
|
28
28
|
get tiles(): TileConfig[];
|
|
29
29
|
toJson(): ConfigJson;
|
|
30
30
|
}
|
|
@@ -24,6 +24,9 @@ class Config {
|
|
|
24
24
|
get blankScore() {
|
|
25
25
|
return this.config.blankScore;
|
|
26
26
|
}
|
|
27
|
+
get blanksCount() {
|
|
28
|
+
return this.config.blanksCount;
|
|
29
|
+
}
|
|
27
30
|
get boardHeight() {
|
|
28
31
|
return this.config.boardHeight;
|
|
29
32
|
}
|
|
@@ -66,11 +69,8 @@ class Config {
|
|
|
66
69
|
isTwoCharacterTilePrefix(character) {
|
|
67
70
|
return typeof this.getTwoCharacterTileByPrefix(character) !== 'undefined';
|
|
68
71
|
}
|
|
69
|
-
get
|
|
70
|
-
return this.config.
|
|
71
|
-
}
|
|
72
|
-
get numberOfBlanks() {
|
|
73
|
-
return this.config.numberOfBlanks;
|
|
72
|
+
get maximumCharactersCount() {
|
|
73
|
+
return this.config.maximumCharactersCount;
|
|
74
74
|
}
|
|
75
75
|
get tiles() {
|
|
76
76
|
return this.config.tiles;
|
|
@@ -3,13 +3,13 @@ import TileConfig from './TileConfig';
|
|
|
3
3
|
interface ConfigJson {
|
|
4
4
|
allTilesBonusScore: number;
|
|
5
5
|
blankScore: number;
|
|
6
|
+
blanksCount: number;
|
|
6
7
|
boardHeight: number;
|
|
7
8
|
boardWidth: number;
|
|
8
9
|
bonuses: BonusJson[];
|
|
9
10
|
id: string;
|
|
10
|
-
|
|
11
|
+
maximumCharactersCount: number;
|
|
11
12
|
name: string;
|
|
12
|
-
numberOfBlanks: number;
|
|
13
13
|
tiles: TileConfig[];
|
|
14
14
|
}
|
|
15
15
|
export default ConfigJson;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isLocale = void 0;
|
|
3
4
|
// eslint-disable-next-line no-shadow
|
|
4
5
|
var Locale;
|
|
5
6
|
(function (Locale) {
|
|
@@ -10,4 +11,7 @@ var Locale;
|
|
|
10
11
|
Locale["PL_PL"] = "pl-PL";
|
|
11
12
|
Locale["DE_DE"] = "de-DE";
|
|
12
13
|
})(Locale || (Locale = {}));
|
|
14
|
+
const locales = Object.values(Locale);
|
|
15
|
+
const isLocale = (locale) => locales.includes(locale);
|
|
16
|
+
exports.isLocale = isLocale;
|
|
13
17
|
exports.default = Locale;
|
|
@@ -13,7 +13,7 @@ declare class Pattern {
|
|
|
13
13
|
clone(): Pattern;
|
|
14
14
|
collides(): boolean;
|
|
15
15
|
getIndexOfFirstCellWithoutTile(): number;
|
|
16
|
-
|
|
16
|
+
getEmptyCellsCount(): number;
|
|
17
17
|
goesThroughBoardCenter(): boolean;
|
|
18
18
|
hasAtLeast1EmptyCell(): boolean;
|
|
19
19
|
hasAtLeast1NonEmptyCell(): boolean;
|
|
@@ -6,9 +6,9 @@ class Pattern {
|
|
|
6
6
|
this.cells = cells;
|
|
7
7
|
}
|
|
8
8
|
canBePlaced(config) {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
return (
|
|
9
|
+
const emptyCellsCount = this.getEmptyCellsCount();
|
|
10
|
+
const isUsedCellsCountInRange = emptyCellsCount >= 1 && emptyCellsCount <= config.maximumCharactersCount;
|
|
11
|
+
return (isUsedCellsCountInRange &&
|
|
12
12
|
(this.hasAtLeast1NonEmptyCell() || this.collides() || (this.goesThroughBoardCenter() && this.board.isEmpty())));
|
|
13
13
|
}
|
|
14
14
|
clone() {
|
|
@@ -23,7 +23,7 @@ class Pattern {
|
|
|
23
23
|
getIndexOfFirstCellWithoutTile() {
|
|
24
24
|
return this.cells.findIndex((cell) => !cell.hasTile());
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
getEmptyCellsCount() {
|
|
27
27
|
return this.cells.filter((cell) => cell.isEmpty).length;
|
|
28
28
|
}
|
|
29
29
|
goesThroughBoardCenter() {
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import Cell from './Cell';
|
|
2
2
|
import ResultJson from './ResultJson';
|
|
3
3
|
import Tile from './Tile';
|
|
4
|
+
declare type Collision = Cell[];
|
|
4
5
|
declare class Result {
|
|
5
6
|
static fromJson(json: ResultJson): Result;
|
|
7
|
+
readonly blanksCount: number;
|
|
6
8
|
readonly cells: Cell[];
|
|
9
|
+
readonly collisions: Collision[];
|
|
10
|
+
readonly consonantsCount: number;
|
|
7
11
|
readonly id: number;
|
|
8
12
|
readonly length: number;
|
|
9
|
-
readonly numberOfBlanks: number;
|
|
10
|
-
readonly numberOfCollisions: number;
|
|
11
|
-
readonly numberOfConsonants: number;
|
|
12
|
-
readonly numberOfTiles: number;
|
|
13
|
-
readonly numberOfVowels: number;
|
|
14
|
-
readonly numberOfWords: number;
|
|
15
13
|
readonly points: number;
|
|
16
14
|
readonly pointsRatio: number;
|
|
17
15
|
readonly tiles: Tile[];
|
|
18
16
|
readonly tilesCharacters: string;
|
|
17
|
+
readonly tilesCount: number;
|
|
18
|
+
readonly vowelsCount: number;
|
|
19
19
|
readonly word: string;
|
|
20
|
-
|
|
20
|
+
readonly words: string[];
|
|
21
|
+
readonly wordsCount: number;
|
|
22
|
+
constructor({ cells, id, collisions, points, }: {
|
|
21
23
|
cells: Cell[];
|
|
22
24
|
id: number;
|
|
23
|
-
|
|
25
|
+
collisions: Collision[];
|
|
24
26
|
points: number;
|
|
25
27
|
});
|
|
26
28
|
toJson(): ResultJson;
|
|
@@ -6,28 +6,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const constants_1 = require("@scrabble-solver/constants");
|
|
7
7
|
const Cell_1 = __importDefault(require("./Cell"));
|
|
8
8
|
class Result {
|
|
9
|
-
constructor({ cells, id,
|
|
9
|
+
constructor({ cells, id, collisions, points, }) {
|
|
10
10
|
const tiles = getTiles(cells);
|
|
11
|
+
this.blanksCount = getBlanks(tiles).length;
|
|
11
12
|
this.cells = cells;
|
|
13
|
+
this.collisions = collisions;
|
|
14
|
+
this.consonantsCount = getConsonants(tiles).length;
|
|
12
15
|
this.id = id;
|
|
13
16
|
this.length = cells.length;
|
|
14
|
-
this.numberOfCollisions = numberOfCollisions;
|
|
15
|
-
this.numberOfConsonants = getConsonants(tiles).length;
|
|
16
|
-
this.numberOfBlanks = getBlanks(tiles).length;
|
|
17
|
-
this.numberOfTiles = tiles.length;
|
|
18
|
-
this.numberOfVowels = getVowels(tiles).length;
|
|
19
|
-
this.numberOfWords = 1 + this.numberOfCollisions;
|
|
20
17
|
this.points = points;
|
|
21
18
|
this.pointsRatio = getPointsRatio(tiles, points);
|
|
22
19
|
this.tiles = tiles;
|
|
23
20
|
this.tilesCharacters = getTilesCharacters(tiles);
|
|
21
|
+
this.tilesCount = tiles.length;
|
|
22
|
+
this.vowelsCount = getVowels(tiles).length;
|
|
24
23
|
this.word = getWord(cells);
|
|
24
|
+
this.words = getWords(cells, collisions);
|
|
25
|
+
this.wordsCount = 1 + this.collisions.length;
|
|
25
26
|
}
|
|
26
27
|
static fromJson(json) {
|
|
27
28
|
return new Result({
|
|
28
|
-
cells: json.cells.map(Cell_1.default.fromJson),
|
|
29
29
|
id: json.id,
|
|
30
|
-
|
|
30
|
+
cells: json.cells.map(Cell_1.default.fromJson),
|
|
31
|
+
collisions: json.collisions.map((collision) => collision.map(Cell_1.default.fromJson)),
|
|
31
32
|
points: json.points,
|
|
32
33
|
});
|
|
33
34
|
}
|
|
@@ -35,7 +36,7 @@ class Result {
|
|
|
35
36
|
return {
|
|
36
37
|
cells: this.cells.map((cell) => cell.toJson()),
|
|
37
38
|
id: this.id,
|
|
38
|
-
|
|
39
|
+
collisions: this.collisions.map((collision) => collision.map((cell) => cell.toJson())),
|
|
39
40
|
points: this.points,
|
|
40
41
|
};
|
|
41
42
|
}
|
|
@@ -50,6 +51,10 @@ const getPointsRatio = (tiles, points) => points / tiles.length;
|
|
|
50
51
|
const getTiles = (cells) => cells.filter(({ isEmpty }) => isEmpty).map(({ tile }) => tile);
|
|
51
52
|
const getTilesCharacters = (tiles) => getNonBlankCharacters(tiles).sort(charactersComparator).join('');
|
|
52
53
|
const getWord = (cells) => cells.map(String).join('');
|
|
54
|
+
const getWords = (cells, collisions) => [
|
|
55
|
+
getWord(cells),
|
|
56
|
+
...collisions.map((collision) => collision.map(String).join('')),
|
|
57
|
+
];
|
|
53
58
|
const isConsonant = ({ character, isBlank }) => constants_1.CONSONANTS.includes(character) && !isBlank;
|
|
54
59
|
const isVowel = ({ character, isBlank }) => constants_1.VOWELS.includes(character) && !isBlank;
|
|
55
60
|
exports.default = Result;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import CellJson from './CellJson';
|
|
2
|
+
import CollisionJson from './CollisionJson';
|
|
2
3
|
interface ResultJson {
|
|
3
|
-
cells:
|
|
4
|
+
cells: CellJson[];
|
|
5
|
+
collisions: CollisionJson[];
|
|
4
6
|
id: number;
|
|
5
|
-
numberOfCollisions: number;
|
|
6
7
|
points: number;
|
|
7
8
|
}
|
|
8
9
|
export default ResultJson;
|
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isTileJson = void 0;
|
|
7
|
+
const isObject_1 = __importDefault(require("./isObject"));
|
|
8
|
+
const isTileJson = (value) => {
|
|
9
|
+
return (0, isObject_1.default)(value) && typeof value.character === 'string' && typeof value.isBlank === 'boolean';
|
|
10
|
+
};
|
|
11
|
+
exports.isTileJson = isTileJson;
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
export { default as Board } from './Board';
|
|
2
|
-
export { default as BoardJson } from './BoardJson';
|
|
2
|
+
export { default as BoardJson, isBoardJson } from './BoardJson';
|
|
3
3
|
export { default as Bonus } from './Bonus';
|
|
4
4
|
export { default as BonusJson } from './BonusJson';
|
|
5
5
|
export { default as BonusValue } from './BonusValue';
|
|
6
6
|
export { default as Cell } from './Cell';
|
|
7
|
-
export { default as CellJson } from './CellJson';
|
|
7
|
+
export { default as CellJson, isCellJson } from './CellJson';
|
|
8
8
|
export { default as CharacterBonus } from './CharacterBonus';
|
|
9
|
+
export { default as Collision } from './Collision';
|
|
10
|
+
export { default as CollisionJson } from './CollisionJson';
|
|
9
11
|
export { default as Config } from './Config';
|
|
10
12
|
export { default as ConfigJson } from './ConfigJson';
|
|
11
13
|
export { default as HorizontalPattern } from './HorizontalPattern';
|
|
12
|
-
export { default as
|
|
14
|
+
export { default as isObject } from './isObject';
|
|
15
|
+
export { default as Locale, isLocale } from './Locale';
|
|
13
16
|
export { default as Pattern } from './Pattern';
|
|
14
17
|
export { default as PatternJson } from './PatternJson';
|
|
15
18
|
export { default as Result } from './Result';
|
|
16
19
|
export { default as ResultJson } from './ResultJson';
|
|
17
20
|
export { default as Tile } from './Tile';
|
|
18
21
|
export { default as TileConfig } from './TileConfig';
|
|
19
|
-
export { default as TileJson } from './TileJson';
|
|
22
|
+
export { default as TileJson, isTileJson } from './TileJson';
|
|
20
23
|
export { default as VerticalPattern } from './VerticalPattern';
|
|
21
24
|
export { default as WordBonus } from './WordBonus';
|
|
22
25
|
export { default as WordDefinition } from './WordDefinition';
|
|
@@ -3,27 +3,36 @@ 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.WordDefinition = exports.WordBonus = exports.VerticalPattern = exports.Tile = exports.Result = exports.Pattern = exports.Locale = exports.HorizontalPattern = exports.Config = exports.CharacterBonus = exports.Cell = exports.Bonus = exports.Board = void 0;
|
|
6
|
+
exports.WordDefinition = exports.WordBonus = exports.VerticalPattern = exports.isTileJson = exports.Tile = exports.Result = exports.Pattern = exports.isLocale = exports.Locale = exports.isObject = exports.HorizontalPattern = exports.Config = exports.CharacterBonus = exports.isCellJson = exports.Cell = exports.Bonus = exports.isBoardJson = exports.Board = void 0;
|
|
7
7
|
var Board_1 = require("./Board");
|
|
8
8
|
Object.defineProperty(exports, "Board", { enumerable: true, get: function () { return __importDefault(Board_1).default; } });
|
|
9
|
+
var BoardJson_1 = require("./BoardJson");
|
|
10
|
+
Object.defineProperty(exports, "isBoardJson", { enumerable: true, get: function () { return BoardJson_1.isBoardJson; } });
|
|
9
11
|
var Bonus_1 = require("./Bonus");
|
|
10
12
|
Object.defineProperty(exports, "Bonus", { enumerable: true, get: function () { return __importDefault(Bonus_1).default; } });
|
|
11
13
|
var Cell_1 = require("./Cell");
|
|
12
14
|
Object.defineProperty(exports, "Cell", { enumerable: true, get: function () { return __importDefault(Cell_1).default; } });
|
|
15
|
+
var CellJson_1 = require("./CellJson");
|
|
16
|
+
Object.defineProperty(exports, "isCellJson", { enumerable: true, get: function () { return CellJson_1.isCellJson; } });
|
|
13
17
|
var CharacterBonus_1 = require("./CharacterBonus");
|
|
14
18
|
Object.defineProperty(exports, "CharacterBonus", { enumerable: true, get: function () { return __importDefault(CharacterBonus_1).default; } });
|
|
15
19
|
var Config_1 = require("./Config");
|
|
16
20
|
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return __importDefault(Config_1).default; } });
|
|
17
21
|
var HorizontalPattern_1 = require("./HorizontalPattern");
|
|
18
22
|
Object.defineProperty(exports, "HorizontalPattern", { enumerable: true, get: function () { return __importDefault(HorizontalPattern_1).default; } });
|
|
23
|
+
var isObject_1 = require("./isObject");
|
|
24
|
+
Object.defineProperty(exports, "isObject", { enumerable: true, get: function () { return __importDefault(isObject_1).default; } });
|
|
19
25
|
var Locale_1 = require("./Locale");
|
|
20
26
|
Object.defineProperty(exports, "Locale", { enumerable: true, get: function () { return __importDefault(Locale_1).default; } });
|
|
27
|
+
Object.defineProperty(exports, "isLocale", { enumerable: true, get: function () { return Locale_1.isLocale; } });
|
|
21
28
|
var Pattern_1 = require("./Pattern");
|
|
22
29
|
Object.defineProperty(exports, "Pattern", { enumerable: true, get: function () { return __importDefault(Pattern_1).default; } });
|
|
23
30
|
var Result_1 = require("./Result");
|
|
24
31
|
Object.defineProperty(exports, "Result", { enumerable: true, get: function () { return __importDefault(Result_1).default; } });
|
|
25
32
|
var Tile_1 = require("./Tile");
|
|
26
33
|
Object.defineProperty(exports, "Tile", { enumerable: true, get: function () { return __importDefault(Tile_1).default; } });
|
|
34
|
+
var TileJson_1 = require("./TileJson");
|
|
35
|
+
Object.defineProperty(exports, "isTileJson", { enumerable: true, get: function () { return TileJson_1.isTileJson; } });
|
|
27
36
|
var VerticalPattern_1 = require("./VerticalPattern");
|
|
28
37
|
Object.defineProperty(exports, "VerticalPattern", { enumerable: true, get: function () { return __importDefault(VerticalPattern_1).default; } });
|
|
29
38
|
var WordBonus_1 = require("./WordBonus");
|