Spaces:
Running
title: DIS IPL 2026 — Predictions
emoji: 🏏
colorFrom: blue
colorTo: red
sdk: docker
app_port: 7860
pinned: false
license: mit
🏏 DIS IPL 2026 — Team Match Predictions
A full-featured IPL match prediction app for your team. Built with Python (Flask) + SQLite.
⚡ Quick Start
pip install -r requirements.txt
set ADMIN_PASSWORD=your-admin-password-for-results-panel
# Optional: set PORT=7860 to match Hugging Face; default local port is 5000
set SECRET_KEY=long-random-string-for-session-cookies
python app.py
When you run python app.py, live reload is on by default: editing app.py, templates, static/, or seed JSON (users.json, etc.) restarts the dev server automatically. Set FLASK_DEBUG=0 (or false / off) to disable. Production / Hugging Face uses gunicorn and does not use this dev reloader.
Open http://127.0.0.1:5000/ when running python app.py locally (default port 5000). On Hugging Face Spaces, use the Space URL. No passwords for team members — pick your name on the home page (roster comes from the database after the first sync from users.json; new players from Admin appear automatically).
Admins use Admin login in the nav and enter ADMIN_PASSWORD (legacy: ADMIN_SECRET if ADMIN_PASSWORD is unset).
Hugging Face Spaces (free tier — persistent state without paid disk)
The Space container disk is ephemeral. The app can save ipl_predictions.db to:
- Storage Buckets — S3-style object storage (see the Python buckets guide).
- A private Hub dataset — Git + LFS history per upload.
You can set both DIS_STATE_BUCKET and DIS_STATE_REPO: every save uploads to each configured target (redundant backup). On restore, the app tries the bucket first, then the dataset if the local file is still missing or too small.
What you need to do (one-time)
Create a Hugging Face account (free) if you don’t have one.
Create storage (one or both):
- Bucket: private bucket, e.g.
Jay-Rajput/dis-ipl-state(Hub UI orhf buckets create). - Dataset: private dataset with the same or another id, e.g.
Jay-Rajput/dis-ipl-state(new dataset). Dataset and bucket are different Hub resources; the id string can match on both sides.
- Bucket: private bucket, e.g.
Create an access token with read/write on the bucket and dataset you use: Settings → Access Tokens.
Create a Space: New Space → SDK Docker → connect this repo. CPU basic is enough (free).
Add Space secrets (Space → Settings → Repository secrets):
Secret Value ADMIN_PASSWORDStrong password for the admin panel SECRET_KEYLong random string (keep the same across redeploys so sessions stay valid) HF_TOKENToken with write access to your bucket and/or dataset DIS_STATE_BUCKET(optional) Bucket id, e.g. Jay-Rajput/dis-ipl-stateDIS_STATE_REPO(optional) Dataset id, e.g. Jay-Rajput/dis-ipl-stateRebuild / restart the Space. Use the app once, then wait ~10–30 seconds so the background upload finishes before you restart the Space to test restore.
How it behaves
- After a prediction is saved or results are settled (points applied for every player who had a pick), the app uploads the full database to each configured target (bucket and/or dataset) before the page finishes loading, so the file on Hub always includes all members’ predictions and scores. Other admin tweaks still use a quick background upload.
- On a cold start, if the local DB is missing or very small, it tries bucket first, then dataset.
- Optional
DIS_FORCE_HUB_RESTORE=1forces a download from Hub (overwrites local DB). Use only when you intend to reset from remote state.
Optional (not required for free hosting)
- Paid Hugging Face persistent disk mounted at
/data: you may setDIS_DATA_DIR=/datato keep SQLite on that volume (Spaces storage docs). - To override bundled JSON at runtime, place
users.json/matches.json/players.jsonunder the same directory as the database when usingDIS_DATA_DIR.
Bundled data: users.json, matches.json, and players.json in the repo seed the DB; the name picker reads active users from the database.
🎮 How It Works
Points System
| Event | Points |
|---|---|
| ✅ Correct winner | +bid amount (e.g. bid 100 → earn 100) |
| ❌ Wrong winner | −bid amount (e.g. bid 100 → lose 100) |
| ⭐ Correct MOTM | +75 bonus |
| 🚫 Wrong MOTM | −25 penalty |
| 🤷 No MOTM predicted | 0 (safe, no risk) |
| 🌧️ Match abandoned | bid refunded (no winner/MOTM points) |
| 🚫 No prediction made | 0 (missed opportunity only) |
Starting Points
- Every player starts with 1,000 points
- Admin can adjust per-player starting points when adding them
- Points can go negative (no floor — creates drama!)
Bid Rules
- Minimum bid: 10 points
- Maximum bid: 500 points OR your current balance (whichever is lower)
- Quick-bid buttons: 10%, 25%, 50%, 75%, 100% of your max bid
Prediction Lock
- Predictions lock automatically at the scheduled match start time
- Once locked, no new predictions or edits are allowed
- The lock is automatic — no admin action needed
👥 Admin Guide
Adding Matches
- Go to Admin → Add Match
- Select Team 1, Team 2, date, and time
- Add venue and match number (optional but recommended)
- Predictions are allowed only on the match’s calendar day, until the scheduled start time, then they lock automatically
Setting Results
- Go to Admin → Set Results
- Select the winner and Man of the Match
- Click "Set Result & Settle" — points are calculated automatically
- If you made a mistake, check "Reverse previous settlement & recalculate" and re-submit
Managing Users
- Add players: Admin → Users → Add New Player
- Manually adjust points (for disputes, bonuses, etc.)
- Disable/enable users
Match Statuses
| Status | Meaning |
|---|---|
upcoming |
Predictions open |
locked |
Auto-locked at scheduled start (no new predictions) |
live |
Match in progress (manual — set for drama!) |
completed |
Match done, result can be entered |
abandoned |
Rain/DLS/etc — bids are automatically refunded |
postponed |
Rescheduled — set new date/time by deleting and re-adding |
🌍 Real-World Scenarios Handled
| Scenario | How it's handled |
|---|---|
| 2 matches in a day | Both appear on dashboard; predict each separately |
| Match abandoned | Admin sets status → bids refunded automatically |
| Wrong result entered | Admin uses "Recalculate" to reverse & redo |
| User forgets to predict | No penalty — just missed opportunity |
| User has ≤ 10 pts | Can bid all remaining points (no forced minimum) |
| Player name variations (V Kohli vs Virat Kohli) | Fuzzy last-name matching |
| No MOTM predicted | Zero impact — neither bonus nor penalty |
| Admin needs to correct MOTM | Re-enter result with "Recalculate" checked |
| New user joins mid-season | Admin adds with custom starting points |
| Suspended/banned user | Admin disables account — they can't log in |
🗂️ File Structure
ipl-predictions/
├── app.py # Main Flask app (all routes + logic)
├── requirements.txt
├── ipl_predictions.db # SQLite DB (auto-created)
└── templates/
├── base.html # Shared layout, nav, styling
├── login.html # Login page
├── dashboard.html # Home — today's matches
├── matches.html # All matches list
├── predict.html # Prediction form
├── leaderboard.html # Full leaderboard + podium
├── history.html # Personal stats & history
├── admin.html # Admin panel
└── admin_predictions.html # Per-match prediction viewer
🔧 Configuration (in app.py)
POINTS_CONFIG = {
'initial': 1000, # Starting points per player
'min_bid': 10, # Minimum bid
'max_bid': 500, # Maximum bid cap
'correct_winner': 1.0, # Multiplier on bid for correct winner
'wrong_winner': -1.0, # Multiplier on bid for wrong winner
'correct_motm': 75, # Flat bonus for correct MOTM
'wrong_motm': -25, # Flat penalty for wrong MOTM
'lock_minutes_before': 0, # 0 = at start; set e.g. 30 to lock N minutes before
}
Change these values and restart the app. Existing settled predictions are unaffected.
🚀 Production Deployment
For production (not just local use):
# Install gunicorn
pip install gunicorn
# Run with gunicorn
gunicorn -w 4 -b 0.0.0.0:5000 app:app
Also set a real secret key:
export SECRET_KEY="your-very-long-random-secret-key-here"
🏏 IPL 2025 Teams
| Team | Abbr |
|---|---|
| Mumbai Indians | MI |
| Chennai Super Kings | CSK |
| Royal Challengers Bengaluru | RCB |
| Kolkata Knight Riders | KKR |
| Sunrisers Hyderabad | SRH |
| Delhi Capitals | DC |
| Rajasthan Royals | RR |
| Punjab Kings | PBKS |
| Lucknow Super Giants | LSG |
| Gujarat Titans | GT |