Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ValveSoftware/counter-strike_regional_standings/llms.txt

Use this file to discover all available pages before exploring further.

The CS2 Regional Standings use a modified Glicko rating system to adjust team ranks based on head-to-head match results. Originally developed for chess, Glicko extends the ELO algorithm by tracking each player’s rating deviation (RD) — a measure of uncertainty in the rating. Matches are processed in chronological order, and each match’s impact on ratings is scaled by an informationContent parameter that captures how much weight that result should carry.

Key constants

// glicko.js
const Q = Math.log(10) / 400;  // ≈ 0.005756
const C = 34.6;                 // RD decay constant
  • Q — converts rank differences into win probabilities. A rank delta of 400 points corresponds to approximately a 90% win probability for the higher-rated team.
  • C — controls how quickly rating deviation grows when a team is inactive. The default configuration decays back to the maximum RD (350) after 100 time units of inactivity.

Fixed RD mode (ELO equivalent)

In the CS2 standings, Glicko is configured with a fixed RD of 75 for all teams. Fixing the RD to a single value eliminates the uncertainty dimension and makes the system behave like a standard ELO rating.
// ranking.js
const glicko = new Glicko();
glicko.setFixedRD( 75 );   // glicko -> elo
// glicko.js — setFixedRD()
setFixedRD( val ) {
    this.mStartingRD = val;
    this.mMaxRD      = val;
    this.mMinRD      = val;
    return this;
}
With a fixed RD, clampRD() always returns 75, so the RD never changes. The only variable that evolves match-to-match is each team’s rank.

Processing a single match

Every match in the dataset is processed by singleMatch(), which immediately applies the rating change for both teams after each result:
// glicko.js
singleMatch( winningTeam, losingTeam, informationContent = 1.0 ) {
    this.incrementalMatch( winningTeam, losingTeam, informationContent );
    this.finalizeMatches( [winningTeam, losingTeam] );
}
incrementalMatch calls addPendingMatch for both participants (score 1.0 for the winner, 0.0 for the loser), then finalizeMatches applies the accumulated adjustments immediately.

Rating adjustment math

The core of the Glicko update is in addPendingMatch. For each team, the algorithm computes:
// glicko.js — addPendingMatch()
addPendingMatch( otherTeam, score, info = 1.0 ) {
    const r   = this.mRank;
    const ro  = otherTeam.mRank;
    const rdo = otherTeam.mRD;

    const g  = 1 / Math.sqrt( 1 + ( 3*Q*Q*rdo*rdo / (Math.PI*Math.PI) ) );
    const ev = 1 / ( 1 + Math.pow( 10, g*(r-ro)/(-400) ) );

    this.mAdjRDSq += g*g * ev * (1-ev) * info * info;
    this.mAdjRank += g * (score - ev) * info;
}
Then applyPendingMatches converts accumulated adjustments into a new rank:
// glicko.js — applyPendingMatches()
applyPendingMatches( glicko ) {
    const rd = this.mRD;
    const adjustedRDSq = 1 / ( 1/(rd*rd) + Q*Q*this.mAdjRDSq );

    this.mRank += Q * adjustedRDSq * this.mAdjRank;
    this.mRD    = glicko.clampRD( Math.sqrt( adjustedRDSq ) );

    this.resetPendingMatches();
}
VariableDescription
rThis team’s current rank
roOpponent’s current rank
rdoOpponent’s rating deviation
gRD scaling factor — reduces the weight of matches against teams with high uncertainty
evExpected value (predicted win probability for this team)
scoreActual outcome: 1.0 for a win, 0.0 for a loss
infoInformation content — scales how much this match affects the rating
mAdjRankAccumulated rank adjustment pending across all matches in this period
mAdjRDSqAccumulated RD² adjustment pending across all matches in this period
The g factor comes from the Glicko paper by Mark Glickman (1999). It attenuates the contribution of an opponent’s result proportionally to how uncertain their rating is (their RD):
g(RD) = 1 / sqrt(1 + 3·Q²·RD² / π²)
When RD is 0, g = 1 (full weight). As RD grows, g approaches 0.The expected value ev is a logistic function of the adjusted rank difference:
ev = 1 / (1 + 10^(g·(r - ro) / -400))
This gives a 50% win probability when r == ro, and approximately 90% when r - ro == 400 (with g = 1).
Because RD is fixed at 75 for all teams, adjustedRDSq simplifies to a near-constant value that acts as a learning rate. The rank update becomes approximately:
new_rank = old_rank + Q · adjustedRDSq · Σ[ g · (score - ev) · info ]
For a win against an equal opponent (ev = 0.5, info = 1, g ≈ 1), the rank gain is roughly Q · adjustedRDSq · 0.5.

Information content

Every match carries an informationContent value passed to singleMatch. This scales how much the result moves both teams’ ranks.
// ranking.js — runMatches()
glicko.singleMatch( winTeam.glickoTeam, loseTeam.glickoTeam, match.informationContent );
Information content affects both the rank adjustment (mAdjRank += ... * info) and the RD adjustment (mAdjRDSq += ... * info * info). A match with informationContent = 0.5 moves ratings roughly half as much as a full-weight match.
When informationContent is less than 1 — for example, because a match occurred early in the time window and has been time-decayed — the match’s effect on both teams’ ratings is proportionally dampened. This means older results fade in influence without being discarded entirely.

Build docs developers (and LLMs) love