Skip to content

Leaderboards: search the board by name, alias or SteamID - #36

Open
jbob06 wants to merge 1 commit into
warcon-app:mainfrom
jbob06:leaderboard-search
Open

jbob06 wants to merge 1 commit into
warcon-app:mainfrom
jbob06:leaderboard-search

Conversation

@jbob06

@jbob06 jbob06 commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

What

A search field on the Leaderboards tab and on the public board, working like the Players tab's search: the board reloads 300 ms after typing stops, from page one, with q in the query and in the URL, so a search can be linked.

Ranks stay put

A search narrows the rows, never their ranks. boardSlice now ranks every row on the whole board first, using ROW_NUMBER() over the same order the board already sorted by (the metric, then kills, then SteamID). The search filters those rows, and only then is the page sliced. So a player in 37th place is found as #37, not #1. total, and with it the "N players" line and the pager, counts the matches. shapeRow reads the rank from the row instead of computing it from the page offset.

With no search the filter is TRUE, so the board, its ranks and its export come out as before. The existing career and board-export suites pass unchanged.

What a search matches depends on who is looking

  • Panel (/api/servers/:id/leaderboard, export): any name the player used on these servers, matched anywhere in it, and digits also match the start of a SteamID. This is the Players tab's rule from seen.ts.
  • Public board (/s/:id/leaderboard and /api/public/.../leaderboard): only the name the board shows, the last one. A public board does not show SteamIDs or old names, so a search there cannot be used to tie either to a player. loadBoard takes an optional { public: true } for this, and both public reads pass it.

% and _ are escaped with the same likeEscape as seen.ts. q is trimmed and kept to 100 characters (BOARD_SEARCH_MAX), and it is left out of the URL when empty.

UI

The field sits after the playtime floor, at the controls' height. The placeholder is "Name, alias or SteamID…" on the panel and "Name…" on a public board, following showIds. The count reads "N players matching" while a search is on, and an empty result says "Nobody on this board matches “…”." instead of the floor or range message.

Tests

  • src/lib/leaderboard.test.ts: q is parsed, trimmed, capped and round-tripped, and dropped when empty.
  • src/test/board-search.test.ts (database): no search ranks from the top; a match keeps its rank and the total counts matches; the panel finds an old name, a full SteamID and a SteamID prefix; a public board finds the shown name but not the old name or the SteamID; % and _ are literal.

CI on my fork, with the TimescaleDB service as in ci.yml: lint, check and bun test all green, 853 pass, 0 fail, including the five new database tests. That run was jbob06#1, opened only for CI and now closed.

Note

This touches the same files as #25 (sortable HS and TK columns), but different lines. Whichever lands second may need a small rebase.

🤖 Generated with Claude Code

https://claude.ai/code/session_011wkaN3kHsCQGhxCxeAqERQ

The Leaderboards tab and the public board get a search field, like the
Players tab's: typing pauses for 300 ms, then the board reloads from page
one with `q` in the query (and the URL, so a search can be linked).

A search narrows the rows and never their ranks. Every row is ranked on the
whole board first (ROW_NUMBER over the same order the board already used),
then the search filters, then the page is sliced, so a player in 37th place
is found as warcon-app#37, not #1. The total and the pager count the matches.

What matches depends on who is looking, as with the rest of the board:
- the panel matches any name a player used on these servers, anywhere in
  it, and digits also match the start of a SteamID (the Players tab's
  rule);
- a public board matches only the name it shows, the last one, so a search
  there cannot tie a SteamID or an old name to a player.

`%` and `_` are escaped, as in seen.ts. The export follows the search too,
since it writes "the board as it is set". With no search the query is the
one it was, and ranks come out the same.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011wkaN3kHsCQGhxCxeAqERQ
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