Appearance
Ranking Algorithm
RankHub uses the Glicko-2 rating system to compute rankings from pairwise votes. This page describes the algorithm and the integer storage conventions used in the codebase.
Overview
Glicko-2 improves on the original Glicko and Elo systems by introducing an explicit volatility parameter and a more robust rating update procedure. Every item has three metrics:
| Metric | Symbol | Default | Range |
|---|---|---|---|
| Rating | $\mu$ | 1500.00 | 0.00 -- 3000.00 |
| Rating Dev. | $\phi$ | 350.00 | 1.00 -- 350.00 |
| Volatility | $\sigma$ | 0.06 | 0.000001 -- 1.0 |
Step 1: Convert to Glicko-2 Scale
Before computing updates, ratings and RDs are converted to the Glicko-2 scale:
$$\mu = \frac{r - 1500}{173.7178}$$
$$\phi = \frac{RD}{173.7178}$$
Step 2: Compute g(phi)
The scale factor reduces the impact of high-uncertainty opponents:
$$g(\phi) = \frac{1}{\sqrt{1 + \frac{3\phi^2}{\pi^2}}}$$
Step 3: Compute Expected Score
The expected score of item $i$ against opponent $j$:
$$E(\mu_i, \mu_j) = \frac{1}{1 + \exp(-g(\phi_j)(\mu_i - \mu_j))}$$
Scores are 1 for a win, 0 for a loss.
Step 4: Compute Variance
The variance of the ratings based on the game outcomes:
$$v = \left(\sum_{j=1}^{n} g(\phi_j)^2 \cdot E_j \cdot (1 - E_j)\right)^{-1}$$
Step 5: Determine New Volatility
Volatility is updated using the Illinois algorithm (a modified regula falsi method) to solve:
Let $x = \ln(\sigma'^2)$. The objective function solved by Illinois is:
$$f(x) = \frac{e^x(\Delta^2 - \phi^2 - v - e^x)}{2(\phi^2 + v + e^x)^2} - \frac{x - a}{\tau^2}$$
where $a = \ln(\sigma^2)$.
where:
$$\Delta = v \cdot \sum_{j=1}^{n} g(\phi_j)(s_j - E_j)$$
The algorithm iterates until convergence (tolerance $< 10^{-7}$ in Glicko-2 units), with a hard cap of 100 iterations.
Step 6: Update Rating and RD
$$\phi^* = \sqrt{\phi^2 + \sigma_{new}^2}$$
$$\phi_{new} = \frac{1}{\sqrt{\frac{1}{(\phi^*)^2} + \frac{1}{v}}}$$
$$\mu_{new} = \mu + \phi_{new}^2 \cdot \sum_{j=1}^{n} g(\phi_j)(s_j - E_j)$$
Finally, convert back from Glicko-2 scale to display values:
$$r_{new} = 173.7178 \cdot \mu_{new} + 1500$$
$$RD_{new} = 173.7178 \cdot \phi_{new}$$
Integer Storage Convention
To ensure deterministic results across Cloudflare isolate boundaries (which use 64-bit floats), all Glicko-2 metrics are stored as integers:
| Metric | Display Format | Storage Format | Multiplier |
|---|---|---|---|
| Rating | 1500.00 | 150000 | x 100 |
| RD | 350.00 | 35000 | x 100 |
| Volatility | 0.06 | 60000 | x 10^6 |
Conversion helpers are provided in @repo/engine:
ratingToDisplay(value)-- storage integer to display floatratingToStorage(value)-- display float to storage integerrdToDisplay(value)/rdToStorage(value)volatilityToDisplay(value)/volatilityToStorage(value)
System Constants
| Constant | Storage Value | Display Value |
|---|---|---|
| Initial rating | 150000 | 1500.00 |
| Initial RD | 35000 | 350.00 |
| Initial volatility | 60000 | 0.06 |
| System constant (tau) | 50000 | 0.50 |
Numerical Stability
- Minimum variance enforced at 0.0001 to prevent division by near-zero.
- Convergence tolerance for the Illinois algorithm: $10^{-7}$ in Glicko-2 units.
- All arithmetic uses integer operations where possible to avoid floating-point divergence between isolates.