@scrabble-solver/solver 2.15.10 → 2.15.12

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 (37) hide show
  1. package/build/areDigraphsValid.d.ts +1 -1
  2. package/build/fillPattern.d.ts +2 -2
  3. package/build/generateEndIndices.d.ts +1 -1
  4. package/build/generateHorizontalPatterns.d.ts +1 -1
  5. package/build/generatePattern.d.ts +1 -1
  6. package/build/generatePatterns.d.ts +1 -1
  7. package/build/generateStartIndices.d.ts +1 -1
  8. package/build/generateVectors.d.ts +1 -1
  9. package/build/generateVerticalPatterns.d.ts +1 -1
  10. package/build/getCellsScore.d.ts +1 -1
  11. package/build/getPatternHash.d.ts +1 -1
  12. package/build/getPatternScore.d.ts +1 -1
  13. package/build/getPatternScore.js +13 -4
  14. package/build/getUniquePatterns.d.ts +1 -1
  15. package/build/solve.d.ts +2 -2
  16. package/package.json +6 -6
  17. package/src/areDigraphsValid.ts +1 -1
  18. package/src/fillPattern.test.ts +2 -2
  19. package/src/fillPattern.ts +2 -2
  20. package/src/generateEndIndices.test.ts +1 -1
  21. package/src/generateEndIndices.ts +1 -1
  22. package/src/generateHorizontalPatterns.test.ts +1 -1
  23. package/src/generateHorizontalPatterns.ts +1 -1
  24. package/src/generatePattern.ts +1 -1
  25. package/src/generatePatterns.ts +1 -1
  26. package/src/generateStartIndices.test.ts +1 -1
  27. package/src/generateStartIndices.ts +1 -1
  28. package/src/generateVectors.ts +1 -1
  29. package/src/generateVerticalPatterns.test.ts +1 -1
  30. package/src/generateVerticalPatterns.ts +1 -1
  31. package/src/getCellsScore.ts +1 -1
  32. package/src/getPatternHash.ts +1 -1
  33. package/src/getPatternScore.test.ts +139 -53
  34. package/src/getPatternScore.ts +15 -5
  35. package/src/getUniquePatterns.ts +1 -1
  36. package/src/solve.test.ts +1 -1
  37. package/src/solve.ts +2 -2
@@ -1,2 +1,2 @@
1
- import { Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Config, type Pattern } from '@scrabble-solver/types';
2
2
  export declare const areDigraphsValid: (config: Config, pattern: Pattern) => boolean;
@@ -1,5 +1,5 @@
1
- import { Trie } from '@kamilmielnik/trie';
2
- import { Config, Pattern, Tile } from '@scrabble-solver/types';
1
+ import { type Trie } from '@kamilmielnik/trie';
2
+ import { type Config, type Pattern, type Tile } from '@scrabble-solver/types';
3
3
  export declare const fillPattern: (trie: Trie, config: Config, pattern: Pattern, tiles: Tile[]) => Pattern[];
