diff --git a/package.json b/package.json index 7496d62..d480150 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,8 @@ "author": "Nelson Torres ", "license": "Apache-2.0", "dependencies": { + "axios": "^0.21.1", + "csv-parser": "^3.0.0", "tslib": "~2.3.0" }, "volta": { diff --git a/src/datasources/statcast.ts b/src/datasources/statcast.ts new file mode 100644 index 0000000..e854f10 --- /dev/null +++ b/src/datasources/statcast.ts @@ -0,0 +1,30 @@ +import axios from 'axios'; +import * as csv from 'csv-parser'; +import { Readable } from 'stream'; +import { Pitch, Teams } from '../models/statcast'; + +const ROOT_URL = 'https://baseballsavant.mlb.com' + +async function get_statcast_data_from_url(url: string): Promise { + try { + const data = (await axios.get(ROOT_URL + url)).data; + const readable = Readable.from(data); + const pitches: Pitch[] = []; + + return new Promise((resolve, reject) => { + readable.pipe(csv()) + .on('data', (pitch: Pitch) => { + pitches.push(pitch); + }) + .on('end', () => resolve(pitches)) + .on('error', (e) => reject(e)); + }); + } catch (e) { + return e; + } +} + +export async function small_request(startDate: string, endDate: string, team?: Teams): Promise { + const url = `/statcast_search/csv?all=true&hfPT=&hfAB=&hfBBT=&hfPR=&hfZ=&stadium=&hfBBL=&hfNewZones=&hfGT=R%7CPO%7CS%7C=&hfSea=&hfSit=&player_type=pitcher&hfOuts=&opponent=&pitcher_throws=&batter_stands=&hfSA=&game_date_gt=${startDate}&game_date_lt=${endDate}&team=${team}&position=&hfRO=&home_road=&hfFlag=&metric_1=&hfInn=&min_pitches=0&min_results=0&group_by=name&sort_col=pitches&player_event_sort=h_launch_speed&sort_order=desc&min_abs=0&type=details&` + return get_statcast_data_from_url(url); +} diff --git a/src/models/statcast.ts b/src/models/statcast.ts new file mode 100644 index 0000000..4eae67d --- /dev/null +++ b/src/models/statcast.ts @@ -0,0 +1,125 @@ +// TODO: Make sure these are the correct abbreveations for teams +export enum Teams { + ARI = 'ARI', + ATL = 'ATL', + BAL = 'BAL', + CHC = 'CHC', + CHW = 'CHW', + CIN = 'CIN', + CLE = 'CLE', + COL = 'COL', + DET = 'DET', + FLA = 'FLA', + HOU = 'HOU', + KAN = 'KAN', + LAA = 'LAA', + LAD = 'LAD', + MIL = 'MIL', + MIN = 'MIN', + NYM = 'NYM', + NYY = 'NYY', + OAK = 'OAK', + PHI = 'PHI', + PIT = 'PIT', + SD = 'SD', + SF = 'SF', + SEA = 'SEA', + STL = 'STL', + TB = 'TB', + TEX = 'TEX', + TOR = 'TOR', + WAS = 'WAS', +} + +export type Pitch = { + pitch_type: string, + game_date: string, + release_speed: string, + release_pos_x: string, + release_pos_z: string, + player_name: string, + batter: string, + pitcher: string, + events: string, + description: string, + spin_dir: string, + spin_rate_deprecated: string, + break_angle_deprecated: string, + break_length_deprecated: string, + zone: string, + des: string, + game_type: string, + stand: string, + p_throws: string, + home_team: string, + away_team: string, + type: string, + hit_location: string, + bb_type: string, + balls: string, + strikes: string, + game_year: string, + pfx_x: string, + pfx_z: string, + plate_x: string, + plate_z: string, + on_3b: string, + on_2b: string, + on_1b: string, + outs_when_up: string, + inning: string, + inning_topbot: string, + hc_x: string, + hc_y: string, + tfs_deprecated: string, + tfs_zulu_deprecated: string, + fielder_2: string, + umpire: string, + sv_id: string, + vx0: string, + vy0: string, + vz0: string, + ax: string, + ay: string, + az: string, + sz_top: string, + sz_bot: string, + hit_distance_sc: string, + launch_speed: string, + launch_angle: string, + effective_speed: string, + release_spin_rate: string, + release_extension: string, + game_pk: string, + fielder_3: string, + fielder_4: string, + fielder_5: string, + fielder_6: string, + fielder_7: string, + fielder_8: string, + fielder_9: string, + release_pos_y: string, + estimated_ba_using_speedangle: string, + estimated_woba_using_speedangle: string, + woba_value: string, + woba_denom: string, + babip_value: string, + iso_value: string, + launch_speed_angle: string, + at_bat_number: string, + pitch_number: string, + pitch_name: string, + home_score: string, + away_score: string, + bat_score: string, + fld_score: string, + post_away_score: string, + post_home_score: string, + post_bat_score: string, + post_fld_score: string, + if_fielding_alignment: string, + of_fielding_alignment: string, + spin_axis: string, + delta_home_win_exp: string, + delta_run_exp: string, +} diff --git a/yarn.lock b/yarn.lock index f77e647..292a9d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -647,9 +647,9 @@ integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== "@types/node@*": - version "16.6.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.1.tgz#aee62c7b966f55fc66c7b6dfa1d58db2a616da61" - integrity sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw== + version "16.6.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50" + integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA== "@types/node@~14.14.45": version "14.14.45" @@ -926,6 +926,13 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +axios@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" + integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== + dependencies: + follow-redirects "^1.10.0" + babel-jest@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.0.6.tgz#e99c6e0577da2655118e3608b68761a5a69bd0d8" @@ -1013,15 +1020,15 @@ browser-process-hrtime@^1.0.0: integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== browserslist@^4.16.6: - version "4.16.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.7.tgz#108b0d1ef33c4af1b587c54f390e7041178e4335" - integrity sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA== + version "4.16.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.8.tgz#cb868b0b554f137ba6e33de0ecff2eda403c4fb0" + integrity sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ== dependencies: - caniuse-lite "^1.0.30001248" - colorette "^1.2.2" - electron-to-chromium "^1.3.793" + caniuse-lite "^1.0.30001251" + colorette "^1.3.0" + electron-to-chromium "^1.3.811" escalade "^3.1.1" - node-releases "^1.1.73" + node-releases "^1.1.75" bs-logger@0.x: version "0.2.6" @@ -1057,7 +1064,7 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001248: +caniuse-lite@^1.0.30001251: version "1.0.30001251" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85" integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A== @@ -1137,7 +1144,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.2.2: +colorette@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w== @@ -1187,6 +1194,13 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" +csv-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/csv-parser/-/csv-parser-3.0.0.tgz#b88a6256d79e090a97a1b56451f9327b01d710e7" + integrity sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ== + dependencies: + minimist "^1.2.0" + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -1264,10 +1278,10 @@ domexception@^2.0.1: dependencies: webidl-conversions "^5.0.0" -electron-to-chromium@^1.3.793: - version "1.3.809" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.809.tgz#86db795c41c97f252ee1c849a2f70d0739710776" - integrity sha512-bZoXTEhEe8o10dHX2gNY9KkCSwz1AFk4c0GbmzlTD5WAkUpDb/zY7JjvLvJ/y1wUsURiVmlGdnIeU+gFyTeaXA== +electron-to-chromium@^1.3.811: + version "1.3.812" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.812.tgz#4c4fb407e0e1335056097f172e9f2c0a09efe77d" + integrity sha512-7KiUHsKAWtSrjVoTSzxQ0nPLr/a+qoxNZwkwd9LkylTOgOXSVXkQbpIVT0WAUQcI5gXq3SwOTCrK+WfINHOXQg== emittery@^0.8.1: version "0.8.1" @@ -1558,6 +1572,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== +follow-redirects@^1.10.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.2.tgz#cecb825047c00f5e66b142f90fed4f515dec789b" + integrity sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -2477,7 +2496,7 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.5: +minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -2502,10 +2521,10 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-releases@^1.1.73: - version "1.1.74" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.74.tgz#e5866488080ebaa70a93b91144ccde06f3c3463e" - integrity sha512-caJBVempXZPepZoZAPCWRTNxYQ+xtG/KAi4ozTA5A+nJ7IU+kLQCbqaUjb5Rwy14M9upBWiQ4NutcmW04LJSRw== +node-releases@^1.1.75: + version "1.1.75" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe" + integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw== normalize-path@^3.0.0: version "3.0.0"