moth/theme/moth.js

284 lines
7.2 KiB
JavaScript
Raw Normal View History

2019-02-22 17:52:41 -07:00
// jshint asi:true
var teamId
var heartbeatInterval = 40000
2019-02-22 20:46:52 -07:00
function toast(message, timeout=5000) {
let p = document.createElement("p")
p.innerText = message
document.getElementById("messages").appendChild(p)
setTimeout(
e => { p.remove() },
timeout
)
}
function renderNotices(obj) {
let ne = document.getElementById("notices")
if (ne) {
ne.innerHTML = obj
}
}
2019-02-22 17:52:41 -07:00
function renderPuzzles(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 = "⬇️"
2019-02-27 16:15:45 -07:00
a.href = "mothballer/" + cat + ".mb"
2019-02-22 17:52:41 -07:00
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
let url = new URL("puzzle.html", window.location)
url.searchParams.set("cat", cat)
url.searchParams.set("points", points)
url.searchParams.set("pid", id)
a.href = url.toString()
2019-02-22 17:52:41 -07:00
}
}
puzzlesElement.appendChild(pdiv)
}
// Drop that thing in
let container = document.getElementById("puzzles")
while (container.firstChild) {
container.firstChild.remove()
}
container.appendChild(puzzlesElement)
}
2019-11-02 15:24:01 -06:00
function heartbeat(teamId, participantId) {
let noticesUrl = new URL("notices.html", window.location)
fetch(noticesUrl)
.then(resp => {
if (resp.ok) {
resp.text()
.then(renderNotices)
.catch(err => console.log)
}
})
.catch(err => console.log)
2019-11-07 12:34:53 -07:00
let url = new URL("puzzles.json", window.location)
url.searchParams.set("id", teamId)
2019-11-02 15:24:01 -06:00
if (participantId) {
url.searchParams.set("pid", participantId)
}
2019-02-23 12:04:42 -07:00
let fd = new FormData()
fd.append("id", teamId)
2019-11-07 12:34:53 -07:00
fetch(url)
2019-02-22 17:52:41 -07:00
.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)
})
}
2019-11-02 15:24:01 -06:00
function showPuzzles(teamId, participantId) {
2019-02-22 17:52:41 -07:00
let spinner = document.createElement("span")
spinner.classList.add("spinner")
2019-02-22 19:09:38 -07:00
sessionStorage.setItem("id", teamId)
2019-11-02 15:24:01 -06:00
if (participantId) {
sessionStorage.setItem("pid", participantId)
}
2019-02-22 19:09:38 -07:00
2019-02-22 17:52:41 -07:00
document.getElementById("login").style.display = "none"
document.getElementById("puzzles").appendChild(spinner)
2019-11-02 15:24:01 -06:00
heartbeat(teamId, participantId)
2019-02-22 17:52:41 -07:00
setInterval(e => { heartbeat(teamId) }, 40000)
drawCacheButton(teamId)
}
2019-10-25 16:53:40 -06:00
function drawCacheButton(teamId) {
let cacher = document.querySelector("#cacheButton")
function updateCacheButton() {
2019-11-04 09:22:44 -07:00
let headers = new Headers()
headers.append("pragma", "no-cache")
headers.append("cache-control", "no-cache")
2019-11-07 12:34:53 -07:00
let url = new URL("current_manifest.json", window.location)
url.searchParams.set("id", teamId)
fetch(url, {method: "HEAD", headers: headers})
.then( resp => {
if (resp.ok) {
cacher.classList.remove("disabled")
} else {
cacher.classList.add("disabled")
}
})
.catch(ex => {
cacher.classList.add("disabled")
})
}
2019-11-07 12:38:03 -07:00
setInterval (updateCacheButton , 30000)
2019-11-04 09:22:44 -07:00
updateCacheButton()
2019-10-25 16:53:40 -06:00
}
async function fetchAll() {
let teamId = sessionStorage.getItem("id")
2019-11-04 09:22:44 -07:00
let headers = new Headers()
headers.append("pragma", "no-cache")
headers.append("cache-control", "no-cache")
requests = []
2019-11-07 12:34:53 -07:00
let url = new URL("current_manifest.json", window.location)
url.searchParams.set("id", teamId)
2019-10-25 16:53:40 -06:00
toast("Caching all currently-open content")
2019-11-07 12:34:53 -07:00
requests.push( fetch(url, {headers: headers})
2019-10-25 16:53:40 -06:00
.then( resp => {
if (resp.ok) {
resp.json()
.then(contents => {
2019-11-04 09:22:44 -07:00
console.log("Processing manifest")
2019-10-25 16:53:40 -06:00
for (let resource of contents) {
if (resource == "puzzles.json") {
2019-11-04 09:22:44 -07:00
continue
2019-10-25 16:53:40 -06:00
}
fetch(resource)
.then(e => {
2019-11-07 12:38:03 -07:00
console.log("Fetched " + resource)
2019-10-25 16:53:40 -06:00
})
}
})
}
2019-11-04 09:22:44 -07:00
}))
2019-10-25 16:53:40 -06:00
2019-11-04 09:22:44 -07:00
let resp = await fetch("puzzles.json?id=" + teamId, {headers: headers})
2019-10-25 16:53:40 -06:00
if (resp.ok) {
2019-11-04 09:22:44 -07:00
let categories = await resp.json()
2019-10-25 16:53:40 -06:00
let cat_names = Object.keys(categories)
cat_names.sort()
for (let cat_name of cat_names) {
if (cat_name.startsWith("__")) {
// Skip metadata
continue
}
2019-11-04 09:22:44 -07:00
let puzzles = categories[cat_name]
2019-10-25 16:53:40 -06:00
for (let puzzle of puzzles) {
2019-11-07 12:34:53 -07:00
let url = new URL("puzzle.html", window.location)
url.searchParams.set("cat", cat_name)
url.searchParams.set("points", puzzle[0])
url.searchParams.set("pid", puzzle[1])
requests.push( fetch(url)
.then(e => {
2019-11-04 09:22:44 -07:00
console.log("Fetched " + url)
}))
2019-10-25 16:53:40 -06:00
}
}
}
await Promise.all(requests)
toast("Done caching content")
2019-02-22 17:52:41 -07:00
}
2019-02-22 19:09:38 -07:00
function login(e) {
2019-02-22 20:46:52 -07:00
e.preventDefault()
2019-02-22 17:52:41 -07:00
let name = document.querySelector("[name=name]").value
2019-11-02 15:24:01 -06:00
let teamId = document.querySelector("[name=id]").value
let pide = document.querySelector("[name=pid]")
let participantId = pide?pide.value:""
2019-02-22 17:52:41 -07:00
2019-02-23 12:04:42 -07:00
fetch("register", {
method: "POST",
body: new FormData(e.target),
2019-02-22 17:52:41 -07:00
})
.then(resp => {
if (resp.ok) {
resp.json()
.then(obj => {
if (obj.status == "success") {
toast("Team registered")
2019-11-02 15:24:01 -06:00
showPuzzles(teamId, participantId)
2019-02-22 17:52:41 -07:00
} else if (obj.data.short == "Already registered") {
toast("Logged in with previously-registered team name")
2019-11-02 15:24:01 -06:00
showPuzzles(teamId, participantId)
2019-02-22 17:52:41 -07:00
} 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 init() {
2019-02-22 19:09:38 -07:00
// Already signed in?
2019-11-02 15:24:01 -06:00
let teamId = sessionStorage.getItem("id")
let participantId = sessionStorage.getItem("pid")
if (teamId) {
showPuzzles(teamId, participantId)
2019-02-22 19:09:38 -07:00
}
2019-10-25 16:53:40 -06:00
2019-02-22 19:09:38 -07:00
document.getElementById("login").addEventListener("submit", login)
2019-02-22 17:52:41 -07:00
}
if (document.readyState === "loading") {
2019-11-04 09:22:44 -07:00
document.addEventListener("DOMContentLoaded", init)
2019-02-22 17:52:41 -07:00
} else {
2019-11-04 09:22:44 -07:00
init()
2019-02-22 17:52:41 -07:00
}
2019-10-25 16:53:40 -06:00