/* BT player stat ranges v1.5 (October 15, 2026; exact PA; Acquired-by-trade links to the Trade Tree): hitters Last game / Last 10-20-50-100 PA, pitchers Last game / Last 3-5-10-20 apps, Year menu (MLB seasons only), custom date range across seasons. MLB Stats API game logs, regular season. */ (function(){ var Q=String.fromCharCode(63),E=String.fromCharCode(61),A=String.fromCharCode(38),API='https://statsapi.mlb.com/api/v1/'; var FIPC={2015:3.134,2016:3.147,2017:3.158,2018:3.161,2019:3.214,2020:3.191,2021:3.170,2022:3.112,2023:3.255,2024:3.166,2025:3.135,2026:3.150}; var MON=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; function q(o){return Object.keys(o).map(function(k){return k+E+o[k]}).join(A)} function J(u){return fetch(u).then(function(r){return r.json()})} function fd(d){var p=d.split('-');return MON[+p[1]-1]+' '+(+p[2])+', '+p[0]} function fds(a,b){if(a===b)return fd(a);var x=a.split('-'),y=b.split('-');if(x[0]===y[0])return MON[+x[1]-1]+' '+(+x[2])+'–'+(x[1]===y[1]?'':MON[+y[1]-1]+' ')+(+y[2])+', '+y[0];return fd(a)+' – '+fd(b)} function r3(v){if(!isFinite(v))return '—';var s=v.toFixed(3);return v<1?s.replace(/^0/,''):s} function pct(a,b){return b?(100*a/b).toFixed(1)+'%':'—'} function ip(o){return Math.floor(o/3)+'.'+(o%3)} function box(l,v){return '
| Date | Opp | IP | H | ER | BB | K | HR | ':'Date | Opp | PA | AB | H | 2B | HR | BB | K | ')+'
|---|
MLB regular season. Source: MLB Stats API game logs.
'; function btFgApply(y){fgExtra(y).then(function(fg){if(!fg)return;function ap(){if(window.btpYr!==y){mo.disconnect();return}var M=body.querySelector('.btp-line4');if(M&&fg.w!=null&&!M.querySelector('.btp-fwar')){var d=document.createElement('div');d.className='btp-fwar';d.innerHTML='fWAR'+(+fg.w).toFixed(1)+'';M.appendChild(d)}var c=body.querySelector('.btp-idx');if(c&&!pit&&fg.rc!=null&&/wRC\+/.test(c.textContent)){var st=c.querySelector('strong'),v=String(Math.round(fg.rc));if(st&&st.textContent!==v)st.textContent=v;var u=c.querySelector('span em');if(u&&/park/i.test(u.textContent))u.remove()}}var mo=new MutationObserver(ap);mo.observe(body,{childList:true,subtree:true});ap();setTimeout(function(){mo.disconnect()},20000)})['catch'](function(){})} function btCsv(t){var rows=[],L=t.split(/\r?\n/),hd=null;L.forEach(function(l){if(!l)return;var o=[],c='',qq=false;for(var i=0;iPercentile among MLB '+(pit?'pitchers':'hitters')+' via Baseball Savant: red is above average, blue below, and the darker the color the further from average. 50 = average.'+(d.q?'':' Not enough playing time to be ranked that season, so only his numbers are shown.')+'
';return el} function btScApply(y){btScData(y).then(function(d){if(!d)return;function ap(){if(window.btpYr!==y){mo.disconnect();return}if(!body.querySelector('.btp-sc')&&body.querySelector('.btp-line4'))body.appendChild(btScHtml(d,y))}var mo=new MutationObserver(ap);mo.observe(body,{childList:true,subtree:true});ap();setTimeout(function(){mo.disconnect()},20000)})} function fgExtra(yr){var key='btpr-fg-'+grp+'-'+yr+'-'+id;try{var c=sessionStorage.getItem(key);if(c)return Promise.resolve(JSON.parse(c))}catch(e){} return J('https://www.fangraphs.com/api/leaders/major-league/data'+Q+q({pos:'all',stats:pit?'pit':'bat',lg:'all',qual:0,type:8,season:yr,season1:yr,ind:0,team:0,pageitems:3000})).then(function(j){var r=(j.data||[]).filter(function(x){return String(x.xMLBAMID)===String(id)})[0];var o=r?{w:r.WAR,rc:r['wRC+']}:null;try{sessionStorage.setItem(key,JSON.stringify(o))}catch(e){}return o})["catch"](function(){return null})} function showYear(y){if(y===Y[0]&&origIsMLB){if(window.btpYr&&window.btpSetYear){window.btpYr=0;window.btpSetYear(0)}showOrig();return}if(window.btpSetYear){loading();setOn(null);sel.value=String(y);window.btpYr=y;window.btpSetYear(y).then(function(){showOrig();sel.value=String(y);btFgApply(y);btScApply(y)});return}loading();setOn(null);sel.value=String(y);Promise.all([logs(y),fgExtra(y)]).then(function(r){var G=r[0],fg=r[1];var t=agg(G);var ex='';if(fg){if(!pit&&fg.rc!=null)ex+=box('wRC+',Math.round(fg.rc));if(fg.w!=null)ex+='No MLB regular-season games.
')+NOTE)})} var PBP={};function pbp(pk){if(!PBP[pk])PBP[pk]=J(API+'game/'+pk+'/playByPlay'+Q+'fields'+E+'allPlays,result,type,eventType,matchup,batter,id,pitcher,fullName,about,atBatIndex,isComplete,inning').then(function(d){return (d.allPlays||[]).filter(function(p){return p.matchup&&p.matchup.batter&&String(p.matchup.batter.id)===String(id)&&p.about&&p.about.isComplete!==false&&p.result&&p.result.eventType})})["catch"](function(){return []});return PBP[pk]} var EVN={single:'Single',double:'Double',triple:'Triple',home_run:'Home run',walk:'Walk',intent_walk:'Intentional walk',hit_by_pitch:'Hit by pitch',strikeout:'Strikeout',strikeout_double_play:'Strikeout (DP)',sac_fly:'Sac fly',sac_bunt:'Sac bunt',field_out:'Out',force_out:'Forceout',grounded_into_double_play:'GIDP',double_play:'Double play',fielders_choice:"Fielder's choice",fielders_choice_out:"Fielder's choice",field_error:'Reached on error',catcher_interf:'Catcher interference'}; function paStats(P){var t={pa:P.length,ab:0,h:0,d:0,tr:0,hr:0,bb:0,hbp:0,sf:0,k:0};P.forEach(function(x){var e=x.ev;if(e==='single')t.h++;else if(e==='double'){t.h++;t.d++}else if(e==='triple'){t.h++;t.tr++}else if(e==='home_run'){t.h++;t.hr++}if(e==='walk'||e==='intent_walk')t.bb++;if(e==='hit_by_pitch')t.hbp++;if(/^sac_fly/.test(e))t.sf++;if(/^strikeout/.test(e))t.k++;var noab=/^(walk|intent_walk|hit_by_pitch|sac_fly|sac_fly_double_play|sac_bunt|sac_bunt_double_play|catcher_interf)$/.test(e);if(!noab)t.ab++});return t} function showLast(code,btn){setOn(btn);loading();var kind=code.charAt(0),n=+code.slice(1);var i=0,out=[]; if(kind==='p'){var games=[],gi=0,got=[];(function collect(){if(i>=Y.length)return pull();logs(Y[i]).then(function(G){for(var k=G.length-1;k>=0;k--)if(+(G[k].stat||{}).plateAppearances)games.push(G[k]);var tot=games.reduce(function(a,x){return a+(+(x.stat||{}).plateAppearances||0)},0);if(tot>=n)return pull();i++;collect()})})(); function pull(){if(!games.length){showMine('No MLB plate appearances.
');return}var batch=games.slice(gi,gi+6);gi+=batch.length;Promise.all(batch.map(function(g){return pbp(g.game.gamePk).then(function(P){return P.map(function(p){return {pk:g.game.gamePk,date:g.date,opp:g.opponent,home:g.isHome,inn:p.about.inning,idx:p.about.atBatIndex,ev:p.result.eventType,pit:(p.matchup.pitcher||{}).fullName||''}})})})).then(function(L){L.forEach(function(P){got=got.concat(P)});if(got.length| Date | Opp | Inn | Pitcher | Result |
|---|---|---|---|---|
| '+fd(x.date)+' | '+(x.home?'vs ':'@ ')+o+' | '+x.inn+' | '+x.pit+' | '+(EVN[x.ev]||x.ev.replace(/_/g,' '))+' |
Exactly the last '+P.length+' plate appearances, in order, from MLB play-by-play (regular season). Stolen bases aren’t plate appearances, so they aren’t shown here.
')})} return} (function step(){if(i>=Y.length)return done();logs(Y[i]).then(function(G){for(var k=G.length-1;k>=0;k--){out.unshift(G[k]);if(out.length>=n)return done()}i++;step()})})(); function done(){if(!out.length){showMine('No MLB games.
');return}var t=agg(out),yr=+out[out.length-1].date.slice(0,4);var lab=code==='g1'?'Last game':'Last '+n+' apps';showMine('Pick a start date before the end date.
');return}setOn('cust');loading();var ys=Y.filter(function(y){return y>=+a.slice(0,4)&&y<=+b.slice(0,4)}).sort();Promise.all(ys.map(logs)).then(function(L){var G=[].concat.apply([],L).filter(function(s){return s.date>=a&&s.date<=b});if(!G.length){showMine('No MLB regular-season games in this range.
');return}var t=agg(G);showMine('