Skip to content

ELO Tier System — Cross-Rating Mapping Specification

Status: Active
Last updated: 2026-06-21
Related: elo-rating.md · progression-system.md · international-data-model.md


Design Principles

  1. Honest mapping — Korean 동호인 levels are mapped conservatively to NTRP/UTR. No inflation.
  2. Dense where it matters — 80% of Korean recreational players sit in NTRP 2.5–4.5. The ELO range is dense there.
  3. Headroom above — The scale extends to NTRP 7.0 / UTR 16 for international expansion and 선수출신, even though current users will never reach it.
  4. Sub-tiers for granularity — Each tier has III (bottom), II (mid), I (top) sub-tiers. Players see incremental progress within a tier.
  5. ELO is relative — It measures you against the people you play. The absolute number only matters for tier placement.
  6. Rating integrity — A self-assessed seed is a provisional suggestion, never a verified rating. Competitive gating applies only to players with a trusted, play-verified rating.

The 5-Tier System

Single source of truth

The canonical definitions live in packages/app/src/domain/rules/tier.config.ts (TIER_DEFINITIONS array and EloTier type). The server-side cut points mirror this in private.tier_index_from_elo / private.tier_from_elo (migration 00235_tier_at_match_time.sql). Both use the same four boundaries: 900 / 1400 / 2000 / 2500. There are exactly five tiers: bronze | silver | gold | master | grandmaster.

There is no platinum tier and no diamond tier. Those names appeared in an earlier draft; they were removed before launch (migrations 00151 + 00229 pin the 5-tier CHECK constraint on profiles.display_tier and clubs.min/max_tier). Any documentation or code that references platinum or diamond describes a dead state.


Step 1: The Full ELO Range

Scale Design

ZoneELO RangeWho Is HereNotes
Floor400–900Bronze — theoretical minimum to Silver entryTrue beginners. Almost nobody stays near 400 long.
Korean 동호인 bulk900–200095%+ of Korean recreational playersSilver through Gold — the active zone for the Korean market.
Korean ceiling2000–2500Best 동호인 + strong 선수출신오픈부 champions, former junior players
International competitive2500–2900College players, Futures/Challengers, strong club playersNTRP 6.0–6.5, UTR 11–15
Professional2900+ATP/WTA tour levelNTRP 7.0, UTR 15+. Theoretical ceiling.

Why This Range

  • Floor at 400: With K=32 (K=40 provisional), a player who loses every match drops roughly 16–20 points per loss against equal opponents. After 30 straight losses from 1000 they land near 400–500. Realistic floor.
  • Korean bulk at 900–2000: Silver through Gold covers the dense NTRP 3.0–4.5 block where nearly all active Korean players converge.
  • Center of mass at ~1100–1400: Where most active Korean players settle after 20+ matches (신인부 to 오픈부 하위 range).

Step 2: The Tier Table

Korean Reality Check (Before Mapping)

Korean DivisionWhat It Actually MeansHonest NTRPWhy
테린이 / 입문Can barely rally. Serves are push-serves.1.5–2.0Still learning basic contact
신인부 하위Can rally at slow pace. Double-faults often.2.0–2.5Inconsistent groundstrokes
신인부Steady rally. Basic serve goes in. Can play a set.2.5–3.0The "finally playing tennis" moment
신인부 상위 ~ 오픈부 하위Directional control. Starting to use spin. Net approaches.3.0–3.5Where most active 동호인 players sit
오픈부Good topspin. Reliable serve with some pace. Tactical play.3.5–4.5Club tournament winners
오픈부 상위Weapon shots. Controls points. Tournament level.4.5–5.0Top 5–10% of 동호인
선수출신 (banned from most 동호인)Former registered competitive players5.0–6.0+Literally banned because the gap is too large

Note on terminology: Korean 동호인 tennis uses 신인부/오픈부/챌린저부/마스터즈부 (KATA/KATO system). D조/C조/B조/A조 is the badminton division system — not tennis. We use 신인부/오픈부 as the universally understood labels.

The Complete Tier Table

TierSubELO RangeNTRPUTRKorean Division% KR PlayersDescription
BronzeIII400–5672.01–2테린이<1%First time holding a racquet. Learning grip and contact.
BronzeII567–7342.0–2.52–3.5테린이2%Can make contact but rallies end in 2–3 hits. Push serve.
BronzeI734–9002.5–3.02–3.5테린이 / 입문5%Slow rallies work. Basic forehand exists. Double-faults most serves.
SilverIII900–10673.03.5–4.5신인부 하위10%Medium-pace rallies. Serve goes in sometimes. Backhand is weak.
SilverII1067–12343.0–3.53.5–4.5신인부15%Consistent medium rallies. Flat serve. Starting to play sets.
SilverI1234–14003.53.5–4.5신인부 상위15%Rally with direction. Serve rarely double-faults. Basic volleys.
GoldIII1400–16003.5–4.04.5–6.0신인부 ~ 오픈부 하위18%Directional control both sides. Starting topspin. Net approaches.
GoldII1600–18004.0–4.55.0–7.0오픈부 하위15%Reliable topspin. Second serve has spin. Tactical awareness.
GoldI1800–20004.5–5.06.0–7.5오픈부10%Good all-court player. Club tournament competitive.
MasterIII2000–21675.0–5.57.5–10오픈부 상위 / 선수출신5%Weapon shots. Controls points. Top 동호인 territory.
MasterII2167–23345.5–6.010–13선수급<1%Near ceiling of Korean recreational tennis.
MasterI2334–25006.0–6.511–14선수급 상위~0%Former competitive players. Strong college level (US).
Grand MasterIII2500–27006.513–15~0%Futures/Challenger level. International expansion tier.
Grand MasterII2700–29006.5–7.014–16~0%Low professional. ATP Challenger regulars.
Grand MasterI2900+7.0+15+~0%ATP/WTA Tour. Theoretical ceiling.

Distribution Summary (Korean 동호인 Only)

Bronze III–I   (400–900):   ~7%  — 테린이/입문
Silver III–I   (900–1400):  ~40% — 초급~중급 하위 ← LARGEST GROUP
Gold   III–I  (1400–2000):  ~43% — 중급~오픈부 ← where the bulk actually are
Master III–I  (2000–2500):  ~9%  — 오픈부 상위 / 선수출신
Grand Master  (2500+):      ~1%  — international expansion / pro-level

The median Korean 동호인 player is Silver II–III (~1000–1200 ELO, ~NTRP 3.0). Gold is intentionally wide (600 ELO, three equal 200-ELO sub-bands) to represent the dense NTRP 3.5–5.0 cluster that makes up the majority of active club players.


Step 3: Honesty Checks

Check 1: Is Korean Silver really NTRP 3.0–3.5?

YES. Korean 신인부 players:

  • Can rally at moderate pace on forehand
  • Backhand is often a slice or inconsistent two-hander
  • Serve is flat, moderate pace, ~50% in
  • No meaningful spin, no net game

This is textbook NTRP 3.0 (can sustain rally) to 3.5 (beginning to direct shots). An American NTRP 3.0 self-rating often means "I took lessons for a year." A Korean 신인부 regular is comparable.

Check 2: Is Korean Gold really NTRP 3.5–5.0?

YES. Korean 오픈부 players at the low end:

  • Consistent forehand with direction and developing topspin
  • Second serve exists but is weak
  • Starting to approach net
  • Maps to NTRP 3.5–4.0

At the high end of Gold (오픈부 / 오픈부 상위):

  • Has weapon shots (big forehand, reliable serve with pace)
  • Controls points and works the court
  • Plays with spin and variety
  • Maps to NTRP 4.0–4.5

Gold I (오픈부, 1800–2000) reaches NTRP 4.5–5.0. The temptation is to call 중급 players NTRP 4.0+ early, but that is inflation. NTRP 4.0 means "uses pace AND spin as weapons, has dependable overhead, approach shots." Most 오픈부 하위 players are not quite there.

Check 3: Is Korean Master really beyond 선수출신?

YES. Master III–I (2000–2500) covers the level where former registered competitive players (선수출신) converge. They seed at ~2100 and climb quickly. Master I and Grand Master are effectively international-expansion territory — very few Korean recreational players will ever reach them.

Check 4: Does the ELO range give enough resolution?

With sub-tiers of ~167–200 ELO each:

  • K=32 means a win against an equal opponent gives +16 points
  • Sub-tier promotion takes ~10–12 wins against equal opponents
  • Full tier promotion from Silver to Gold takes ~25 wins against equal opponents
  • This feels right for recreational play (1–2 matches per week = tier progress every 2–4 months)

