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.md for 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 singles and doubles MMR records created by a signal in users.User on account creation
  • After each verified match, new MMR records 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 signal
  • matches: MMR records reference Match and Set to associate rating changes with specific results
  • clubs: The sport field uses Sport choices from the clubs app