moth/theme/scoreboard.mjs

98 lines
2.8 KiB
JavaScript
Raw Normal View History

2023-09-15 15:17:07 -06:00
import * as moth from "./moth.mjs"
import * as common from "./common.mjs"
2020-02-29 17:12:35 -07:00
2023-09-15 15:17:07 -06:00
const server = new moth.Server(".")
2023-09-15 16:09:08 -06:00
const ReplayDuration = 0.3 * common.Second
const MaxFrameRate = 60
2023-09-15 15:17:07 -06:00
/** Don't let any team's score exceed this percentage width */
const MaxScoreWidth = 95
2023-09-15 15:17:07 -06:00
/**
* Returns a promise that resolves after timeout.
*
* @param {Number} timeout How long to sleep (milliseconds)
* @returns {Promise}
*/
function sleep(timeout) {
return new Promise(resolve => setTimeout(resolve, timeout));
}
2023-09-15 15:17:07 -06:00
/**
* Pull new points log, and update the scoreboard.
*
* The update is animated, because I think that looks cool.
*/
async function update() {
2023-09-15 16:09:08 -06:00
let config = await common.Config()
for (let e of document.querySelectorAll(".location")) {
e.textContent = common.BaseURL
e.classList.toggle("hidden", !config.URLInScoreboard)
}
2023-09-15 15:17:07 -06:00
let state = await server.GetState()
let rankingsElement = document.querySelector("#rankings")
let logSize = state.PointsLog.length
2023-09-15 15:17:07 -06:00
// Figure out the timing so that we can replay the scoreboard in about
// ReplayDuration, but no more than 24 frames per second.
let frameModulo = 1
let delay = 0
while (delay < (common.Second / MaxFrameRate)) {
frameModulo += 1
delay = ReplayDuration / (logSize / frameModulo)
}
2023-09-15 15:17:07 -06:00
let frame = 0
2023-09-27 16:10:31 -06:00
for (let scores of state.ScoresHistory()) {
2023-09-15 15:17:07 -06:00
frame += 1
if ((frame < state.PointsLog.length) && (frame % frameModulo)) {
continue
}
2023-09-15 15:17:07 -06:00
while (rankingsElement.firstChild) rankingsElement.firstChild.remove()
2023-09-15 15:17:07 -06:00
let sortedTeamIDs = [...scores.TeamIDs]
sortedTeamIDs.sort((a, b) => scores.CyFiScore(a) - scores.CyFiScore(b))
sortedTeamIDs.reverse()
2020-02-29 17:12:35 -07:00
2023-09-15 15:17:07 -06:00
let topScore = scores.CyFiScore(sortedTeamIDs[0])
for (let teamID of sortedTeamIDs) {
let teamName = state.TeamNames[teamID]
2020-02-29 17:12:35 -07:00
2023-09-15 15:17:07 -06:00
let row = rankingsElement.appendChild(document.createElement("div"))
2020-02-29 17:12:35 -07:00
2023-09-27 17:56:40 -06:00
let teamname = row.appendChild(document.createElement("span"))
teamname.textContent = teamName
teamname.classList.add("teamname")
2023-09-15 15:17:07 -06:00
let categoryNumber = 0
2023-09-27 17:56:40 -06:00
let teampoints = row.appendChild(document.createElement("span"))
teampoints.classList.add("teampoints")
2023-09-15 15:17:07 -06:00
for (let category of scores.Categories) {
let score = scores.CyFiCategoryScore(category, teamID)
if (!score) {
continue
}
2023-09-27 17:56:40 -06:00
let block = teampoints.appendChild(document.createElement("span"))
2023-09-15 15:17:07 -06:00
let points = scores.GetPoints(category, teamID)
let width = MaxScoreWidth * score / topScore
block.textContent = category
block.title = `${points} points`
block.style.width = `${width}%`
2023-09-27 17:56:40 -06:00
block.classList.add("category", `cat${categoryNumber}`)
2023-09-15 15:17:07 -06:00
categoryNumber += 1
}
2020-02-29 17:12:35 -07:00
}
2023-09-15 15:17:07 -06:00
await sleep(delay)
2020-02-29 17:12:35 -07:00
}
}
2023-09-15 15:17:07 -06:00
function init() {
setInterval(update, common.Minute)
update()
2020-02-29 17:12:35 -07:00
}
2023-09-15 15:17:07 -06:00
common.WhenDOMLoaded(init)