4
4
  export declare const fillPatternRecursive: (
5
5
  /** gets mutated when this function is called */
@@ -1,2 +1,2 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
  export declare const generateEndIndices: (cells: Cell[], startIndex: number) => number[];
@@ -1,2 +1,2 @@
1
- import { Board, Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Board, type Config, type Pattern } from '@scrabble-solver/types';
2
2
  export declare const generateHorizontalPatterns: (config: Config, board: Board) => Pattern[];
@@ -1,4 +1,4 @@
1
- import { Board, Cell, Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Board, type Cell, type Config, type Pattern } from '@scrabble-solver/types';
2
2
  export declare const generatePattern: <P extends Pattern>({ board, cells, config, PatternModel, }: {
3
3
  board: Board;
4
4
  cells: Cell[];
@@ -1,2 +1,2 @@
1
- import { Board, Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Board, type Config, type Pattern } from '@scrabble-solver/types';
2
2
  export declare const generatePatterns: (config: Config, board: Board) => Pattern[];
@@ -1,2 +1,2 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
  export declare const generateStartIndices: (cells: Cell[]) => number[];
@@ -1,4 +1,4 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
  interface Parameters {
3
3
  getNthVector: (index: number) => Cell[];
4
4
  vectorsCount: number;
@@ -1,2 +1,2 @@
1
- import { Board, Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Board, type Config, type Pattern } from '@scrabble-solver/types';
2
2
  export declare const generateVerticalPatterns: (config: Config, board: Board) => Pattern[];
@@ -1,2 +1,2 @@
1
- import { Cell, Config } from '@scrabble-solver/types';
1
+ import { type Cell, type Config } from '@scrabble-solver/types';
2
2
  export declare const getCellsScore: (config: Config, cells: Cell[]) => number;
@@ -1,2 +1,2 @@
1
- import { Pattern } from '@scrabble-solver/types';
1
+ import { type Pattern } from '@scrabble-solver/types';
2
2
  export declare const getPatternHash: (pattern: Pattern) => string;
@@ -1,2 +1,2 @@
1
- import { Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Config, type Pattern } from '@scrabble-solver/types';
2
2
  export declare const getPatternScore: (config: Config, pattern: Pattern) => number;
@@ -1,13 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPatternScore = void 0;
4
+ const types_1 = require("@scrabble-solver/types");
4
5
  const getCellsScore_1 = require("./getCellsScore");
5
6
  const getPatternScore = (config, pattern) => {
6
7
  const areAllTilesUsed = pattern.getEmptyCellsCount() === config.rackSize;
7
- const bonusScore = areAllTilesUsed ? config.bingoScore : 0;
8
- const score = pattern
8
+ const baseScore = (0, getCellsScore_1.getCellsScore)(config, pattern.cells);
9
+ const collisionsScore = pattern
9
10
  .getCollisions()
10
- .reduce((sum, collision) => sum + (0, getCellsScore_1.getCellsScore)(config, collision.cells), (0, getCellsScore_1.getCellsScore)(config, pattern.cells));
11
- return score + bonusScore;
11
+ .reduce((sum, collision) => sum + (0, getCellsScore_1.getCellsScore)(config, collision.cells), 0);
12
+ if (areAllTilesUsed) {
13
+ if ((0, types_1.isScoreBingo)(config.bingo)) {
14
+ return baseScore + collisionsScore + config.bingo.score;
15
+ }
16
+ if ((0, types_1.isMultiplierBingo)(config.bingo)) {
17
+ return baseScore * config.bingo.multiplier + collisionsScore;
18
+ }
19
+ }
20
+ return baseScore + collisionsScore;
12
21
  };
13
22
  exports.getPatternScore = getPatternScore;
@@ -1,2 +1,2 @@
1
- import { Pattern } from '@scrabble-solver/types';
1
+ import { type Pattern } from '@scrabble-solver/types';
2
2
  export declare const getUniquePatterns: (patterns: Pattern[]) => Pattern[];
package/build/solve.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { Trie } from '@kamilmielnik/trie';
2
- import { Board, Config, ResultJson, Tile } from '@scrabble-solver/types';
1
+ import { type Trie } from '@kamilmielnik/trie';
2
+ import { type Board, type Config, type ResultJson, type Tile } from '@scrabble-solver/types';
3
3
  export declare const solve: (trie: Trie, config: Config, board: Board, tiles: Tile[]) => ResultJson[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/solver",
3
- "version": "2.15.10",
3
+ "version": "2.15.12",
4
4
  "description": "Scrabble Solver 2 - Solver",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -24,12 +24,12 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@kamilmielnik/trie": "^4.0.0",
27
- "@scrabble-solver/types": "^2.15.10"
27
+ "@scrabble-solver/types": "^2.15.12"
28
28
  },
29
29
  "devDependencies": {
30
- "@scrabble-solver/configs": "^2.15.10",
31
- "@scrabble-solver/constants": "^2.15.10",
32
- "@scrabble-solver/dictionaries": "^2.15.10"
30
+ "@scrabble-solver/configs": "^2.15.12",
31
+ "@scrabble-solver/constants": "^2.15.12",
32
+ "@scrabble-solver/dictionaries": "^2.15.12"
33
33
  },
34
- "gitHead": "dab5a817c1bde1a3ebf8e8907215adf12af5cb27"
34
+ "gitHead": "1eeef2b2975e63b195885dd2636c53624d300c6b"
35
35
  }
@@ -1,4 +1,4 @@
1
- import { Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Config, type Pattern } from '@scrabble-solver/types';
2
2
 
3
3
  export const areDigraphsValid = (config: Config, pattern: Pattern): boolean => {
4
4
  const { twoCharacterTiles } = config;
@@ -1,7 +1,7 @@
1
- import { Trie } from '@kamilmielnik/trie';
1
+ import { type Trie } from '@kamilmielnik/trie';
2
2
  import { getConfig } from '@scrabble-solver/configs';
3
3
  import { dictionaries } from '@scrabble-solver/dictionaries';
4
- import { Board, Cell, FinalPattern, Game, Locale, Pattern, Tile, VerticalPattern } from '@scrabble-solver/types';
4
+ import { Board, Cell, FinalPattern, Game, Locale, type Pattern, Tile, VerticalPattern } from '@scrabble-solver/types';
5
5
 
6
6
  import { fillPattern, fillPatternRecursive } from './fillPattern';
7
7
 
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable max-params, max-statements */
2
- import { Trie } from '@kamilmielnik/trie';
2
+ import { type Trie } from '@kamilmielnik/trie';
3
3
  import { EMPTY_CELL } from '@scrabble-solver/constants';
4
- import { Config, FinalPattern, Pattern, Tile } from '@scrabble-solver/types';
4
+ import { type Config, FinalPattern, type Pattern, type Tile } from '@scrabble-solver/types';
5
5
 
6
6
  export const fillPattern = (trie: Trie, config: Config, pattern: Pattern, tiles: Tile[]): Pattern[] => {
7
7
  if (pattern.getEmptyCellsCount() > tiles.length) {
@@ -1,4 +1,4 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
 
3
3
  import { generateEndIndices } from './generateEndIndices';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
 
3
3
  export const generateEndIndices = (cells: Cell[], startIndex: number): number[] => {
4
4
  if (cells.length === 0) {
@@ -1,5 +1,5 @@
1
1
  import { EMPTY_CELL } from '@scrabble-solver/constants';
2
- import { Board, Config } from '@scrabble-solver/types';
2
+ import { Board, type Config } from '@scrabble-solver/types';
3
3
 
4
4
  import { generateHorizontalPatterns } from './generateHorizontalPatterns';
5
5
 
@@ -1,4 +1,4 @@
1
- import { Board, Config, HorizontalPattern, Pattern } from '@scrabble-solver/types';
1
+ import { type Board, type Config, HorizontalPattern, type Pattern } from '@scrabble-solver/types';
2
2
 
3
3
  import { generatePattern } from './generatePattern';
4
4
  import { generateVectors } from './generateVectors';
@@ -1,4 +1,4 @@
1
- import { Board, Cell, Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Board, type Cell, type Config, type Pattern } from '@scrabble-solver/types';
2
2
 
3
3
  import { generateEndIndices } from './generateEndIndices';
4
4
  import { generateStartIndices } from './generateStartIndices';
@@ -1,4 +1,4 @@
1
- import { Board, Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Board, type Config, type Pattern } from '@scrabble-solver/types';
2
2
 
3
3
  import { generateHorizontalPatterns } from './generateHorizontalPatterns';
4
4
  import { generateVerticalPatterns } from './generateVerticalPatterns';
@@ -1,4 +1,4 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
 
3
3
  import { generateStartIndices } from './generateStartIndices';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
 
3
3
  export const generateStartIndices = (cells: Cell[]): number[] => {
4
4
  if (cells.length === 0) {
@@ -1,4 +1,4 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
 
3
3
  interface Parameters {
4
4
  getNthVector: (index: number) => Cell[];
@@ -1,5 +1,5 @@
1
1
  import { EMPTY_CELL } from '@scrabble-solver/constants';
2
- import { Board, Config } from '@scrabble-solver/types';
2
+ import { Board, type Config } from '@scrabble-solver/types';
3
3
 
4
4
  import { generateVerticalPatterns } from './generateVerticalPatterns';
5
5
 
@@ -1,4 +1,4 @@
1
- import { Board, Config, Pattern, VerticalPattern } from '@scrabble-solver/types';
1
+ import { type Board, type Config, type Pattern, VerticalPattern } from '@scrabble-solver/types';
2
2
 
3
3
  import { generatePattern } from './generatePattern';
4
4
  import { generateVectors } from './generateVectors';
@@ -1,5 +1,5 @@
1
1
  import { NO_BONUS } from '@scrabble-solver/constants';
2
- import { Cell, Config } from '@scrabble-solver/types';
2
+ import { type Cell, type Config } from '@scrabble-solver/types';
3
3
 
4
4
  export const getCellsScore = (config: Config, cells: Cell[]): number => {
5
5
  const total = cells.reduce(
@@ -1,4 +1,4 @@
1
- import { Pattern } from '@scrabble-solver/types';
1
+ import { type Pattern } from '@scrabble-solver/types';
2
2
 
3
3
  export const getPatternHash = (pattern: Pattern): string => {
4
4
  return pattern.cells
@@ -3,68 +3,154 @@ import { Board, Cell, Game, HorizontalPattern, Locale, Pattern, Tile, VerticalPa
3
3
 
4
4
  import { getPatternScore } from './getPatternScore';
5
5
 
6
- const locale = Locale.PL_PL;
7
- const config = getConfig(Game.Literaki, locale);
8
- const board = Board.fromStringArray([
9
- ' kasom ',
10
- ' i ',
11
- ' napiją ',
12
- ' w i ',
13
- ' krabim ',
14
- ' z ',
15
- ' ę eh ',
16
- 'f s srać ',
17
- 'i z t s ',
18
- 'knebel e ',
19
- 'a ew warcz',
20
- 'ł żyło wody ',
21
- 'o pecyj chu',
22
- ' y ',
23
- ' t ',
24
- ]);
25
-
26
6
  describe('getPatternScore', () => {
27
- it('gives proper score without collisions', () => {
28
- const pattern = new Pattern(board, [
29
- new Cell({ x: 0, y: 0, tile: new Tile({ character: 'ź' }), isEmpty: true }),
30
- new Cell({ x: 1, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
31
- new Cell({ x: 2, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
32
- new Cell({ x: 3, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
33
- new Cell({ x: 4, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
34
- new Cell({ x: 5, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
35
- new Cell({ x: 6, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
36
- new Cell({ x: 7, y: 0, tile: new Tile({ character: 'ź' }), isEmpty: false }),
7
+ describe('Literaki - PL_PL', () => {
8
+ const config = getConfig(Game.Literaki, Locale.PL_PL);
9
+ const board = Board.fromStringArray([
10
+ ' kasom ',
11
+ ' i ',
12
+ ' napiją ',
13
+ ' w i ',
14
+ ' krabim ',
15
+ ' z ',
16
+ ' ę eh ',
17
+ 'f s srać ',
18
+ 'i z t s ',
19
+ 'knebel e ',
20
+ 'a ew warcz',
21
+ 'ł żyło wody ',
22
+ 'o pecyj chu',
23
+ ' y ',
24
+ ' t ',
37
25
  ]);
38
26
 
39
- expect(getPatternScore(config, pattern)).toBe(128);
40
- });
27
+ it('gives proper score without collisions (źaaaaaaź)', () => {
28
+ const pattern = new Pattern(board, [
29
+ new Cell({ x: 0, y: 0, tile: new Tile({ character: 'ź' }), isEmpty: true }),
30
+ new Cell({ x: 1, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
31
+ new Cell({ x: 2, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
32
+ new Cell({ x: 3, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
33
+ new Cell({ x: 4, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
34
+ new Cell({ x: 5, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
35
+ new Cell({ x: 6, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
36
+ new Cell({ x: 7, y: 0, tile: new Tile({ character: 'ź' }), isEmpty: false }),
37
+ ]);
41
38
 
42
- it('gives proper score with collisions', () => {
43
- const pattern = new VerticalPattern(board, [
44
- new Cell({ x: 2, y: 11, tile: new Tile({ character: 'l' }), isEmpty: true }),
45
- new Cell({ x: 2, y: 12, tile: new Tile({ character: 'i' }), isEmpty: true }),
46
- new Cell({ x: 2, y: 13, tile: new Tile({ character: 'n' }), isEmpty: true }),
47
- new Cell({ x: 2, y: 14, tile: new Tile({ character: 'o' }), isEmpty: true }),
48
- ]);
39
+ expect(getPatternScore(config, pattern)).toBe(128);
40
+ });
49
41
 
50
- expect(getPatternScore(config, pattern)).toBe(44);
51
- });
42
+ it('gives proper score with collisions (źaaaaaaź)', () => {
43
+ const pattern = new HorizontalPattern(board, [
44
+ new Cell({ x: 0, y: 0, tile: new Tile({ character: 'ź' }), isEmpty: true }),
45
+ new Cell({ x: 1, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
46
+ new Cell({ x: 2, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
47
+ new Cell({ x: 3, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
48
+ new Cell({ x: 4, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
49
+ new Cell({ x: 5, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
50
+ new Cell({ x: 6, y: 0, tile: new Tile({ character: 'a' }), isEmpty: true }),
51
+ new Cell({ x: 7, y: 0, tile: new Tile({ character: 'ź' }), isEmpty: false }),
52
+ ]);
52
53
 
53
- it('gives proper score for blank', () => {
54
- const pattern = new HorizontalPattern(board, [
55
- new Cell({ x: 13, y: 14, tile: new Tile({ character: 'o', isBlank: true }), isEmpty: true }),
56
- new Cell({ x: 12, y: 14, tile: new Tile({ character: 't' }), isEmpty: false }),
57
- ]);
54
+ expect(getPatternScore(config, pattern)).toBe(133);
55
+ });
56
+
57
+ it('gives proper score with collisions (lino)', () => {
58
+ const pattern = new VerticalPattern(board, [
59
+ new Cell({ x: 2, y: 11, tile: new Tile({ character: 'l' }), isEmpty: true }),
60
+ new Cell({ x: 2, y: 12, tile: new Tile({ character: 'i' }), isEmpty: true }),
61
+ new Cell({ x: 2, y: 13, tile: new Tile({ character: 'n' }), isEmpty: true }),
62
+ new Cell({ x: 2, y: 14, tile: new Tile({ character: 'o' }), isEmpty: true }),
63
+ ]);
64
+
65
+ expect(getPatternScore(config, pattern)).toBe(44);
66
+ });
67
+
68
+ it('gives proper score for blank', () => {
69
+ const pattern = new HorizontalPattern(board, [
70
+ new Cell({ x: 13, y: 14, tile: new Tile({ character: 'o', isBlank: true }), isEmpty: true }),
71
+ new Cell({ x: 12, y: 14, tile: new Tile({ character: 't' }), isEmpty: false }),
72
+ ]);
73
+
74
+ expect(getPatternScore(config, pattern)).toBe(2);
75
+ });
58
76
 
59
- expect(getPatternScore(config, pattern)).toBe(2);
77
+ it('gives 0 score for unknown characters', () => {
78
+ const pattern = new HorizontalPattern(board, [
79
+ new Cell({ x: 13, y: 14, tile: new Tile({ character: '?', isBlank: false }), isEmpty: true }),
80
+ new Cell({ x: 12, y: 14, tile: new Tile({ character: 't' }), isEmpty: false }),
81
+ ]);
82
+
83
+ expect(getPatternScore(config, pattern)).toBe(2);
84
+ });
85
+
86
+ it('gives 50 points bonus for bingo', () => {
87
+ const pattern = new HorizontalPattern(board, [
88
+ new Cell({ x: 6, y: 14, tile: new Tile({ character: 'p' }), isEmpty: true }),
89
+ new Cell({ x: 7, y: 14, tile: new Tile({ character: 'o' }), isEmpty: true }),
90
+ new Cell({ x: 8, y: 14, tile: new Tile({ character: 'r' }), isEmpty: true }),
91
+ new Cell({ x: 9, y: 14, tile: new Tile({ character: 'o' }), isEmpty: true }),
92
+ new Cell({ x: 10, y: 14, tile: new Tile({ character: 'w' }), isEmpty: true }),
93
+ new Cell({ x: 11, y: 14, tile: new Tile({ character: 'a', isBlank: true }), isEmpty: true }),
94
+ new Cell({ x: 11, y: 14, tile: new Tile({ character: 't' }), isEmpty: false }),
95
+ new Cell({ x: 13, y: 14, tile: new Tile({ character: 'e' }), isEmpty: true }),
96
+ ]);
97
+
98
+ expect(getPatternScore(config, pattern)).toBe(59);
99
+ });
60
100
  });
61
101
 
62
- it('gives 0 score for unknown characters', () => {
63
- const pattern = new HorizontalPattern(board, [
64
- new Cell({ x: 13, y: 14, tile: new Tile({ character: '?', isBlank: false }), isEmpty: true }),
65
- new Cell({ x: 12, y: 14, tile: new Tile({ character: 't' }), isEmpty: false }),
66
- ]);
102
+ describe('Letter League - EN_US', () => {
103
+ const config = getConfig(Game.LetterLeague, Locale.EN_US);
104
+
105
+ it('gives double multiplier bonus for bingo without collisions', () => {
106
+ const board = Board.create(config.boardWidth, config.boardHeight);
107
+ const pattern = new HorizontalPattern(board, [
108
+ new Cell({ x: 13, y: 6, tile: new Tile({ character: 'r' }), isEmpty: true }),
109
+ new Cell({ x: 13, y: 7, tile: new Tile({ character: 'o' }), isEmpty: true }),
110
+ new Cell({ x: 13, y: 8, tile: new Tile({ character: 'm' }), isEmpty: true }),
111
+ new Cell({ x: 13, y: 9, tile: new Tile({ character: 'a' }), isEmpty: true }),
112
+ new Cell({ x: 13, y: 10, tile: new Tile({ character: 'i' }), isEmpty: true }),
113
+ new Cell({ x: 13, y: 11, tile: new Tile({ character: 'n' }), isEmpty: true }),
114
+ new Cell({ x: 13, y: 12, tile: new Tile({ character: 'e' }), isEmpty: true }),
115
+ ]);
116
+
117
+ expect(getPatternScore(config, pattern)).toBe(18);
118
+ });
119
+
120
+ it('gives double multiplier bonus for bingo with collisions', () => {
121
+ const board = Board.fromStringArray([
122
+ ' ',
123
+ ' ',
124
+ ' ',
125
+ ' ',
126
+ ' ',
127
+ ' ',
128
+ ' ',
129
+ ' ',
130
+ ' ',
131
+ ' ',
132
+ ' ',
133
+ ' ',
134
+ ' on ',
135
+ ' ',
136
+ ' ',
137
+ ' ',
138
+ ' ',
139
+ ' ',
140
+ ' ',
141
+ ]);
142
+
143
+ const pattern = new VerticalPattern(board, [
144
+ new Cell({ x: 13, y: 6, tile: new Tile({ character: 'r' }), isEmpty: true }),
145
+ new Cell({ x: 13, y: 7, tile: new Tile({ character: 'o' }), isEmpty: true }),
146
+ new Cell({ x: 13, y: 8, tile: new Tile({ character: 'm' }), isEmpty: true }),
147
+ new Cell({ x: 13, y: 9, tile: new Tile({ character: 'a' }), isEmpty: true }),
148
+ new Cell({ x: 13, y: 10, tile: new Tile({ character: 'i' }), isEmpty: true }),
149
+ new Cell({ x: 13, y: 11, tile: new Tile({ character: 'n' }), isEmpty: true }),
150
+ new Cell({ x: 13, y: 12, tile: new Tile({ character: 'e' }), isEmpty: true }),
151
+ ]);
67
152
 
68
- expect(getPatternScore(config, pattern)).toBe(2);
153
+ expect(getPatternScore(config, pattern)).toBe(21);
154
+ });
69
155
  });
70
156
  });
@@ -1,13 +1,23 @@
1
- import { Config, Pattern } from '@scrabble-solver/types';
1
+ import { type Config, isMultiplierBingo, isScoreBingo, type Pattern } from '@scrabble-solver/types';
2
2
 
3
3
  import { getCellsScore } from './getCellsScore';
4
4
 
5
5
  export const getPatternScore = (config: Config, pattern: Pattern) => {
6
6
  const areAllTilesUsed = pattern.getEmptyCellsCount() === config.rackSize;
7
- const bonusScore = areAllTilesUsed ? config.bingoScore : 0;
8
- const score = pattern
7
+ const baseScore = getCellsScore(config, pattern.cells);
8
+ const collisionsScore = pattern
9
9
  .getCollisions()
10
- .reduce((sum, collision) => sum + getCellsScore(config, collision.cells), getCellsScore(config, pattern.cells));
10
+ .reduce((sum, collision) => sum + getCellsScore(config, collision.cells), 0);
11
11
 
12
- return score + bonusScore;
12
+ if (areAllTilesUsed) {
13
+ if (isScoreBingo(config.bingo)) {
14
+ return baseScore + collisionsScore + config.bingo.score;
15
+ }
16
+
17
+ if (isMultiplierBingo(config.bingo)) {
18
+ return baseScore * config.bingo.multiplier + collisionsScore;
19
+ }
20
+ }
21
+
22
+ return baseScore + collisionsScore;
13
23
  };
@@ -1,4 +1,4 @@
1
- import { Pattern } from '@scrabble-solver/types';
1
+ import { type Pattern } from '@scrabble-solver/types';
2
2
 
3
3
  import { getPatternHash } from './getPatternHash';
4
4
 
package/src/solve.test.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable max-lines */
2
2
 
3
- import { Trie } from '@kamilmielnik/trie';
3
+ import { type Trie } from '@kamilmielnik/trie';
4
4
  import { getConfig } from '@scrabble-solver/configs';
5
5
  import { dictionaries } from '@scrabble-solver/dictionaries';
6
6
  import { Board, Game, Locale, Result, Tile } from '@scrabble-solver/types';
package/src/solve.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Trie } from '@kamilmielnik/trie';
2
- import { Board, Config, ResultJson, Tile } from '@scrabble-solver/types';
1
+ import { type Trie } from '@kamilmielnik/trie';
2
+ import { type Board, type Config, type ResultJson, type Tile } from '@scrabble-solver/types';
3
3
 
4
4
  import { areDigraphsValid } from './areDigraphsValid';
5
5
  import { fillPattern } from './fillPattern';