|
|
@@ -133,8 +133,17 @@
|
|
|
</div>
|
|
|
<div class="col-md-6">
|
|
|
<h6>Activity Snapshot</h6>
|
|
|
- <div class="alert alert-light">
|
|
|
- <canvas id="snapshotChart"></canvas>
|
|
|
+ <div class="alert alert-light">
|
|
|
+ <div class="row">
|
|
|
+ <div class="col-md-6">
|
|
|
+ <h6>Events over time (Snapshots)</h6>
|
|
|
+ <canvas id="snapshotChart"></canvas>
|
|
|
+ </div>
|
|
|
+ <div class="col-md-6">
|
|
|
+ <h6>Events over time (Events)</h6>
|
|
|
+ <canvas id="eventsChart"></canvas>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -250,6 +259,7 @@
|
|
|
|
|
|
let selectedShardId = null;
|
|
|
let snapshotChart = null;
|
|
|
+ let eventsChart = null;
|
|
|
|
|
|
async function refreshShardsTab() {
|
|
|
try {
|
|
|
@@ -260,6 +270,7 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* FUNCIONES PARA ACTUALIZAR LA PESTAÑA SHARDS */
|
|
|
async function loadDashboardSummary() {
|
|
|
const response = await fetch(`${API_BASE}/master/dashboard/summary`);
|
|
|
const summary = await response.json();
|
|
|
@@ -300,6 +311,7 @@
|
|
|
|
|
|
if (shard.shardId === selectedShardId) {
|
|
|
tr.classList.add("shard-selected");
|
|
|
+ loadShardDetail();
|
|
|
}
|
|
|
|
|
|
tr.addEventListener("click", () => {
|
|
|
@@ -371,9 +383,62 @@
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ async function loadShardEventsChart() {
|
|
|
+ if (!selectedShardId) return;
|
|
|
+
|
|
|
+ const res = await fetch(
|
|
|
+ `${API_BASE}/master/shards/${selectedShardId}/events/timeseries`
|
|
|
+ );
|
|
|
+ const series = await res.json();
|
|
|
+
|
|
|
+ const labels = series.map(p =>
|
|
|
+ new Date(p.timestamp).toLocaleTimeString()
|
|
|
+ );
|
|
|
+ const data = series.map(p => p.totalEvents);
|
|
|
+
|
|
|
+ if (eventsChart) eventsChart.destroy();
|
|
|
+
|
|
|
+ eventsChart = new Chart(
|
|
|
+ document.getElementById("eventsChart"),
|
|
|
+ {
|
|
|
+ type: "line",
|
|
|
+ data: {
|
|
|
+ labels,
|
|
|
+ datasets: [{
|
|
|
+ label: "Total Events (Events table)",
|
|
|
+ data,
|
|
|
+ borderColor: "red",
|
|
|
+ tension: 0.2
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
async function loadShardDetail() {
|
|
|
await loadShardPlayers();
|
|
|
await loadShardSnapshots();
|
|
|
+ await loadShardEventsChart();
|
|
|
+ }
|
|
|
+
|
|
|
+ /* FUNCIONES PARA ACTUALIZAR LA PESTAÑA PLAYERS */
|
|
|
+ async function loadPlayersGlobal() {
|
|
|
+ const res = await fetch(`${API_BASE}/master/players`);
|
|
|
+ const players = await res.json();
|
|
|
+
|
|
|
+ const tbody = document.getElementById("tablePlayers");
|
|
|
+ tbody.innerHTML = "";
|
|
|
+
|
|
|
+ players.forEach(p => {
|
|
|
+ const tr = document.createElement("tr");
|
|
|
+ tr.innerHTML = `
|
|
|
+ <td>${p.playerId}</td>
|
|
|
+ <td>${p.globalScore}</td>
|
|
|
+ <td>${p.shardsPlayed}</td>
|
|
|
+ <td>${p.totalActions}</td>
|
|
|
+ `;
|
|
|
+ tbody.appendChild(tr);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -408,6 +473,13 @@
|
|
|
// Refresco automático
|
|
|
setInterval(refreshShardsTab, REFRESH_INTERVAL_MS);
|
|
|
|
|
|
+
|
|
|
+ document.querySelector('button[data-bs-target="#tabPlayers"]')
|
|
|
+ .addEventListener("shown.bs.tab", () => {
|
|
|
+ loadPlayersGlobal();
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
</script>
|
|
|
|
|
|
</body>
|