This repository has been archived on 2023-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
gameserver/website/js/xonscore.js

136 lines
4.5 KiB
JavaScript

// Parse the Xonotic score log format and return a JSON
// The returned data contains data for the individual
// rounds as well as totals
async function xonoticGetScores() {
const data = await fetch("xonscore.txt");
const text = await data.text();
let stats = {
rounds: [],
totals: []
};
let map_name = "[unknown]";
let duration_in_seconds = 0;
let labels = [];
let round_stats = [];
text.split("\n").forEach((row) => {
const fields = row.split(":");
if(fields.length > 1) {
const verb = fields[1]
switch(verb) {
case "scores":
map_name = fields[2];
duration_in_seconds = fields[3];
break;
case "labels":
if(fields[2] === "player") {
labels = fields[3].split(",");
}
break;
case "player":
if(fields[2] === "see-labels") {
if(fields[5] === "spectator") {
break;
}
let split_fields = fields[3].split(",");
let player_name = fields[6]
.replace(/\^.../g, "")
.replaceAll("^7", "");
let player_stats = {name: player_name};
for(let i = 0; i < labels.length; i++) {
if(labels[i] != "") {
player_stats[labels[i]] = split_fields[i]
}
}
round_stats.push(player_stats);
}
break;
case "end":
if(round_stats.length > 0) {
round_stats = round_stats.sort((a,b) => +a["score!!"] < +b["score!!"]);
stats.rounds.push({
map_name: map_name,
duration_in_seconds: duration_in_seconds,
stats: round_stats
})
}
round_stats = [];
labels = [];
duration_in_seconds = 0;
map_name = "";
break;
}
}
})
let final = {};
stats.rounds.forEach((map) => {
map.stats.forEach((stat) => {
if(stat.name in final) {
final[stat.name] += +stat["score!!"]
}
else {
final[stat.name] = +stat["score!!"]
}
});
});
Object.keys(final).forEach(name => {
stats.totals.push({
name: name,
score: final[name]
})
});
stats.totals = stats.totals.sort((a,b) => a.score < b.score);
return stats;
}
function xonoticScoreUpdate() {
xonoticGetScores().then((data) => {
d3.select("#xonotic-ranking")
.selectAll("li")
.data(data.totals)
.join("li")
.text(d => d.name + " (" + d.score + ")");
let tables = d3.select("#xonotic-results")
.selectAll("table")
.data(data.rounds)
.join(
(enter) => {
let table = enter.append("table");
let thead = table.append("thead");
thead.append("tr")
.append("th")
.attr("colspan", 5)
.text((d) => "Map name: " + d.map_name);
let headerrows = thead.append("tr");
["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => {
headerrows.append("th").text(col);
})
table.append("tbody");
return table;
},
(update) => {
let u = update;
u.select("th").text((d) => "Map name: " + d.map_name);
return u;
},
(exit) => exit.remove()
)
.classed("table", true);
let tbodies = tables.select('tbody');
tbodies.selectAll("tr")
.data((d) => d.stats)
.join("tr")
.selectAll("td")
.data((d) => ["name", "score!!", "kills", "deaths<", "suicides<"].map((col) => d[col]))
.join("td")
.text((d) => d);
});
}