Spaces:
Sleeping
Sleeping
James McCool
commited on
Commit
·
e334040
1
Parent(s):
9ce7dfc
clean up and moving functions to specific folder in dir
Browse files- MULTI_SPORT_REFACTOR.md +0 -224
- OPTIMIZATION_CHANGES.md +0 -166
- REFACTOR_COMPLETE.md +0 -176
- src/database.py +59 -0
- src/sports/nhl_functions.py +0 -0
- src/streamlit_app.py +0 -0
MULTI_SPORT_REFACTOR.md
DELETED
|
@@ -1,224 +0,0 @@
|
|
| 1 |
-
# 🏆 Multi-Sport Refactor - Implementation Guide
|
| 2 |
-
|
| 3 |
-
## ✅ What's Been Done
|
| 4 |
-
|
| 5 |
-
### 1. Created Sports Module Structure
|
| 6 |
-
```
|
| 7 |
-
src/sports/
|
| 8 |
-
├── __init__.py # Module initialization
|
| 9 |
-
├── nfl_functions.py # NFL pipeline (placeholder)
|
| 10 |
-
├── nba_functions.py # NBA pipeline (placeholder)
|
| 11 |
-
└── mlb_functions.py # MLB pipeline (placeholder)
|
| 12 |
-
```
|
| 13 |
-
|
| 14 |
-
### 2. Updated UI for Sport Selection
|
| 15 |
-
- ✅ Changed title to "Paydirt Model Updates" (generic)
|
| 16 |
-
- ✅ Added sport selection dropdown in sidebar
|
| 17 |
-
- ✅ Sport-specific icons and descriptions
|
| 18 |
-
- ✅ Dynamic button text based on selected sport
|
| 19 |
-
- ✅ Added routing structure for NFL, NBA, MLB
|
| 20 |
-
|
| 21 |
-
### 3. Placeholder Functions Created
|
| 22 |
-
Each sport module has a `run_<sport>_pipeline()` function that:
|
| 23 |
-
- Takes standard parameters (db, gc, gc2, discord)
|
| 24 |
-
- Shows "Coming soon" message
|
| 25 |
-
- Returns True for successful execution
|
| 26 |
-
|
| 27 |
-
## ⚠️ What Needs to Be Fixed
|
| 28 |
-
|
| 29 |
-
### Critical: Indentation Issue
|
| 30 |
-
|
| 31 |
-
The NHL code in `streamlit_app.py` needs to be indented by **4 spaces** (one level) because it's now inside the `if selected_sport == "NHL":` block.
|
| 32 |
-
|
| 33 |
-
**Lines to indent:** ~2193-2355 (approximately 160 lines)
|
| 34 |
-
|
| 35 |
-
**Before:**
|
| 36 |
-
```python
|
| 37 |
-
if selected_sport == "NHL":
|
| 38 |
-
st.write("Starting prop betting table generation...")
|
| 39 |
-
build_prop_betting_table(db)
|
| 40 |
-
|
| 41 |
-
try: # ← This should be indented
|
| 42 |
-
discord.post(content="NHL Prop Betting Table refreshed")
|
| 43 |
-
```
|
| 44 |
-
|
| 45 |
-
**After:**
|
| 46 |
-
```python
|
| 47 |
-
if selected_sport == "NHL":
|
| 48 |
-
st.write("Starting prop betting table generation...")
|
| 49 |
-
build_prop_betting_table(db)
|
| 50 |
-
|
| 51 |
-
try: # ← Now properly indented
|
| 52 |
-
discord.post(content="NHL Prop Betting Table refreshed")
|
| 53 |
-
```
|
| 54 |
-
|
| 55 |
-
### How to Fix:
|
| 56 |
-
|
| 57 |
-
**Option 1: Manual Fix (Recommended)**
|
| 58 |
-
1. Open `src/streamlit_app.py` in your editor
|
| 59 |
-
2. Find line ~2194 (after `build_prop_betting_table(db)`)
|
| 60 |
-
3. Select all code from line ~2195 to line ~2357 (before the `elif selected_sport ==` lines)
|
| 61 |
-
4. Indent everything by 4 spaces (or one tab)
|
| 62 |
-
5. The `elif` and final `client.close()` should remain at their current indentation
|
| 63 |
-
|
| 64 |
-
**Option 2: Search & Replace**
|
| 65 |
-
In your editor:
|
| 66 |
-
- Find: `^(\s{4})(try:|except:|st\.|build_|DK_|FD_|now =|current_time|sh =|worksheet|collection|prop_trends|Overall_Proj|chunk_size|time\.sleep)`
|
| 67 |
-
- Replace: `$1 $2` (adds 4 spaces)
|
| 68 |
-
- This should indent most lines automatically
|
| 69 |
-
|
| 70 |
-
## 📋 Current File Structure
|
| 71 |
-
|
| 72 |
-
### streamlit_app.py (Main App)
|
| 73 |
-
```python
|
| 74 |
-
# Imports and configuration
|
| 75 |
-
# ...
|
| 76 |
-
|
| 77 |
-
# UI Setup
|
| 78 |
-
st.set_page_config(...)
|
| 79 |
-
st.title("🏆 Paydirt Model Updates")
|
| 80 |
-
selected_sport = st.sidebar.selectbox(...) # Sport selector
|
| 81 |
-
|
| 82 |
-
# Main button with routing
|
| 83 |
-
if st.button(...):
|
| 84 |
-
if selected_sport == "NHL":
|
| 85 |
-
# NHL pipeline (NEEDS INDENTATION FIX)
|
| 86 |
-
build_prop_betting_table(db)
|
| 87 |
-
# ... 160 lines of NHL code ...
|
| 88 |
-
|
| 89 |
-
elif selected_sport == "NFL":
|
| 90 |
-
run_nfl_pipeline(db, gc, gc2, discord)
|
| 91 |
-
|
| 92 |
-
elif selected_sport == "NBA":
|
| 93 |
-
run_nba_pipeline(db, gc, gc2, discord)
|
| 94 |
-
|
| 95 |
-
elif selected_sport == "MLB":
|
| 96 |
-
run_mlb_pipeline(db, gc, gc2, discord)
|
| 97 |
-
|
| 98 |
-
client.close()
|
| 99 |
-
```
|
| 100 |
-
|
| 101 |
-
## 🔮 Future Enhancements
|
| 102 |
-
|
| 103 |
-
### 1. Extract NHL to Separate Module (Optional)
|
| 104 |
-
For cleaner code organization, you could:
|
| 105 |
-
|
| 106 |
-
```python
|
| 107 |
-
# src/sports/nhl_functions.py
|
| 108 |
-
def run_nhl_pipeline(db, gc, gc2, discord, slate_info, ...):
|
| 109 |
-
"""Complete NHL pipeline"""
|
| 110 |
-
# Move all 160 lines of NHL code here
|
| 111 |
-
build_prop_betting_table(db)
|
| 112 |
-
# ... rest of code ...
|
| 113 |
-
|
| 114 |
-
# src/streamlit_app.py
|
| 115 |
-
if selected_sport == "NHL":
|
| 116 |
-
run_nhl_pipeline(db, gc, gc2, discord, slate_info, ...)
|
| 117 |
-
```
|
| 118 |
-
|
| 119 |
-
### 2. Add Configuration Per Sport
|
| 120 |
-
```python
|
| 121 |
-
SPORT_CONFIG = {
|
| 122 |
-
"NHL": {
|
| 123 |
-
"master_sheet": "...",
|
| 124 |
-
"position_reqs": {"C": 2, "W": 3, ...},
|
| 125 |
-
"salary_cap": 50000,
|
| 126 |
-
},
|
| 127 |
-
"NFL": {
|
| 128 |
-
"master_sheet": "...",
|
| 129 |
-
# NFL-specific config
|
| 130 |
-
},
|
| 131 |
-
# ...
|
| 132 |
-
}
|
| 133 |
-
```
|
| 134 |
-
|
| 135 |
-
### 3. Dynamic Go Binary Selection
|
| 136 |
-
```python
|
| 137 |
-
sport_binary_map = {
|
| 138 |
-
"NHL": "nhl",
|
| 139 |
-
"NFL": "nfl",
|
| 140 |
-
"NBA": "nba",
|
| 141 |
-
"MLB": "mlb"
|
| 142 |
-
}
|
| 143 |
-
|
| 144 |
-
go_binary = os.path.join(
|
| 145 |
-
app_dir,
|
| 146 |
-
f"{site.lower()}_{sport_binary_map[sport]}_go",
|
| 147 |
-
"seed_frames"
|
| 148 |
-
)
|
| 149 |
-
```
|
| 150 |
-
|
| 151 |
-
## 🎯 Implementation Checklist
|
| 152 |
-
|
| 153 |
-
- [x] Create sports module structure
|
| 154 |
-
- [x] Add placeholder functions for NFL, NBA, MLB
|
| 155 |
-
- [x] Update UI with sport selector
|
| 156 |
-
- [x] Add routing logic for different sports
|
| 157 |
-
- [ ] **Fix indentation of NHL code (CRITICAL)**
|
| 158 |
-
- [ ] Test NHL functionality
|
| 159 |
-
- [ ] Test UI with different sport selections
|
| 160 |
-
- [ ] Build NFL pipeline when ready
|
| 161 |
-
- [ ] Build NBA pipeline when ready
|
| 162 |
-
- [ ] Build MLB pipeline when ready
|
| 163 |
-
|
| 164 |
-
## 🚀 Testing the Changes
|
| 165 |
-
|
| 166 |
-
Once indentation is fixed:
|
| 167 |
-
|
| 168 |
-
1. **Test Sport Selection**
|
| 169 |
-
- Select each sport from dropdown
|
| 170 |
-
- Verify description updates
|
| 171 |
-
- Verify button text changes
|
| 172 |
-
|
| 173 |
-
2. **Test NHL Pipeline**
|
| 174 |
-
- Select NHL
|
| 175 |
-
- Click "Generate NHL Lineups"
|
| 176 |
-
- Should work exactly as before
|
| 177 |
-
|
| 178 |
-
3. **Test Other Sports**
|
| 179 |
-
- Select NFL/NBA/MLB
|
| 180 |
-
- Click generate button
|
| 181 |
-
- Should show "Coming soon" message
|
| 182 |
-
|
| 183 |
-
## 📝 Notes
|
| 184 |
-
|
| 185 |
-
- All NHL functionality remains unchanged
|
| 186 |
-
- The refactor is purely organizational
|
| 187 |
-
- Easy to add new sports by creating new module
|
| 188 |
-
- Maintains backward compatibility with existing NHL code
|
| 189 |
-
|
| 190 |
-
## 🐛 Known Issues
|
| 191 |
-
|
| 192 |
-
1. **Indentation Error** - NHL code not indented properly (see above)
|
| 193 |
-
2. **Import Order** - Sports modules imported after UI setup (works but not ideal)
|
| 194 |
-
|
| 195 |
-
## 💡 Tips for Adding New Sports
|
| 196 |
-
|
| 197 |
-
When you're ready to add NFL:
|
| 198 |
-
|
| 199 |
-
1. Edit `src/sports/nfl_functions.py`
|
| 200 |
-
2. Replace placeholder with actual implementation:
|
| 201 |
-
```python
|
| 202 |
-
def run_nfl_pipeline(db, gc, gc2, discord):
|
| 203 |
-
st.write("Starting NFL pipeline...")
|
| 204 |
-
|
| 205 |
-
# Build prop betting table
|
| 206 |
-
build_nfl_prop_betting_table(db)
|
| 207 |
-
|
| 208 |
-
# Build player outcomes
|
| 209 |
-
roo_file = build_nfl_player_outcomes(db)
|
| 210 |
-
|
| 211 |
-
# Generate seed frames
|
| 212 |
-
DK_NFL_seed_frame(db, roo_file)
|
| 213 |
-
FD_NFL_seed_frame(db, roo_file)
|
| 214 |
-
|
| 215 |
-
st.success("✅ NFL pipeline complete!")
|
| 216 |
-
return True
|
| 217 |
-
```
|
| 218 |
-
3. Create NFL-specific helper functions in same file
|
| 219 |
-
4. Update Go binaries for NFL if needed
|
| 220 |
-
|
| 221 |
-
---
|
| 222 |
-
|
| 223 |
-
**Status:** Multi-sport UI ready, indentation fix required for full functionality
|
| 224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OPTIMIZATION_CHANGES.md
DELETED
|
@@ -1,166 +0,0 @@
|
|
| 1 |
-
# 🚀 Build Time Optimization - Changes Made
|
| 2 |
-
|
| 3 |
-
## Problem
|
| 4 |
-
Docker build was taking ~1 hour due to:
|
| 5 |
-
1. **NHL_own_regress.py** training 3 ML models on every import
|
| 6 |
-
2. **Heavy ML dependencies** (xgboost, lightgbm, scikit-learn)
|
| 7 |
-
3. MongoDB data download during build
|
| 8 |
-
|
| 9 |
-
## Solutions Implemented
|
| 10 |
-
|
| 11 |
-
### 1. ✅ Removed ML Model Training at Import Time
|
| 12 |
-
**Before:** NHL_own_regress.py would:
|
| 13 |
-
- Connect to MongoDB
|
| 14 |
-
- Download thousands of rows of historical data
|
| 15 |
-
- Train 3 models with 1000 estimators each
|
| 16 |
-
- This happened EVERY time the file was imported!
|
| 17 |
-
|
| 18 |
-
**After:**
|
| 19 |
-
- Models are no longer imported
|
| 20 |
-
- Using simplified heuristic-based ownership prediction
|
| 21 |
-
- No training at startup
|
| 22 |
-
|
| 23 |
-
### 2. ✅ Simplified Ownership Prediction
|
| 24 |
-
**Replaced this:**
|
| 25 |
-
```python
|
| 26 |
-
basic_own_df['XGB'] = np_clip(xgb_model.predict(X_current), 0, 100)
|
| 27 |
-
basic_own_df['LGB'] = np_clip(lgb_model.predict(X_current), 0, 100) * 100
|
| 28 |
-
basic_own_df['KNN'] = np_clip(knn_model.predict(X_current), 0, 100)
|
| 29 |
-
basic_own_df['Combo'] = (XGB * .30) + (LGB * .30) + (KNN * .40)
|
| 30 |
-
```
|
| 31 |
-
|
| 32 |
-
**With this:**
|
| 33 |
-
```python
|
| 34 |
-
basic_own_df['Combo'] = (
|
| 35 |
-
(basic_own_df['value'] * 10) *
|
| 36 |
-
(100 / (basic_own_df['Salary'] / 1000))
|
| 37 |
-
) / 100
|
| 38 |
-
```
|
| 39 |
-
|
| 40 |
-
### 3. ✅ Reduced Python Dependencies
|
| 41 |
-
**Before (12 packages):**
|
| 42 |
-
- streamlit
|
| 43 |
-
- pandas
|
| 44 |
-
- numpy
|
| 45 |
-
- altair
|
| 46 |
-
- pytz
|
| 47 |
-
- **ortools** (still needed - 500MB!)
|
| 48 |
-
- gspread
|
| 49 |
-
- discordwebhook
|
| 50 |
-
- pymongo
|
| 51 |
-
- **xgboost** (❌ removed - 250MB)
|
| 52 |
-
- **lightgbm** (❌ removed - 150MB)
|
| 53 |
-
- **scikit-learn** (❌ removed - 200MB)
|
| 54 |
-
|
| 55 |
-
**After (8 packages):**
|
| 56 |
-
Only the essential packages remain.
|
| 57 |
-
|
| 58 |
-
**Space Saved:** ~600MB in dependencies!
|
| 59 |
-
|
| 60 |
-
### 4. ✅ Optimized Dockerfile
|
| 61 |
-
- Removed copying of `func/` directory (not needed)
|
| 62 |
-
- Only copies `src/` (the actual app)
|
| 63 |
-
- Go binaries copied directly from builder stage
|
| 64 |
-
|
| 65 |
-
## Expected Build Time Improvement
|
| 66 |
-
|
| 67 |
-
| Phase | Before | After | Savings |
|
| 68 |
-
|-------|--------|-------|---------|
|
| 69 |
-
| Download Dependencies | ~15 min | ~5 min | **10 min** |
|
| 70 |
-
| Install Dependencies | ~25 min | ~8 min | **17 min** |
|
| 71 |
-
| Model Training | ~15 min | 0 min | **15 min** |
|
| 72 |
-
| Copy Files | ~3 min | ~2 min | **1 min** |
|
| 73 |
-
| Go Build | ~5 min | ~5 min | 0 min |
|
| 74 |
-
| **TOTAL** | **~60 min** | **~20 min** | **~40 min (67% faster)** |
|
| 75 |
-
|
| 76 |
-
## Files Modified
|
| 77 |
-
|
| 78 |
-
1. **`requirements.txt`** - Removed heavy ML packages
|
| 79 |
-
2. **`src/streamlit_app.py`** - Removed ML model imports, simplified prediction
|
| 80 |
-
3. **`func/NHL_own_regress.py`** - Wrapped training in `if __name__ == '__main__'`
|
| 81 |
-
4. **`Dockerfile`** - Removed unnecessary file copying
|
| 82 |
-
|
| 83 |
-
## Trade-offs
|
| 84 |
-
|
| 85 |
-
### What We Lost:
|
| 86 |
-
- ML-based ownership predictions
|
| 87 |
-
- Historical model accuracy metrics
|
| 88 |
-
|
| 89 |
-
### What We Kept:
|
| 90 |
-
- Fast build times
|
| 91 |
-
- All core functionality
|
| 92 |
-
- Lineup optimization (ortools)
|
| 93 |
-
- Data processing
|
| 94 |
-
- Google Sheets integration
|
| 95 |
-
- MongoDB integration
|
| 96 |
-
- Discord notifications
|
| 97 |
-
|
| 98 |
-
### What We Gained:
|
| 99 |
-
- **67% faster builds** (60min → 20min)
|
| 100 |
-
- Faster app startup
|
| 101 |
-
- Lower memory usage
|
| 102 |
-
- Simpler codebase
|
| 103 |
-
|
| 104 |
-
## Ownership Prediction Accuracy
|
| 105 |
-
|
| 106 |
-
The simplified heuristic uses:
|
| 107 |
-
- Player value (projection/salary)
|
| 108 |
-
- Salary tier adjustments
|
| 109 |
-
- Leverage multipliers
|
| 110 |
-
|
| 111 |
-
While not as sophisticated as ML models, it's:
|
| 112 |
-
- ✅ Fast (instant vs minutes)
|
| 113 |
-
- ✅ Transparent (no black box)
|
| 114 |
-
- ✅ Good enough for most use cases
|
| 115 |
-
- ✅ Customizable with business logic
|
| 116 |
-
|
| 117 |
-
## If You Need ML Models Later
|
| 118 |
-
|
| 119 |
-
If you want ML-based predictions back:
|
| 120 |
-
|
| 121 |
-
### Option 1: Pre-train and Pickle Models
|
| 122 |
-
```python
|
| 123 |
-
# Train once locally
|
| 124 |
-
import pickle
|
| 125 |
-
# ... train models ...
|
| 126 |
-
pickle.dump(xgb_model, open('xgb_model.pkl', 'wb'))
|
| 127 |
-
|
| 128 |
-
# Load in app
|
| 129 |
-
xgb_model = pickle.load(open('xgb_model.pkl', 'rb'))
|
| 130 |
-
```
|
| 131 |
-
|
| 132 |
-
### Option 2: Use Lighter Models
|
| 133 |
-
- Replace XGBoost/LightGBM with simpler sklearn models
|
| 134 |
-
- Use fewer estimators (100 instead of 1000)
|
| 135 |
-
- Cache predictions
|
| 136 |
-
|
| 137 |
-
### Option 3: Train in Background
|
| 138 |
-
- Train models async after app starts
|
| 139 |
-
- Use default predictions until models ready
|
| 140 |
-
- Scheduled retraining
|
| 141 |
-
|
| 142 |
-
## Validation
|
| 143 |
-
|
| 144 |
-
To ensure everything still works:
|
| 145 |
-
|
| 146 |
-
1. ✅ App imports successfully
|
| 147 |
-
2. ✅ No missing dependencies
|
| 148 |
-
3. ✅ Streamlit UI loads
|
| 149 |
-
4. ✅ MongoDB connection works
|
| 150 |
-
5. ✅ Google Sheets connection works
|
| 151 |
-
6. ✅ Lineup optimization works (ortools)
|
| 152 |
-
7. ✅ Go binaries execute
|
| 153 |
-
8. ✅ Ownership predictions calculate
|
| 154 |
-
|
| 155 |
-
## Deploy Now
|
| 156 |
-
|
| 157 |
-
Your app should now build in ~20 minutes instead of ~60 minutes!
|
| 158 |
-
|
| 159 |
-
```bash
|
| 160 |
-
git add .
|
| 161 |
-
git commit -m "Optimize build: Remove heavy ML dependencies"
|
| 162 |
-
git push
|
| 163 |
-
```
|
| 164 |
-
|
| 165 |
-
Monitor the build logs - you should see it complete much faster! 🚀
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
REFACTOR_COMPLETE.md
DELETED
|
@@ -1,176 +0,0 @@
|
|
| 1 |
-
# ✅ Multi-Sport Refactor - Complete!
|
| 2 |
-
|
| 3 |
-
## 🎉 What's Working
|
| 4 |
-
|
| 5 |
-
Your Streamlit app now supports multiple sports! Here's what's been implemented:
|
| 6 |
-
|
| 7 |
-
### 1. **Sport Selection UI** ✅
|
| 8 |
-
- Dropdown selector in sidebar with sport icons:
|
| 9 |
-
- 🏒 NHL
|
| 10 |
-
- 🏈 NFL
|
| 11 |
-
- 🏀 NBA
|
| 12 |
-
- ⚾ MLB
|
| 13 |
-
|
| 14 |
-
### 2. **Modular Structure** ✅
|
| 15 |
-
```
|
| 16 |
-
src/sports/
|
| 17 |
-
├── __init__.py # Module initialization
|
| 18 |
-
├── nfl_functions.py # NFL pipeline (placeholder)
|
| 19 |
-
├── nba_functions.py # NBA pipeline (placeholder)
|
| 20 |
-
└── mlb_functions.py # MLB pipeline (placeholder)
|
| 21 |
-
```
|
| 22 |
-
|
| 23 |
-
### 3. **Sport Routing** ✅
|
| 24 |
-
The app now routes to different pipelines based on sport selection:
|
| 25 |
-
- NHL: Full pipeline (existing code)
|
| 26 |
-
- NFL/NBA/MLB: Placeholder "Coming soon" messages
|
| 27 |
-
|
| 28 |
-
## 🚀 How to Use
|
| 29 |
-
|
| 30 |
-
1. **Launch the app**
|
| 31 |
-
```bash
|
| 32 |
-
streamlit run src/streamlit_app.py
|
| 33 |
-
```
|
| 34 |
-
|
| 35 |
-
2. **Select a sport** from the sidebar dropdown
|
| 36 |
-
|
| 37 |
-
3. **Click the Generate button** (button text changes based on sport)
|
| 38 |
-
|
| 39 |
-
4. **See results**:
|
| 40 |
-
- NHL: Runs full lineup generation
|
| 41 |
-
- Other sports: Shows "Coming soon" message
|
| 42 |
-
|
| 43 |
-
## 📝 Current Features
|
| 44 |
-
|
| 45 |
-
### NHL (Fully Functional)
|
| 46 |
-
- ✅ Prop betting table generation
|
| 47 |
-
- ✅ DK player level outcomes
|
| 48 |
-
- ✅ FD player level outcomes
|
| 49 |
-
- ✅ Stack matrix generation (DK & FD)
|
| 50 |
-
- ✅ PP stack matrix generation
|
| 51 |
-
- ✅ Seed frame generation (DK & FD)
|
| 52 |
-
- ✅ MongoDB updates
|
| 53 |
-
- ✅ Google Sheets updates
|
| 54 |
-
- ✅ Discord notifications
|
| 55 |
-
|
| 56 |
-
### NFL, NBA, MLB (Placeholder)
|
| 57 |
-
- ✅ "Coming soon" messages
|
| 58 |
-
- ✅ Ready for implementation
|
| 59 |
-
- ✅ Same structure as NHL
|
| 60 |
-
|
| 61 |
-
## 🔧 Adding New Sports
|
| 62 |
-
|
| 63 |
-
When you're ready to implement NFL:
|
| 64 |
-
|
| 65 |
-
1. **Edit `src/sports/nfl_functions.py`**:
|
| 66 |
-
```python
|
| 67 |
-
def run_nfl_pipeline(db, gc, gc2, discord):
|
| 68 |
-
st.write("🏈 Starting NFL pipeline...")
|
| 69 |
-
|
| 70 |
-
# Your NFL-specific code here
|
| 71 |
-
build_nfl_prop_betting_table(db)
|
| 72 |
-
roo_file = build_nfl_player_outcomes(db)
|
| 73 |
-
DK_NFL_seed_frame(db, roo_file)
|
| 74 |
-
FD_NFL_seed_frame(db, roo_file)
|
| 75 |
-
|
| 76 |
-
st.success("✅ NFL complete!")
|
| 77 |
-
return True
|
| 78 |
-
```
|
| 79 |
-
|
| 80 |
-
2. **Create NFL-specific helper functions** in the same file
|
| 81 |
-
|
| 82 |
-
3. **Test** by selecting NFL from dropdown
|
| 83 |
-
|
| 84 |
-
## ⚠️ Known Issues (Minor)
|
| 85 |
-
|
| 86 |
-
### Indentation Inconsistency
|
| 87 |
-
Some lines in the NHL block (lines ~2195-2206) have inconsistent indentation. This doesn't affect functionality but may show linter warnings.
|
| 88 |
-
|
| 89 |
-
**To fix manually** (optional):
|
| 90 |
-
1. Open `src/streamlit_app.py`
|
| 91 |
-
2. Find line 2195 (`try:`)
|
| 92 |
-
3. Add 4 spaces to lines 2195-2206
|
| 93 |
-
4. Everything between `build_prop_betting_table(db)` and `elif selected_sport == "NFL"` should be indented 8 spaces
|
| 94 |
-
|
| 95 |
-
**Impact**: None - code works correctly despite formatting inconsistency
|
| 96 |
-
|
| 97 |
-
## 📊 File Changes Summary
|
| 98 |
-
|
| 99 |
-
### Modified:
|
| 100 |
-
- `src/streamlit_app.py` - Added sport selection UI and routing
|
| 101 |
-
|
| 102 |
-
### Created:
|
| 103 |
-
- `src/sports/__init__.py`
|
| 104 |
-
- `src/sports/nfl_functions.py`
|
| 105 |
-
- `src/sports/nba_functions.py`
|
| 106 |
-
- `src/sports/mlb_functions.py`
|
| 107 |
-
- `MULTI_SPORT_REFACTOR.md` (implementation guide)
|
| 108 |
-
- `REFACTOR_COMPLETE.md` (this file)
|
| 109 |
-
|
| 110 |
-
## 🎯 Next Steps
|
| 111 |
-
|
| 112 |
-
1. **Test NHL functionality** - Verify everything still works
|
| 113 |
-
2. **Implement NFL** when ready
|
| 114 |
-
3. **Implement NBA** when ready
|
| 115 |
-
4. **Implement MLB** when ready
|
| 116 |
-
|
| 117 |
-
## 🏗️ Architecture Benefits
|
| 118 |
-
|
| 119 |
-
### Before:
|
| 120 |
-
- Single sport (NHL) hardcoded
|
| 121 |
-
- No easy way to add new sports
|
| 122 |
-
- Everything in one massive file
|
| 123 |
-
|
| 124 |
-
### After:
|
| 125 |
-
- ✅ Multi-sport support
|
| 126 |
-
- ✅ Easy to add new sports
|
| 127 |
-
- ✅ Modular structure
|
| 128 |
-
- ✅ Clean separation of concerns
|
| 129 |
-
- ✅ Professional UI with sport selection
|
| 130 |
-
|
| 131 |
-
## 💡 Tips
|
| 132 |
-
|
| 133 |
-
### Sport Icons
|
| 134 |
-
Update icons in `streamlit_app.py`:
|
| 135 |
-
```python
|
| 136 |
-
sport_icons = {
|
| 137 |
-
"NHL": "🏒",
|
| 138 |
-
"NFL": "🏈",
|
| 139 |
-
"NBA": "🏀",
|
| 140 |
-
"MLB": "⚾",
|
| 141 |
-
"SOCCER": "⚽", # Easy to add more!
|
| 142 |
-
}
|
| 143 |
-
```
|
| 144 |
-
|
| 145 |
-
### Sport Descriptions
|
| 146 |
-
Update descriptions:
|
| 147 |
-
```python
|
| 148 |
-
sport_descriptions = {
|
| 149 |
-
"NHL": "Generate NHL lineup projections...",
|
| 150 |
-
"NFL": "Generate NFL lineup projections...",
|
| 151 |
-
# ...
|
| 152 |
-
}
|
| 153 |
-
```
|
| 154 |
-
|
| 155 |
-
## 🎨 UI Improvements Made
|
| 156 |
-
|
| 157 |
-
1. **Generic branding**: "Paydirt Model Updates" instead of "Paydirt NHL..."
|
| 158 |
-
2. **Sport selector**: Prominent dropdown with icons
|
| 159 |
-
3. **Dynamic content**: Button and messages change based on sport
|
| 160 |
-
4. **Clean layout**: Organized sidebar and main content
|
| 161 |
-
5. **Status indicators**: Connection status for MongoDB and Google Sheets
|
| 162 |
-
|
| 163 |
-
## ✨ Success Metrics
|
| 164 |
-
|
| 165 |
-
- ✅ All NHL functionality preserved
|
| 166 |
-
- ✅ Easy to add new sports (3 lines of code)
|
| 167 |
-
- ✅ Professional multi-sport UI
|
| 168 |
-
- ✅ Backward compatible
|
| 169 |
-
- ✅ Ready for production
|
| 170 |
-
|
| 171 |
-
---
|
| 172 |
-
|
| 173 |
-
**Status**: Multi-sport refactor complete and ready for use! 🚀
|
| 174 |
-
|
| 175 |
-
To deploy: `git push` (build should complete in ~10-20 minutes)
|
| 176 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/database.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import os
|
| 3 |
+
from pymongo import MongoClient
|
| 4 |
+
from gspread.auth import service_account_from_dict
|
| 5 |
+
|
| 6 |
+
# Helper function to get secrets
|
| 7 |
+
def get_secret(key, default=None):
|
| 8 |
+
"""Get secret from Streamlit secrets or environment variables"""
|
| 9 |
+
try:
|
| 10 |
+
return st.secrets[key]
|
| 11 |
+
except:
|
| 12 |
+
return os.getenv(key, default)
|
| 13 |
+
|
| 14 |
+
# Load credentials from Streamlit secrets or environment variables
|
| 15 |
+
scope = ['https://www.googleapis.com/auth/spreadsheets',
|
| 16 |
+
"https://www.googleapis.com/auth/drive"]
|
| 17 |
+
|
| 18 |
+
# Google Sheets credentials
|
| 19 |
+
credentials = {
|
| 20 |
+
"type": "service_account",
|
| 21 |
+
"project_id": get_secret("GOOGLE_PROJECT_ID_1", "model-sheets-connect"),
|
| 22 |
+
"private_key_id": get_secret("GOOGLE_PRIVATE_KEY_ID_1", "0e0bc2fdef04e771172fe5807392b9d6639d945e"),
|
| 23 |
+
"private_key": get_secret("GOOGLE_PRIVATE_KEY_1", "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDiu1v/e6KBKOcK\ncx0KQ23nZK3ZVvADYy8u/RUn/EDI82QKxTd/DizRLIV81JiNQxDJXSzgkbwKYEDm\n48E8zGvupU8+Nk76xNPakrQKy2Y8+VJlq5psBtGchJTuUSHcXU5Mg2JhQsB376PJ\nsCw552K6Pw8fpeMDJDZuxpKSkaJR6k9G5Dhf5q8HDXnC5Rh/PRFuKJ2GGRpX7n+2\nhT/sCax0J8jfdTy/MDGiDfJqfQrOPrMKELtsGHR9Iv6F4vKiDqXpKfqH+02E9ptz\nBk+MNcbZ3m90M8ShfRu28ebebsASfarNMzc3dk7tb3utHOGXKCf4tF8yYKo7x8BZ\noO9X4gSfAgMBAAECggEAU8ByyMpSKlTCF32TJhXnVJi/kS+IhC/Qn5JUDMuk4LXr\naAEWsWO6kV/ZRVXArjmuSzuUVrXumISapM9Ps5Ytbl95CJmGDiLDwRL815nvv6k3\nUyAS8EGKjz74RpoIoH6E7EWCAzxlnUgTn+5oP9Flije97epYk3H+e2f1f5e1Nn1d\nYNe8U+1HqJgILcxA1TAUsARBfoD7+K3z/8DVPHI8IpzAh6kTHqhqC23Rram4XoQ6\nzj/ZdVBjvnKuazETfsD+Vl3jGLQA8cKQVV70xdz3xwLcNeHsbPbpGBpZUoF73c65\nkAXOrjYl0JD5yAk+hmYhXr6H9c6z5AieuZGDrhmlFQKBgQDzV6LRXmjn4854DP/J\nI82oX2GcI4eioDZPRukhiQLzYerMQBmyqZIRC+/LTCAhYQSjNgMa+ZKyvLqv48M0\n/x398op/+n3xTs+8L49SPI48/iV+mnH7k0WI/ycd4OOKh8rrmhl/0EWb9iitwJYe\nMjTV/QxNEpPBEXfR1/mvrN/lVQKBgQDuhomOxUhWVRVH6x03slmyRBn0Oiw4MW+r\nrt1hlNgtVmTc5Mu+4G0USMZwYuOB7F8xG4Foc7rIlwS7Ic83jMJxemtqAelwOLdV\nXRLrLWJfX8+O1z/UE15l2q3SUEnQ4esPHbQnZowHLm0mdL14qSVMl1mu1XfsoZ3z\nJZTQb48CIwKBgEWbzQRtKD8lKDupJEYqSrseRbK/ax43DDITS77/DWwHl33D3FYC\nMblUm8ygwxQpR4VUfwDpYXBlklWcJovzamXpSnsfcYVkkQH47NuOXPXPkXQsw+w+\nDYcJzeu7F/vZqk9I7oBkWHUrrik9zPNoUzrfPvSRGtkAoTDSwibhoc5dAoGBAMHE\nK0T/ANeZQLNuzQps6S7G4eqjwz5W8qeeYxsdZkvWThOgDd/ewt3ijMnJm5X05hOn\ni4XF1euTuvUl7wbqYx76Wv3/1ZojiNNgy7ie4rYlyB/6vlBS97F4ZxJdxMlabbCW\n6b3EMWa4EVVXKoA1sCY7IVDE+yoQ1JYsZmq45YzPAoGBANWWHuVueFGZRDZlkNlK\nh5OmySmA0NdNug3G1upaTthyaTZ+CxGliwBqMHAwpkIRPwxUJpUwBTSEGztGTAxs\nWsUOVWlD2/1JaKSmHE8JbNg6sxLilcG6WEDzxjC5dLL1OrGOXj9WhC9KX3sq6qb6\nF/j9eUXfXjAlb042MphoF3ZC\n-----END PRIVATE KEY-----\n"),
|
| 24 |
+
"client_email": get_secret("GOOGLE_CLIENT_EMAIL_1", "gspread-connection@model-sheets-connect.iam.gserviceaccount.com"),
|
| 25 |
+
"client_id": get_secret("GOOGLE_CLIENT_ID_1", "100369174533302798535"),
|
| 26 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
| 27 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
| 28 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
| 29 |
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40model-sheets-connect.iam.gserviceaccount.com"
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
credentials2 = {
|
| 33 |
+
"type": "service_account",
|
| 34 |
+
"project_id": get_secret("GOOGLE_PROJECT_ID_2", "sheets-api-connect-378620"),
|
| 35 |
+
"private_key_id": get_secret("GOOGLE_PRIVATE_KEY_ID_2", "1005124050c80d085e2c5b344345715978dd9cc9"),
|
| 36 |
+
"private_key": get_secret("GOOGLE_PRIVATE_KEY_2", "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtKa01beXwc88R\nnPZVQTNPVQuBnbwoOfc66gW3547ja/UEyIGAF112dt/VqHprRafkKGmlg55jqJNt\na4zceLKV+wTm7vBu7lDISTJfGzCf2TrxQYNqwMKE2LOjI69dBM8u4Dcb4k0wcp9v\ntW1ZzLVVuwTvmrg7JBHjiSaB+x5wxm/r3FOiJDXdlAgFlytzqgcyeZMJVKKBQHyJ\njEGg/1720A0numuOCt71w/2G0bDmijuj1e6tH32MwRWcvRNZ19K9ssyDz2S9p68s\nYDhIxX69OWxwScTIHLY6J2t8txf/XMivL/636fPlDADvBEVTdlT606n8CcKUVQeq\npUVdG+lfAgMBAAECggEAP38SUA7B69eTfRpo658ycOs3Amr0JW4H/bb1rNeAul0K\nZhwd/HnU4E07y81xQmey5kN5ZeNrD5EvqkZvSyMJHV0EEahZStwhjCfnDB/cxyix\nZ+kFhv4y9eK+kFpUAhBy5nX6T0O+2T6WvzAwbmbVsZ+X8kJyPuF9m8ldcPlD0sce\ntj8NwVq1ys52eosqs7zi2vjt+eMcaY393l4ls+vNq8Yf27cfyFw45W45CH/97/Nu\n5AmuzlCOAfFF+z4OC5g4rei4E/Qgpxa7/uom+BVfv9G0DIGW/tU6Sne0+37uoGKt\nW6DzhgtebUtoYkG7ZJ05BTXGp2lwgVcNRoPwnKJDxQKBgQDT5wYPUBDW+FHbvZSp\nd1m1UQuXyerqOTA9smFaM8sr/UraeH85DJPEIEk8qsntMBVMhvD3Pw8uIUeFNMYj\naLmZFObsL+WctepXrVo5NB6RtLB/jZYxiKMatMLUJIYtcKIp+2z/YtKiWcLnwotB\nWdCjVnPTxpkurmF2fWP/eewZ+wKBgQDRMtJg7etjvKyjYNQ5fARnCc+XsI3gkBe1\nX9oeXfhyfZFeBXWnZzN1ITgFHplDznmBdxAyYGiQdbbkdKQSghviUQ0igBvoDMYy\n1rWcy+a17Mj98uyNEfmb3X2cC6WpvOZaGHwg9+GY67BThwI3FqHIbyk6Ko09WlTX\nQpRQjMzU7QKBgAfi1iflu+q0LR+3a3vvFCiaToskmZiD7latd9AKk2ocsBd3Woy9\n+hXXecJHPOKV4oUJlJgvAZqe5HGBqEoTEK0wyPNLSQlO/9ypd+0fEnArwFHO7CMF\nycQprAKHJXM1eOOFFuZeQCaInqdPZy1UcV5Szla4UmUZWkk1m24blHzXAoGBAMcA\nyH4qdbxX9AYrC1dvsSRvgcnzytMvX05LU0uF6tzGtG0zVlub4ahvpEHCfNuy44UT\nxRWW/oFFaWjjyFxO5sWggpUqNuHEnRopg3QXx22SRRTGbN45li/+QAocTkgsiRh1\nqEcYZsO4mPCsQqAy6E2p6RcK+Xa+omxvSnVhq0x1AoGAKr8GdkCl4CF6rieLMAQ7\nLNBuuoYGaHoh8l5E2uOQpzwxVy/nMBcAv+2+KqHEzHryUv1owOi6pMLv7A9mTFoS\n18B0QRLuz5fSOsVnmldfC9fpUc6H8cH1SINZpzajqQA74bPwELJjnzrCnH79TnHG\nJuElxA33rFEjbgbzdyrE768=\n-----END PRIVATE KEY-----\n"),
|
| 37 |
+
"client_email": get_secret("GOOGLE_CLIENT_EMAIL_2", "gspread-connection@sheets-api-connect-378620.iam.gserviceaccount.com"),
|
| 38 |
+
"client_id": get_secret("GOOGLE_CLIENT_ID_2", "106625872877651920064"),
|
| 39 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
| 40 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
| 41 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
| 42 |
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40sheets-api-connect-378620.iam.gserviceaccount.com"
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
gc = service_account_from_dict(credentials)
|
| 46 |
+
gc2 = service_account_from_dict(credentials2)
|
| 47 |
+
|
| 48 |
+
# MongoDB URI
|
| 49 |
+
uri = get_secret("MONGODB_URI", "mongodb+srv://multichem:Xr1q5wZdXPbxdUmJ@testcluster.lgwtp5i.mongodb.net/?retryWrites=true&w=majority")
|
| 50 |
+
|
| 51 |
+
client = MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=10000, w=0)
|
| 52 |
+
|
| 53 |
+
nhl_db = client['NHL_Database']
|
| 54 |
+
|
| 55 |
+
# Google Sheets URL
|
| 56 |
+
NHL_Master_hold = get_secret("MASTER_SHEET_URL", 'https://docs.google.com/spreadsheets/d/1NmKa-b-2D3w7rRxwMPSchh31GKfJ1XcDI2GU8rXWnHI/edit#gid=578660863')
|
| 57 |
+
|
| 58 |
+
# Discord Webhook
|
| 59 |
+
discord = Discord(url=get_secret("DISCORD_WEBHOOK_URL", "https://discord.com/api/webhooks/1244687568394780672/COng4Gz1JFdoS-zCCcB24tQWo1upansxWFdfIv16_HZIb_j7-glZoGd4TXAGJDLIRiIJ"))
|
src/sports/nhl_functions.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/streamlit_app.py
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|