Documentation of all data models in the MMR (Match Making Rating) app
MMR App Data Models Documentation
Brand values alignment: All features and data models should align with Courtex values: Community, Transparency, Accessibility, Integrity, Humility. MMR/leaderboards should be transparent (ratings visible), accessible (no gatekeeping), and respectful (no shaming lower-ranked players). See
docs/markdown/brand/copilot-instructions.mdfor full guidance.
Overview
The MMR app implements a Match Making Rating system for Courtex. Each rating entry records a snapshot of a player's skill rating at a specific point in time, enabling a full history of rating changes over their career.
The rating algorithm uses the PlackettLuce model from the openskill library — a Bayesian skill rating system well-suited to multi-player and team-based sports.
Core Models
1. MMR (Match Making Rating)
The MMR model stores a single skill rating snapshot for a user, tied to a specific sport, match format (combination), and match/set.
Key Fields:
- user: Foreign key to users.User (CASCADE on delete; related name mmr_history)
- sport: Sport type (Sport choices from clubs; defaults to Badminton)
- combination: Match format — singles, doubles, or other (for future use)
- match: Foreign key to matches.Match (CASCADE on delete; nullable)
- set: Foreign key to matches.Set (CASCADE on delete; nullable)
- mu: Mean skill estimate (default 25.0)
- sigma: Uncertainty/standard deviation of the skill estimate (default 8.333...)
- rating: Calculated ordinal rating derived from mu and sigma (auto-computed on save)
- date: Auto-set timestamp when this rating snapshot was created
Meta:
- ordering = ['-date'] — most recent records first
- verbose_name = 'Match Making Rating'
- verbose_name_plural = 'Match Making Ratings'
Business Logic (via save()):
- The rating field is automatically calculated using PlackettLuce.create_rating([mu, sigma]).ordinal() before each save
- This means rating is always a derived value and should not be set manually
Display:
- MMR values (mu) should be displayed with one decimal place (e.g., |floatformat:1 in Django templates)
How MMR Works
- Every user starts with initial
singlesanddoublesMMR records created by a signal inusers.Useron account creation - After each verified match, new
MMRrecords are appended for each player to capture the new rating - The rating history is stored as an append-only log — old records are never modified
user.get_latest_mmr(combination)retrieves the most recent MMR record for a given combination
Rating Parameters
| Parameter | Default | Description |
|---|---|---|
mu |
25.0 | Mean skill estimate |
sigma |
8.333... | Uncertainty (higher = less confident) |
rating |
Auto | Ordinal score (mu - 3*sigma approximately) |
Related Apps
users: Initial MMR records are created for every new user (singles + doubles) via a signalmatches: MMR records referenceMatchandSetto associate rating changes with specific resultsclubs: Thesportfield usesSportchoices from the clubs app