New scoreboard view

This commit is contained in:
Neale Pickett 2023-11-16 23:44:32 -07:00
parent c4bf25f8fa
commit 63881f05fa
5 changed files with 117 additions and 21 deletions

View File

@ -492,9 +492,7 @@ class State {
* @returns {Scores}
*/
CurrentScores() {
let scores
for (scores of this.ScoreHistory());
return scores
return [...this.ScoresHistory()].pop()
}
}
@ -676,4 +674,5 @@ class Server {
export {
Hash,
Server,
State,
}

19
theme/scoreboard-all.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Scoreboard</title>
<link rel="stylesheet" href="basic.css">
<link rel="stylesheet" href="scoreboard.css">
<meta name="viewport" content="width=device-width">
<link rel="icon" href="luna-moth.svg">
<script type="module" src="scoreboard.mjs"></script>
</head>
<body>
<div class="no-scores hidden"></div>
<div class="rotate">
<div class="rankings category"></div>
<div class="rankings classic"></div>
</div>
<div class="location"></div>
</body>
</html>

View File

@ -33,32 +33,37 @@
max-height: 60vh;
}
/* Only the first child of a rotate class is visible */
.rotate > div:nth-child(n + 2) {
display: none;
}
/** Scoreboard */
.rankings {
.rankings.classic {
width: 100%;
position: relative;
background-color: #000c;
}
.rankings div {
.rankings.classic div {
height: 1.2rem;
display: flex;
align-items: center;
}
.rankings div:nth-child(6n){
.rankings.classic div:nth-child(6n){
background-color: #ccc3;
}
.rankings div:nth-child(6n+3) {
.rankings.classic div:nth-child(6n+3) {
background-color: #0f03;
}
.rankings span {
.rankings.classic span {
display: inline-block;
overflow: hidden;
}
.rankings span.category {
.rankings.classic span.category {
font-size: 80%;
}
.rankings span.teamname {
.rankings.classic span.teamname {
height: auto;
font-size: inherit;
color: white;
@ -67,8 +72,8 @@
position: absolute;
right: 0.2em;
}
.rankings span.teamname:hover,
.rankings span.category:hover {
.rankings.classic span.teamname:hover,
.rankings.classic span.category:hover {
width: inherit;
max-width: 100%;
}
@ -78,8 +83,24 @@
vertical-align: top;
}
.rankings.category {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}
.rankings.category div {
border: solid black 2px;
min-width: 15em;
}
.rankings.category table {
width: 100%;
}
.rankings.category td.number {
text-align: right;
}
@media only screen and (max-width: 450px) {
.rankings span.teamname {
.rankings.classic span.teamname {
max-width: 6em;
text-overflow: ellipsis;
}

View File

@ -10,7 +10,7 @@
</head>
<body>
<div class="no-scores hidden"></div>
<div class="rankings"></div>
<div class="rankings classic"></div>
<div class="location"></div>
</body>
</html>

View File

@ -34,22 +34,39 @@ async function update() {
}
// 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")
}
let ScoreboardConfig = config.Scoreboard ?? {}
let state = await server.GetState()
// Show URL of server
for (let e of document.querySelectorAll(".location")) {
e.textContent = common.BaseURL
e.classList.toggle("hidden", !(ScoreboardConfig.DisplayServerURLWhenEnabled && state.Enabled))
}
let rankingsElement = document.querySelector(".rankings")
// Rotate views
for (let e of document.querySelectorAll(".rotate")) {
e.appendChild(e.firstChild)
}
// Render rankings
for (let e of document.querySelectorAll(".rankings")) {
if (e.classList.contains("classic")) {
classicRankings(e, state, ScoreboardConfig)
} else if (e.classList.contains("category")) {
categoryRankings(e, state, ScoreboardConfig)
}
}
}
async function classicRankings(rankingsElement, state, ScoreboardConfig) {
let ReplayHistory = ScoreboardConfig.ReplayHistory ?? false
let ReplayDurationMS = ScoreboardConfig.ReplayDurationMS ?? 300
let ReplayFPS = ScoreboardConfig.ReplayFPS ?? 24
let logSize = state.PointsLog.length
// Figure out the timing so that we can replay the scoreboard in about
@ -78,7 +95,7 @@ async function update() {
let topScore = scores.CyFiScore(sortedTeamIDs[0])
for (let teamID of sortedTeamIDs) {
let teamName = state.TeamNames[teamID]
let teamName = state.TeamNames[teamID] ?? "rodney"
let row = rankingsElement.appendChild(document.createElement("div"))
@ -118,6 +135,46 @@ async function update() {
}
}
/**
*
* @param {*} rankingsElement
* @param {moth.State} state
* @param {*} ScoreboardConfig
*/
async function categoryRankings(rankingsElement, state, ScoreboardConfig) {
while (rankingsElement.firstChild) rankingsElement.firstChild.remove()
let scores = state.CurrentScores()
for (let category of scores.Categories) {
let categoryBox = rankingsElement.appendChild(document.createElement("div"))
categoryBox.classList.add("category")
categoryBox.appendChild(document.createElement("h2")).textContent = category
let categoryScores = []
for (let teamID in state.TeamNames) {
categoryScores.push({
teamName: state.TeamNames[teamID],
score: scores.GetPoints(category, teamID),
})
}
categoryScores.sort((a, b) => b.score - a.score)
let table = categoryBox.appendChild(document.createElement("table"))
let rows = 0
for (let categoryScore of categoryScores) {
let row = table.appendChild(document.createElement("tr"))
row.appendChild(document.createElement("td")).textContent = categoryScore.teamName
let td = row.appendChild(document.createElement("td"))
td.textContent = categoryScore.score
td.classList.add("number")
rows += 1
if (rows == 5) {
break
}
}
}
}
function init() {
setInterval(update, common.Minute)
update()