scrabble-solver
Version:
Scrabble Solver 2 - Free, open-source, cross-platform, multi-language analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter League, Crossplay, Literaki, and Kelimelik. Quickly find the top-scoring words using the given board and tiles.
91 lines (78 loc) • 3.09 kB
text/typescript
import { getConfig } from '@scrabble-solver/configs';
import { Game, Locale } from '@scrabble-solver/types';
import {
PLAIN_TILES_COLOR_DEFAULT,
PLAIN_TILES_PADDING_HORIZONTAL,
PLAIN_TILES_PADDING_VERTICAL,
PLAIN_TILES_POINTS_COLORS,
PLAIN_TILES_TILE_MARGIN,
PLAIN_TILES_TILE_MAX_ROTATE,
PLAIN_TILES_TILE_MAX_SCATTER,
PLAIN_TILES_TILE_SIZE,
} from '@/parameters';
import type { CreatePlainTileOptions, CreatePlainTilesOptions, PlainTile } from './types';
export const createPlainTiles = ({ color, content, showPoints }: CreatePlainTilesOptions): PlainTile[] => {
const rows = content.map((words, rowIndex) => {
return words.map((word, wordIndex) => {
const cellOffset = words.slice(0, wordIndex).reduce((result, { length }) => result + length + ' '.length, 0);
const characters = word.split('');
return characters.map((character, cellIndex) => {
return createPlainTile({
cellIndex: cellOffset + cellIndex,
character,
color,
rowIndex,
showPoints,
});
});
});
});
const tiles = rows.flat(2);
return tiles;
};
export const createPlainTile = ({
cellIndex,
character,
color,
rowIndex,
showPoints,
}: CreatePlainTileOptions): PlainTile => {
const configPoints = getConfig(Game.Literaki, Locale.EN_US).getCharacterPoints(character.toLowerCase());
const points = showPoints ? configPoints : undefined;
const defaultColor =
typeof configPoints === 'number' ? PLAIN_TILES_POINTS_COLORS[configPoints] : PLAIN_TILES_COLOR_DEFAULT;
const x = getX(cellIndex) + PLAIN_TILES_TILE_SIZE / 2;
const y = getY(0) + PLAIN_TILES_TILE_SIZE / 2;
return {
character,
color: color || defaultColor,
points,
size: PLAIN_TILES_TILE_SIZE,
transform: `rotate(${randomize(0, PLAIN_TILES_TILE_MAX_ROTATE)}, ${x}, ${y})`,
x: randomize(getX(cellIndex), PLAIN_TILES_TILE_MAX_SCATTER),
y: randomize(getY(rowIndex), PLAIN_TILES_TILE_MAX_SCATTER),
};
};
export const getViewbox = (content: string[][]): string => {
const longestRowLength = content.reduce((result, words) => {
const wordsLength = words.reduce((sum, word) => sum + word.length, 0);
const rowLength = wordsLength + Math.max(words.length - 1, 0);
return Math.max(result, rowLength);
}, 0);
const width =
longestRowLength * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN) -
(longestRowLength === 0 ? 0 : PLAIN_TILES_TILE_MARGIN);
const height =
content.length * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN) -
(content.length === 0 ? 0 : PLAIN_TILES_TILE_MARGIN);
return `0 0 ${width} ${height}`;
};
export const getX = (index: number): number => {
return PLAIN_TILES_PADDING_HORIZONTAL + index * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN);
};
export const getY = (index: number): number => {
return PLAIN_TILES_PADDING_VERTICAL + index * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN);
};
export const randomize = (value: number, maxChange: number): number => {
return value + maxChange * 2 * (0.5 - Math.random());
};