import { CONSONANTS, VOWELS } from '@scrabble-solver/constants'; import { Cell } from './Cell'; import { type ResultJson } from './ResultJson'; import { type Tile } from './Tile'; type Collision = Cell[]; export class Result { public static fromJson = (json: ResultJson): Result => { return new Result({ id: json.id, cells: json.cells.map(Cell.fromJson), collisions: json.collisions.map((collision) => collision.map(Cell.fromJson)), points: json.points, }); }; public readonly blanksCount: number; public readonly cells: Cell[]; public readonly collisions: Collision[]; public readonly consonantsCount: number; public readonly id: number; public readonly length: number; public readonly points: number; public readonly pointsRatio: number; public readonly tiles: Tile[]; public readonly tilesCount: number; public readonly vowelsCount: number; public readonly word: string; public readonly words: string[]; public readonly wordsCount: number; constructor({ cells, id, collisions, points, }: { cells: Cell[]; id: number; collisions: Collision[]; points: number; }) { const tiles = getTiles(cells); this.blanksCount = getBlanks(tiles).length; this.cells = cells; this.collisions = collisions; this.consonantsCount = getConsonants(tiles).length; this.id = id; this.length = cells.length; this.points = points; this.pointsRatio = getPointsRatio(tiles, points); this.tiles = tiles; this.tilesCount = tiles.length; this.vowelsCount = getVowels(tiles).length; this.word = getWord(cells); this.words = getWords(cells, collisions); this.wordsCount = 1 + this.collisions.length; } public toJson(): ResultJson { return { cells: this.cells.map((cell) => cell.toJson()), id: this.id, collisions: this.collisions.map((collision) => collision.map((cell) => cell.toJson())), points: this.points, }; } public isHorizontal(): boolean { return this.cells[0].y === this.cells[1].y; } public isVertical(): boolean { return this.cells[0].x === this.cells[1].x; } } const getBlanks = (tiles: Tile[]): Tile[] => tiles.filter(({ isBlank }) => isBlank); const getConsonants = (tiles: Tile[]): Tile[] => tiles.filter(isConsonant); const getVowels = (tiles: Tile[]): Tile[] => tiles.filter(isVowel); const getPointsRatio = (tiles: Tile[], points: number): number => points / tiles.length; const getTiles = (cells: Cell[]): Tile[] => cells.filter(({ isEmpty }) => isEmpty).map(({ tile }) => tile); const getWord = (cells: Cell[]): string => cells.reduce((word, cell) => word + cell.toString(), ''); const getWords = (cells: Cell[], collisions: Collision[]): string[] => [cells, ...collisions].map(getWord); const isConsonant = ({ character, isBlank }: Tile): boolean => CONSONANTS.includes(character) && !isBlank; const isVowel = ({ character, isBlank }: Tile): boolean => VOWELS.includes(character) && !isBlank;