Add ranking to Xonotic scripts and clean up names

This commit is contained in:
DeathByDenim 2023-05-07 12:15:21 -04:00
parent 75b55979ac
commit e4f91b4b5a
Signed by: DeathByDenim
GPG Key ID: 4A475283D925365B
2 changed files with 115 additions and 74 deletions

View File

@ -1,97 +1,135 @@
// 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 = [];
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(",");
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;
}
break;
case "player":
if(fields[2] === "see-labels") {
let split_fields = fields[3].split(",");
let player_stats = {name: fields[6]};
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.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) => {
let tables = d3.select("#xonotic-results")
.selectAll("table")
.data(data)
.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");
d3.select("#xonotic-ranking")
.selectAll("li")
.data(data.totals)
.join("li")
.text(d => d.name + " (" + d.score + ")");
["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => {
headerrows.append("th").text(col);
})
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");
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);
["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => {
headerrows.append("th").text(col);
})
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);
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);
});
}

View File

@ -24,6 +24,9 @@ nav_pill: tournament
{% endif %}
{% endfor %}
</ul>
<h2>Ranking</h2>
<ol id="xonotic-ranking"></ol>
<h2>Rounds</h2>
<div id="xonotic-results"></div>
<script>
if(typeof d3 === 'undefined') {