mirror of https://github.com/dirtbags/moth.git
Compare commits
2 Commits
3d8c47d316
...
6ff379e0f4
Author | SHA1 | Date |
---|---|---|
Neale Pickett | 6ff379e0f4 | |
Neale Pickett | eb786ba184 |
|
@ -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"
|
||||||
}
|
}
|
|
@ -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,20 +52,22 @@ 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
|
||||||
|
if (!ReplayHistory || (frame % frameModulo)) { // Skip if we're not animating, or if we need to drop frames
|
||||||
continue
|
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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue