This project analyzes FRC district and regional point systems using The Blue Alliance API.
It simulates a redistribution model where:
- Teams competing at their 3rd+ play do NOT receive points
- Inter-district teams do NOT receive points
- Those removed points are redistributed evenly to eligible teams at that same event
- Demo teams from 9970 to 9999 are ignored
- Regional redistribution works for the new regional point system starting in 2026
The tool exports everything into a formatted Excel workbook.
- Original district rankings
- Redistributed district rankings
- Rank movement
- Point movement
- DCMP qualification changes
- Actual DCMP advancement counts from TBA
- Inter-district redistribution
- 3rd+ play redistribution
- District tiebreaker logic
- Conditional formatting
- Alphabetically sorted districts
- Summary tab
- Regional pool redistribution
- Regional auto-qualifier comparison
- Prevents duplicate auto-qualified teams
- District teams at regionals do not receive points
- 3rd+ regional plays do not receive points
- Regional tiebreaker logic
- Regional Events tab
Install Python packages:
pip install requests pandas xlsxwriter tqdm python-dotenvFRC-Point-Redistribution/
│
├── __pycache__/ # ignored by Git
├── .env # ignored by Git
├── .gitignore
├── config.py
├── district_model.py
├── excel_writer.py
├── frc_district_and_regional_redistribution.xlsx # ignored by Git
├── main.py
├── README.md
├── regional_model.py
├── tba_api.py
└── utils.py
Create a file named:
.env
Inside .env:
TBA_KEY=YOUR_REAL_TBA_API_KEYDo not put quotes around the key.
-
Log in
-
Create a Read API Key
-
Copy the key
-
Paste it into
.env
Open terminal in the project folder:
python main.pyInside config.py:
RUN_SINGLE_YEAR = True
TARGET_YEAR = 2026This is recommended for testing.
Inside config.py:
RUN_SINGLE_YEAR = False
ENABLED_YEARS = {
2024,
2025,
2026
}Only those years will run.
Inside config.py:
RUN_SINGLE_YEAR = False
ENABLED_YEARS = set()The script will automatically run:
- 2009 to current completed FRC season
- skips disabled years
Inside config.py:
DISABLED_YEARS = {
2020,
2021
}Districts can also be enabled or disabled.
ENABLED_DISTRICTS = {
"fit",
"fim"
}Supported identifiers:
- abbreviation
- district key
- district display name
DISABLED_DISTRICTS = {
"ont",
"ca"
}Current default skips:
- Ontario
- California
The script automatically determines the latest valid FRC season.
Logic:
- January to April: previous year
- May to December: current year
This is because the FRC season usually ends in April.
The workbook contains:
- One tab per year
- Districts placed side-by-side
- Districts sorted alphabetically
- Regional redistribution tables for 2026+
- Summary tab
- Regional Events tab
| Column | Description |
|---|---|
| Team | FRC team number |
| Original Points | Official points |
| OP Rank | Official ranking |
| Distributed Points | Points after redistribution |
| DP Rank | Ranking after redistribution |
| Change Points | Distributed Points - Original Points |
| Change Rank | Original Rank - Distributed Rank |
| DCMP Status | Whether the team gained or lost DCMP qualification |
| Event(s) | Redistribution details |
At a district event:
- Teams from that district on their 1st or 2nd play keep their points
- Teams on their 3rd+ play do not receive points
- Teams from another district do not receive points
- Removed points are redistributed to eligible teams at that same event
Redistribution math:
Non-counting team points / number of eligible teams
Rounding:
- 1.3 becomes 1
- 1.7 becomes 2
- Anything below 1 still becomes 1
At a regional event:
- Regional teams on their 1st or 2nd play keep their points
- Regional teams on their 3rd+ play do not receive points
- District teams at regionals do not receive points
- Removed points are redistributed to eligible regional teams at that same event
- Already auto-qualified teams are skipped when selecting future auto-qualifiers
The script uses these available TBA point fields:
- Total district points
- Total playoff points
- Best playoff points at a single event
- Total alliance selection points
- Best alliance selection points at a single event
- Total qualification points
- Lower team number as fallback
The script uses:
- Total regional points
- Best playoff points at a single event
- Best alliance selection points at a single event
- Best qualification points at a single event
- Lower team number as fallback
The official manuals also include individual match score tiebreakers.
Those are not included because they require parsing every match score from every event.
- Green means positive gain
- Red means negative loss
- White means zero change
- Yellow means within DCMP qualification range
- Green means gained DCMP spot
- Red means lost DCMP spot
The script automatically excludes:
9970 to 9999
These teams:
- do not receive redistributed points
- do not create redistributed points
- do not count toward eligible team counts
- do not appear in the final workbook
Your TBA API key is invalid or missing.
Fix:
- Check
.env - Verify the key on The Blue Alliance account page
Example:
PermissionError: [Errno 13]
This usually means the Excel file is open.
Fix:
- Close the workbook
- Run the script again
Usually:
- 30 seconds to 2 minutes
Usually:
- several minutes
The regional system is heavier than districts because it must compare all regional teams and district teams.
The project uses .env and .gitignore to prevent secrets from being uploaded.
The .env file should never be committed.
=== Running 2026 ===
Checking FIRST Chesapeake...
Checking FIRST in Texas...
Checking FIRST Indiana...
Running 2026 regional model...
2026 completed in 1m 25s
Created frc_district_and_regional_redistribution.xlsx
Data provided by The Blue Alliance API: