Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@

#### ② Frontend
![JavaScript](https://img.shields.io/badge/JavaScript-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)
![Plotly](https://img.shields.io/badge/Plotly-0d1117?style=for-the-badge&logo=plotly&logoColor=3F4F75)
![CSS](https://img.shields.io/badge/CSS-1572B6?style=for-the-badge&logo=css3&logoColor=white)
![HTML](https://img.shields.io/badge/HTML-E34F26?style=for-the-badge&logo=html5&logoColor=white)

- JavaScript + CSS + HTML — visualize plotly graphs and interactive components.
- JavaScript + Plotly + CSS + HTML — visualize plotly graphs and interactive components.

#### ③ CI/CD
![Pytest](https://img.shields.io/badge/Pytest-0A9EDC?style=for-the-badge&logo=pytest&logoColor=white)
Expand All @@ -48,3 +49,13 @@
- Pytest — unit & API tests.
- GitHub — CI/CD pipeline triggers.
- Railway — exploration platform deployment.

#### [④ Special Image Exporter: html2canvas](https://html2canvas.hertzen.com)

Is the card-export engine since LinesShines v1.3.0~~

I truly recommend [html2canvas](https://github.com/niklasvh/html2canvas) for:

- DOM-to-image conversion without needing a server-side rendering step.
- ignoreElements support — let UI controls (close buttons, resize handles) stay out of exported images.
- MIT-licensed, which is cleanly preserved in vendored files.
5 changes: 3 additions & 2 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
NFL_BASE_PATH = os.path.dirname(os.path.abspath(__file__))
DATA_FOLDER_PATH = os.path.join(NFL_BASE_PATH, "data")

ROUNDING_DIGITS = 1
ROUNDING_DECIMALS = 3 # Better precision alleviates overlaps in plots.
DISPLAY_DECIMALS = 1 # For UI displays only.

FRONT_7_NAMES = {"DI": "Defensive Interior", "ED": "Edge", "LB": "Linebacker"}
OL_NAMES = {"T": "Offensive Tackles", "G": "Guards", "C": "Centers"}
Expand All @@ -15,7 +16,7 @@
"Allowed Havoc Rate = (Sacks + QB Hits) / Non Spike Pass Block Snaps."
)

# Default thresholds applied on page load.
# Default "historical seasons'" thresholds applied on page load.
DEFAULT_THRESHOLDS = {
"pass_rush": 230, # Min PR Opp for pass rush filter.
"pass_block": 300, # Min Non Spike PB Snaps for pass block filter.
Expand Down
14 changes: 7 additions & 7 deletions database/db_ingestion.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
per-row upsert and dialect-agnostic (works on both SQLite and Postgres).

Usage:
1. Must always go from repo root.
1. Must always go from project root.
2. After running two preprocessing scripts.
3. python -m database.db_ingestion

For Railway, set DATABASE_URL to Postgres URL Railway assigns.
Point LINESHINES_REPO_ROOT at LinesShines repo root so scripts can
Point LINESHINES_REPO_ROOT at LinesShines project root so scripts can
locate xlsx files under $LINESHINES_REPO_ROOT/data/.
"""

Expand All @@ -37,14 +37,14 @@
OL_POSITIONS = ("T", "G", "C")


def _find_repo_root() -> Path:
"""Walk up from this file until we find a marker that identifies the repo root."""
def _find_project_root() -> Path:
"""Walk up from this file until we find a marker that identifies project root."""
here = Path(__file__).resolve().parent
for candidate in [here, *here.parents]:
if (candidate / ".gitignore").exists():
return candidate # Root is found.

raise RuntimeError("could not locate repo root from " + str(here))
raise RuntimeError("could not locate project root from " + str(here))


def _repo_root() -> Path:
Expand All @@ -64,7 +64,7 @@ def _repo_root() -> Path:
if env_root:
return Path(env_root) / "data"

return _find_repo_root() / "data"
return _find_project_root() / "data"


def _safe_int(val):
Expand Down Expand Up @@ -238,7 +238,7 @@ def main() -> None:
pass_block_rows = ingest_pass_block(sess, data_dir, args.seasons)

print(
f"\nIngested {pass_rush_rows} pass-rush rows and {pass_block_rows} pass-block rows."
f"\nBulk-inserted {pass_rush_rows} pass-rush rows and {pass_block_rows} pass-block rows."
)


Expand Down
Loading
Loading