@scrabble-solver/scrabble-solver 2.15.10 → 2.15.11

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 (56) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +4 -4
  3. package/.next/cache/.rscinfo +1 -1
  4. package/.next/cache/.tsbuildinfo +1 -1
  5. package/.next/cache/webpack/client-production/0.pack +0 -0
  6. package/.next/cache/webpack/client-production/index.pack +0 -0
  7. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  8. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  9. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  10. package/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  11. package/.next/cache/webpack/server-production/0.pack +0 -0
  12. package/.next/cache/webpack/server-production/index.pack +0 -0
  13. package/.next/cache/webpack/server-production/index.pack.old +0 -0
  14. package/.next/next-minimal-server.js.nft.json +1 -1
  15. package/.next/next-server.js.nft.json +1 -1
  16. package/.next/prerender-manifest.json +4 -4
  17. package/.next/routes-manifest.json +1 -1
  18. package/.next/server/chunks/60.js +1 -1
  19. package/.next/server/chunks/812.js +1 -1
  20. package/.next/server/chunks/974.js +1 -1
  21. package/.next/server/middleware-build-manifest.js +1 -1
  22. package/.next/server/pages/404.html +1 -1
  23. package/.next/server/pages/404.js.nft.json +1 -1
  24. package/.next/server/pages/500.html +1 -1
  25. package/.next/server/pages/_app.js.nft.json +1 -1
  26. package/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  27. package/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  28. package/.next/server/pages/api/solve.js +1 -1
  29. package/.next/server/pages/api/solve.js.nft.json +1 -1
  30. package/.next/server/pages/api/verify.js.nft.json +1 -1
  31. package/.next/server/pages/index.html +1 -1
  32. package/.next/server/pages/index.js +1 -1
  33. package/.next/server/pages/index.js.nft.json +1 -1
  34. package/.next/server/pages/index.json +1 -1
  35. package/.next/server/pages-manifest.json +1 -1
  36. package/.next/static/{ylO_ttKeJTuoqDYywao5A → 47JHul8F9NSWCNSEuahuL}/_buildManifest.js +1 -1
  37. package/.next/static/chunks/pages/_app-0e951de0aebb6505.js +1 -0
  38. package/.next/static/chunks/pages/index-c1d5a66d0f4794a6.js +1 -0
  39. package/.next/trace +23 -23
  40. package/package.json +11 -10
  41. package/src/components/Board/BoardPure.tsx +1 -1
  42. package/src/components/NavButtons/NavButtons.tsx +13 -10
  43. package/src/components/SeoMessage/SeoMessage.tsx +4 -3
  44. package/src/lib/getCoordinate.test.ts +22 -0
  45. package/src/lib/getCoordinate.ts +9 -1
  46. package/src/lib/getRemainingTilesCount.ts +7 -1
  47. package/src/lib/getTotalRemainingTilesCount.ts +7 -1
  48. package/src/modals/RemainingTilesModal/components/Character/Character.tsx +5 -0
  49. package/src/pages/_app.tsx +2 -1
  50. package/src/pages/index.tsx +5 -2
  51. package/src/state/selectors.ts +1 -1
  52. package/src/types/index.ts +1 -1
  53. package/tsconfig.tsbuildinfo +1 -0
  54. package/.next/static/chunks/pages/_app-ac93a74c390f2ab8.js +0 -1
  55. package/.next/static/chunks/pages/index-e5f1caa581e6d3b8.js +0 -1
  56. /package/.next/static/{ylO_ttKeJTuoqDYywao5A → 47JHul8F9NSWCNSEuahuL}/_ssgManifest.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/scrabble-solver",
3
- "version": "2.15.10",
3
+ "version": "2.15.11",
4
4
  "description": "Scrabble Solver 2 - App",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,19 +21,20 @@
21
21
  "clean": "rimraf .next/",
22
22
  "debug": "NODE_OPTIONS='--inspect' next dev",
23
23
  "dev": "env-cmd next dev",
24
- "start": "env-cmd next start -p 3333"
24
+ "start": "env-cmd next start -p 3333",
25
+ "type-check": "tsc --noEmit"
25
26
  },
26
27
  "dependencies": {
27
28
  "@floating-ui/react": "^0.27.5",
28
29
  "@kamilmielnik/trie": "^4.0.0",
29
30
  "@reduxjs/toolkit": "^2.6.1",
30
- "@scrabble-solver/configs": "^2.15.10",
31
- "@scrabble-solver/constants": "^2.15.10",
32
- "@scrabble-solver/dictionaries": "^2.15.10",
33
- "@scrabble-solver/logger": "^2.15.10",
34
- "@scrabble-solver/solver": "^2.15.10",
35
- "@scrabble-solver/types": "^2.15.10",
36
- "@scrabble-solver/word-definitions": "^2.15.10",
31
+ "@scrabble-solver/configs": "^2.15.11",
32
+ "@scrabble-solver/constants": "^2.15.11",
33
+ "@scrabble-solver/dictionaries": "^2.15.11",
34
+ "@scrabble-solver/logger": "^2.15.11",
35
+ "@scrabble-solver/solver": "^2.15.11",
36
+ "@scrabble-solver/types": "^2.15.11",
37
+ "@scrabble-solver/word-definitions": "^2.15.11",
37
38
  "classnames": "^2.5.1",
38
39
  "env-cmd": "^10.1.0",
39
40
  "include-media": "^2.0.0",
@@ -71,5 +72,5 @@
71
72
  "@types/redux-saga": "^0.10.5",
72
73
  "sass": "^1.86.0"
73
74
  },
74
- "gitHead": "dab5a817c1bde1a3ebf8e8907215adf12af5cb27"
75
+ "gitHead": "4fa527098d5e67120adb7964777c044a09378332"
75
76
  }
