Best landing page yet, lost logged in links to lists of bets
This commit is contained in:
235
SPREAD_BETTING_IMPLEMENTATION.md
Normal file
235
SPREAD_BETTING_IMPLEMENTATION.md
Normal file
@ -0,0 +1,235 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user