Automatic score updating for Xonotic tournament
This commit is contained in:
parent
55fa2a41d1
commit
cbf6cd07e6
|
@ -53,7 +53,7 @@ sv_vote_call 1
|
||||||
sv_weaponstats_file http://www.xonotic.org/weaponbalance/
|
sv_weaponstats_file http://www.xonotic.org/weaponbalance/
|
||||||
sv_logscores_console 1
|
sv_logscores_console 1
|
||||||
sv_logscores_file 1
|
sv_logscores_file 1
|
||||||
sv_logscores_filename xonotic-scores.log
|
sv_logscores_filename xonscore.txt
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat > /etc/systemd/system/xonotic.service <<EOF
|
cat > /etc/systemd/system/xonotic.service <<EOF
|
||||||
|
@ -85,4 +85,8 @@ location /xonotic {
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if ! [ -h /var/www/html/xonscore.txt ]; then
|
||||||
|
ln -s "${systemuserhome}"/xonotic/data/data/xonscore.txt /var/www/html
|
||||||
|
fi
|
||||||
|
|
||||||
firewall-cmd --zone=public --add-port=26000/udp --permanent
|
firewall-cmd --zone=public --add-port=26000/udp --permanent
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
async function xonoticGetScores() {
|
||||||
|
const data = await fetch("xonscore.txt");
|
||||||
|
const text = await data.text();
|
||||||
|
|
||||||
|
let stats = [];
|
||||||
|
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") {
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
["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);
|
||||||
|
});
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
nav_pill: tournament
|
nav_pill: tournament
|
||||||
---
|
---
|
||||||
|
<script src="js/xonscore.js"></script>
|
||||||
<h1>Tournament</h1>
|
<h1>Tournament</h1>
|
||||||
{% assign sitetime = site.time | date: "%FT%T" %}
|
{% assign sitetime = site.time | date: "%FT%T" %}
|
||||||
{% assign nextevent = site.data.events | where_exp: "item", "item.date >= sitetime" | last %}
|
{% assign nextevent = site.data.events | where_exp: "item", "item.date >= sitetime" | last %}
|
||||||
|
@ -23,6 +24,17 @@ nav_pill: tournament
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
<div id="xonotic-results"></div>
|
||||||
|
<script>
|
||||||
|
if(typeof d3 === 'undefined') {
|
||||||
|
document.write('<p><a href="xonscore.csv">Results</a> (allow access to d3js.org for dynamic updates)</p>');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xonoticScoreUpdate();
|
||||||
|
setInterval(xonoticScoreUpdate, 10000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<noscript><p><a href="xonscore.csv">Results</a> (Enable JavaScript for dynamic updates)</p></noscript>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No tournaments have been planned for the next event.</p>
|
<p>No tournaments have been planned for the next event.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
Reference in New Issue