@@ -134,7 +134,7 @@ const BoardPureBase = forwardRef<HTMLDivElement, Props>(
134
134
  cell={cell}
135
135
  cellBottom={y < rows.length - 1 ? rows[y + 1][x] : undefined}
136
136
  cellLeft={x > 0 ? rows[y][x - 1] : undefined}
137
- cellRight={x < rows.length - 1 ? rows[y][x + 1] : undefined}
137
+ cellRight={x < rows[y].length - 1 ? rows[y][x + 1] : undefined}
138
138
  cellTop={y > 0 ? rows[y - 1][x] : undefined}
139
139
  inputRef={inputRefs[y][x]}
140
140
  key={x}
@@ -4,7 +4,7 @@ import { FunctionComponent, memo } from 'react';
4
4
  import { useAppLayout } from 'hooks';
5
5
  import { CardChecklist, Cog, Eraser, Github, KeyboardFill, List, Sack } from 'icons';
6
6
  import { GITHUB_PROJECT_URL } from 'parameters';
7
- import { selectHasInvalidWords, selectHasOverusedTiles, useTranslate, useTypedSelector } from 'state';
7
+ import { selectConfig, selectHasInvalidWords, selectHasOverusedTiles, useTranslate, useTypedSelector } from 'state';
8
8
 
9
9
  import { IconButton } from '../IconButton';
10
10
 
@@ -28,6 +28,7 @@ const NavButtonsBase: FunctionComponent<Props> = ({
28
28
  onShowWords,
29
29
  }) => {
30
30
  const translate = useTranslate();
31
+ const config = useTypedSelector(selectConfig);
31
32
  const hasOverusedTiles = useTypedSelector(selectHasOverusedTiles);
32
33
  const hasInvalidWords = useTypedSelector(selectHasInvalidWords);
33
34
  const { showKeyMap, showShortNav } = useAppLayout();
@@ -75,15 +76,17 @@ const NavButtonsBase: FunctionComponent<Props> = ({
75
76
  <div className={styles.separator} />
76
77
 
77
78
  <div className={styles.group}>
78
- <IconButton
79
- aria-label={translate('remaining-tiles')}
80
- className={classNames(styles.button, {
81
- [styles.error]: hasOverusedTiles,
82
- })}
83
- Icon={Sack}
84
- tooltip={translate('remaining-tiles')}
85
- onClick={onShowRemainingTiles}
86
- />
79
+ {config.supportsRemainingTiles && (
80
+ <IconButton
81
+ aria-label={translate('remaining-tiles')}
82
+ className={classNames(styles.button, {
83
+ [styles.error]: hasOverusedTiles,
84
+ })}
85
+ Icon={Sack}
86
+ tooltip={translate('remaining-tiles')}
87
+ onClick={onShowRemainingTiles}
88
+ />
89
+ )}
87
90
 
88
91
  <IconButton
89
92
  aria-label={translate('words')}
@@ -10,8 +10,9 @@ const INVISIBLE_STYLE: CSSProperties = {
10
10
 
11
11
  export const SeoMessage: FunctionComponent = () => (
12
12
  <p style={INVISIBLE_STYLE}>
13
- Scrabble Solver 2 is a free and open-source analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Literaki, and
14
- Kelimelik. Quickly find top scoring words using given letters and board state. Available in English, French, German,
15
- Persian, Polish, Romanian, Spanish, and Turkish. Source code is available on GitHub - contributions are welcome!
13
+ Scrabble Solver 2 is a free and open-source analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter
14
+ League, Literaki, and Kelimelik. Quickly find top scoring words using given letters and board state. Available in
15
+ English, French, German, Persian, Polish, Romanian, Spanish, and Turkish. Source code is available on GitHub -
16
+ contributions are welcome!
16
17
  </p>
17
18
  );
@@ -0,0 +1,22 @@
1
+ import { getCoordinate } from './getCoordinate';
2
+
3
+ describe('getCoordinate', () => {
4
+ it.each([
5
+ { index: 0, type: 'number' as const, expected: '1' },
6
+ { index: 99, type: 'number' as const, expected: '100' },
7
+ ])(`getCoordinate($index, "number") === "$expected"`, ({ index, type, expected }) => {
8
+ expect(getCoordinate(index, type)).toEqual(expected);
9
+ });
10
+
11
+ it.each([
12
+ { index: 0, type: 'letter' as const, expected: 'A' },
13
+ { index: 25, type: 'letter' as const, expected: 'Z' },
14
+ { index: 26, type: 'letter' as const, expected: 'AA' },
15
+ { index: 27, type: 'letter' as const, expected: 'AB' },
16
+ { index: 51, type: 'letter' as const, expected: 'AZ' },
17
+ { index: 52, type: 'letter' as const, expected: 'BA' },
18
+ { index: 53, type: 'letter' as const, expected: 'BB' },
19
+ ])(`getCoordinate("$index", "letter") === "$expected"`, ({ index, type, expected }) => {
20
+ expect(getCoordinate(index, type)).toEqual(expected);
21
+ });
22
+ });
@@ -5,5 +5,13 @@ export const getCoordinate = (index: number, type: 'letter' | 'number'): string
5
5
  return String(index + 1);
6
6
  }
7
7
 
8
- return alphabet[index];
8
+ let result = '';
9
+ let nextIndex = index;
10
+
11
+ while (nextIndex >= 0) {
12
+ result = alphabet[nextIndex % alphabet.length] + result;
13
+ nextIndex = Math.floor(nextIndex / alphabet.length) - 1;
14
+ }
15
+
16
+ return result;
9
17
  };
@@ -1,5 +1,11 @@
1
1
  import { RemainingTile } from 'types';
2
2
 
3
3
  export const getRemainingTilesCount = (remainingTiles: RemainingTile[]): number => {
4
- return remainingTiles.reduce((sum, { count, usedCount }) => sum + count - usedCount, 0);
4
+ return remainingTiles.reduce((sum, { count, usedCount }) => {
5
+ if (typeof count === 'undefined') {
6
+ return sum;
7
+ }
8
+
9
+ return sum + count - usedCount;
10
+ }, 0);
5
11
  };
@@ -1,5 +1,11 @@
1
1
  import { RemainingTile } from 'types';
2
2
 
3
3
  export const getTotalRemainingTilesCount = (remainingTiles: RemainingTile[]): number => {
4
- return remainingTiles.reduce((sum, { count }) => sum + count, 0);
4
+ return remainingTiles.reduce((sum, { count }) => {
5
+ if (typeof count === 'undefined') {
6
+ return sum;
7
+ }
8
+
9
+ return sum + count;
10
+ }, 0);
5
11
  };
@@ -18,6 +18,11 @@ export const Character: FunctionComponent<Props> = ({ tile }) => {
18
18
  const locale = useTypedSelector(selectLocale);
19
19
  const { direction } = LOCALE_FEATURES[locale];
20
20
  const { character, count, usedCount } = tile;
21
+
22
+ if (typeof count === 'undefined') {
23
+ throw new Error('Remaining tiles not supported for this config');
24
+ }
25
+
21
26
  const remainingCount = count - usedCount;
22
27
  const points = useTypedSelector((state) => selectCharacterPoints(state, character));
23
28
  const current = direction === 'ltr' ? remainingCount : count;
@@ -11,7 +11,7 @@ import 'styles/global.scss';
11
11
 
12
12
  const DESCRIPTION =
13
13
  // eslint-disable-next-line max-len
14
- 'Scrabble Solver 2 - Free and open-source analysis tool for Scrabble, Scrabble Duel, Super Scrabble & Literaki. Quickly find top scoring words using given letters and board state. Available in English, French, German, Persian, Polish, Romanian, Spanish, and Turkish.';
14
+ 'Scrabble Solver 2 - Free and open-source analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter League & Literaki. Quickly find top scoring words using given letters and board state. Available in English, French, German, Persian, Polish, Romanian, Spanish, and Turkish.';
15
15
 
16
16
  const KEYWORDS = [
17
17
  'Scrabble Solver',
@@ -20,6 +20,7 @@ const KEYWORDS = [
20
20
  'Solver',
21
21
  'Super Scrabble',
22
22
  'Kelimelik',
23
+ 'Letter League',
23
24
  'Literaki',
24
25
  'Board',
25
26
  'Open-source',
@@ -18,7 +18,7 @@ import {
18
18
  WordsModal,
19
19
  } from 'modals';
20
20
  import { registerServiceWorker } from 'serviceWorkerManager';
21
- import { initialize, reset, selectLocale, useTypedSelector } from 'state';
21
+ import { initialize, reset, selectConfig, selectLocale, useTypedSelector } from 'state';
22
22
 
23
23
  import styles from './index.module.scss';
24
24
 
@@ -31,6 +31,7 @@ interface Props {
31
31
  // eslint-disable-next-line max-statements
32
32
  const Index: FunctionComponent<Props> = ({ version }) => {
33
33
  const dispatch = useDispatch();
34
+ const config = useTypedSelector(selectConfig);
34
35
  const locale = useTypedSelector(selectLocale);
35
36
  const [showDictionary, setShowDictionary] = useState(false);
36
37
  const [showKeyMap, setShowKeyMap] = useState(false);
@@ -113,7 +114,9 @@ const Index: FunctionComponent<Props> = ({ version }) => {
113
114
 
114
115
  <WordsModal isOpen={showWords} onClose={handleHideWords} />
115
116
 
116
- <RemainingTilesModal isOpen={showRemainingTiles} onClose={handleHideRemainingTiles} />
117
+ {config.supportsRemainingTiles && (
118
+ <RemainingTilesModal isOpen={showRemainingTiles} onClose={handleHideRemainingTiles} />
119
+ )}
117
120
 
118
121
  <ResultsModal isOpen={showResults} onClose={handleHideResults} />
119
122
 
@@ -218,7 +218,7 @@ export const selectRemainingTiles = createSelector(
218
218
  );
219
219
 
220
220
  export const selectHasOverusedTiles = createSelector([selectRemainingTiles], (remainingTiles) => {
221
- return remainingTiles.some(({ count, usedCount }) => usedCount > count);
221
+ return remainingTiles.some(({ count = 0, usedCount }) => usedCount > count);
222
222
  });
223
223
 
224
224
  export const selectRemainingTilesGroups = createSelector([selectRemainingTiles], getRemainingTilesGroups);
@@ -36,7 +36,7 @@ export enum SortDirection {
36
36
 
37
37
  export interface RemainingTile {
38
38
  character: string;
39
- count: number;
39
+ count?: number;
40
40
  score: number;
41
41
  usedCount: number;
42
42
  }