summaryrefslogtreecommitdiff
path: root/static/script.js
diff options
context:
space:
mode:
Diffstat (limited to 'static/script.js')
-rw-r--r--static/script.js233
1 files changed, 233 insertions, 0 deletions
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 +=
+ `<div class="answer">
+ <div class="answerline">${group.group}</div>
+ <div class="clues">${group.clues.map(renderClue).join(', ')}</div>
+ </div>`;
+}
+
+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 += `<div class="box" x-group=${i} x-clue=${j}>${renderClue(clue)}</div>`;
+ }
+}
+
+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;
+}