Compare commits

..

2 Commits

Author SHA1 Message Date
Neale Pickett 6ff379e0f4 try to prevent future bad decisions 2023-09-28 12:59:51 -06:00
Neale Pickett eb786ba184 More scoreboard configurables 2023-09-28 12:42:25 -06:00
2 changed files with 41 additions and 14 deletions

View File

@ -1,6 +1,13 @@
{ {
"TrackSolved": true, "TrackSolved": true,
"URLInScoreboard": true, "Scoreboard": {
"DisplayServerURL": true,
"ShowCategoryLeaders": true,
"ReplayHistory": true,
"ReplayFPS": 30,
"ReplayDurationMS": 2000,
"": ""
},
"Messages": "<!-- Messages can go here (HTML) -->", "Messages": "<!-- Messages can go here (HTML) -->",
"__sentry__": "this is here so you don't have to remember to take the comma off the last item" "": "this is here so you don't have to remember to take the comma off the last item"
} }

View File

@ -2,14 +2,16 @@ import * as moth from "./moth.mjs"
import * as common from "./common.mjs" import * as common from "./common.mjs"
const server = new moth.Server(".") const server = new moth.Server(".")
const ReplayDuration = 0.3 * common.Second
const MaxFrameRate = 60
/** Don't let any team's score exceed this percentage width */ /** Don't let any team's score exceed this percentage width */
const MaxScoreWidth = 95 const MaxScoreWidth = 90
/** /**
* Returns a promise that resolves after timeout. * Returns a promise that resolves after timeout.
* *
* This uses setTimeout instead of some other fancy thing like
* requestAnimationFrame, because who actually cares about scoreboard update
* framerate?
*
* @param {Number} timeout How long to sleep (milliseconds) * @param {Number} timeout How long to sleep (milliseconds)
* @returns {Promise} * @returns {Promise}
*/ */
@ -23,10 +25,26 @@ function sleep(timeout) {
* The update is animated, because I think that looks cool. * The update is animated, because I think that looks cool.
*/ */
async function update() { async function update() {
let config = await common.Config() let config = {}
try {
config = await common.Config()
}
catch (err) {
console.warn("Parsing config.json:", err)
}
// Pull configuration settings
let ScoreboardConfig = config.Scoreboard ?? {}
let ReplayHistory = ScoreboardConfig.ReplayHistory ?? false
let ReplayDurationMS = ScoreboardConfig.ReplayDurationMS ?? 300
let ReplayFPS = ScoreboardConfig.ReplayFPS ?? 24
if (!config.Scoreboard) {
console.warn("config.json has empty Scoreboard section")
}
for (let e of document.querySelectorAll(".location")) { for (let e of document.querySelectorAll(".location")) {
e.textContent = common.BaseURL e.textContent = common.BaseURL
e.classList.toggle("hidden", !config.URLInScoreboard) e.classList.toggle("hidden", !ScoreboardConfig.DisplayServerURL)
} }
let state = await server.GetState() let state = await server.GetState()
@ -34,19 +52,21 @@ async function update() {
let logSize = state.PointsLog.length let logSize = state.PointsLog.length
// Figure out the timing so that we can replay the scoreboard in about // Figure out the timing so that we can replay the scoreboard in about
// ReplayDuration, but no more than 24 frames per second. // ReplayDurationMS, but no more than 24 frames per second.
let frameModulo = 1 let frameModulo = 1
let delay = 0 let delay = 0
while (delay < (common.Second / MaxFrameRate)) { while (delay < (common.Second / ReplayFPS)) {
frameModulo += 1 frameModulo += 1
delay = ReplayDuration / (logSize / frameModulo) delay = ReplayDurationMS / (logSize / frameModulo)
} }
let frame = 0 let frame = 0
for (let scores of state.ScoresHistory()) { for (let scores of state.ScoresHistory()) {
frame += 1 frame += 1
if ((frame < state.PointsLog.length) && (frame % frameModulo)) { if (frame < state.PointsLog.length) { // Always render the last frame
continue if (!ReplayHistory || (frame % frameModulo)) { // Skip if we're not animating, or if we need to drop frames
continue
}
} }
while (rankingsElement.firstChild) rankingsElement.firstChild.remove() while (rankingsElement.firstChild) rankingsElement.firstChild.remove()
@ -83,7 +103,7 @@ async function update() {
block.title = `${points} points` block.title = `${points} points`
block.style.width = `${width}%` block.style.width = `${width}%`
block.classList.add("category", `cat${categoryNumber}`) block.classList.add("category", `cat${categoryNumber}`)
block.classList.toggle("topscore", score == 1) block.classList.toggle("topscore", (score == 1) && ScoreboardConfig.ShowCategoryLeaders)
categoryNumber += 1 categoryNumber += 1
} }