Check 5: Can 선수출신 coexist without breaking the scale?

YES. 선수출신 seed at Master III (~2100). They quickly climb to Master II–I through ELO convergence. They are separated from the 동호인 bulk by 700–1000 ELO points, which means a Master I player has roughly 3–5% expected win rate against a Silver II player. That accurately reflects reality.


Step 4: Onboarding Seed ELOs

Seed ELOs represent where a player starts before any play-verified matches. They are a provisional placement, not a verified rating. See the rating integrity section below for how rating_state and rating_source gate what these seeds can unlock.

Korean Onboarding

Self-AssessmentKorean LabelSeed ELOStarting TierReasoning
완전 입문 (Complete Beginner)"테니스를 막 시작했어요"500Bronze IIIFirst time on court. Converges quickly.
입문 (Beginner)"기본 그립과 공 접촉이 돼요"750Bronze II/ILearning basic contact. Slow rallies.
초급 (Lower-Intermediate)"기본 스트로크와 서브가 돼요"1000Silver IIICan rally and serve. Most common 동호인 entry point.
중급 (Intermediate)"랠리하며 경기를 즐겨요"1300Silver IDirectional play. Playing sets regularly.
상급 (Advanced)"대회 출전 경험이 있어요"1700Gold IIClub tournament players. Strong all-court game.
선수출신 (Former Competitive)"선수 등록 경험이 있어요"2100Master IIIFormer registered players. Converges quickly upward.

Default ELO for new profiles: 1000 (Silver III floor) — the single most common Korean 동호인 entry level, and the median after convergence for self-described 초급 players.

International Onboarding

NTRP Self-RatingSeed ELOStarting TierNotes
NTRP 2.0600Bronze III/IITrue beginner, basic contact
NTRP 2.5800Bronze ICan rally slowly
NTRP 3.0950Silver IIIConsistent rally, basic serves
NTRP 3.51300Silver IDeveloping direction and spin
NTRP 4.01600Gold IIIGood all-court game
NTRP 4.51900Gold II/IStrong club-tournament level
NTRP 5.02100Master IIICollege-level background
NTRP 5.52250Master IIStrong college / post-college
NTRP 6.02400Master IFutures/Challenger level
NTRP 6.5–7.02600Grand Master IITour-level
UTR Self-RatingSeed ELOStarting TierNotes
UTR 1–2600Bronze IIIBeginner
UTR 2–3.5800Bronze IBasic recreational
UTR 3.5–4.51000Silver IIIClub player, 신인부
UTR 4.5–6.01400Gold III오픈부 하위
UTR 6.0–7.51700Gold IIStrong club
UTR 7.5–102050Master III오픈부 상위 / 선수출신
UTR 10–132300Master IFormer competitive
UTR 13–152600Grand Master IICollege/low professional
UTR 15+2900Grand Master ITour level

Step 5: Rating Integrity — rating_state, rating_source, and display_tier_sub

These three fields, added to profiles as part of the WS-3 foundation (see docs/architecture/international-data-model.md §5), govern what a rating means and what it can unlock. They are the anti-sandbagging layer.

rating_state

ValueMeaningMatch-delta behaviour
unratedNo play-verified matches yet (newly seeded).Results stored; opponent ELO delta = 0.
provisional1–9 play-verified matches. Rating is converging.Normal K-factor, lower confidence display.
established≥10 play-verified matches. High-confidence rating.Normal K-factor. Full competitive gating.

An unrated player's score is stored so their own rating can converge, but it does not count against calibrated opponents until the new player has played enough to be trusted (UTR's "no impact until 3 results" principle extended here). This prevents a brand-new player with a high self-assessed seed from deflating an experienced opponent's rating on their first match.

rating_source

ValueWhat It MeansTier badge displayed?
self_assessedPlayer chose their level during onboarding; no matches played.No — shows "미측정" with tap-explain.
intra_clubRating derived from matches within a single club.Yes — with a confidence indicator.
inter_clubRating derived from cross-club or pickup matches.Yes — stronger trust signal.
verified_tournamentRating anchored by an external verified tournament result.Yes — highest trust.

Key rule: self_assessed ratings never gate competitive RSVP enforcement (rsvps_enforce_tier). A player who says "나는 상급이에요" and seeds at 1700 Gold II is shown a provisional badge, but a Gold-and-above club CAN still accept them — the club has no verified evidence they are NOT Gold. Only a player with intra_club+ source and provisional+ state can be confidently barred from a Bronze-only club on the basis of their ELO alone. This is the USTA self-rated NTRP lesson: self-ratings inflate ~0.5 NTRP on average, so treating them as verified leads to sandbagging and mismatched matches.

