From 02b99889178b5f7b1c54437e8f7f9d13d6b8da08 Mon Sep 17 00:00:00 2001 From: cyfraeviolae Date: Sun, 19 Nov 2023 15:47:12 -0500 Subject: init --- static/script.js | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 static/script.js (limited to 'static/script.js') diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..dfe5fd8 --- /dev/null +++ b/static/script.js @@ -0,0 +1,233 @@ +"use strict"; + +function newGroup() { + var keys = Object.keys(corpus); + var i = keys.length * Math.random() << 0; + var group = corpus[keys[i]]; + var clues = randomSelect(group.clues, 4); + + return { + group: group.group, + clues: clues, + fullClues: group.clues, + }; +} + +function newNonintersectingGroup(oldGroups) { + var group = newGroup(); + for (var oldGroup of oldGroups) { + var intersection = oldGroup.fullClues.filter(value => group.fullClues.includes(value)); + if (intersection.length > 0) { + return newNonintersectingGroup(oldGroups); + } + } + return group; +} + +function newBoard() { + var groups = []; + for (var i = 0; i < 4; i++) { + var group = newNonintersectingGroup(groups); + groups.push(group); + } + return groups; +} + +var currentBoard = null; +var selected = {}; + +function chooseBox(box) { + var clue = parseInt(box.getAttribute('x-clue')); + if (box.classList.contains('selected')) { + box.classList.remove('selected'); + delete selected[clue]; + } else { + box.classList.add('selected'); + selected[clue] = parseInt(box.getAttribute('x-group')); + } + + if (Object.keys(selected).length == 4) { + var [ok, grp] = checkGuess(selected) + if (ok) { + console.log('SUCCESS') + consume(grp); + } else { + console.log('FAIL') + clear(); + } + } +} + +function clear() { + selected = {} + var els = [...document.getElementsByClassName('selected')]; + for (var i = 0; i < 4; i++) { + els[i].classList.remove('selected'); + } +} + +function consume(grp) { + selected = {} + var els = document.querySelectorAll(`[x-group="${grp}"]`); + for (var el of els) { + el.remove(); + } + var group = currentBoard[grp]; + + document.getElementById('answers').innerHTML += + `
+
${group.group}
+
${group.clues.map(renderClue).join(', ')}
+
`; +} + +function checkGuess(selected) { + var ans = null; + for (var clue of Object.keys(selected)) { + var group = selected[clue]; + if (ans === null) { + ans = group; + } else if (ans != group) { + return [false, 0]; + } + } + return [true, group]; +} + +function renderClue(clue) { + return clue.split('_').join(' '); +} + +function serializeBoard(board) { + var copy = [] + for (var group of board) { + copy.push({ + clues: group.clues, + group: group.group, + }) + } + return encodeURIComponent(btoa(JSON.stringify(copy))) +} + +function deserializeBoard(s) { + var copy = JSON.parse(atob(decodeURIComponent(s))) + var board = [] + for (var group of copy) { + board.push({ + clues: group.clues, + group: group.group, + fullClues: group.clues, + }) + } + return board; +} + +function generateUrl(board) { + return `${location.origin}/infinite-connections?q=${serializeBoard(board)}` +} + +function startBoard(board) { + selected = {}; + + document.getElementById('url').value = generateUrl(board); + + document.getElementById('answers').innerHTML = ''; + var el = document.getElementById('board'); + + currentBoard = board; + + var clues = []; + for (var [i, group] of board.entries()) { + for (var [j, clue] of group.clues.entries()) { + clues.push([i, i*4+j, clue]); + } + } + + shuffle(clues); + el.innerHTML = ``; + for (var [i, j, clue] of clues) { + el.innerHTML += `
${renderClue(clue)}
`; + } +} + +function giveUp() { + document.getElementById('board').innerHTML = ''; + document.getElementById('answers').innerHTML = ''; + consume(0); + consume(1); + consume(2); + consume(3); +} + +document.getElementById('board').addEventListener('click', function(evt) { + if (evt.target.classList.contains('box')) { + evt.preventDefault(); + chooseBox(evt.target); + } +}); + +document.getElementById('new-board').addEventListener('click', function(evt) { + startBoard(newBoard()); +}); + +document.getElementById('copy-link').addEventListener('click', function(evt) { + document.getElementById('url').select() + document.execCommand('copy'); +}); + +document.getElementById('clear').addEventListener('click', function(evt) { + clear(); +}); + +document.getElementById('reset').addEventListener('click', function(evt) { + startBoard(currentBoard); +}); + +document.getElementById('give-up').addEventListener('click', function(evt) { + giveUp(); +}); + + +window.onload = function() { + var urlParams = new URLSearchParams(window.location.search); + var q = urlParams.get('q') + if (q) { + startBoard(deserializeBoard(q)); + return; + } + startBoard(newBoard()); +} + +// Source: https://stackoverflow.com/a/19270021 +function randomSelect(arr, n) { + var result = new Array(n), + len = arr.length, + taken = new Array(len); + if (n > len) + throw new RangeError("randomSelect: more elements taken than available"); + while (n--) { + var x = Math.floor(Math.random() * len); + result[n] = arr[x in taken ? taken[x] : x]; + taken[x] = --len in taken ? taken[len] : len; + } + return result; +} + +// Source: https://stackoverflow.com/a/2450976 +function shuffle(array) { + let currentIndex = array.length, randomIndex; + + // While there remain elements to shuffle. + while (currentIndex > 0) { + + // Pick a remaining element. + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + + // And swap it with the current element. + [array[currentIndex], array[randomIndex]] = [ + array[randomIndex], array[currentIndex]]; + } + + return array; +} -- cgit v1.2.3