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() { async function xonoticGetScores() {
const data = await fetch("xonscore.txt"); const data = await fetch("xonscore.txt");
const text = await data.text(); const text = await data.text();
let stats = []; let stats = {
rounds: [],
totals: []
};
let map_name = "[unknown]"; let map_name = "[unknown]";
let duration_in_seconds = 0; let duration_in_seconds = 0;
let labels = []; let labels = [];
let round_stats = []; let round_stats = [];
text.split("\n").forEach((row) => { text.split("\n").forEach((row) => {
const fields = row.split(":"); const fields = row.split(":");
if(fields.length > 1) { if(fields.length > 1) {
const verb = fields[1] const verb = fields[1]
switch(verb) { switch(verb) {
case "scores": case "scores":
map_name = fields[2]; map_name = fields[2];
duration_in_seconds = fields[3]; duration_in_seconds = fields[3];
break; break;
case "labels": case "labels":
if(fields[2] === "player") { if(fields[2] === "player") {
labels = fields[3].split(","); 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; return stats;
} }
function xonoticScoreUpdate() { function xonoticScoreUpdate() {
xonoticGetScores().then((data) => { xonoticGetScores().then((data) => {
let tables = d3.select("#xonotic-results") d3.select("#xonotic-ranking")
.selectAll("table") .selectAll("li")
.data(data) .data(data.totals)
.join( .join("li")
(enter) => { .text(d => d.name + " (" + d.score + ")");
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) => { let tables = d3.select("#xonotic-results")
headerrows.append("th").text(col); .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"); ["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => {
return table; headerrows.append("th").text(col);
}, })
(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'); table.append("tbody");
tbodies.selectAll("tr") return table;
.data((d) => d.stats) },
.join("tr") (update) => {
.selectAll("td") let u = update;
.data((d) => ["name", "score!!", "kills", "deaths<", "suicides<"].map((col) => d[col])) u.select("th").text((d) => "Map name: " + d.map_name);
.join("td") return u;
.text((d) => d); },
(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 %} {% endif %}
{% endfor %} {% endfor %}
</ul> </ul>
<h2>Ranking</h2>
<ol id="xonotic-ranking"></ol>
<h2>Rounds</h2>
<div id="xonotic-results"></div> <div id="xonotic-results"></div>
<script> <script>
if(typeof d3 === 'undefined') { if(typeof d3 === 'undefined') {