Spaces:
Sleeping
Sleeping
Hatmanstack commited on
Commit ·
7b3455b
1
Parent(s): e692f4f
Address reviewer feedback: fix grammar, path resolution, and sampling logic
Browse files- README.md +1 -1
- src/database/connection.py +4 -2
- src/database/queries.py +21 -7
- tests/test_database.py +3 -1
README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# NBA Fantasy App
|
| 2 |
|
| 3 |
-
This repository has a Streamlit app that lets you create
|
| 4 |
|
| 5 |
To determine the winner of each game, the app uses a functional Keras model that was trained using the 2018 season's game by game results. The model uses season averages in stats from the starting five players as features against thier wins and losses. The training data and model script are included.
|
| 6 |
|
|
|
|
| 1 |
# NBA Fantasy App
|
| 2 |
|
| 3 |
+
This repository has a Streamlit app that lets you create an NBA fantasy team and compete against computer-generated teams. The app uses a local CSV file that contains historical NBA player data.
|
| 4 |
|
| 5 |
To determine the winner of each game, the app uses a functional Keras model that was trained using the 2018 season's game by game results. The model uses season averages in stats from the starting five players as features against thier wins and losses. The training data and model script are included.
|
| 6 |
|
src/database/connection.py
CHANGED
|
@@ -10,7 +10,8 @@ import streamlit as st
|
|
| 10 |
|
| 11 |
logger = logging.getLogger("streamlit_nba")
|
| 12 |
|
| 13 |
-
|
|
|
|
| 14 |
|
| 15 |
|
| 16 |
class DatabaseConnectionError(Exception):
|
|
@@ -46,7 +47,8 @@ def load_data() -> pd.DataFrame:
|
|
| 46 |
return df
|
| 47 |
except Exception as e:
|
| 48 |
logger.error(f"Failed to load CSV data: {e}")
|
| 49 |
-
|
|
|
|
| 50 |
|
| 51 |
|
| 52 |
@contextmanager
|
|
|
|
| 10 |
|
| 11 |
logger = logging.getLogger("streamlit_nba")
|
| 12 |
|
| 13 |
+
# Resolve path relative to this module
|
| 14 |
+
CSV_PATH = Path(__file__).resolve().parent.parent.parent / "snowflake_nba.csv"
|
| 15 |
|
| 16 |
|
| 17 |
class DatabaseConnectionError(Exception):
|
|
|
|
| 47 |
return df
|
| 48 |
except Exception as e:
|
| 49 |
logger.error(f"Failed to load CSV data: {e}")
|
| 50 |
+
msg = f"Could not load data from {CSV_PATH}: {e}"
|
| 51 |
+
raise DatabaseConnectionError(msg) from e
|
| 52 |
|
| 53 |
|
| 54 |
@contextmanager
|
src/database/queries.py
CHANGED
|
@@ -91,16 +91,30 @@ def get_away_team_by_stats(
|
|
| 91 |
DataFrame with 5 players
|
| 92 |
|
| 93 |
Raises:
|
| 94 |
-
|
| 95 |
"""
|
| 96 |
for attempt in range(max_attempts):
|
| 97 |
try:
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
if len(results) == 5:
|
| 106 |
logger.info(f"Got away team on attempt {attempt + 1}")
|
|
|
|
| 91 |
DataFrame with 5 players
|
| 92 |
|
| 93 |
Raises:
|
| 94 |
+
QueryExecutionError: If unable to get 5 players within max_attempts
|
| 95 |
"""
|
| 96 |
for attempt in range(max_attempts):
|
| 97 |
try:
|
| 98 |
+
# Sample without replacement across all picks
|
| 99 |
+
df1 = df[df["PTS"] > pts_threshold].sample(n=2, replace=False)
|
| 100 |
+
|
| 101 |
+
# For subsequent picks, exclude already chosen players
|
| 102 |
+
chosen = df1
|
| 103 |
+
|
| 104 |
+
df2 = df[
|
| 105 |
+
(df["REB"] > reb_threshold) & (~df.index.isin(chosen.index))
|
| 106 |
+
].sample(n=1, replace=False)
|
| 107 |
+
chosen = pd.concat([chosen, df2])
|
| 108 |
+
|
| 109 |
+
df3 = df[
|
| 110 |
+
(df["AST"] > ast_threshold) & (~df.index.isin(chosen.index))
|
| 111 |
+
].sample(n=1, replace=False)
|
| 112 |
+
chosen = pd.concat([chosen, df3])
|
| 113 |
+
|
| 114 |
+
df4 = df[
|
| 115 |
+
(df["STL"] > stl_threshold) & (~df.index.isin(chosen.index))
|
| 116 |
+
].sample(n=1, replace=False)
|
| 117 |
+
results = pd.concat([chosen, df4])
|
| 118 |
|
| 119 |
if len(results) == 5:
|
| 120 |
logger.info(f"Got away team on attempt {attempt + 1}")
|
tests/test_database.py
CHANGED
|
@@ -54,7 +54,9 @@ class TestGetPlayersByFullNames:
|
|
| 54 |
assert set(result["FULL_NAME"]) == set(names)
|
| 55 |
assert list(result.columns) == PLAYER_COLUMNS
|
| 56 |
|
| 57 |
-
def test_empty_names_returns_empty_dataframe(
|
|
|
|
|
|
|
| 58 |
"""Test that empty input returns empty DataFrame."""
|
| 59 |
result = get_players_by_full_names(sample_player_df, [])
|
| 60 |
|
|
|
|
| 54 |
assert set(result["FULL_NAME"]) == set(names)
|
| 55 |
assert list(result.columns) == PLAYER_COLUMNS
|
| 56 |
|
| 57 |
+
def test_empty_names_returns_empty_dataframe(
|
| 58 |
+
self, sample_player_df: pd.DataFrame
|
| 59 |
+
) -> None:
|
| 60 |
"""Test that empty input returns empty DataFrame."""
|
| 61 |
result = get_players_by_full_names(sample_player_df, [])
|
| 62 |
|