Autosave: 20260325-174136

This commit is contained in:
Flatlogic Bot 2026-03-25 17:41:36 +00:00
parent 342ba02e74
commit 1a199bfeb2
2 changed files with 68 additions and 1 deletions

View File

@ -11,6 +11,15 @@ run_migrations();
try {
$method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET'));
header('Allow: GET, POST, HEAD, OPTIONS');
if ($method === 'OPTIONS') {
jsonResponse(['success' => true], 204);
}
if ($method === 'HEAD') {
listScores((int) ($_GET['limit'] ?? 10), false);
}
if ($method === 'GET') {
listScores((int) ($_GET['limit'] ?? 10));
@ -106,7 +115,7 @@ function saveScore(array $payload): void
]);
}
function listScores(int $limit = 10): void
function listScores(int $limit = 10, bool $includeBody = true): void
{
$limit = max(1, min(25, $limit));
@ -136,6 +145,11 @@ function listScores(int $limit = 10): void
];
}
if (!$includeBody) {
http_response_code(200);
exit;
}
jsonResponse([
'success' => true,
'scores' => $scores,

View File

@ -634,6 +634,59 @@ document.addEventListener('DOMContentLoaded', () => {
: 'Just now';
}
function escapeHtml(value) {
return String(value ?? '')
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function renderScoreboard() {
if (!ui.scoreboardList || !ui.scoreboardEmpty) return;
if (!Array.isArray(scoreboardEntries) || scoreboardEntries.length === 0) {
ui.scoreboardList.innerHTML = '';
ui.scoreboardEmpty.classList.remove('d-none');
return;
}
ui.scoreboardEmpty.classList.add('d-none');
ui.scoreboardList.innerHTML = scoreboardEntries.map((entry, index) => {
const playerName = escapeHtml(entry.player_name || 'Player');
const scoreLabel = Number(entry.score || 0).toLocaleString();
const levelLabel = Number(entry.level || 0).toString();
const linesLabel = Number(entry.lines || 0).toString();
const modeLabel = entry.mode === 'multiplayer' ? 'Multiplayer' : 'Solo';
const durationLabel = formatDuration(Number(entry.duration_seconds || 0) * 1000);
const createdAt = entry.created_at
? new Date(String(entry.created_at).replace(' ', 'T')).toLocaleString([], {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})
: 'Just now';
const roomCode = entry.room_code ? ` · Room ${escapeHtml(entry.room_code)}` : '';
return `
<article class="scoreboard-item">
<div class="scoreboard-rank">#${index + 1}</div>
<div class="scoreboard-item-body">
<div class="scoreboard-topline">
<span class="scoreboard-name">${playerName}</span>
<span class="scoreboard-score">${scoreLabel}</span>
</div>
<div class="scoreboard-meta">Level ${levelLabel} · Lines ${linesLabel} · ${durationLabel}</div>
<div class="scoreboard-meta">${modeLabel}${roomCode} · ${createdAt}</div>
</div>
</article>
`;
}).join('');
}
async function loadScoreboard(options = {}) {
if (!ui.scoreboardStatus) return;
const preserveOnError = Boolean(options.preserveOnError);