Add ranking to Xonotic scripts and clean up names
This commit is contained in:
parent
75b55979ac
commit
e4f91b4b5a
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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') {
|
||||
|
|
Reference in New Issue