# Spread Betting Implementation ## Overview Complete reimplementation of H2H as a sports spread betting platform where: - **Admins** create sporting events with official spreads - **Users** create bets at specific spreads (first come, first serve) - **Users** take bets and get automatically assigned the opposite side - **House** takes 10% commission (adjustable by admin) ## Database Schema ### New Models Created: **1. SportEvent** (`sport_events` table) - Admin-created sporting events - Teams, official spread, game time, venue, league - Configurable spread range (default -10 to +10) - Bet limits (min/max amounts) - Status tracking: upcoming, live, completed, cancelled **2. SpreadBet** (`spread_bets` table) - Bets on specific spreads for events - Links to creator and taker - Spread value and team side (home/away) - Stake amount (equal for both sides) - House commission percentage - Status: open, matched, completed, cancelled, disputed - Payout tracking **3. AdminSettings** (`admin_settings` table) - Global platform settings (single row) - Default house commission (10%) - Default bet limits - Default spread range - Spread increment (0.5 for half-point spreads) - Platform name, maintenance mode **4. User Model Update** - Added `is_admin` boolean field ## API Endpoints ### Admin Routes (`/api/v1/admin`) **Settings:** - `GET /settings` - Get current admin settings - `PATCH /settings` - Update settings (commission %, bet limits, etc.) **Event Management:** - `POST /events` - Create new sport event - `GET /events` - List all events (with filters) - `GET /events/{id}` - Get specific event - `PATCH /events/{id}` - Update event details - `DELETE /events/{id}` - Delete event (only if no active bets) - `POST /events/{id}/complete` - Mark complete with final scores ### User Routes **Sport Events (`/api/v1/sport-events`):** - `GET /` - List upcoming events - `GET /{id}` - Get event with spread grid **Spread Bets (`/api/v1/spread-bets`):** - `POST /` - Create spread bet - `POST /{id}/take` - Take an open bet - `GET /my-active` - Get user's active bets - `DELETE /{id}` - Cancel open bet (creator only) ## How It Works ### Example Flow: **1. Admin Creates Event:** ```json { "sport": "football", "home_team": "Wake Forest", "away_team": "MS State", "official_spread": 3.0, "game_time": "2024-01-15T19:00:00", "league": "NCAA", "min_spread": -10.0, "max_spread": 10.0, "min_bet_amount": 10.0, "max_bet_amount": 1000.0 } ``` **2. User Views Spread Grid:** ``` Wake Forest vs MS State Official Line: WF +3 / MS -3 Spread Grid: -10 -9.5 -9 -8.5 -8 -7.5 -7 ... -3 ... 0 ... +3 ... +10 [Alice $100] - Empty slots = can create bet - Occupied slots = can take bet - Official spread highlighted ``` **3. Alice Creates Bet:** ```json { "event_id": 1, "spread": -3.0, "team": "home", // Wake Forest "stake_amount": 100.00 } ``` Meaning: Alice bets Wake Forest will win by MORE than 3 points **4. Charlie Takes Bet:** ``` POST /api/v1/spread-bets/5/take ``` - Charlie automatically gets: MS State +3 (opposite side) - Both $100 stakes locked in escrow - Bet status: MATCHED **5. Game Ends:** ``` Final Score: Wake Forest 24, MS State 20 Wake Forest wins by 4 points Result: Alice wins (-3 spread covered) Payout: - Total pot: $200 - House commission (10%): $20 - Alice receives: $180 ``` ## Spread Grid Display Logic **GET /api/v1/sport-events/{id}** returns: ```json { "id": 1, "home_team": "Wake Forest", "away_team": "MS State", "official_spread": 3.0, "spread_grid": { "-10.0": null, "-9.5": null, ... "-3.0": { "bet_id": 5, "creator_id": 1, "creator_username": "alice", "stake": 100.00, "status": "open", "team": "home", "can_take": true }, "-2.5": null, ... "3.0": null, ... } } ``` ## Key Business Rules 1. **First Come, First Serve**: Only ONE bet allowed per spread per team 2. **Equal Stakes**: Both users must bet the same amount 3. **Opposite Sides**: Taker automatically gets opposite spread 4. **House Commission**: Default 10%, adjustable per bet 5. **Escrow**: Funds locked when bet is matched 6. **Spread Increments**: 0.5 points (e.g., -3, -2.5, -2, -1.5, etc.) ## Admin Settings Adjustable via `/api/v1/admin/settings`: - `default_house_commission_percent` - Default 10% - `default_min_bet_amount` - Default $10 - `default_max_bet_amount` - Default $1000 - `default_min_spread` - Default -10 - `default_max_spread` - Default +10 - `spread_increment` - Default 0.5 - `maintenance_mode` - Enable/disable betting ## Payout Calculation ```python total_pot = creator_stake + taker_stake house_fee = total_pot * (house_commission_percent / 100) payout_to_winner = total_pot - house_fee Example: - Alice stakes: $100 - Charlie stakes: $100 - Total pot: $200 - House commission (10%): $20 - Winner gets: $180 ``` ## Database Migration Notes New tables need to be created: - `sport_events` - `spread_bets` - `admin_settings` User table needs migration: - Add `is_admin` boolean column (default false) ## Next Steps 1. ✅ Database models created 2. ✅ API routes implemented 3. ⏳ Initialize database with new tables 4. ⏳ Create seed script for admin user and sample event 5. ⏳ Build frontend grid view 6. ⏳ Test complete flow ## Files Created ### Backend: - `backend/app/models/sport_event.py` - SportEvent model - `backend/app/models/spread_bet.py` - SpreadBet model - `backend/app/models/admin_settings.py` - AdminSettings model - `backend/app/schemas/sport_event.py` - SportEvent schemas - `backend/app/schemas/spread_bet.py` - SpreadBet schemas - `backend/app/routers/admin.py` - Admin routes - `backend/app/routers/sport_events.py` - Sport event routes - `backend/app/routers/spread_bets.py` - Spread bet routes ### Modified: - `backend/app/models/user.py` - Added is_admin field - `backend/app/models/__init__.py` - Exported new models - `backend/app/main.py` - Registered new routers