diff --git a/TODO.md b/TODO.md index af759e6..8dce45e 100644 --- a/TODO.md +++ b/TODO.md @@ -34,9 +34,7 @@ For screenshots: - add some custom daily puzzles - add link to sponsors? -- relocate to new file: - - getWordValidityGrids - - countingGrid - just rename dispatch params to dispatcher everywhere -- put arrayToGrid to common or to word-logic package - piecesOverlapQ should use getGridFromPieces + +- move common functions to word-logic package diff --git a/src/logic/arrayToGrid.js b/src/common/arrayToGrid.js similarity index 100% rename from src/logic/arrayToGrid.js rename to src/common/arrayToGrid.js diff --git a/src/logic/arrayToGrid.test.js b/src/common/arrayToGrid.test.js similarity index 100% rename from src/logic/arrayToGrid.test.js rename to src/common/arrayToGrid.test.js diff --git a/src/components/Board.js b/src/components/Board.js index f76a2be..9e40681 100644 --- a/src/components/Board.js +++ b/src/components/Board.js @@ -1,119 +1,8 @@ import React from "react"; import Piece from "./Piece"; import DragShadow from "./DragShadow"; -import {getGridFromPieces} from "../logic/getGridFromPieces"; -import {isKnown} from "@skedwards88/word_logic"; -import {trie} from "../logic/trie"; -import {getWordsFromPieces} from "../logic/getWordsFromPieces"; -import {transposeGrid} from "@skedwards88/word_logic"; - -// Returns a grid with the number of letters at each location in the grid -export function countingGrid(height, width, pieces) { - let grid = Array(height) - .fill(undefined) - .map(() => Array(width).fill(0)); - - for (let piece of pieces) { - const letters = piece.letters; - let top = piece.boardTop ?? piece.dragGroupTop; - for (let rowIndex = 0; rowIndex < letters.length; rowIndex++) { - let left = piece.boardLeft ?? piece.dragGroupLeft; - for (let colIndex = 0; colIndex < letters[rowIndex].length; colIndex++) { - if (letters[rowIndex][colIndex]) { - grid[top][left]++; - } - left++; - } - top++; - } - } - return grid; -} - -function getHorizontalValidityGrid({grid, originalWords}) { - // return a 2D array of bools indicating whether - // the position corresponds to a letter on the board - // that is part of a valid horizontal word - const height = grid.length; - const width = grid[0].length; - - const horizontalValidityGrid = Array(height) - .fill(undefined) - .map(() => Array(width).fill(false)); - - for (const [rowIndex, row] of grid.entries()) { - let word = ""; - let indexes = []; - for (const [columnIndex, letter] of row.entries()) { - if (letter != "") { - word += letter; - indexes.push(columnIndex); - } else { - if (word.length > 1) { - // If the word is one of the original words, always consider it valid (in case we updated the dictionary in the interim). - // Otherwise, check whether it is a word in the trie. - let isWord = originalWords.includes(word); - if (!isWord) { - ({isWord} = isKnown(word, trie)); - } - if (isWord) { - indexes.forEach( - (index) => (horizontalValidityGrid[rowIndex][index] = true), - ); - } - } - word = ""; - indexes = []; - } - } - // Also end the word if we reach the end of the row - if (word.length > 1) { - // If the word is one of the original words, always consider it valid (in case we updated the dictionary in the interim). - // Otherwise, check whether it is a word in the trie. - let isWord = originalWords.includes(word); - if (!isWord) { - ({isWord} = isKnown(word, trie)); - } - if (isWord) { - indexes.forEach( - (index) => (horizontalValidityGrid[rowIndex][index] = true), - ); - } - } - } - - return horizontalValidityGrid; -} - -export function getWordValidityGrids({ - pieces, - gridSize, - includeOriginalSolution = true, -}) { - const originalWords = includeOriginalSolution - ? getWordsFromPieces({ - pieces, - gridSize, - solution: true, - }) - : []; - - const grid = getGridFromPieces({pieces, gridSize, solution: false}); - - const horizontalValidityGrid = getHorizontalValidityGrid({ - grid, - originalWords, - }); - - const transposedGrid = transposeGrid(grid); - const horizontalTransposedValidityGrid = getHorizontalValidityGrid({ - grid: transposedGrid, - originalWords, - }); - const verticalValidityGrid = transposeGrid(horizontalTransposedValidityGrid); - - return [horizontalValidityGrid, verticalValidityGrid]; -} +import {getLetterCountPerSquare} from "../logic/getLetterCountPerSquare"; +import {getWordValidityGrids} from "../logic/getWordValidityGrids"; export default function Board({ pieces, @@ -131,7 +20,7 @@ export default function Board({ const overlapGrid = customCreation ? undefined - : countingGrid(gridSize, gridSize, boardPieces); + : getLetterCountPerSquare(gridSize, gridSize, boardPieces); const [horizontalValidityGrid, verticalValidityGrid] = indicateValidity ? getWordValidityGrids({ @@ -160,7 +49,7 @@ export default function Board({ const draggedPieces = pieces.filter((piece) => dragPieceIDs.includes(piece.id), ); - const grid = countingGrid(gridSize, gridSize, draggedPieces); + const grid = getLetterCountPerSquare(gridSize, gridSize, draggedPieces); dragShadow = ( piece.poolIndex >= 0); @@ -29,9 +29,11 @@ export default function Pool({pieces, dragDestination, dispatchGameState}) {
)), diff --git a/src/logic/convertRepresentativeStringToGrid.js b/src/logic/convertRepresentativeStringToGrid.js index 1993c63..7ab9b68 100644 --- a/src/logic/convertRepresentativeStringToGrid.js +++ b/src/logic/convertRepresentativeStringToGrid.js @@ -1,4 +1,4 @@ -import {arrayToGrid} from "./arrayToGrid"; +import {arrayToGrid} from "../common/arrayToGrid"; import {cipherLetter} from "./cipherLetter"; // Converts a string of letters and integers into a square grid of single letters and empty strings. diff --git a/src/logic/getLetterCountPerSquare.js b/src/logic/getLetterCountPerSquare.js new file mode 100644 index 0000000..64acfe3 --- /dev/null +++ b/src/logic/getLetterCountPerSquare.js @@ -0,0 +1,22 @@ +// Returns a grid with the number of letters at each location in the grid +export function getLetterCountPerSquare(height, width, pieces) { + let grid = Array(height) + .fill(undefined) + .map(() => Array(width).fill(0)); + + for (let piece of pieces) { + const letters = piece.letters; + let top = piece.boardTop ?? piece.dragGroupTop; + for (let rowIndex = 0; rowIndex < letters.length; rowIndex++) { + let left = piece.boardLeft ?? piece.dragGroupLeft; + for (let colIndex = 0; colIndex < letters[rowIndex].length; colIndex++) { + if (letters[rowIndex][colIndex]) { + grid[top][left]++; + } + left++; + } + top++; + } + } + return grid; +} diff --git a/src/logic/getWordValidityGrids.js b/src/logic/getWordValidityGrids.js new file mode 100644 index 0000000..71fe1f9 --- /dev/null +++ b/src/logic/getWordValidityGrids.js @@ -0,0 +1,90 @@ +import {getGridFromPieces} from "../logic/getGridFromPieces"; +import {getWordsFromPieces} from "../logic/getWordsFromPieces"; +import {transposeGrid} from "@skedwards88/word_logic"; +import {isKnown} from "@skedwards88/word_logic"; +import {trie} from "../logic/trie"; + +function getHorizontalValidityGrid({grid, originalWords}) { + // return a 2D array of bools indicating whether + // the position corresponds to a letter on the board + // that is part of a valid horizontal word + const height = grid.length; + const width = grid[0].length; + + const horizontalValidityGrid = Array(height) + .fill(undefined) + .map(() => Array(width).fill(false)); + + for (const [rowIndex, row] of grid.entries()) { + let word = ""; + let indexes = []; + for (const [columnIndex, letter] of row.entries()) { + if (letter != "") { + word += letter; + indexes.push(columnIndex); + } else { + if (word.length > 1) { + // If the word is one of the original words, always consider it valid (in case we updated the dictionary in the interim). + // Otherwise, check whether it is a word in the trie. + let isWord = originalWords.includes(word); + if (!isWord) { + ({isWord} = isKnown(word, trie)); + } + if (isWord) { + indexes.forEach( + (index) => (horizontalValidityGrid[rowIndex][index] = true), + ); + } + } + word = ""; + indexes = []; + } + } + // Also end the word if we reach the end of the row + if (word.length > 1) { + // If the word is one of the original words, always consider it valid (in case we updated the dictionary in the interim). + // Otherwise, check whether it is a word in the trie. + let isWord = originalWords.includes(word); + if (!isWord) { + ({isWord} = isKnown(word, trie)); + } + if (isWord) { + indexes.forEach( + (index) => (horizontalValidityGrid[rowIndex][index] = true), + ); + } + } + } + + return horizontalValidityGrid; +} + +export function getWordValidityGrids({ + pieces, + gridSize, + includeOriginalSolution = true, +}) { + const originalWords = includeOriginalSolution + ? getWordsFromPieces({ + pieces, + gridSize, + solution: true, + }) + : []; + + const grid = getGridFromPieces({pieces, gridSize, solution: false}); + + const horizontalValidityGrid = getHorizontalValidityGrid({ + grid, + originalWords, + }); + + const transposedGrid = transposeGrid(grid); + const horizontalTransposedValidityGrid = getHorizontalValidityGrid({ + grid: transposedGrid, + originalWords, + }); + const verticalValidityGrid = transposeGrid(horizontalTransposedValidityGrid); + + return [horizontalValidityGrid, verticalValidityGrid]; +}