A raw score is almost useless on its own. "You scored 74" — good? bad? The number people actually understand is a percentile: where do I sit relative to everyone else. Building that ranking layer was more interesting than I expected.
The naive version breaks fast. The textbook definition of a percentile is "the fraction of the population scoring below you." The obvious implementation is: pull every score, sort, find your position. That's fine for a demo and miserable in production — you don't want to load and sort an ever-growing table on every result page.
Streaming quantiles fix it. Instead of storing raw scores forever, I keep a compact summary per game type using a t-digest — a data structure that estimates quantiles from a stream with tight accuracy at the tails (which is exactly where percentile questions get interesting: the 95th matters more than the 50th). New scores update the digest; querying a percentile is cheap and O(1)-ish. You trade a sliver of precision for not hauling around the whole dataset.
The cold-start problem is the real trap. Early on you don't have a population. Your first user can't meaningfully be "in the 60th percentile of 12 people." I handled this by:
- seeding each game with a modelled reference distribution based on published norms, then
- blending toward the empirical distribution as real data accumulated, and
- hiding the percentile entirely below a minimum-N threshold, showing a raw breakdown instead so I wasn't lying with confidence. Interpolate, or your numbers look chunky. With discrete data, exact-match percentiles jump in ugly steps. Linear interpolation between the two nearest ranked points smooths it into something that reads as a real, continuous score.
The general lesson: "show me where I rank" sounds like one line of SQL and is actually a small system — a summary structure, a norming strategy, and a rule for what to show when you don't know enough yet.
I built this ranking layer for CogniPrep, a practice platform for psychometric assessments. https://cogniprep.app if you want to see it in action.
Top comments (0)