A React TypeScript application that helps organize badminton players into court assignments using image-based player list extraction.
- ๐ธ Image Upload & OCR: Take a picture of a player list and automatically extract names using Tesseract.js
- โ๏ธ Manual Player Entry: Add players manually - one at a time or multiple at once
- ๐ฅ Player Management: Toggle player presence, remove players
- ๐ฒ Random Team Generation: Automatically create "fair" team assignments
- ๐ Smart Court Assignment:
- Doubles (4 players) preferred
- Singles (2 players) for odd numbers
- Automatic bench assignment for extra players
- ๐ฑ Responsive Design: Works on desktop and mobile devices
- Add Players:
- From Image: Take a photo or upload an image of your player list for automatic OCR extraction
- Manual Entry: Add players one by one or paste multiple names (comma or line separated)
- Manage Players: Check/uncheck players who are present, remove players as needed
- Set Courts: Configure the number of available courts
- Generate Assignments: Click to randomly assign players to courts
The court-assignment engine aims to give everyone a fun, varied and fair session. It does this by turning each candidate set of courts into a cost and repeatedly searching for the lowest-cost layout. The cost function is made up of the rules below โ lower cost means "more desirable".
- Bench rotation fairness โ players who have sat out more often get priority to play next, ensuring everyone gets equal court time.
- Singles match rotation fairness โ when player numbers are odd and singles matches are needed, players who have played fewer singles matches get priority, ensuring no one plays singles twice before everyone has played singles once.
- Partner variety โ players who have already been teammates many times are less likely to be paired again, so everyone plays with different partners.
- Opponent variety โ players who have faced each other frequently are less likely to be opponents again, giving variety in who you play against.
- Balanced matches
โข Players with many wins avoid being paired together (preventing "super teams").
โข Players with many losses avoid being paired together (preventing weak teams).
โข When two teams face each other, their skill levels are matched so games stay competitive (avoiding mismatches like strong winners vs. weak losers). - Proper game formats โ courts always have either singles (2 players) or doubles (4 players), never 3 players.
- Optimal team pairings โ for each doubles match, the system tries all possible team combinations and picks the fairest pairing.
These rules are layered on top of the basic constraints:
- Doubles preferred โ courts of 4 players are created whenever possible.
- Singles fallback โ courts of 2 players are allowed when numbers are odd.
- Bench โ any surplus players are rotated to the bench.
Because the system's optimiser is stochastic, there is always an element of randomness, but over time the history-based penalties push the system towards an even distribution of partners, opponents, singles matches, and results.
- Take clear photos with good lighting
- Ensure names are clearly visible and separated (one per line works best)
- Supported formats: PNG, JPG, JPEG, WebP
- The OCR will attempt to filter out non-name text automatically
- Single Player: Use the text input to add one player at a time
- Multiple Players: Use the textarea to add many players at once
- Separate names with commas:
John Doe, Jane Smith, Mike Johnson - Or use new lines (one name per line)
- Mix and match: paste a list from anywhere!
- Separate names with commas:
- Uncheck players who aren't present today
- Remove players using the โ button
- Players can be added from either image OCR or manual entry (or both!)
- Set the number of available courts
- Click "Generate Random Assignments" to create new team combinations
- Click "Generate New Assignments" to shuffle players again
- Install dependencies:
npm install- Start the development server:
npm run dev- Open your browser and navigate to
http://localhost:5174
npm run build- Build for productionnpm run lint- Run ESLintnpm run test- Run unit testsnpm run test:e2e- Run e2e tests