From 33b4f391c9c27cf6575b5339c2360a0b038605ea Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sat, 23 Feb 2019 00:52:41 +0000 Subject: [PATCH] Add moth.js --- theme/moth.js | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 theme/moth.js diff --git a/theme/moth.js b/theme/moth.js new file mode 100644 index 0000000..bec145e --- /dev/null +++ b/theme/moth.js @@ -0,0 +1,168 @@ +// jshint asi:true + +var teamId +var heartbeatInterval = 40000 + +function rpc(url, params={}) { + let formData = new FormData() + for (let k in params) { + formData.append(k, params[k]) + } + return fetch(url, { + method: "POST", + body: formData, + }) +} + +function renderPuzzles(obj) { + console.log(obj) + let puzzlesElement = document.createElement('div') + + // Create a sorted list of category names + let cats = Object.keys(obj) + cats.sort() + for (let cat of cats) { + if (cat.startsWith("__")) { + // Skip metadata + continue + } + let puzzles = obj[cat] + + let pdiv = document.createElement('div') + pdiv.className = 'category' + + let h = document.createElement('h2') + pdiv.appendChild(h) + h.textContent = cat + + // Extras if we're running a devel server + if (obj.__devel__) { + let a = document.createElement('a') + h.insertBefore(a, h.firstChild) + a.textContent = "⬇️" + a.href = "mothballer/" + cat + a.classList.add("mothball") + a.title = "Download a compiled puzzle for this category" + } + + // List out puzzles in this category + let l = document.createElement('ul') + pdiv.appendChild(l) + for (let puzzle of puzzles) { + let points = puzzle[0] + let id = puzzle[1] + + let i = document.createElement('li') + l.appendChild(i) + i.textContent = " " + + if (points === 0) { + // Sentry: there are no more puzzles in this category + i.textContent = "✿" + } else { + let a = document.createElement('a') + i.appendChild(a) + a.textContent = points + a.href = "puzzle.html?cat=" + cat + "&points=" + points + "&pid=" + id + } + } + + puzzlesElement.appendChild(pdiv) + } + + // Drop that thing in + let container = document.getElementById("puzzles") + while (container.firstChild) { + container.firstChild.remove() + } + container.appendChild(puzzlesElement) + container.style.display = "none" + + document.getElementById("login").style.display = "block" +} + +function heartbeat(teamId) { + rpc("puzzles.json", {teamid: teamId}) + .then(resp => { + if (resp.ok) { + resp.json() + .then(renderPuzzles) + .catch(err => { + toast("Error fetching recent puzzles. I'll try again in a moment.") + console.log(err) + }) + } + }) + .catch(err => { + toast("Error fetching recent puzzles. I'll try again in a moment.") + console.log(err) + }) +} + +function showPuzzles(teamId) { + let spinner = document.createElement("span") + spinner.classList.add("spinner") + + document.getElementById("login").style.display = "none" + document.getElementById("puzzles").appendChild(spinner) + heartbeat(teamId) + setInterval(e => { heartbeat(teamId) }, 40000) +} + +function login() { + let name = document.querySelector("[name=name]").value + let id = document.querySelector("[name=id]").value + + rpc("register", { + name: name, + id: id, + }) + .then(resp => { + if (resp.ok) { + resp.json() + .then(obj => { + if (obj.status == "success") { + toast("Team registered") + showPuzzles(id) + } else if (obj.data.short == "Already registered") { + toast("Logged in with previously-registered team name") + showPuzzles(id) + } else { + toast(obj.data.description) + } + }) + .catch(err => { + toast("Oops, the server has lost its mind. You probably need to tell someone so they can fix it.") + console.log(err, resp) + }) + } else { + toast("Oops, something's wrong with the server. Try again in a few seconds.") + console.log(resp) + } + }) + .catch(err => { + toast("Oops, something went wrong. Try again in a few seconds.") + console.log(err) + }) +} + +function toast(message, timeout=5000) { + let p = document.createElement("p") + + p.innerText = message + document.getElementById("messages").appendChild(p) + setTimeout( + e => { p.remove() }, + timeout + ) +} + +function init() { + document.getElementById("submit").addEventListener("click", login) +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); +} else { + init(); +}