This page walks through the complete pipeline that transforms raw match data into the published CS2 Regional Standings. Each stage builds on the previous one: data is loaded and cleaned, teams are identified and seeded, ratings are updated match by match, and the final ranked tables are written to disk. The entry point is a single function call: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.
-1 as the version timestamp tells the model to use the most recent match in the dataset as the cutoff. The function returns the filtered match list and the fully-ranked team list, which are then handed to Report.generateOutput to produce the markdown files.
Data ingestion
The model reads Filters applied in order:
matchdata.json from disk and applies a series of filters to remove data that should not influence rankings.- Incomplete matches — any match where either team does not have exactly 5 players recorded is dropped. This ensures only full 5v5 results are counted.
- Unranked matches — matches after 1 January 2025 must carry an explicit
valveRanked: trueflag. Earlier matches are included unconditionally. - Showmatches — any event whose name contains the word “showmatch” (case-insensitive) is excluded entirely.
- In-progress events — matches belonging to events where
finishedisfalseare removed. Only completed events count.
These filters run before the time window is applied, so they affect which matches are even considered when computing the rolling window boundaries.
Time windowing
After filtering, the model determines the date range of matches to include.The end time is either the explicit version timestamp passed to Matches outside this window are discarded. Within the window, a grace period of one month is applied to the time-decay weighting: matches in the final month before the cutoff receive full weight, while older matches decay toward zero as they approach the start of the window.
generateRanking, or the timestamp of the most recent remaining match. The start time is exactly 6 months (6 × 30 × 24 × 3600 seconds) before the end time.The grace period prevents a cliff-edge effect where a match played one day before the window boundary is worth nearly nothing. Matches near the cutoff still carry close to full weight.
Team initialization and roster deduplication
Teams are not tracked by a static team ID. Instead, the model builds roster identities from the players who actually played in each match.Matches are first sorted in reverse chronological order so that the most recent lineup is treated as the canonical roster for a given team identity. As the model walks backward through matches, a new roster entry is created whenever no existing roster shares at least 3 players with the incoming match lineup.This mirrors the Major qualification rules: a roster that retains at least 3 players from a previous lineup is treated as the same competitive entity and inherits that lineup’s match history.After all rosters are identified, their active rosters are determined by looking at the most recent 10 matches and selecting up to 5 players who each appeared in at least 5 of those matches.Once roster identity is established, matches are re-sorted into forward chronological order for the rating run.
Seeding calculation
Before any head-to-head results are processed, every roster receives a seed rank based on their historical performance. Seeding uses four factors, each weighted equally:
All factors cap their raw values against the Nth highest value across all teams (where N = 5), preventing a single outlier team from compressing the rest of the field.The four modifier values are averaged into a single
| Factor | Description |
|---|---|
| Bounty offered | Prize winnings earned, scaled by event age and capped at the 5th-highest value across all teams |
| Bounty collected | Quality of opponents defeated, measured by their own prize winnings |
| Opponent network | Breadth of the opponent pool beaten, counting only the most recent win against each opponent |
| LAN wins | Wins recorded at LAN events, scaled by event age; top 10 results only |
seedValue. That value is then linearly remapped onto a 400–2000 point scale:Only the top 10 results contribute to bounty collected, opponent network, and LAN wins. Playing in a low-stakes match can never hurt a team’s seed — it can only add a small positive contribution if it ranks in the top 10.
Glicko rating run
With seed ranks established, the model processes every match in forward chronological order through a modified Glicko rating system. The rating deviation (RD) is fixed at 75, which reduces the system to standard Elo-style updates with consistent step sizes.For each match, the winner gains rating points and the loser loses them. The magnitude of the adjustment depends on the difference between the two teams’ current ratings and the match’s information content — a multiplier between 0 and 1 that reflects how recent the match is within the time window.After all matches are processed, each team’s final Glicko rank is stored as their
rankValue.Filtering ranked teams
Two filters determine which teams appear in the published standings:
- No wins — teams with
distinctTeamsDefeated === 0are removed entirely. A team must have beaten at least one opponent to appear at any rank. - Ranking criteria — teams must have played at least 5 matches to receive a global or regional rank number. Teams with fewer matches remain in the data (their rank value is computed) but are not assigned a standing position.
Regional assignment
Each team is assigned to a region based on the plurality nationality of its active roster players. The model counts how many active roster players belong to each of the three regions (Europe, Americas, Asia), and assigns the team to whichever region has the most representation.Players whose nationality is listed as
"world" or maps to no known region are assigned to the lowest-priority region with any other representation on the roster.Teams can appear in more than one region if the representation is exactly tied — the region array stores a 1 for each region the team belongs to.Global and regional rank numbers are then assigned by iterating over teams sorted by rankValue descending, incrementing each counter only for teams that satisfy the ranking criteria.Output generation
The final step writes the standings to disk as markdown files.
Report.generateOutput produces:- Four standings tables per run: global, Europe, Americas, and Asia. Each is a markdown table with columns for standing, points, team name, active roster, and a link to the per-team detail page.
- Per-team detail pages for every team with a global rank, saved under
details/<date>/. Each page shows the team’s starting rank value, the formula breakdown, and a full match-by-match table listing age weight, event weight, bounty collected, opponent network, LAN wins, and Glicko adjustment for every match played.
live/<year>/ directory are always updated. Files written to the invitation/<year>/ directory are only updated when the run date falls in the first 7 days of the month — this is the periodic snapshot used for invitation decisions.The per-team filename encodes global rank, team name, and active roster player nicks — for example,
0001--natus-vincere--b1t-electronic-iм-jl-w0nderful.md. This makes individual pages directly linkable and diff-friendly in version control.