Public
Edited
Apr 20, 2024
Paused
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
guess
Insert cell
handleSubmitState = () => {
const output = handleSubmit(guess, data)
log(guess)
mutable data = output
return output
}
Insert cell
handleSubmit = (word, data) => {
let copy = JSON.parse(JSON.stringify(data))
// get highest y among selected
// const rowsToDrop = Math.max(...data.filter(x=>x.clicked).map(x=> x.y)) + 1

// this was for downwords, remove for bjb
// for (let i = 0; i < rowsToDrop; ++i) {
// copy = addRow(copy)
// }
copy = copy.map((x,i) => ({
...x,
id: i+1,
clicked: false,
clickable: x.letter === "_" ? false : true,
selected_order: 0, // maybe jsonstringify doesn't want nulls? but needed a 0 here
}))

return copy
}
Insert cell
guessIsValid = guess != '' && wordnik.includes(guess.toLowerCase())
Insert cell
displayInGame = (data) => {
const max_selected = Math.max(...data.map(x=>x.selected_order))
const initDiv = x => {
let hitbox = html`<div class="hitbox"></div>`
e => handleClickState(x.id)
hitbox.onpointerdown = e => handleClickState(x.id)
hitbox.onpointerenter = (e) => {
if(e.buttons !== 0 && guess !== '') {
handleClickState(x.id)
}
}
let color = x.clicked === true ? '#479d2f' : 'black'
let backgroundColor = x.letter === '_' ? 'black' : 'white'
if(x.selected_order === max_selected && max_selected > 0) backgroundColor = '#bbdcac'
let underline = checkbox.includes("Play Around The Table") && ['M', 'W', 'N', 'Z'].includes(x.letter) ? 'underline' : 'none'
let deg = !checkbox.includes("Play Around The Table") ? 0 : _.sample([0, 90, 180, 270])
let div = html`<div
id=${x.id}
class="tile"
style="background-color:${backgroundColor}"
>
<div class="tileText" style="color:${color}; transform: rotate(${deg}deg); text-decoration:${underline}; ">${x.letter}</div>
${hitbox}
</div>`
div.onpointerdown = e => handleClickState(x.id)
return div
}

const container = html`<div class="prevent-select"></div>`
// container.appendChild(scoreboard())
const board = html`<div class="board"></div>`
const divs = data.map(x => initDiv(x))

for (const el of divs) board.appendChild(el)

container.appendChild(board)
return container
}
Insert cell
handleClickState = id => {
const output = handleClick(id, data)
mutable data = output
return output
}
Insert cell
handleClick = (id, data) => {
// make a deep copy of data
let copy = JSON.parse(JSON.stringify(data))
// get record for clicked tile
let tile = copy.filter(x => x.id === id)[0]
// check if clickable, if not do nothing
if(tile.clickable === false) return copy
// get max click_order
let max_click_order = Math.max(...data.map(x=> x.selected_order)) || 0
// get currently active tile
let lastTile = copy.filter(x => max_click_order > 0 && x.selected_order === max_click_order)[0]

// // check if record is neighbor
let recordIsNeighbor = lastTile === undefined || (Math.abs(lastTile.x - tile.x) <= 1 && Math.abs(lastTile.y - tile.y) <= 1)
// if the record is not a neighbor do nothing, but we need to pass if there was no lastTile to check against
if(max_click_order > 0 && recordIsNeighbor === false) return copy

// If the tile is a clickable neighbor, set row to clicked and click_order to max+1
tile.clickable = false
tile.clicked = true
tile.selected_order = max_click_order + 1
return copy
}
Insert cell
handleReset = () => {
let copy = JSON.parse(JSON.stringify(data))
mutable data = copy
.map((x,i) => ({
...x,
id: i+1,
clicked: false,
clickable: x.letter === "_" ? false : true,
selected_order: 0, // maybe jsonstringify doesn't want nulls? but needed a 0 here
}))
}
Insert cell
mutable data = {
resetGame;
let board = newBoard(n_cols,n_rows)

// if No ING option is selected, this rerolls until the board has no INGs
if(checkbox.includes("No INGs")) board = newBoardNoIng(n_cols, n_rows)
if(checkbox.includes("CVC Checkerboard")) {
for (const tile of board) {
while(isVowel(tile.letter) && (tile.x + tile.y) % 2 === 0) tile.letter = randomElement()
while(!isVowel(tile.letter) && (tile.x + tile.y) % 2 === 1) tile.letter = randomElement()
}
}
return board.map((x,i) => ({
...x,
id: i+1,
clicked: false,
clickable: x.letter === "_" ? false : true,
selected_order: 0, // maybe jsonstringify doesn't want nulls? but needed a 0 here
}))
}
Insert cell
isVowel = x => ['A','E','I','O', 'U'].includes(x.toUpperCase())
Insert cell
guess = data
.filter(x=>x.selected_order > 0)
.sort((x,y) => x.selected_order - y.selected_order)
.map(x => x.letter)
.join('')
Insert cell
log = (data) => {
mutable history = [data, ...history]
}
Insert cell
mutable history = []
Insert cell
bagOfLetters = frequencies
.filter(x => x.name === selectFreqs)
.flatMap(x => Array(x.freq).fill(x.letter))
.map(x => x === "Q" ? "Qu" : x)
Insert cell
randomElement = () => _.sample(bagOfLetters)
Insert cell
newBoard = (n_row,m_col) => {
let out = []
for (let i = 0; i < m_col; ++i) {
for (let j = 0; j < n_row; ++j) {
let row = {
letter:randomElement(),
y:i,
x:j,
}
out.push(row)
}
}
return out.flat()
}
Insert cell
newBoardNoIng = (n,m) => {
let board = newBoard(n,m)
while(hasING(board)) {
board = newBoard(n,m)
}
return board
}
Insert cell
neighbors = (tile, board) => {
let x = tile.x
let y = tile.y
return board
// neighors are within +/-1 X and +/-1 Y of a tile
.filter(letter => Math.abs(y - letter.y) <= 1 && Math.abs(x - letter.x) <= 1)
// a tile isn't its own neighbor
.filter(letter => letter != tile)
}
Insert cell
hasING = board => board
.filter(x => x.letter == "N")
.map(x => neighbors(x, board).map(y => y.letter))
.some(x => x.includes("I") && x.includes("G"))
Insert cell
tileWidth = Math.min(width/n_cols - 8, 75)
Insert cell
<style>
button {
padding: 10px 15px;
font-size: 20px;
}
.board {
display: grid;
grid-template-columns: repeat(${n_cols}, 1fr);
gap: 0px;
width: ${4 * tileWidth}px;
touch-action: none;
}
.tile {
display: flex;
justify-content: center;
align-items: center;
height: ${tileWidth}px;
width: ${tileWidth}px;
font-family: sans-serif;
font-size: ${tileWidth * .83}px;
border-style: solid;
position: relative;
}
.tileText {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
user-select: none;
}
.hitbox {
position: absolute;
height: 70%;
width: 70%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

/*this was copypasted*/
.prevent-select {
-webkit-user-select: none; /* Safari */
-ms-user-select: none; /* IE 10 and IE 11 */
user-select: none; /* Standard syntax */
}

.gameButtons {
display: flex;
}
</style>
Insert cell
wordnik = {
const url = 'https://raw.githubusercontent.com/wordnik/wordlist/main/wordlist-20210729.txt';
const response = await fetch(url)
const text = await response.text()
const rows = text.split('\n')
return rows.map(row => row.replace(/"/g, ''))
}
Insert cell
import {frequencies, names} from '@a-lexwein/mrboggles-letter-frequencies-for-prolific'
Insert cell
import {seedrandom} from "@fil/seedrandom-minimal"
Insert cell
{
const f = new seedrandom('abc')
return [f(), f()]
}
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more