display_tier_sub

Stored as 'I' | 'II' | 'III' (or NULL). Derived from the player's ELO position within their tier band using the sub-tier boundaries in TIER_DEFINITIONS. The sub-tier is displayed alongside the tier badge (e.g. "Silver II") and is used by the roster display so viewers can quickly scan player-pool compatibility. It is recalculated on every elo_history write; the stored column is a denormalized display cache.

The sub-tier is a granularity tool inside a wide tier. Gold spans 600 ELO (NTRP 3.5–5.0) — an enormous practical skill range. Gold III (1400–1600) and Gold I (1800–2000) are very different players; the sub-tier makes that visible without splitting the tier into separate competitive brackets.


Step 6: Korean Points System (1.0–9.0)

Korean 동호인 communities use a 9-point informal scale. Here is the mapping to the 5-tier ELO system:

PointsELO RangeNTRPLevelDivision
1.0400–5672.0완전 초보
2.0567–7342.0–2.5테린이
3.0734–9002.5–3.0입문입문부
3.5900–10673.0초급 하위신인부 하위
4.01067–12343.0–3.5초급신인부
4.51234–14003.5중급 하위신인부 상위
5.01400–16003.5–4.0중급오픈부 하위
5.51600–18004.0–4.5중상급오픈부
6.01800–20004.5–5.0상급오픈부 상위
6.52000–21675.0–5.5상급 상위선수출신 초입
7.02167–23345.5–6.0선수출신선수급
7.52334–25006.0–6.5선수출신 상위
8.0+2500+6.5+프로급

Formula: koreanPoints = Math.min(9.0, Math.max(1.0, Math.round((elo - 400) / 200 * 2) / 2 + 1.0))

Each 100 ELO ≈ 0.5 Korean points, starting from 1.0 at ELO 400.


International Benchmarks (Real Data Points)

Korean Professional Anchors

