Spaces:
Sleeping
Sleeping
| 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 | |
| ```bash | |
| 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](https://huggingface.co/docs/hub/storage-buckets)** — S3-style object storage (see the [Python buckets guide](https://huggingface.co/docs/huggingface_hub/guides/buckets)). | |
| - **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) | |
| 1. **Create a Hugging Face account** (free) if you don’t have one. | |
| 2. **Create storage** (one or both): | |
| - **Bucket:** private bucket, e.g. **`Jay-Rajput/dis-ipl-state`** (Hub UI or [`hf buckets create`](https://huggingface.co/docs/huggingface_hub/guides/buckets)). | |
| - **Dataset:** private dataset with the same or another id, e.g. **`Jay-Rajput/dis-ipl-state`** ([new dataset](https://huggingface.co/new-dataset)). Dataset and bucket are different Hub resources; the id string can match on both sides. | |
| 3. **Create an access token** with **read/write** on the bucket and dataset you use: [Settings → Access Tokens](https://huggingface.co/settings/tokens). | |
| 4. **Create a Space**: [New Space](https://huggingface.co/new-space) → SDK **Docker** → connect this repo. **CPU basic** is enough (free). | |
| 5. **Add Space secrets** (Space → **Settings** → **Repository secrets**): | |
| | Secret | Value | | |
| |--------|--------| | |
| | `ADMIN_PASSWORD` | Strong password for the admin panel | | |
| | `SECRET_KEY` | Long random string (keep the same across redeploys so sessions stay valid) | | |
| | `HF_TOKEN` | Token with write access to your bucket and/or dataset | | |
| | `DIS_STATE_BUCKET` | *(optional)* Bucket id, e.g. `Jay-Rajput/dis-ipl-state` | | |
| | `DIS_STATE_REPO` | *(optional)* Dataset id, e.g. `Jay-Rajput/dis-ipl-state` | | |
| 6. **Rebuild / 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=1`** forces 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 set **`DIS_DATA_DIR=/data`** to keep SQLite on that volume ([Spaces storage docs](https://huggingface.co/docs/hub/spaces-storage)). | |
| - To override bundled JSON at runtime, place `users.json` / `matches.json` / `players.json` under the same directory as the database when using `DIS_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 | |
| 1. Go to **Admin → Add Match** | |
| 2. Select Team 1, Team 2, date, and time | |
| 3. Add venue and match number (optional but recommended) | |
| 4. Predictions are allowed **only on the match’s calendar day**, until the scheduled start time, then they lock automatically | |
| ### Setting Results | |
| 1. Go to **Admin → Set Results** | |
| 2. Select the winner and Man of the Match | |
| 3. Click "Set Result & Settle" — points are calculated automatically | |
| 4. 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) | |
| ```python | |
| 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): | |
| ```bash | |
| # 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: | |
| ```bash | |
| 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 | | |