feat: add scoreboard with player names, per-category leaderboards, and themed tables

Add player_name column to games (migration included), with regex-based
validation and anti-abuse sanitization. New /scoreboard page shows recent
games from localStorage, popular categories with play counts, and top-10
per-category leaderboards sorted by completion time. Also includes
two-click reverse word matching, base URL prefix support for reverse-proxy
hosting, BasePageHandler refactoring, themed table CSS for all 5 themes,
and comprehensive test coverage for player names and scoreboard API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Mathew Sir Guest the best
2026-05-07 10:38:19 -06:00
co-authored by Claude Opus 4.6
parent 9319f08875
commit 36c3c712fe
27 changed files with 3038 additions and 24 deletions
+7 -7
View File
@@ -19,12 +19,12 @@
})();
</script>
</head>
<body>
<body data-base-url="{{ base_url }}">
{% block active_page %}{% end %}
<nav class="navbar navbar-expand-lg">
<div class="container">
<a class="navbar-brand" href="/">
<a class="navbar-brand" href="{{ base_url }}">
<i class="bi bi-search"></i> Word Search
</a>
<button class="navbar-toggler" type="button"
@@ -35,31 +35,31 @@
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link {% if active_page == 'home' %}active{% end %}"
href="/">
href="{{ base_url }}">
<i class="bi bi-house-door"></i> Home
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if active_page == 'play' %}active{% end %}"
href="/game">
href="{{ base_url }}game">
<i class="bi bi-controller"></i> Play
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if active_page == 'howtoplay' %}active{% end %}"
href="/howtoplay">
href="{{ base_url }}howtoplay">
<i class="bi bi-question-circle"></i> How to Play
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if active_page == 'scoreboard' %}active{% end %}"
href="/scoreboard">
href="{{ base_url }}scoreboard">
<i class="bi bi-trophy"></i> Scoreboard
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if active_page == 'about' %}active{% end %}"
href="/about">
href="{{ base_url }}about">
<i class="bi bi-info-circle"></i> About
</a>
</li>
+1 -1
View File
@@ -12,6 +12,6 @@
Find hidden words in a grid of letters. Words can appear horizontally,
vertically, or diagonally. How fast can you find them all?
</p>
<a href="/game" class="btn btn-accent btn-lg px-5">🎮 Start Game</a>
<a href="{{ base_url }}game" class="btn btn-accent btn-lg px-5">🎮 Start Game</a>
</header>
{% end %}
+1 -1
View File
@@ -48,7 +48,7 @@
<div id="scoreboard-empty" class="d-none text-center py-4">
<p class="text-muted fs-5">No completed games yet. Be the first to finish a puzzle!</p>
<a href="/game" class="btn btn-accent">Start a Game</a>
<a href="{{ base_url }}game" class="btn btn-accent">Start a Game</a>
</div>
<script src="{{ static_url('js/scoreboard.js') }}"></script>