109 lines
7.0 KiB
Markdown
109 lines
7.0 KiB
Markdown
# Leaderboard
|
||
|
||
Open **Leaderboard** in the main navigation to compare players across the fleet,
|
||
with one entry per GUID combining Black Ops I (T5) and Black Ops II (T6). Game
|
||
and map filters limit which matches contribute to each player's statistics and
|
||
rank. Choose a ranking, search a name or GUID, and share the page URL with its
|
||
filters intact. Results refresh while the page is visible.
|
||
Matches only appear in server/global history and leaderboard map options once
|
||
they reach round 2. Player records only contribute to leaderboards, summaries,
|
||
profiles and player history once that player is observed at round 2 or later.
|
||
This also excludes existing round 1 records. Early telemetry is retained so
|
||
qualifying games keep their start time, roster and cumulative counters.
|
||
|
||
Click a player's name to open their shareable profile at
|
||
`/leaderboard/players/[guid]`. Profiles combine Black Ops I (T5) and Black Ops II
|
||
(T6) records for the same GUID. Existing `/leaderboard/players/[game]/[guid]`
|
||
links redirect to the combined profile. Profiles show all ten lifetime statistics,
|
||
headshots as a percentage of kills, kills per down, average kills and observed
|
||
rounds per game, and completion rate. Each map has its own complete set of
|
||
records; map records and match history identify their game. Match history shows
|
||
individual counters, server, date and completion credit in pages of 25 matches
|
||
across both games. Map names link back to that map's leaderboard in its game.
|
||
Use **Refresh stats** to load the latest reports. Ratios with a zero denominator
|
||
display a dash. Profiles always cover all recorded maps across both games.
|
||
|
||
The leaderboard uses the existing three telemetry events; no reporter change is
|
||
required. The leaderboard and profiles identify a player by **GUID**, displaying
|
||
the latest reported name across both games, regardless of game or map filters.
|
||
Different names for the same GUID do not split their leaderboard entry or
|
||
profile; identical names with different GUIDs remain separate. Stored player
|
||
records remain keyed by **game + GUID** for telemetry ingestion; the combined
|
||
leaderboard and profiles require no storage migration. GUIDs stay strings.
|
||
|
||
## Recorded statistics
|
||
|
||
| Statistic | Meaning |
|
||
| --- | --- |
|
||
| Highest round | Highest round reported with that player present, including players who joined mid-game. |
|
||
| Total kills, headshots, revives, downs | Sum of each player's highest reported counter in each game. Round snapshots are cumulative, so they are never added together within a game. |
|
||
| Total rounds | Round progression during observed participation, added across games. A player observed at game start and then round 8 receives seven rounds. A player first seen at round 8 gets a highest-round record of 8, but zero total rounds; reaching round 9 then adds one. |
|
||
| Games played | Games in which a stats report at round 2 or later contains the player. Start-only and round 1 participation do not count. |
|
||
| Games completed | Games whose `game_end` roster contains the player. Disconnected players retain earlier stats without receiving completion credit. |
|
||
| Best game kills | Highest kill count recorded in any one game. |
|
||
| Highest reported score | Highest observed score balance. Spending points can lower the score, so this is not cumulative points earned. |
|
||
|
||
Every ranking sorts highest first, including downs (a count, not an efficiency
|
||
rating). Equal values share a rank; name and GUID provide a stable display order.
|
||
Searching preserves the player's rank for the selected game/map filters, or
|
||
across both games when unfiltered. Summary cards describe the same selection,
|
||
regardless of the search text. Player counts include each qualifying GUID once,
|
||
including when they have records in both games. Summary rounds are
|
||
player-rounds: four players progressing from game start to round 8 contribute 28.
|
||
Highest-round records always use the round reached, including the final round
|
||
and players who joined mid-game.
|
||
|
||
Round totals require the player to appear in consecutive observations. If a
|
||
report omits them, their return starts a new participation interval and the gap
|
||
is not credited. The payload cannot tell whether a present player was alive,
|
||
spectating, or absent between reports. Mid-game snapshots still contribute their
|
||
reported kills and other counters, even when earlier participation is unknown.
|
||
|
||
## Persistence and match boundaries
|
||
|
||
Match and player records live in SQLite alongside the rest of Electric Cherry.
|
||
They persist across app restarts and server deletion, and are not subject to
|
||
campaign history retention. The latest scoreboard and leaderboard update in the
|
||
same transaction. Each match keeps player counters even after someone leaves.
|
||
|
||
A `game_start` opens a match; `game_end` completes it. A changed map, a lower round,
|
||
or a round report after a completed game can also establish a new match when the
|
||
start was missed. Superseded active matches remain in history as interrupted.
|
||
Repeated starts before any stats belong to the same match. Identical consecutive
|
||
payloads (ignoring receipt time and roster order) do not add records. Repeated
|
||
snapshots in a match cannot increase counters or rounds twice.
|
||
|
||
The first upgrade imports the latest stored full scoreboard from each server
|
||
once. That provides the available counters and highest round, but not discarded
|
||
earlier games or unobserved round progression. Old round-only snapshots have no
|
||
player identity and cannot be imported. Tracking continues from future reports.
|
||
|
||
T6 selections sharing an engine map, such as Town Survival and TranZit, remain
|
||
separate using the server's registered map variant. Unknown variants remain
|
||
explicitly identified instead of being labeled as a known selection. A match
|
||
retains the game/map identity recorded at ingestion even if the server is later
|
||
reconfigured or removed.
|
||
|
||
The current protocol sends events in gameplay order and has no match ID, event
|
||
ID, or source sequence. A late report from an older game cannot be reliably
|
||
distinguished from a new game. Likewise, identical starts before any stats are
|
||
indistinguishable from retries. Send reports once in order. Within a match,
|
||
counter decreases use the previous high-water mark; if a reconnect resets a
|
||
player's counters, subsequent activity may be undercounted until those counters
|
||
pass their earlier maxima. Exact replay handling and counter-reset accounting
|
||
would require additional reporter identity/ordering information.
|
||
|
||
## Read API
|
||
|
||
`GET /api/leaderboard` accepts optional `game` (`t5` or `t6`), `map` (the opaque
|
||
key returned in `maps`), `metric` (default `highestRound`), `q` (name/GUID search),
|
||
`limit` (1–100, default 50), and `offset` (default 0). It returns ranked `entries`,
|
||
available `maps`, the matching player `total`, pagination values, and `summary`.
|
||
Each entry represents one GUID and combines its qualifying matches within the
|
||
game/map filters. Entries have no game field; map options retain their game
|
||
identity. Both `total` and `summary.players` count unique GUIDs; only `total` is
|
||
limited by the player search.
|
||
|
||
Metric keys are `highestRound`, `kills`, `roundsSurvived`, `headshots`, `revives`,
|
||
`downs`, `gamesPlayed`, `gamesCompleted`, `bestKills`, and `bestScore`.
|