Public
Edited
Jan 28, 2024
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
displayInGame = (data) => {
const initDiv = x => {
let color = x.clicked === true ? '#479d2f' : 'black'
let backgroundColor = x.click_count > 0 ? '#bbdcac' : 'white'
let div = html`<div
id=${x.id}
class="tile"
style="background-color:${backgroundColor}"
>
${x.letter.toUpperCase()}
</div>
`
div.onpointerdown = e => handleClickState(x.id)
return div
}

const initGroupZone = i => {
let borderColor = activatedGroups.includes(i) ? '#bbdcac' : '#ccc'
let borderWidth = activatedGroups.includes(i) ? 5 : 1
let div = html`<div
id=${i}
class="groupZone"
style="border-color:${borderColor}; border-width:${borderWidth}px"
></div>`
return div
}

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

for (let i = 0; i < 4; ++i) {
let groupZone = initGroupZone(i)
groupZone.appendChild(divs[2 * i])
groupZone.appendChild(divs[2 * i + 1])

board.appendChild(groupZone)
}
// for (const el of divs) board.appendChild(el)

container.appendChild(board)
return container
}
Insert cell
<style>
.board {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 10px;
width: ${Math.max(width/2, 400)}px
}
.groupZone {
display: grid;
grid-template-columns: repeat(2, 1fr);
border: 1px solid #ccc;
padding: 5px;
width: ${Math.max(width/4, 200)}px
}
.tile {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #ccc;
padding: 10px;
height: 100px;
font-size: 32px;
}
div:focus {
background-color: #ccc;
}
</style>
Insert cell
guessIsValid = isOnBoard(guess, currentBoard) && results.map(x=>x.word).includes(guess)
Insert cell
activatedGroups = data
.filter((x,i) => i % 2)
.filter(x => x.group_activated === true)
.map(x=>x.group)
Insert cell
makeData = str => str
.split('')
.map((l,i) => ({
id: i,
letter: l,
group: Math.floor(i/2),
group_order: i % 2,
click_count: 0,
last_clicked: false,
click_indexes: [],
group_activated: false,
}))
Insert cell
handleClick = (id, data) => {
// You can't repeat the same letter twice in a row, so do nothing if the use clicks on last_clicked
if(data[id].last_clicked === true) return data

// otherwise, we'll make copy of the data and return the copy
let copy = JSON.parse(JSON.stringify(data))
let row = copy[id]
row.click_count++
row.click_indexes.push(clickCount)
row.group_activated = true
// not sure i'll end up needeing this, but the idea is to activate the other letter in the group
// might make more sense to just normalize
if(row.group_order === 0) copy[id + 1].group_activated = true
if(row.group_order === 1) copy[id - 1].group_activated = true
mutable clickCount++
mutable guess = guess.concat(row.letter)
return copy
.map(x =>({ ...x, last_clicked: id === x.id }))
}
Insert cell
handleClickState = id => {
const output = handleClick(id, data)
mutable data = output
return output
}
Insert cell
handleSubmit = (word, results) => {
let copy = JSON.parse(JSON.stringify(results))
let record = copy.filter(x=> x.word === word)[0]
record.found = true
return copy
}
Insert cell
handleSubmitState = () => {
const output = handleSubmit(guess, results)
mutable results = output
handleReset()
return output
}
Insert cell
handleReset = () => {
mutable clickCount = 0
mutable guess = ''
mutable data = makeData(currentBoard)
}
Insert cell
handleNewBoard = () => {
mutable currentPangram = _.sample(words)
mutable currentBoard = scramble(currentPangram)
mutable clickCount = 0
mutable guess = ''
mutable data = makeData(currentBoard)
mutable results = wordsOnBoard(currentBoard, wordnik)
}
Insert cell
mutable currentPangram = _.sample(words)
Insert cell
mutable currentBoard = scramble(currentPangram)
Insert cell
mutable data = makeData(currentBoard)
Insert cell
mutable results = wordsOnBoard(currentBoard, wordnik)
Insert cell
pangrams = results.filter(x=> x.n_letters_used === 8)
Insert cell
mutable clickCount = 0
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
scramble = w => _(w.split('')).shuffle().join('')
Insert cell
words = wordnik
.filter(x => x.length == 8)
.filter(x => _.uniq(x.split('')).length === x.length)
Insert cell
wordbankSubset = (w1,w2) => {
const wordbank = w => new Set(w.split(''))
let set1 = wordbank(w1)
let set2 = wordbank(w2)
return [...set1].every(x => set2.has(x))
}
Insert cell
noDupes = w => {
let s = new Set(w.split(''))
return s.size === w.length
}
Insert cell
noRepeats = w => {
for (let i = 0; i < w.length - 1; ++i) {
if(w[i] === w[i+1]) return false
}
return true
}
Insert cell
isOnBoard = (word,board) => {
// test the word doesn't use the same letter twice in a row
if(!noRepeats(word)) return false
// if a word has a letter that precludes it from being formed, it isn't on the board
if(!wordbankSubset(word,board)) return false
// test that all four corners are used
for (let i = 0; i < 8; i = i + 2) {
if(!word.includes(board[i]) && !word.includes(board[i+1])) return false
}

// if it hasn't been eliminated yet, the word is on the board
return true
}
Insert cell
wordsOnBoard = (board, wordlist) => wordlist
.filter(w => isOnBoard(w, board))
.map(x=>({
word: x,
length: x.length,
n_letters_used: (new Set(x.split(''))).size,
found: false,
}))
Insert cell
{
// this was an attempt at a text input box. It works fine with console log, but the function I want to call is
const div = html`<div tabindex="0"
style="width: 100px; height: 100px; border: 1px solid black;"
>
</div>`

const handleKeystroke = e => {
e.preventDefault()
console.log(e.key)
// this is the call I want to make, but because handle click state depends on data
// handleClickState(letterToId(e.key))
}
div.addEventListener("keydown", handleKeystroke)
return div
}
Insert cell
// letterToId = (letter) => data.filter(x => x.letter === letter)[0].id
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