Skip to content

Add global leaderboards#59

Merged
vicplusplus merged 9 commits intomainfrom
global-leaderboards
Apr 3, 2026
Merged

Add global leaderboards#59
vicplusplus merged 9 commits intomainfrom
global-leaderboards

Conversation

@vicplusplus
Copy link
Copy Markdown
Owner

Summary

  • Server-side replay verification (ReplayVerifier) validates replays by regenerating the board from seed, comparing to snapshot, and simulating clear events
  • Score submission with idempotency, rate limiting (10/hour), and top-50 snapshot management (gzip-base64 compression, eager displacement stripping)
  • Leaderboard endpoints: per-size top-50, cross-size "All" ranking, player entry with rank context, replay fetch
  • Client global tab in leaderboard scene with server fetch, player panel, refresh button, replay playback (decompresses snapshots for top-50, regenerates from seed for others, saves locally for instant subsequent loads)
  • Silent score submission during victory animation with toast notification and retry on failure
  • Victory modal decluttered: removed "New Best!" label (gold timer suffices)

Bug fixes

  • ReplayPlayer/ReplayRecorder handle orphan session_rejoin (no prior session_leave from force-quit)
  • ReplayPlayer handles legacy replays without start_solve event
  • Replay viewer: seek bar no longer passes input through to camera pan; play button centered; controls bar blocks camera input
  • Cleaned up stale deadEndLimit parameter from PerformanceTests and TestBoardHelper

Infrastructure

  • Score model with EF Core migration, unique index per (user, board size), time index for fast ranking
  • docker-compose.dev.yml for local PostgreSQL
  • .env-based local dev config (replaces user-secrets approach)
  • seed-leaderboard.js for populating test data
  • 14 new server integration tests (ScoresTests), 10 new Unity EditMode tests (ReplayVerifierTests), 2 new ReplayPlayer tests

Test plan

  • Manual: 19 test cases covering submission, retry, global tab states, replay playback, cross-device
  • Automated: Server integration tests (61 total), Unity EditMode tests (ReplayVerifier + ReplayPlayer)
  • Deploy to staging and verify migration + endpoint health
  • Verify WebGL build submits scores correctly

🤖 Generated with Claude Code

vicplusplus and others added 9 commits March 31, 2026 21:01
Simplify ReplayVerifier to 4-step verification (regenerate + compare
snapshot, walk clears, verify empty, compute time from events). Remove
deadEndLimit references (removed from codebase). Replace OnlineController
MonoBehaviour with static ScoreSubmitter helper. Remove inline victory
leaderboard. Add totalEntries to leaderboard response DTOs. Renumber
phases 6-10 to 6-9.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server: ReplayVerifier validates replays by regenerating the board from
seed, comparing to snapshot, and simulating all clear events. GameService
handles submission with idempotency, rate limiting, and top-50 snapshot
management. LeaderboardService provides per-size and cross-size rankings
with totalEntries. Score model with EF migration, 6 new API endpoints.

Client: ApiClient extended with score/leaderboard/replay methods.
ScoreSubmitter fires submission silently during victory animation with
toast notification on failure and retry. LeaderboardScreenController
global tab with server fetch, player panel, refresh icon, replay
playback, and snapshot decompression. ReplayViewController regenerates
boards from seed for non-top-50 replays and saves locally for instant
subsequent loads.

Fixes: ReplayPlayer/ReplayRecorder handle orphan session_rejoin (no
prior session_leave from force-quit). ReplayPlayer handles legacy
replays without start_solve event. PerformanceTests cleaned up for
removed deadEndLimit parameter.

UI: Victory modal decluttered (removed New Best label, gold timer
suffices). Submission toast in victory overlay. Leaderboard player panel
with play button. Circular refresh icon in tab bar. Replay viewer play
button centered, controls bar blocks camera input pass-through.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, and others

TechnicalDesign: Fix VictoryController (gold timer styling, not "New
Best!" label; toast not inline note). Fix SettingsController (singleton
with auto-bootstrap, not manual per-scene setup). Fix ReplayData version
description (defaults to 1, set to 3 by recorder).

OnlineRoadmap: Remove stale DeadEndLimit from Score model. Mark all
endpoints and tests as done (were still "planned"). Update test count
from 38 to 61. Update VictoryController description.

CLAUDE.md: Fix VictoryController (gold timer, ScoreSubmitter, toast).
Add ScoreSubmitter and ApiClient leaderboard descriptions. Update
LeaderboardScreenController (global tab) and ReplayViewController
(seed-restore path).

BoardGeneration.md: Remove deadEndLimit from function signatures.

LocalServerSetup.md: Rewrite for .env-based config (replaces user
secrets approach). Add docker-compose.dev.yml instructions, leaderboard
endpoints table, seed script usage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
EditMode: ReplayRecorderTests.Resume_ContinuesSeqFromNextSeq expects
4 events (injected session_leave + session_rejoin) instead of 3.

PlayMode: Rename Victory_NewBestAndLeaderboard to Victory_GoldTimer,
remove assertion on deleted new-best-label element.

Server: SubmitValidReplay asserts rank > 0 (not exact 1) since tests
share a DB. GetLeaderboard uses isolated 5x5 board size. MalformedJson
expects 400 (service returns BadRequest). RateLimit test skipped (needs
separate counter, not row-based).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vicplusplus vicplusplus merged commit 6cfba72 into main Apr 3, 2026
4 checks passed
@vicplusplus vicplusplus deleted the global-leaderboards branch April 3, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant