Skip to content

Commit

Permalink
Merge pull request #824 from a-luna/patch-release/v0.5.4
Browse files Browse the repository at this point in the history
v0.5.4
  • Loading branch information
a-luna authored Aug 8, 2021
2 parents 54fbbb7 + a4b3b7b commit 0031458
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 111 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vig-node-deps",
"version": "0.5.3",
"version": "0.5.4",
"description": "This file is used for heroku deployment, the postbuild script below is called after each push to install the dependencies listed in the REAL package.json in the nightmarejs folder. Yes, I know that it is lame and hacky to have this root package.json file that exists solely to tap on the shoulder of another package.json and ask sheepishly to run freaking 'npm install' simply because heroku couldn't possibly manage the herculean feat of locating a package.json file anywhere but the root folder, but that's where we are and that's why this file exists.",
"scripts": {
"heroku-postbuild": "cd src/vigorish/nightmarejs && npm install"
Expand Down
26 changes: 13 additions & 13 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ backports.entry-points-selectable==1.1.0
black==21.5b1
bleach==3.3.1
blessed==1.18.1
boto3==1.18.10
botocore==1.21.10
boto3==1.18.16
botocore==1.21.16
bullet==2.2.0
certifi==2021.5.30
cffi==1.14.6
chardet==4.0.0
charset-normalizer==2.0.3
cheap-repr==0.4.5
charset-normalizer==2.0.4
cheap-repr==0.4.6
click==7.1.2
cognitive-complexity==1.2.0
cohesion==1.0.0
Expand Down Expand Up @@ -49,9 +49,9 @@ flake8-use-fstring==1.1
flake8-variables-names==0.0.4
getversion==1.0.2
halo==0.0.31
identify==2.2.11
identify==2.2.13
idna==2.10
importlib-metadata==4.6.1
importlib-metadata==4.6.3
iniconfig==1.1.1
ipdb==0.13.9
ipykernel==6.0.3
Expand Down Expand Up @@ -80,7 +80,7 @@ pathspec==0.9.0
pexpect==4.8.0
pickleshare==0.7.5
pip-upgrader==1.4.15
pipdeptree==2.0.0
pipdeptree==2.1.0
pkginfo==1.7.1
platformdirs==2.2.0
pluggy==0.13.1
Expand Down Expand Up @@ -110,15 +110,15 @@ python-dateutil==2.8.2
python-dotenv==0.19.0
pytz==2021.1
PyYAML==5.4.1
pyzmq==22.1.0
pyzmq==22.2.1
rapidfuzz==1.4.1
readme-renderer==29.0
regex==2021.7.6
regex==2021.8.3
requests==2.26.0
requests-toolbelt==0.9.1
rfc3986==1.5.0
s3transfer==0.5.0
scipy==1.7.0
scipy==1.7.1
SecretStorage==3.3.1
setuptools-scm==6.0.1
six==1.16.0
Expand All @@ -134,15 +134,15 @@ termcolor==1.1.0
terminaltables==3.1.0
toml==0.10.2
tornado==6.1
tox==3.24.0
tqdm==4.61.2
tox==3.24.1
tqdm==4.62.0
traitlets==5.0.5
twine==3.4.2
typed-ast==1.4.3
typepy==1.2.0
typing-extensions==3.10.0.0
urllib3==1.26.6
virtualenv==20.6.0
virtualenv==20.7.0
w3lib==1.22.0
wcwidth==0.2.5
webencodings==0.5.1
Expand Down
8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
aenum==3.1.0
blessed==1.18.1
boto3==1.18.10
botocore==1.21.10
boto3==1.18.16
botocore==1.21.16
bullet==2.2.0
certifi==2021.5.30
chardet==4.0.0
Expand All @@ -25,14 +25,14 @@ PyYAML==5.4.1
rapidfuzz==1.4.1
requests==2.26.0
s3transfer==0.5.0
scipy==1.7.0
scipy==1.7.1
six==1.16.0
spinners==0.0.24
SQLAlchemy>=1.3.23,<1.4.0
SQLAlchemy-Utils==0.37.8
tabulate==0.8.9
termcolor==1.1.0
tqdm==4.61.2
tqdm==4.62.0
urllib3==1.26.6
w3lib==1.22.0
wcwidth==0.2.5
63 changes: 8 additions & 55 deletions src/vigorish/data/metrics/pfx_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@ def __repr__(self):
def pitch_name(self) -> str:
return self.pitch_type.print_name

@property
def triple_slash(self) -> str:
return (
f"{format_decimal_bat_stat(self.avg)}/"
f"{format_decimal_bat_stat(self.obp)}/"
f"{format_decimal_bat_stat(self.slg)} ({format_decimal_bat_stat(self.ops)})"
)

@cached_property
def pitch_type_int(self):
return sum({p.pitch_type_int for p in self.pfx})
Expand All @@ -56,6 +48,14 @@ def pitch_type(self) -> PitchType:
def pitch_type_abbrevs(self) -> List[str]:
return [str(pt) for pt in self.pitch_type]

@property
def triple_slash(self) -> str:
return (
f"{format_decimal_bat_stat(self.avg)}/"
f"{format_decimal_bat_stat(self.obp)}/"
f"{format_decimal_bat_stat(self.slg)} ({format_decimal_bat_stat(self.ops)})"
)

@cached_property
def total_pitches(self) -> int:
return len(self.pfx)
Expand Down Expand Up @@ -443,50 +443,3 @@ def get_batted_ball_stats(self, include_bip_count: bool = False) -> Dict[str, st
def get_usage_stats(self, include_pitch_count: bool = False) -> str:
pitch_count = f" ({self.total_pitches})" if include_pitch_count else ""
return f"{self.percent:.0%}{pitch_count} {self.avg_speed:.1f}mph"


# from vigorish.app import Vigorish
# from vigorish.data.metrics.pfx_metrics import PitchFxMetrics
# mlb_id = 621111
# game_id = "LAN202106130"
# app = Vigorish()
# pfx_for_game = PitchFxMetrics.for_pitcher_game(app.db_session, mlb_id, game_id)

# from vigorish.app import Vigorish
# from vigorish.data.metrics.pfx_metrics import PitchFxMetrics
# from vigorish.data.player_data import PlayerData
# mlb_id = 621111
# game_id = "LAN202106130"
# app = Vigorish()
# pd = PlayerData(app, mlb_id)
# pfx = pd.get_pfx_bat_metrics_for_game(game_id)

# import json
# from pathlib import Path
# from vigorish.app import Vigorish
# from vigorish.data.metrics.pfx_metrics import PitchFxMetrics
# from vigorish.util.datetime_util import format_timedelta_str
# mlb_id = 425794
# app = Vigorish()
# pfx_by_year = PitchFxMetrics.for_pitcher_by_year(app.db_session, mlb_id)
# Path("pfx_metrics_example.json").write_text(json.dumps(pfx_by_year, indent=2, sort_keys=False))

# import json
# from pathlib import Path
# from vigorish.app import Vigorish
# from vigorish.data.player_data import PlayerData
# app = Vigorish()
# pd = PlayerData(app, 621111)
# career_pfx=pd.get_all_pfx_career_data()
# career_pfx["all"]["metrics"] = career_pfx["all"]["metrics"].as_dict()
# career_pfx["rhb"]["metrics"] = career_pfx["rhb"]["metrics"].as_dict()
# career_pfx["lhb"]["metrics"] = career_pfx["lhb"]["metrics"].as_dict()
# yearly_pfx=pd.get_all_pfx_yearly_data()
# for year, pfx_stats_for_year in yearly_pfx["all"]["metrics"].items():
# yearly_pfx["all"]["metrics"][year] = pfx_stats_for_year.as_dict()
# for year, pfx_stats_for_year in yearly_pfx["rhb"]["metrics"].items():
# yearly_pfx["rhb"]["metrics"][year] = pfx_stats_for_year.as_dict()
# for year, pfx_stats_for_year in yearly_pfx["lhb"]["metrics"].items():
# yearly_pfx["lhb"]["metrics"][year] = pfx_stats_for_year.as_dict()
# Path("career_pfx.json").write_text(json.dumps(career_pfx, indent=2, sort_keys=False))
# Path("yearly_pfx.json").write_text(json.dumps(yearly_pfx, indent=2, sort_keys=False))
31 changes: 26 additions & 5 deletions src/vigorish/data/scraped_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
)
from vigorish.data.name_search import PlayerNameSearch
from vigorish.enums import DataSet, DefensePosition, PitchType, VigFile
from vigorish.util.dt_format_strings import DATE_ONLY_TABLE_ID
from vigorish.util.list_helpers import flatten_list2d, group_and_sort_list
from vigorish.util.regex import URL_ID_CONVERT_REGEX, URL_ID_REGEX
from vigorish.util.result import Result
Expand Down Expand Up @@ -260,14 +261,34 @@ def get_all_seasons_with_data_for_player(self, player_mlb_id: int) -> List[db.Se
def player_name_search(self, query):
return self.name_search.fuzzy_match(query)

def get_season_standings(self, year=None):
if not year:
most_recent_season = max(s.year for s in db.Season.get_all_regular_seasons(self.db_session))
year = most_recent_season
def get_pitch_apps_for_player_up_to_date(self, mlb_id, game_date):
player_id = db.PlayerId.find_by_mlb_id(self.db_session, mlb_id)
if not player_id:
return []
date_id = game_date.strftime(DATE_ONLY_TABLE_ID)
date_status = self.db_session.query(db.DateScrapeStatus).get(int(date_id))
return (
self.db_session.query(db.PitchStats)
.filter(db.PitchStats.player_id == player_id.db_player_id)
.filter(db.PitchStats.date_id <= date_id)
.filter(db.PitchStats.season_id == date_status.season_id)
)

def get_pitcher_record_on_date(self, mlb_id, game_date):
pitch_apps = self.get_pitch_apps_for_player_up_to_date(mlb_id, game_date)
wins = sum(p.is_wp for p in pitch_apps)
losses = sum(p.is_lp for p in pitch_apps)
return (wins, losses)

def get_pitcher_total_saves_on_date(self, mlb_id, game_date):
pitch_apps = self.get_pitch_apps_for_player_up_to_date(mlb_id, game_date)
return sum(p.is_sv for p in pitch_apps)

def get_season_standings(self, year, game_date=None):
standings = []
all_teams = db.Team.get_all_teams_for_season(self.db_session, year)
for team in all_teams:
all_games = db.GameScrapeStatus.get_all_games_for_team(self.db_session, team.team_id_br, year)
all_games = db.GameScrapeStatus.get_all_games_for_team(self.db_session, team.team_id_br, year, game_date)
away_games = list(filter(lambda x: x.away_team_id_br == team.team_id_br, all_games))
home_games = list(filter(lambda x: x.home_team_id_br == team.team_id_br, all_games))
away_results = self._get_away_game_results(away_games)
Expand Down
4 changes: 4 additions & 0 deletions src/vigorish/models/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ def __repr__(self):
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}

@property
def name(self):
return f"{self.name_first} {self.name_last}"

@classmethod
def find_by_bbref_id(cls, db_session, bbref_id):
return db_session.query(cls).filter_by(bbref_id=bbref_id).first()
Expand Down
8 changes: 5 additions & 3 deletions src/vigorish/models/season.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""Db model that describes a MLB season and tracks data scraping progress."""
from __future__ import annotations

from datetime import date, datetime
from typing import List

from sqlalchemy import Column, DateTime, Integer
from sqlalchemy.ext.hybrid import hybrid_property
Expand Down Expand Up @@ -522,9 +525,8 @@ def is_date_in_season(cls, db_session, check_date, season_type=SeasonType.REGULA
f'{season_type.replace("_", " ").title()}'
)
return Result.Fail(error)
date_str = check_date.strftime(DATE_ONLY)
if check_date < season.start_date or check_date > season.end_date:
error = f"{date_str} is not within the scope of the {season.name}"
error = f"{check_date.strftime(DATE_ONLY)} is not within the scope of the {season.name}"
return Result.Fail(error)
return Result.Ok(season)

Expand Down Expand Up @@ -575,7 +577,7 @@ def validate_date_range(cls, db_session, start, end):
return Result.Ok(season)

@classmethod
def get_all_regular_seasons(cls, db_session):
def get_all_regular_seasons(cls, db_session) -> List[db.Season]:
return db_session.query(cls).filter_by(season_type=SeasonType.REGULAR_SEASON).all()

@classmethod
Expand Down
31 changes: 18 additions & 13 deletions src/vigorish/models/status_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
from sqlalchemy.sql.elements import or_

import vigorish.database as db
from vigorish.models.season import Season
from vigorish.util.dt_format_strings import (
DATE_ONLY,
DATE_ONLY_2,
Expand Down Expand Up @@ -328,7 +328,7 @@ def get_all_brooks_game_ids_for_date(cls, db_session, date):

@classmethod
def get_all_bbref_game_ids_for_team(cls, db_session, team_id_br, year):
season = Season.find_by_year(db_session, year)
season = db.Season.find_by_year(db_session, year)
if not season:
return None
games_for_season = list(db_session.query(cls).filter_by(season_id=season.id).all())
Expand All @@ -341,19 +341,24 @@ def get_all_bbref_game_ids_for_team(cls, db_session, team_id_br, year):
]

@classmethod
def get_all_games_for_team(cls, db_session, team_id_br, year):
season = Season.find_by_year(db_session, year)
def get_all_games_for_team(cls, db_session, team_id_br, year, game_date=None):
if not game_date:
game_date = db.Season.get_most_recent_scraped_date(db_session, year)
if game_date.year != year:
raise ValueError('"year" and "game_date" parameters must belong to the same season')
date_id = game_date.strftime(DATE_ONLY_TABLE_ID)
season = db.Season.find_by_year(db_session, year)
if not season:
return None
games_for_season = list(db_session.query(cls).filter_by(season_id=season.id).all())
games_for_season.sort(key=lambda x: x.scrape_status_date_id)
bb_team_id = get_brooks_team_id(team_id_br)
return [
game
for game in games_for_season
if (game.away_team_id_bb == bb_team_id or game.home_team_id_bb == bb_team_id)
and game.scraped_bbref_boxscore
]
return (
db_session.query(cls)
.filter(cls.season_id == season.id)
.filter(cls.scrape_status_date_id <= date_id)
.filter(or_(cls.away_team_id_br == team_id_br, cls.home_team_id_br == team_id_br))
.filter(cls.scraped_bbref_boxscore == 1)
.order_by(cls.scrape_status_date_id)
.all()
)

@classmethod
def get_game_id_map(cls, db_session):
Expand Down
2 changes: 1 addition & 1 deletion src/vigorish/nightmarejs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/vigorish/nightmarejs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vig-nodejs",
"version": "0.5.3",
"version": "0.5.4",
"description": "NightmareJS and other node modules used to scrape html from websites",
"author": "Aaron Luna <[email protected]> (https://aaronluna.dev)",
"license": "MIT",
Expand Down
Loading

0 comments on commit 0031458

Please sign in to comment.