Player / ContextPeak ATP/WTAEst. UTREst. NTRPApprox. ELO
Hong Seong-chan (Korea #1 men)ATP ~#14113–146.5–7.0~2700
Ku Yeon-woo (Korea #1 women)WTA ~#19810–115.5–6.0~2400
Korea ATP #10ATP ~10009–105.5–6.0~2300
Korean Futures circuit playerATP 1000+10–125.5–6.5~2300–2600

Korean Amateur Anchors

ProfileNTRP (US-assessed)UTRWTNApprox. ELO
테린이 (6 months in)2.0–2.51–335–40~700
Median club player (3–5yr, 테춘기)3.0–3.54–522–28~1100–1300
13-yr veteran (US coach assessed)4.0–4.55–717–23~1600–1700
신인부 우승자4.0–4.55–717–22~1650–1750
오픈부 우승자4.5–5.07–910–15~1900–2100
슈퍼급4.5–5.08–108–12~2000–2100
선수출신 (former registered)5.0–5.59–115–10~2100–2250

Key Findings

  • Korean amateur self-assessment inflates ~0.5 NTRP vs US USTA standards
  • The entire 동호인 spectrum (테린이 → 슈퍼) = NTRP 1.5–5.0
  • ~75% of Korean recreational players are NTRP 3.0–4.5 (our Silver–Gold range)
  • Korea is an ITF WTN partner but no bulk amateur WTN data is publicly available
  • Korea has zero players inside ATP/WTA Top 100 as of 2026

NTRP Distribution (US reference for calibration)

  • NTRP 3.5: 28% of USTA league players (largest group)
  • NTRP 4.0: 21%
  • NTRP 4.5: 6%
  • NTRP 5.0: <1%

Sources: DC Inside tennis gallery, Brunch (Korean NTRP comparison), Tennis Explorer, KATA/KATO, ITF WTN


Appendix A: Visual Distribution

ELO    400    567    734    900   1067  1234  1400        1600        1800        2000        2167  2334  2500        2700  2900
       |      |      |      |      |     |     |           |           |           |           |     |     |           |     |
Tier   ├──── Bronze ────────┤───────────── Silver ─────────┤─────────────────── Gold ──────────────────────┤─── Master ────┤─── Grand Master ──→
       │ III │  II  │   I   │  III  │  II  │  I  │   III   │    II     │    I     │   III    │ II  │  I  │ III  │  II  │  I
NTRP   2.0   2.0-2.5  2.5-3.0  3.0   3.0-3.5  3.5  3.5-4.0   4.0-4.5    4.5-5.0   5.0-5.5  5.5-6.0 6.0-6.5  6.5  6.5-7.0  7.0+
       │                            │                                             │
       │  테린이/입문               │  신인부~오픈부 하위                          │  오픈부 상위 / 선수출신
       │                            │                                             │
       ├────── ~7% ─────────────────┼──────────────── ~83% ───────────────────────┼────── ~9% ──────┤~1%
       │                            │                                             │
       │  Bronze                    │  Silver + Gold (the Korean market core)     │  Master + GM

Appendix B: Cross-System Conversion Functions

These functions live in packages/app/src/domain/rules/tier.config.ts and are re-exported from @twomore/app. Use the exported versions; never inline the math in feature code.

typescript
/** Convert NTRP to approximate ELO seed (use for onboarding suggestion only). */
function ntrpToElo(ntrp: number): number {
  // NTRP 1.5 → 500, NTRP 7.0 → 2800
  // slope = (2800 - 500) / (7.0 - 1.5) ≈ 418 per NTRP point
  return Math.round(500 + (ntrp - 1.5) * 418);
}

/** Convert UTR to approximate ELO seed (use for onboarding suggestion only). */
function utrToElo(utr: number): number {
  // UTR 1 → 500, UTR 16 → 3100
  // slope = (3100 - 500) / (16 - 1) ≈ 173 per UTR point
  return Math.round(500 + (utr - 1) * 173);
}

/** Convert ELO to approximate Korean points (1.0–9.0 scale). */
function eloToKoreanPoints(elo: number): number {
  const raw = (elo - 400) / 200 + 1.0;
  return Math.min(9.0, Math.max(1.0, Math.round(raw * 2) / 2));
}

The helpers eloToNtrp, eloToUtr, eloToKoreanDiv, and eloToKoreanWomenDiv also live in tier.config.ts and map ELO to human-readable range strings aligned with the 5-tier boundaries above.


Appendix C: Validation Against Known References

Real-World PlayerExpected NTRPOur ELOOur TierPasses?
Korean 테린이 (6 months in)2.0~700Bronze IIYes
Korean 신인부 regular2.5–3.0~1000Silver IIIYes
Korean 신인부 상위3.5~1300Silver IYes
Korean 오픈부 하위3.5–4.0~1500Gold IIIYes
Korean 오픈부 winner4.5~1900Gold I/IIYes
Korean 슈퍼 champion4.5–5.0~2050Master IIIYes
Korean 선수출신 (strong)5.5~2250Master IIYes
American club 4.04.0~1600Gold IIIYes
American college D35.0–5.5~2200Master IIYes
American college D16.0–6.5~2450Master IYes
ATP top 5007.0~2800Grand Master IYes

Appendix D: Gender-Adjusted Display Tier

Deprecated (2026-07): the tier is now pure-skill / gender-neutral (owner decision); gender-awareness lives in the leaderboards, not the tier. getGenderAdjustedTier() / eloToKoreanWomenDiv() are retained for reference only. Canonical model: rating-system-v2 §0.

The raw ELO is always gender-neutral (used for matchmaking). For display purposes the app can adjust the shown tier so that a woman at the 60th percentile of women and a man at the 60th percentile of men both display the same tier — even if their raw ELO differs (men's pool tends to be denser at higher ELO early in the app's lifecycle).

This is implemented via getGenderAdjustedTier(elo, gender, genderStats, combinedStats) in tier.config.ts, which applies a z-score re-mapping. Key constraints:

  • The adjustment activates only once the gender pool reaches ≥50 players (MIN_POOL_SIZE_FOR_ADJUSTMENT). Until then, all genders use raw ELO tiers.
  • Matchmaking always uses raw ELO regardless of display adjustment.
  • The display_tier_sub column on profiles reflects the adjusted sub-tier, not the raw one.

Women's Korean division labels (개나리부 / 국화부 per KATA/KATO) are rendered via eloToKoreanWomenDiv(elo) alongside the standard labels where gender-specific display is shown.

Markdown remains the source of truth. Run yarn docs:check before handoff.