forked from Kelder/ceneka-bot-battle
128 lines
4.2 KiB
HTML
128 lines
4.2 KiB
HTML
{% extends "header.html" %} {% block content %}
|
|
<div class="card m-5">
|
|
<div class="card-content is-size-2 has-text-centered">
|
|
Zeus Leaderboard - CeneBotBattle
|
|
</div>
|
|
</div>
|
|
<div class="columns m-5 is-gapless">
|
|
<div class="column">
|
|
<div class="card ">
|
|
<div class="card-content" style="height: 1000px">
|
|
<canvas id="le_graph" width="300" height="150" style="height: 100%;width:100%"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="column ml-5 is-one-third">
|
|
<div class="card">
|
|
<div class="card-content">
|
|
<table class="table is-fullwidth is-size-4">
|
|
<thead>
|
|
<tr>
|
|
<th>Position</th>
|
|
<th>Name</th>
|
|
<th>Elo</th>
|
|
<th>Username</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="leaderboard-body">
|
|
{% for row in data %}
|
|
<tr>
|
|
<td>{{ row['global_position'] }}</td>
|
|
<td>{{ row['name'] }}</td>
|
|
<td>{{ row['elo'] }}</td>
|
|
<td>{{ row['username'] }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
|
async function fetchLeaderboardData() {
|
|
try {
|
|
const response = await fetch("/leaderboard");
|
|
if (!response.ok) return;
|
|
|
|
const data = await response.json();
|
|
|
|
const tableBody = document.getElementById("leaderboard-body");
|
|
|
|
tableBody.innerHTML = "";
|
|
|
|
data.forEach((row) => {
|
|
const tr = document.createElement("tr");
|
|
tr.innerHTML = `
|
|
<td>${row.global_position}</td>
|
|
<td>${row.name}</td>
|
|
<td>${row.elo}</td>
|
|
<td><span class="tag is-large" style="background-color: ${row.color_ring}">${row.username}</span></td>
|
|
`;
|
|
tableBody.appendChild(tr);
|
|
});
|
|
} catch (error) {
|
|
console.error("Failed to fetch leaderboard data:", error);
|
|
}
|
|
}
|
|
|
|
function getX(width, margin, min_game, max_game, game) {
|
|
return ((game - min_game) / (max_game - min_game) * (width - margin * 2)) + margin
|
|
}
|
|
|
|
function getY(height, margin, min_elo, max_elo, elo) {
|
|
return (height - ((elo - min_elo) / (max_elo - min_elo) * (height - margin * 2))) - margin
|
|
}
|
|
|
|
async function draw_graph() {
|
|
let canvas = document.getElementById('le_graph')
|
|
let ctx = canvas.getContext("2d")
|
|
|
|
try {
|
|
let res = await fetch("/graph")
|
|
let graph_data = await res.json()
|
|
|
|
let bots = graph_data.bots
|
|
|
|
resizeToParent(canvas)
|
|
|
|
const width = canvas.width
|
|
const height = canvas.height
|
|
const margin = 20
|
|
|
|
for (const [_, bot] of Object.entries(bots)) {
|
|
ctx.lineWidth = 4
|
|
ctx.strokeStyle = bot.color_ring
|
|
ctx.beginPath()
|
|
ctx.moveTo(getX(width, margin, 0, graph_data.game, bot.x[0]), getY(height, margin, graph_data.min_elo, graph_data.max_elo, bot.y[0]))
|
|
for (let i = 1; i < bot.x.length; i++) {
|
|
ctx.lineTo(getX(width, margin, 0, graph_data.game, bot.x[i]), getY(height, margin, graph_data.min_elo, graph_data.max_elo, bot.y[i]))
|
|
}
|
|
ctx.stroke()
|
|
}
|
|
} catch (err) {
|
|
console.log("Failed to fetch graph data:", err)
|
|
}
|
|
}
|
|
|
|
function resizeToParent(canvas) {
|
|
/* https://stackoverflow.com/questions/70128894/how-to-force-a-canvas-size-to-real-size-of-a-window-in-pixels-disregarding-the */
|
|
canvas.width = canvas.clientWidth * window.devicePixelRatio;
|
|
canvas.height = canvas.clientHeight * window.devicePixelRatio;
|
|
}
|
|
|
|
// Poll the server every 60 seconds
|
|
setInterval(fetchLeaderboardData, 60_000);
|
|
setInterval(draw_graph, 60_000);
|
|
|
|
// Initial load
|
|
fetchLeaderboardData();
|
|
draw_graph();
|
|
</script>
|
|
|
|
{% endblock %}
|