Last active
April 1, 2018 12:25
-
-
Save valex/b076ad9d4c75e88328d0c847dcb10eb2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var qid = location.search; | |
| var PITCH_APP = { | |
| url: 'pitchplot.json', | |
| save_edit_pitch_url: '/save_pitch.php', | |
| eventsData: [], | |
| activeEvent: null, | |
| data: [], | |
| activeIndex: null, | |
| defaultVideoIndex: 0, | |
| activeVideoIndex: null, | |
| autoplay: false, | |
| options: { | |
| edit_pitch_mode: false, | |
| editPitch: { | |
| edit_pitch_module_selector: '#edit-pitch-module', | |
| edit_pitch_form_selector: '#edit_pitch_form', | |
| edit_pitch_btn_selector: '#edit_pitch_btn', | |
| save_edit_pitch_btn_selector: '#save_edit_pitch_btn', | |
| cancel_edit_pitch_btn_selector: '#cancel_edit_pitch_btn', | |
| input_x_selector: '#edit_pitch_x_input', | |
| input_y_selector: '#edit_pitch_y_input', | |
| form_visible: false, | |
| }, | |
| selectModule: { | |
| appendToSelector: '#pitch-select-module', | |
| }, | |
| chartModule: { | |
| appendToSelector: '#pitch-chart-module', | |
| width: 500, | |
| height: 281, | |
| margins: { | |
| top: 10, | |
| right: 10, | |
| bottom: 20, | |
| left: 10, | |
| xAxis: { | |
| left: 116, | |
| right: 104, | |
| }}, | |
| pitchBg: 'pitch-bg.jpg', | |
| pitchBgAlpha: 0.3, | |
| color: null, | |
| defaultBallColor:'#b3b3b3', | |
| ballHoverClass:"hovered", | |
| ballActiveClass:"active", | |
| svg: null, | |
| mainGroup: null, | |
| tooltip: null, | |
| scaleX: null, | |
| scaleY: null, | |
| strikeZone:{ | |
| color: '#2ad146', | |
| width: 1 | |
| }, | |
| heatmap: { | |
| show: false, | |
| instance: null, | |
| }, | |
| topVelo: [], | |
| topVeloNum: 5, | |
| markTopVelo: true, | |
| topSpin: [], | |
| topSpinNum: 5, | |
| markTopSpin: true, | |
| }, | |
| videoModule: { | |
| videoJs: null, | |
| videoJsCache: null, | |
| ready: false, | |
| cache: true, | |
| appendToSelector: '#pitch-video-module' | |
| }, | |
| tableModule:{ | |
| appendToSelector: '#pitch-table-module', | |
| rowActiveClass:"active", | |
| tbody: null, | |
| columns: [ | |
| { | |
| key: 'pitchSpeed', | |
| label: 'P Velo', | |
| fixed: 1, | |
| }, | |
| { | |
| key: 'pitchSpin', | |
| label: 'Spin', | |
| fixed: 0, | |
| }, | |
| { | |
| key: 'pitchType', | |
| label: 'Type', | |
| }, | |
| { | |
| key: 'pitchResult', | |
| label: 'Result', | |
| }, | |
| { | |
| key: 'exitvelo', | |
| label: 'Exit V', | |
| fixed: 1, | |
| }, | |
| { | |
| key: 'videos', | |
| label: '', | |
| }, | |
| ] | |
| }, | |
| }, | |
| start: function(){ | |
| // Set-up the export button | |
| d3.select('#pitch-export').on('click', function(){ | |
| PITCH_APP.export(); | |
| }); | |
| this.activeVideoIndex = this.defaultVideoIndex; | |
| this.loadData(); | |
| }, | |
| loadData: function(){ | |
| var that = this; | |
| d3.json(this.url, function (error, rawData) { | |
| if (error) throw error; | |
| var data = rawData['RECORDS'].map(function (d) { | |
| var videos=[]; | |
| var videoSrc; | |
| if(typeof d["angle1"] != 'undefined' && d["angle1"] !== null){ | |
| videoSrc = (''+d["angle1"]).trim(); | |
| if(videoSrc.length > 0 ){ | |
| videos.push({ | |
| src: videoSrc | |
| }); | |
| } | |
| } | |
| if(typeof d["angle2"] != 'undefined' && d["angle2"] !== null){ | |
| videoSrc = (''+d["angle2"]).trim(); | |
| if(videoSrc.length > 0){ | |
| videos.push({ | |
| src: videoSrc | |
| }); | |
| } | |
| } | |
| return { | |
| playID: +d["playID"], | |
| pitchSpeed: +d["pitchvelo"], | |
| exitvelo: +d["exitvelo"], | |
| pitchSpin: +d["pspin"], | |
| pitchX: +d["pitchX"], | |
| pitchY: +d["pitchY"], | |
| pitchType: (''+d["ptype"]).trim().toLowerCase(), | |
| pitchResult: (''+d["presult"]).trim().toLowerCase(), | |
| eventID: +d["eventID"], | |
| eventName: (''+d["eventName"]).trim(), | |
| eventDate: moment(d["eventDate"], "YYYY-MM-DD HH:mm:ss"), | |
| videos: videos | |
| } | |
| }); | |
| that.eventsData = d3.nest() | |
| .key(function(d) { return d.eventID; }) | |
| .entries(data); | |
| that.updateData(); | |
| that.initModules(); | |
| that.updateModules(); | |
| if(true === that.autoplay){ | |
| that.playNextVideo(); | |
| } | |
| }); | |
| }, | |
| initModules: function(){ | |
| this.initSelectModule(); | |
| this.initTableModule(); | |
| this.initChart(); | |
| this.initAutoplayCheckbox(); | |
| this.initEditPitchModule(); | |
| }, | |
| // when data changes | |
| updateModules: function(){ | |
| this.updateTableModule(); | |
| this.updateChart(); | |
| this.updateEditPitchModule(); | |
| }, | |
| // when active item changes | |
| animateModules:function(){ | |
| this.animateTableModule(); | |
| this.updateVideoModule(); | |
| this.animateChart(); | |
| this.updateEditPitchModule(); | |
| }, | |
| updateData: function(){ | |
| var that = this; | |
| that.data = d3.merge( | |
| this.eventsData.map(function(d){ | |
| return d.values.filter(function(dd){ | |
| if(that.activeEvent === null) | |
| return true; | |
| return dd.eventID == that.activeEvent; | |
| }) | |
| }) | |
| ); | |
| var top5Velo = that.data.slice(0); // clone array | |
| var top5Spin = that.data.slice(0); // clone array | |
| top5Velo.sort(function(x, y){ | |
| return d3.descending(x.pitchSpeed, y.pitchSpeed); | |
| }); | |
| top5Spin.sort(function(x, y){ | |
| return d3.descending(x.pitchSpin, y.pitchSpin); | |
| }); | |
| top5Velo = top5Velo.slice(0, that.options.chartModule.topVeloNum); | |
| top5Spin = top5Spin.slice(0, that.options.chartModule.topSpinNum); | |
| that.options.chartModule.topVelo = top5Velo; | |
| that.options.chartModule.topSpin = top5Spin; | |
| }, | |
| ballManuallySelected: function(index){ | |
| this.setIndexAndAnimate(index); | |
| }, | |
| setIndexAndAnimate: function(index){ | |
| this.setActiveIndex(index); | |
| this.animateModules(); | |
| }, | |
| isActiveIndexSet: function(){ | |
| if(this.activeIndex !== null && this.activeIndex !== '') | |
| return true; | |
| return false; | |
| }, | |
| setActiveIndex:function(index){ | |
| this.activeIndex = index; | |
| }, | |
| hasVideo: function(data){ | |
| return data.videos.length; | |
| }, | |
| // ============================== EDIT PITCH MODULE ============================== | |
| initEditPitchModule: function(){ | |
| var that = this; | |
| var options = this.options.editPitch; | |
| var editPitchBtn = d3.select(options.edit_pitch_btn_selector) | |
| .on('click', function(){ | |
| that.toggleEditPitchMode(); | |
| }); | |
| var cancelEditPitchBtn = d3.select(options.cancel_edit_pitch_btn_selector) | |
| .on('click', function(){ | |
| that.stopEditPitchMode(); | |
| }); | |
| var saveEditPitchBtn = d3.select(options.save_edit_pitch_btn_selector) | |
| .on('click', function(){ | |
| that.sendPitchSaveRequest(); | |
| }); | |
| if(this.options.edit_pitch_mode === false){ | |
| this.stopEditPitchMode(); | |
| }else{ | |
| this.startEditPitchMode(); | |
| } | |
| }, | |
| updateEditPitchModule: function(){ | |
| if( ! this.isActiveIndexSet()){ | |
| this.resetEditPitchForm(); | |
| return; | |
| } | |
| var data = this.data[this.activeIndex]; | |
| this.setEditPitchInputs(data['pitchX'], data['pitchY']); | |
| }, | |
| resetEditPitchForm: function(){ | |
| this.setEditPitchInputs(null, null); | |
| }, | |
| setEditPitchInputs: function(x, y){ | |
| var xInput = d3.select(this.options.editPitch.input_x_selector); | |
| var yInput = d3.select(this.options.editPitch.input_y_selector); | |
| xInput.attr('value', x); | |
| yInput.attr('value', y); | |
| }, | |
| sendPitchSaveRequest: function(){ | |
| var that = this; | |
| if( ! this.isActiveIndexSet()){ | |
| return; | |
| } | |
| var data = this.data[this.activeIndex]; | |
| var http = new XMLHttpRequest(); | |
| var url = this.save_edit_pitch_url; | |
| var x = d3.select(this.options.editPitch.input_x_selector).node().value.trim(); | |
| var y = d3.select(this.options.editPitch.input_y_selector).node().value.trim(); | |
| if(x=='' || y=='') | |
| return; | |
| var params = "playID="+data['playID']+"&x="+x+"&y="+y+"&pw_p_id="+qid; | |
| http.open("POST", url, true); | |
| //Send the proper header information along with the request | |
| http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
| http.onreadystatechange = function() {//Call a function when the state changes. | |
| if(http.readyState == 4 && http.status == 200) { | |
| // success | |
| // update data | |
| if(that.isActiveIndexSet()){ | |
| that.data[that.activeIndex]['pitchX'] = x; | |
| that.data[that.activeIndex]['pitchY'] = y; | |
| } | |
| } | |
| }; | |
| http.send(params); | |
| }, | |
| startEditPitchMode: function(){ | |
| this.options.edit_pitch_mode = true; | |
| this.showEditPitchForm(); | |
| }, | |
| stopEditPitchMode: function(){ | |
| var that = this; | |
| this.options.edit_pitch_mode = false; | |
| if(this.isActiveIndexSet()){ | |
| var data = this.data[this.activeIndex]; | |
| var cx = that.ballXY(data).x; | |
| var cy = that.ballXY(data).y; | |
| that.setCxCyForActiveCircle( | |
| cx, | |
| cy | |
| ); | |
| } | |
| this.hideEditPitchForm(); | |
| }, | |
| toggleEditPitchMode: function(){ | |
| if(this.options.edit_pitch_mode === true){ | |
| this.stopEditPitchMode(); | |
| }else{ | |
| this.startEditPitchMode(); | |
| } | |
| }, | |
| showEditPitchForm: function(){ | |
| var options = this.options.editPitch; | |
| var editPitchForm = d3.select(options.edit_pitch_form_selector) | |
| .style('display', 'block'); | |
| options.form_visible = true; | |
| }, | |
| hideEditPitchForm: function(){ | |
| var options = this.options.editPitch; | |
| var editPitchForm = d3.select(options.edit_pitch_form_selector) | |
| .style('display', 'none'); | |
| options.form_visible = false; | |
| }, | |
| // ============================== VIDEO MODULE ============================== | |
| initVideoPlayer: function(){ | |
| var that = this; | |
| var options = this.options.videoModule; | |
| var outerBlock = d3.select(options.appendToSelector).html(""); | |
| var innerBlock = outerBlock | |
| .append('div') | |
| .attr('class', 'embed-responsive embed-responsive-16by9'); | |
| var videoTag = innerBlock.append('video') | |
| .attr('class', 'pitch-video-js video-js embed-responsive-item'); | |
| var videoUnsupportedWarn = videoTag.append('p') | |
| .attr('class', 'vjs-no-js') | |
| .html('To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>'); | |
| options.videoJs = videojs(document.querySelector('.pitch-video-js'), { | |
| aspectRatio: '16:9', | |
| controls: true, | |
| autoplay: false, | |
| preload: 'auto', | |
| }); | |
| options.videoJs.on('playing', function() { | |
| }); | |
| options.videoJs.on('ended', function() { | |
| if(true == that.autoplay){ | |
| that.playNextVideo(); | |
| } | |
| }); | |
| options.videoJs.ready(function() { | |
| that.onVideoPlayerReady(); | |
| }); | |
| if(options.cache === true){ | |
| var cacheInnerBlock = outerBlock | |
| .append('div') | |
| .style('width', '1px') | |
| .style('height', '1px') | |
| .attr('class', 'embed-responsive embed-responsive-16by9'); | |
| var cacheVideoTag = cacheInnerBlock.append('video') | |
| .attr('class', 'video-js video-js-cache embed-responsive-item'); | |
| options.videoJsCache = videojs(document.querySelector('.video-js-cache'), { | |
| aspectRatio: '16:9', | |
| controls: true, | |
| autoplay: false, | |
| muted: true, | |
| preload: 'auto', | |
| }); | |
| var nextVideo = this.getNextVideoIndex(); | |
| var videoSrc = this.data[nextVideo.row]['videos'][nextVideo.index]['src']; | |
| options.videoJsCache.src({ | |
| src: videoSrc, | |
| type: 'video/mp4' | |
| }); | |
| options.videoJsCache.on('loadedmetadata', function() { | |
| var video = this.children_[0]; | |
| if (video.buffered.length === 0) return; | |
| var bufferedSeconds = video.buffered.end(0) - video.buffered.start(0); | |
| console.log(bufferedSeconds + ' seconds of video are ready to play!'); | |
| }); | |
| } | |
| }, | |
| onVideoPlayerReady: function(){ | |
| this.options.videoModule.ready = true; | |
| this.options.videoModule.videoJs.play(); | |
| }, | |
| updateVideoModule: function(){ | |
| var options = this.options.videoModule; | |
| this.disposeVideoPlayer(); | |
| if(this.isActiveIndexSet()){ | |
| var datum = this.data[this.activeIndex]; | |
| if(this.hasVideo(datum)){ | |
| this.initVideoPlayer(); | |
| if(typeof datum['videos'][this.activeVideoIndex] == 'undefined') | |
| this.setVideoActiveIndex(this.defaultVideoIndex); | |
| this.setVideoSrc(datum['videos'][this.activeVideoIndex]['src']); | |
| } | |
| this.highlightVideoIcon(); | |
| } | |
| }, | |
| setVideoSrc: function(videoSrc){ | |
| this.options.videoModule.videoJs.src({ | |
| src: videoSrc, | |
| type: 'video/mp4' | |
| }); | |
| }, | |
| playNextVideo: function(){ | |
| if( ! this.datasetHasVideo()) | |
| return; | |
| var currentVideoIndex = this.getCurrentVideoIndex(); | |
| var nextVideoIndex = this.getNextVideoIndex(); | |
| this.setVideoActiveIndex(nextVideoIndex.index); | |
| if(currentVideoIndex.row === nextVideoIndex.row){ | |
| this.updateVideoModule(); | |
| }else{ | |
| this.setIndexAndAnimate(nextVideoIndex.row) | |
| } | |
| }, | |
| datasetHasVideo: function(){ | |
| for(var i=0; i < this.data.length; i++){ | |
| if(this.hasVideo(this.data[i])) | |
| return true; | |
| } | |
| return false; | |
| }, | |
| getCurrentVideoIndex: function(){ | |
| return { | |
| row: this.activeIndex, | |
| index: this.activeVideoIndex, | |
| }; | |
| }, | |
| getNextVideoIndex: function(){ | |
| var nextVideo = this.getCurrentVideoIndex(); | |
| do{ | |
| if(nextVideo.row === null || nextVideo.index === null){ | |
| nextVideo = { | |
| row: 0, | |
| index: this.defaultVideoIndex, | |
| }; | |
| }else{ | |
| nextVideo['index']++; | |
| } | |
| if(typeof this.data[nextVideo['row']]['videos'][nextVideo['index']] === 'undefined'){ | |
| nextVideo['index'] = this.defaultVideoIndex; | |
| nextVideo['row']++; | |
| if(typeof this.data[nextVideo['row']] === 'undefined'){ | |
| nextVideo['row'] = 0; | |
| } | |
| } | |
| }while(typeof this.data[nextVideo['row']]['videos'][nextVideo['index']] === 'undefined') | |
| return nextVideo; | |
| }, | |
| startAutoplay: function(){ | |
| if(this.autoplay === true) | |
| return; | |
| this.autoplay = true; | |
| var autoplayCheckbox = d3.select("#pitch-autoplay-checkbox"); | |
| autoplayCheckbox.node().checked = this.autoplay; | |
| this.playNextVideo(); | |
| }, | |
| stopAutoplay: function(){ | |
| if(this.autoplay === false) | |
| return; | |
| this.autoplay = false; | |
| var autoplayCheckbox = d3.select("#pitch-autoplay-checkbox"); | |
| autoplayCheckbox.node().checked = this.autoplay; | |
| }, | |
| initAutoplayCheckbox: function(){ | |
| var that = this; | |
| var autoplayCheckbox = d3.select("#pitch-autoplay-checkbox"); | |
| if(autoplayCheckbox.size() <= 0) | |
| return; | |
| autoplayCheckbox.node().checked = that.autoplay; | |
| autoplayCheckbox.on("change", function(){ | |
| !!this.checked ? that.startAutoplay() : that.stopAutoplay(); | |
| }); | |
| }, | |
| disposeVideoPlayer: function(){ | |
| if(this.options.videoModule.videoJs !== null){ | |
| try{ | |
| this.options.videoModule.videoJs.dispose(); | |
| }catch (e){ | |
| console.log(e); | |
| } | |
| this.options.videoModule.videoJs = null; | |
| this.options.videoModule.ready = false; | |
| } | |
| if(this.options.videoModule.cache === true && this.options.videoModule.videoJsCache !== null){ | |
| try{ | |
| this.options.videoModule.videoJsCache.dispose(); | |
| }catch (e){ | |
| console.log(e); | |
| } | |
| this.options.videoModule.videoJsCache = null; | |
| } | |
| }, | |
| // ============================== TABLE MODULE ============================== | |
| initTableModule: function() { | |
| var options = this.options.tableModule; | |
| var table = d3.select(options.appendToSelector).append('table') | |
| .attr('class', 'table'); | |
| var thead = table.append('thead'); | |
| options.tbody = table.append('tbody'); | |
| // append the header row | |
| thead.append('tr') | |
| .selectAll('th') | |
| .data(options.columns) | |
| .enter() | |
| .append('th') | |
| .text(function (column) { return column.label; }); | |
| }, | |
| updateTableModule:function(){ | |
| var that = this; | |
| var options = this.options.tableModule; | |
| // create a row for each object in the data | |
| var rowsSelection = options.tbody.selectAll('tr') | |
| .data(this.data); | |
| rowsSelection.exit().remove(); | |
| var rowsEnter = rowsSelection | |
| .enter() | |
| .append('tr') | |
| .on('click', function(d, i){ | |
| PITCH_APP.ballManuallySelected(i); | |
| }); | |
| var rows = rowsSelection.merge(rowsEnter); | |
| // create a cell in each row for each column | |
| var cellsSelection = rows.selectAll('td') | |
| .data(function (row, i) { | |
| return options.columns.map(function (column) { | |
| var value, type; | |
| switch(column.key){ | |
| case 'videos': | |
| type = 'videos'; | |
| value = row.videos; | |
| break; | |
| case 'pitchType': | |
| type = 'string'; | |
| switch(row[column.key]){ | |
| case 'fastball': | |
| value = 'FB'; | |
| break; | |
| case 'curveball': | |
| value = 'CB'; | |
| break; | |
| case 'slider': | |
| value = 'SL'; | |
| break; | |
| case 'changeup': | |
| value = 'CH'; | |
| break; | |
| case 'cutter': | |
| value = 'CUT'; | |
| break; | |
| case 'splitter': | |
| value = 'SPL'; | |
| break; | |
| case 'knuckleball': | |
| value = 'KN'; | |
| break; | |
| case 'screwball': | |
| value = 'SCR'; | |
| break; | |
| case 'forkbal': | |
| value = 'FK'; | |
| break; | |
| default: | |
| value = row[column.key]; | |
| break; | |
| } | |
| break; | |
| case 'pitchResult': | |
| type = 'string'; | |
| value = row[column.key]; | |
| break; | |
| default: | |
| type = 'number'; | |
| value = parseFloat(row[column.key]).toFixed(column.fixed); | |
| if(value <= 0) | |
| value = ''; | |
| break; | |
| } | |
| return { | |
| type: type, | |
| value: value | |
| }; | |
| }); | |
| }); | |
| var cellsEnter = cellsSelection | |
| .enter() | |
| .append('td'); | |
| var cells = cellsSelection.merge(cellsEnter); | |
| cells.each(function (d) { | |
| var el = d3.select(this); | |
| switch(d.type){ | |
| case 'videos': | |
| el.html(''); | |
| el.append('div') | |
| .attr('class', 'text-nowrap') | |
| .selectAll('i') | |
| .data(d.value) | |
| .enter() | |
| .append('i') | |
| .attr('class', function(d,i){ | |
| if(i > 0){ | |
| return 'fa fa-video-camera fa-rotate-315'; | |
| }else{ | |
| return 'fa fa-video-camera'; | |
| } | |
| }) | |
| .style('margin-right', '6px') | |
| .on('click', function(d, video_i){ | |
| that.onClickVideoIcon(video_i); | |
| }); | |
| break; | |
| case 'string': | |
| case 'number': | |
| el.html(function (d) { return d.value; }); | |
| break; | |
| } | |
| }); | |
| this.clearAllActiveRows(); | |
| }, | |
| animateTableModule: function(){ | |
| this.setRowActive(this.activeIndex); | |
| }, | |
| onClickVideoIcon: function(video_index){ | |
| this.setVideoActiveIndex(video_index); | |
| }, | |
| setVideoActiveIndex: function(index){ | |
| this.activeVideoIndex = index; | |
| }, | |
| setRowActive: function(index){ | |
| var options = this.options.tableModule; | |
| // only one active | |
| this.clearAllActiveRows(); | |
| var tr = options.tbody.selectAll('tr').filter(function(d,i){return i === index}); | |
| if(tr.size() > 0){ | |
| var alreadyIsActive = tr.classed(options.rowActiveClass); | |
| if( ! alreadyIsActive){ | |
| tr.classed(options.rowActiveClass, ! alreadyIsActive); | |
| } | |
| } | |
| }, | |
| clearAllActiveRows: function(){ | |
| var options = this.options.tableModule; | |
| options.tbody.selectAll('tr') | |
| .classed(options.rowActiveClass, false); | |
| }, | |
| highlightVideoIcon: function(){ | |
| var videoOptions = this.options.videoModule; | |
| this.extinguishAllVideoIcons(); | |
| d3.select('#pitch-table-module tr.active .fa-video-camera:nth-child('+(1+this.activeVideoIndex)+')').classed('green', true); | |
| }, | |
| extinguishAllVideoIcons: function(){ | |
| d3.selectAll('#pitch-table-module .fa-video-camera').classed('green', false); | |
| }, | |
| // ============================== CHART MODULE ============================== | |
| initChart: function(){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| var chartWidth = options.width - options.margins.left - options.margins.right, | |
| chartHeight = options.height - options.margins.top - options.margins.bottom; | |
| options.svg = d3.select(options.appendToSelector) | |
| .append("svg") | |
| .attr("width", options.width) | |
| .attr("height", options.height) | |
| .on('click', function() { | |
| var coords = d3.mouse(this); | |
| if(false === that.options.edit_pitch_mode || ! that.isActiveIndexSet()) | |
| return; | |
| var cx = coords[0] - that.options.chartModule.margins.left; | |
| var cy = coords[1] - that.options.chartModule.margins.top; | |
| that.setCxCyForActiveCircle( | |
| cx, | |
| cy | |
| ); | |
| // set inputs | |
| that.setEditPitchInputs( | |
| that.options.chartModule.scaleX.invert(cx-that.options.chartModule.margins.xAxis.left).toFixed(3), | |
| that.options.chartModule.scaleY.invert(cy).toFixed(3) | |
| ); | |
| }); | |
| // background image | |
| options.svg.append("svg:defs") | |
| .append("svg:pattern") | |
| .attr("id", "pitch-bg") | |
| .attr('patternUnits', 'userSpaceOnUse') | |
| .attr("x", 0) | |
| .attr("y", 0) | |
| .attr('width', options.width) | |
| .attr('height', options.height) | |
| .append("svg:image") | |
| .attr("xlink:href", options.pitchBg) | |
| .attr("x", 0) | |
| .attr("y", 0) | |
| .attr('width', options.width) | |
| .attr('height', options.height); | |
| options.svg.append("rect") | |
| .attr('id', 'pitch-bg-rect') | |
| .attr('fill', 'url(#pitch-bg)') | |
| .attr('width', options.width) | |
| .attr('height', options.height); | |
| options.mainGroup = options.svg.append('g') | |
| .attr('transform', 'translate(' + options.margins.left + ',' + options.margins.top + ')') | |
| .attr('id', options.id); | |
| options.scaleX = d3.scaleLinear() | |
| .domain([-4, 4]) | |
| .range([0, chartWidth - options.margins.xAxis.left - options.margins.xAxis.right]); | |
| options.scaleY = d3.scaleLinear() | |
| .domain([0, 6]) | |
| .range([chartHeight, 0]); | |
| options.color = d3.scaleOrdinal() | |
| .domain(["fastball", "curveball", "changeup", "slider", "knuckleball", "splitter"]) | |
| .range(["red", "blue", "yellow", "green", "purple", "orange", "#b3b3b3"]); | |
| this.initHeatmapCheckbox(); | |
| this.initMarkTopVeloCheckbox(); | |
| this.initMarkTopSpinCheckbox(); | |
| // tooltip | |
| options.tooltip = d3.select("body") | |
| .append("div") | |
| .attr("class", "pitch-tooltip") | |
| .style("opacity", 0); | |
| // strikeZone | |
| var strikeZone = options.svg.append('g') | |
| .attr('transform', 'translate(' + (options.scaleX(-1.1) + options.margins.left + options.margins.xAxis.left) + ',' + (options.scaleY(3.5) + options.margins.top) + ')'); | |
| strikeZone.append('rect') | |
| .attr('width', options.scaleX(1.1) - options.scaleX(-1.1)) | |
| .attr('height', options.scaleY(1.0) - options.scaleY(3.5)) | |
| .attr('fill', 'none') | |
| .attr('stroke', options.strikeZone.color) | |
| .attr('stroke-width', options.strikeZone.width); | |
| // axes | |
| var axisXGroup = options.svg.append('g') | |
| .attr('transform', 'translate(' + (options.margins.left + options.margins.xAxis.left) + ',' + (options.height - options.margins.bottom) + ')'); | |
| var axisX = d3.axisBottom(options.scaleX); | |
| axisXGroup.call(axisX); | |
| var axisYGroup = options.svg.append('g') | |
| .attr('transform', 'translate(' + (options.margins.left + options.margins.xAxis.left + options.scaleX(0)) + ',' + options.margins.top + ')'); | |
| var axisY = d3.axisLeft(options.scaleY).ticks(6); | |
| axisYGroup.call(axisY); | |
| this.styleAxis(); | |
| // labels | |
| var labels = [ | |
| { | |
| color: options.color('fastball'), | |
| label: 'Fastball' | |
| }, | |
| { | |
| color: options.color('curveball'), | |
| label: 'Curveball' | |
| }, | |
| { | |
| color: options.color('changeup'), | |
| label: 'Changeup' | |
| }, | |
| { | |
| color: options.color('slider'), | |
| label: 'Slider' | |
| }, | |
| { | |
| color: options.color('knuckleball'), | |
| label: 'Knuckleball' | |
| }, | |
| { | |
| color: options.color('splitter'), | |
| label: 'Splitter' | |
| }, | |
| ] | |
| var legends = options.mainGroup.selectAll('rect.legend') | |
| .data(labels); | |
| legends | |
| .enter() | |
| .append('rect') | |
| .attr('class', 'legend') | |
| .attr('width', 10) | |
| .attr('height', 10) | |
| .attr('fill', function(d){return d.color;}) | |
| .attr('transform', function(d,i) {return 'translate(' + options.margins.left + ',' + (options.margins.top + i*15) + ')'}) | |
| legends | |
| .enter() | |
| .append('text') | |
| .text(function(d){return d.label;}) | |
| .attr('fill', 'white') | |
| .attr('font-size', '12px') | |
| .attr('x', 13 + options.margins.left) | |
| .attr('y', function(d,i){return options.margins.top + 9+i*15}) | |
| }, | |
| initHeatmap: function(){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| var heatmapWidth = options.width, | |
| heatmapHeight = options.height; | |
| var heatmapWrapper = d3.select(options.appendToSelector) | |
| .append("div") | |
| .attr("class", 'pitch-heatmap-wrapper') | |
| .style("width", heatmapWidth+"px") | |
| .style("height", heatmapHeight+"px"); | |
| var heatmap = heatmapWrapper | |
| .append('div') | |
| .attr("class", 'pitch-heatmap'); | |
| // minimal heatmap instance configuration | |
| options.heatmap.instance = h337.create({ | |
| // only container is required, the rest will be defaults | |
| container: document.querySelector('.pitch-heatmap'), | |
| }); | |
| }, | |
| initHeatmapCheckbox: function(){ | |
| var that = this; | |
| var heatmapCheckbox = d3.select("#pitch-heatmap-checkbox"); | |
| heatmapCheckbox.on("change", function(){ | |
| that.options.chartModule.heatmap.show = !!this.checked; | |
| that.onHeatmapCheckboxChange(); | |
| }); | |
| }, | |
| onHeatmapCheckboxChange: function(){ | |
| this.drawBackground(); | |
| }, | |
| drawBackground: function () { | |
| var that = this; | |
| var options = this.options.chartModule; | |
| if(true === options.heatmap.show){ | |
| that.drawHeatmap(); | |
| d3.select('#pitch-bg-rect').attr('opacity', options.pitchBgAlpha); | |
| }else{ | |
| that.clearHeatmap(); | |
| d3.select('#pitch-bg-rect').attr('opacity', 1.0); | |
| } | |
| }, | |
| setCxCyForActiveCircle: function(cx, cy){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| var circle = options.svg.selectAll('path.pitch-ball') | |
| .filter(function (d, i) { | |
| return i === that.activeIndex; | |
| }); | |
| if(circle.size() <= 0) | |
| return; | |
| circle.attr('transform', function(d, i){ | |
| return 'translate(' + (cx) + ','+ (cy) +')'; | |
| }); | |
| }, | |
| drawHeatmap: function(){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| // now generate some random data | |
| var points = []; | |
| var max = 1; | |
| if(options.heatmap.instance === null){ | |
| this.initHeatmap(); | |
| } | |
| for(var i=0; i < that.data.length; i++){ | |
| var coordinates = that.ballXY(that.data[i]); | |
| var point = { | |
| x: Math.round(coordinates.x + options.margins.left), | |
| y: Math.round(coordinates.y + options.margins.top), | |
| value: 0.7 | |
| }; | |
| points.push(point); | |
| } | |
| // heatmap data format | |
| var data = { | |
| max: max, | |
| data: points | |
| }; | |
| // if you have a set of datapoints always use setData instead of addData | |
| // for data initialization | |
| options.heatmap.instance.setData(data); | |
| }, | |
| clearHeatmap: function(){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| if(options.heatmap.instance === null) | |
| return; | |
| options.heatmap.instance.setData({ | |
| max: 0, | |
| min: 0, | |
| data: [ | |
| ] | |
| }); | |
| }, | |
| initMarkTopVeloCheckbox: function(){ | |
| var that = this; | |
| var el = d3.select("#markTopVelo"); | |
| if(el.size() <= 0) | |
| return; | |
| el.node().checked = that.options.chartModule.markTopVelo; | |
| el.on("change", function(){ | |
| that.options.chartModule.markTopVelo = !!this.checked; | |
| that.updateChart(); | |
| }); | |
| }, | |
| initMarkTopSpinCheckbox: function(){ | |
| var that = this; | |
| var el = d3.select("#markTopSpin"); | |
| if(el.size() <= 0) | |
| return; | |
| el.node().checked = that.options.chartModule.markTopSpin; | |
| el.on("change", function(){ | |
| that.options.chartModule.markTopSpin = !!this.checked; | |
| that.updateChart(); | |
| }); | |
| }, | |
| isInTopVelo: function(d){ | |
| for(var i = 0; i < this.options.chartModule.topVelo.length; i++){ | |
| if(this.options.chartModule.topVelo[i]['playID'] === d['playID']) | |
| return true; | |
| } | |
| return false; | |
| }, | |
| isInTopSpin: function(d){ | |
| for(var i = 0; i < this.options.chartModule.topSpin.length; i++){ | |
| if(this.options.chartModule.topSpin[i]['playID'] === d['playID']) | |
| return true; | |
| } | |
| return false; | |
| }, | |
| updateChart: function(){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| var symbol = d3.symbol().size(50); | |
| var circlesSelection = options.mainGroup.selectAll('path.pitch-ball') | |
| .data(this.data); | |
| circlesSelection.exit().remove(); | |
| var circlesEnter = circlesSelection | |
| .enter() | |
| .append('path') | |
| .attr('class', 'pitch-ball') | |
| .on('click', function(d, i) { | |
| var el = d3.select(this); | |
| if(true === that.options.edit_pitch_mode && that.isActiveIndexSet()) | |
| return; | |
| that.ballManuallySelected(i); | |
| }) | |
| .on('mouseenter', function(d) { | |
| var el = d3.select(this); | |
| // tooltip | |
| options.tooltip.transition() | |
| .duration(200) | |
| .style("opacity", .8); | |
| options.tooltip.html(parseFloat(d.pitchSpeed).toFixed(1)+' mph') | |
| .style("left", (d3.event.pageX + 5) + "px") | |
| .style("top", (d3.event.pageY - 28 - 5) + "px"); | |
| // classes | |
| el.classed(options.ballHoverClass, true); | |
| }) | |
| .on('mouseout', function(d) { | |
| var el = d3.select(this); | |
| // tooltip | |
| options.tooltip.transition() | |
| .duration(500) | |
| .style("opacity", 0); | |
| // classes | |
| el.classed(options.ballHoverClass, false); | |
| }); | |
| var circles = circlesSelection.merge(circlesEnter); | |
| circles | |
| .attr("d", symbol.type(function (d) { | |
| if(options.markTopVelo && that.isInTopVelo(d)){ | |
| return d3.symbolStar; | |
| } | |
| if(options.markTopSpin && that.isInTopSpin(d)){ | |
| return d3.symbolStar; | |
| } | |
| return d3.symbolCircle; | |
| })) | |
| .attr('fill', function(d,i){return options.color(d.pitchType)}) | |
| .attr('transform', function(d, i){ | |
| var coords = that.ballXY(d); | |
| return 'translate(' + (coords.x) + ','+ (coords.y) +')'; | |
| }); | |
| this.clearAllActiveCircles(); | |
| this.drawBackground(); | |
| }, | |
| animateChart: function(){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| this.clearAllActiveCircles(); | |
| var el = options.mainGroup.selectAll('path.pitch-ball').filter(function(d,i){return i===that.activeIndex}); | |
| if(el.size() <= 0) | |
| return; | |
| // only one active | |
| var alreadyIsActive = el.classed(options.ballActiveClass); | |
| if( ! alreadyIsActive){ | |
| el.classed(options.ballActiveClass, ! alreadyIsActive); | |
| el.classed(options.ballHoverClass, false); | |
| } | |
| }, | |
| clearAllActiveCircles: function(){ | |
| var options = this.options.chartModule; | |
| options.mainGroup.selectAll('path.pitch-ball') | |
| .classed(options.ballActiveClass, false); | |
| }, | |
| styleAxis: function(){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| options.svg.selectAll('path.domain').attr('stroke', '#DEDEDE'); | |
| options.svg.selectAll('g.tick line').attr('stroke', '#DEDEDE'); | |
| options.svg.selectAll('g.tick text').attr('fill', '#DEDEDE'); | |
| }, | |
| ballXY: function(d){ | |
| var that = this; | |
| var options = this.options.chartModule; | |
| return { | |
| x: options.margins.xAxis.left + options.scaleX(d.pitchX), | |
| y: options.scaleY(d.pitchY), | |
| } | |
| }, | |
| // ============================== SELECT MODULE ============================== | |
| initSelectModule:function(){ | |
| var options = this.options.selectModule; | |
| var select = d3.select(options.appendToSelector).append('select') | |
| .attr('name', 'active_event') | |
| .attr('class', 'form-control'); | |
| var nullOption = select.append('option') | |
| .attr('value', '') | |
| .text('ALL PITCHES'); | |
| for(var i=0; i < this.eventsData.length; i++){ | |
| select.append('option') | |
| .attr('value', this.eventsData[i].values[0].eventID) | |
| .text(this.eventsData[i].values[0].eventName); | |
| } | |
| select.on('change', this.onSelectChange); | |
| }, | |
| onSelectChange: function (e) { | |
| var old = PITCH_APP.activeEvent; | |
| PITCH_APP.activeEvent = this.value.length > 0 ? this.value : null; | |
| if(old != PITCH_APP.activeEvent){ | |
| PITCH_APP.onActiveEventChange(); | |
| } | |
| }, | |
| onActiveEventChange: function(){ | |
| this.setActiveIndex(null); | |
| this.setVideoActiveIndex(this.defaultVideoIndex); | |
| this.updateData(); | |
| this.updateModules(); | |
| this.updateVideoModule(); | |
| if(true === this.autoplay){ | |
| this.playNextVideo(); | |
| } | |
| }, | |
| // ============================== EXPORT MODULE ============================== | |
| export: function(){ | |
| var svgString = this.getSVGString(this.options.chartModule.svg.node()); | |
| this.svgString2Image( svgString, 2 * this.options.chartModule.width, 2 * this.options.chartModule.height, 'png', save ); // passes Blob and filesize String to the callback | |
| function save( dataBlob, filesize ){ | |
| saveAs( dataBlob, 'pitches_chart.png' ); // FileSaver.js function | |
| } | |
| }, | |
| // Below are the functions that handle actual exporting: | |
| // getSVGString ( svgNode ) and svgString2Image( svgString, width, height, format, callback ) | |
| getSVGString: function( svgNode ) { | |
| svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink'); | |
| var cssStyleText = getCSSStyles( svgNode ); | |
| appendCSS( cssStyleText, svgNode ); | |
| var serializer = new XMLSerializer(); | |
| var svgString = serializer.serializeToString(svgNode); | |
| svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace | |
| svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix | |
| return svgString; | |
| function getCSSStyles( parentElement ) { | |
| var selectorTextArr = []; | |
| // Add Parent element Id and Classes to the list | |
| selectorTextArr.push( '#'+parentElement.id ); | |
| for (var c = 0; c < parentElement.classList.length; c++) | |
| if ( !contains('.'+parentElement.classList[c], selectorTextArr) ) | |
| selectorTextArr.push( '.'+parentElement.classList[c] ); | |
| // Add Children element Ids and Classes to the list | |
| var nodes = parentElement.getElementsByTagName("*"); | |
| for (var i = 0; i < nodes.length; i++) { | |
| var id = nodes[i].id; | |
| if ( !contains('#'+id, selectorTextArr) ) | |
| selectorTextArr.push( '#'+id ); | |
| var classes = nodes[i].classList; | |
| for (var c = 0; c < classes.length; c++) | |
| if ( !contains('.'+classes[c], selectorTextArr) ) | |
| selectorTextArr.push( '.'+classes[c] ); | |
| } | |
| // Extract CSS Rules | |
| var extractedCSSText = ""; | |
| for (var i = 0; i < document.styleSheets.length; i++) { | |
| var s = document.styleSheets[i]; | |
| try { | |
| if(!s.cssRules) continue; | |
| } catch( e ) { | |
| if(e.name !== 'SecurityError') throw e; // for Firefox | |
| continue; | |
| } | |
| var cssRules = s.cssRules; | |
| for (var r = 0; r < cssRules.length; r++) { | |
| if ( contains( cssRules[r].selectorText, selectorTextArr ) ) | |
| extractedCSSText += cssRules[r].cssText; | |
| } | |
| } | |
| return extractedCSSText; | |
| function contains(str,arr) { | |
| return arr.indexOf( str ) === -1 ? false : true; | |
| } | |
| } | |
| function appendCSS( cssText, element ) { | |
| var styleElement = document.createElement("style"); | |
| styleElement.setAttribute("type","text/css"); | |
| styleElement.innerHTML = cssText; | |
| var refNode = element.hasChildNodes() ? element.children[0] : null; | |
| element.insertBefore( styleElement, refNode ); | |
| } | |
| }, | |
| svgString2Image: function( svgString, width, height, format, callback ) { | |
| var that = this; | |
| var format = format ? format : 'png'; | |
| var imgsrc = 'data:image/svg+xml;base64,'+ btoa( unescape( encodeURIComponent( svgString ) ) ); // Convert SVG string to data URL | |
| var canvas = document.createElement("canvas"); | |
| var context = canvas.getContext("2d"); | |
| canvas.width = width; | |
| canvas.height = height; | |
| var image = new Image(); | |
| image.onload = function() { | |
| context.clearRect ( 0, 0, width, height ); | |
| var backgroundImage = new Image(); | |
| backgroundImage.onload = function(){ | |
| if(that.options.chartModule.heatmap.show){ | |
| var heatmapDataURL = that.options.chartModule.heatmap.instance.getDataURL(); | |
| var heatmap = new Image(); | |
| heatmap.onload = function(){ | |
| context.globalAlpha = that.options.chartModule.pitchBgAlpha; | |
| context.drawImage(backgroundImage, 0, 0, width, height); | |
| context.globalAlpha = 1.0; | |
| context.drawImage(heatmap, 0, 0, width, height); | |
| context.drawImage(image, 0, 0, width, height); | |
| that.onAllImagesLoad(canvas, callback); | |
| }; | |
| heatmap.src = heatmapDataURL; | |
| }else{ | |
| context.drawImage(backgroundImage, 0, 0, width, height); | |
| context.drawImage(image, 0, 0, width, height); | |
| // | |
| that.onAllImagesLoad(canvas, callback); | |
| } | |
| }; | |
| backgroundImage.src = that.options.chartModule.pitchBg; | |
| }; | |
| image.src = imgsrc; | |
| }, | |
| onAllImagesLoad: function(canvas, callback){ | |
| canvas.toBlob( function(blob) { | |
| var filesize = Math.round( blob.length/1024 ) + ' KB'; | |
| if ( callback ) callback( blob, filesize ); | |
| }); | |
| } | |
| }; | |
| PITCH_APP.start(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <meta charset='utf-8'> | |
| <html> | |
| <head> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.6.0/alt/video-js-cdn.min.css" rel="stylesheet"> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> | |
| <link rel='stylesheet' href='style.css'> | |
| </head> | |
| <body> | |
| <div class="container-fluid"> | |
| <div class="row"> | |
| <div class="col-sm-4" id="pitch-select-module"></div> | |
| <div class="col-sm-4"> | |
| <div class="form-check"> | |
| <input type="checkbox" class="form-check-input" id="pitch-heatmap-checkbox"> | |
| <label class="form-check-label" for="pitch-heatmap-checkbox">Heatmap</label> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="col-sm-6"> | |
| <div id="pitch-chart-module"></div> | |
| <div> | |
| <button type="button" id="pitch-export" class="btn btn-outline-primary btn-sm">Export to PNG</button> | |
| <label class="switch" title="AUTOPLAY"> | |
| <input id="pitch-autoplay-checkbox" type="checkbox"> | |
| <span class="slider round"></span> | |
| </label> | |
| <div class="form-check"> | |
| <input class="form-check-input" type="checkbox" value="" id="markTopVelo"> | |
| <label class="form-check-label" for="markTopVelo"> | |
| Mark Top Velo | |
| </label> | |
| </div> | |
| <div class="form-check"> | |
| <input class="form-check-input" type="checkbox" value="" id="markTopSpin"> | |
| <label class="form-check-label" for="markTopSpin"> | |
| Mark Top Spin | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-sm-6"> | |
| <div class="row"> | |
| <div class="col-sm-12" id="edit-pitch-module"> | |
| <div class="row"> | |
| <div class="col-sm-2"> | |
| <button type="button" id="edit_pitch_btn" class="btn btn-primary">Edit Pitch</button> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="col-sm-12"> | |
| <form id="edit_pitch_form" class="form-inline my-2"> | |
| <input readonly id="edit_pitch_y_input" type="text" class="form-control mr-sm-2" placeholder="Y (Height)"> | |
| <input readonly id="edit_pitch_x_input" type="text" class="form-control mr-sm-2" placeholder="X (Width)"> | |
| <button type="button" id="save_edit_pitch_btn" class="btn btn-success mr-sm-2">Save</button> | |
| <button type="button" id="cancel_edit_pitch_btn" class="btn btn-danger mr-sm-2">Cancel</button> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="col-sm-4" id="pitch-table-module"></div> | |
| <div class="col-sm-8" id="pitch-video-module"></div> | |
| </div> | |
| </div> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.6.3/video.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/heatmap.js/2.0.2/heatmap.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/javascript-canvas-to-blob/3.14.0/js/canvas-to-blob.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script> | |
| <script type='text/javascript' src='charts_pitcher_plot.js'></script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "RECORDS": [ | |
| { | |
| "playID": "15007", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Swinging Strike", | |
| "pitchvelo": "71.658", | |
| "pitchY": "3.000", | |
| "pitchX": "-0.083", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/10_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21049", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/10_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1637", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15008", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.845", | |
| "pitchY": "1.417", | |
| "pitchX": "-2.583", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/11_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21051", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/11_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1621", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15009", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "68.864", | |
| "pitchY": "3.333", | |
| "pitchX": "-0.250", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/12_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21053", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/12_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1659", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15010", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "70.361", | |
| "pitchY": "2.583", | |
| "pitchX": "-0.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/13_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21055", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/13_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1735", | |
| "exitvelo": "91.392" | |
| }, | |
| { | |
| "playID": "15011", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "71.593", | |
| "pitchY": "2.667", | |
| "pitchX": "1.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/14_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21057", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/14_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1610", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15012", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Error", | |
| "pitchvelo": "72.970", | |
| "pitchY": "2.250", | |
| "pitchX": "-0.417", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/15_JosephPreusser_AlerickSolearie.mp4", | |
| "video_id": "21059", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/15_JosephPreusser_AlerickSolearie.mp4", | |
| "pspin": "1703", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15013", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "72.133", | |
| "pitchY": "2.333", | |
| "pitchX": "-0.167", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/16_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21061", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/16_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1696", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15014", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "72.455", | |
| "pitchY": "2.417", | |
| "pitchX": "-0.417", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/17_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21063", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/17_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "0", | |
| "exitvelo": "95.483" | |
| }, | |
| { | |
| "playID": "15015", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.162", | |
| "pitchY": "3.083", | |
| "pitchX": "2.167", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/18_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21065", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/18_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1642", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15016", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "69.958", | |
| "pitchY": "2.500", | |
| "pitchX": "1.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/19_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21067", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/19_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1690", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15017", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "69.750", | |
| "pitchY": "2.417", | |
| "pitchX": "3.417", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/20_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21069", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/20_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1142", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15018", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Swinging Strike", | |
| "pitchvelo": "71.706", | |
| "pitchY": "3.333", | |
| "pitchX": "-0.833", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/21_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21071", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/21_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "2157", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15019", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "70.151", | |
| "pitchY": "2.667", | |
| "pitchX": "1.333", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/22_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21073", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/22_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1412", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15020", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "71.520", | |
| "pitchY": "2.667", | |
| "pitchX": "-0.333", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/23_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21075", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/23_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1714", | |
| "exitvelo": "84.597" | |
| }, | |
| { | |
| "playID": "15021", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "70.224", | |
| "pitchY": "2.833", | |
| "pitchX": "-0.167", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/24_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21077", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/24_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1658", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15022", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "71.378", | |
| "pitchY": "2.083", | |
| "pitchX": "-0.250", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/25_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21079", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/25_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1679", | |
| "exitvelo": "82.177" | |
| }, | |
| { | |
| "playID": "15038", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "66.904", | |
| "pitchY": "2.250", | |
| "pitchX": "-1.250", | |
| "ptype": "Slider", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/41_JosephPreusser_HerbertIser.mp4", | |
| "video_id": "21111", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/41_JosephPreusser_HerbertIser.mp4", | |
| "pspin": "1680", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15039", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "71.056", | |
| "pitchY": "2.500", | |
| "pitchX": "-0.333", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/42_JosephPreusser_HerbertIser.mp4", | |
| "video_id": "21113", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/42_JosephPreusser_HerbertIser.mp4", | |
| "pspin": "1662", | |
| "exitvelo": "57.024" | |
| }, | |
| { | |
| "playID": "15040", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "70.546", | |
| "pitchY": "3.167", | |
| "pitchX": "-0.500", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/43_JosephPreusser_HerbertIser.mp4", | |
| "video_id": "21115", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/43_JosephPreusser_HerbertIser.mp4", | |
| "pspin": "1691", | |
| "exitvelo": "98.021" | |
| }, | |
| { | |
| "playID": "15041", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.091", | |
| "pitchY": "0.583", | |
| "pitchX": "-1.250", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/44_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21117", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/44_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1704", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15042", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.751", | |
| "pitchY": "2.083", | |
| "pitchX": "1.500", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/45_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21119", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/45_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1635", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15043", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "71.194", | |
| "pitchY": "1.167", | |
| "pitchX": "-1.667", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/46_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21121", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/46_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1674", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15044", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "68.711", | |
| "pitchY": "2.750", | |
| "pitchX": "2.000", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/47_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21123", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/47_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1145", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15045", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "69.776", | |
| "pitchY": "0.000", | |
| "pitchX": "-0.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/48_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21125", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/48_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1738", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15046", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "72.569", | |
| "pitchY": "2.250", | |
| "pitchX": "-0.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/49_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21127", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/49_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1715", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15047", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "73.658", | |
| "pitchY": "1.833", | |
| "pitchX": "-2.167", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/50_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21129", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/50_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1735", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15048", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Double", | |
| "pitchvelo": "69.245", | |
| "pitchY": "2.250", | |
| "pitchX": "-0.167", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/51_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21131", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/51_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1729", | |
| "exitvelo": "82.293" | |
| }, | |
| { | |
| "playID": "15049", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "73.258", | |
| "pitchY": "2.333", | |
| "pitchX": "1.667", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/52_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21133", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/52_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1603", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15050", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Home Run", | |
| "pitchvelo": "73.407", | |
| "pitchY": "2.083", | |
| "pitchX": "-0.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/53_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21135", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/53_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1741", | |
| "exitvelo": "100.199" | |
| }, | |
| { | |
| "playID": "15051", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "", | |
| "pitchvelo": "74.245", | |
| "pitchY": "2.583", | |
| "pitchX": "-0.917", | |
| "ptype": "", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/54_JosephPreusser_AlerickSolearie.mp4", | |
| "video_id": "21137", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/54_JosephPreusser_AlerickSolearie.mp4", | |
| "pspin": "1712", | |
| "exitvelo": "96.746" | |
| }, | |
| { | |
| "playID": "15052", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "72.624", | |
| "pitchY": "3.333", | |
| "pitchX": "1.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/55_JosephPreusser_AlerickSolearie.mp4", | |
| "video_id": "21139", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/55_JosephPreusser_AlerickSolearie.mp4", | |
| "pspin": "1627", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15053", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "", | |
| "pitchvelo": "72.049", | |
| "pitchY": "3.417", | |
| "pitchX": "1.500", | |
| "ptype": "", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/56_JosephPreusser_AlerickSolearie.mp4", | |
| "video_id": "21141", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/56_JosephPreusser_AlerickSolearie.mp4", | |
| "pspin": "1638", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15054", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "71.410", | |
| "pitchY": "2.917", | |
| "pitchX": "-0.750", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/57_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21143", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/57_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1710", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15055", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "69.017", | |
| "pitchY": "2.167", | |
| "pitchX": "-1.250", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/58_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21145", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/58_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1652", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15056", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "70.904", | |
| "pitchY": "2.833", | |
| "pitchX": "-0.750", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/59_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21147", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/59_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1657", | |
| "exitvelo": "89.890" | |
| }, | |
| { | |
| "playID": "15057", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "72.398", | |
| "pitchY": "1.917", | |
| "pitchX": "-0.583", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/60_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21149", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/60_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1727", | |
| "exitvelo": "95.093" | |
| }, | |
| { | |
| "playID": "15076", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "72.540", | |
| "pitchY": "0.417", | |
| "pitchX": "-0.750", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/79_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21187", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/79_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1221", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15077", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "72.726", | |
| "pitchY": "1.333", | |
| "pitchX": "-0.417", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/80_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21189", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/80_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1309", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15078", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "73.428", | |
| "pitchY": "3.250", | |
| "pitchX": "1.500", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/81_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21191", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/81_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1641", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15079", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "72.680", | |
| "pitchY": "2.000", | |
| "pitchX": "-0.750", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/82_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21193", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/82_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1629", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15080", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.838", | |
| "pitchY": "3.333", | |
| "pitchX": "1.167", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/83_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21195", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/83_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "0", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15081", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "70.639", | |
| "pitchY": "2.000", | |
| "pitchX": "-1.500", | |
| "ptype": "Slider", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/84_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21197", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/84_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1838", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15082", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "72.731", | |
| "pitchY": "2.250", | |
| "pitchX": "-2.917", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/85_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21199", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/85_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1702", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15083", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "71.873", | |
| "pitchY": "2.000", | |
| "pitchX": "-0.833", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/86_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21201", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/86_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1708", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15084", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "71.822", | |
| "pitchY": "1.917", | |
| "pitchX": "-0.333", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/87_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21203", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/87_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1708", | |
| "exitvelo": "87.923" | |
| }, | |
| { | |
| "playID": "15085", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "73.310", | |
| "pitchY": "2.167", | |
| "pitchX": "-0.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/88_JosephPreusser_HerbertIser.mp4", | |
| "video_id": "21205", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/88_JosephPreusser_HerbertIser.mp4", | |
| "pspin": "1710", | |
| "exitvelo": "94.317" | |
| }, | |
| { | |
| "playID": "15086", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "70.570", | |
| "pitchY": "2.667", | |
| "pitchX": "-0.250", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/89_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21207", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/89_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1302", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15087", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.462", | |
| "pitchY": "3.417", | |
| "pitchX": "1.333", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/90_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21209", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/90_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1748", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15088", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "71.414", | |
| "pitchY": "2.333", | |
| "pitchX": "-0.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/91_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21211", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/91_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1870", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15089", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "72.657", | |
| "pitchY": "3.250", | |
| "pitchX": "-0.333", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/92_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21213", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/92_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1728", | |
| "exitvelo": "56.211" | |
| }, | |
| { | |
| "playID": "15090", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "73.468", | |
| "pitchY": "1.917", | |
| "pitchX": "1.750", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/93_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21215", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/93_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1761", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15091", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "72.708", | |
| "pitchY": "2.000", | |
| "pitchX": "1.417", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/94_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21217", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/94_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1684", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15092", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.452", | |
| "pitchY": "3.250", | |
| "pitchX": "1.750", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/95_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21219", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/95_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1783", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15093", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "73.427", | |
| "pitchY": "2.000", | |
| "pitchX": "2.250", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/96_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21221", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/96_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1787", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15094", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "72.897", | |
| "pitchY": "2.833", | |
| "pitchX": "-0.333", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/97_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21223", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/97_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1813", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15095", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Home Run", | |
| "pitchvelo": "72.032", | |
| "pitchY": "2.333", | |
| "pitchX": "-0.417", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/98_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21225", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/98_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1737", | |
| "exitvelo": "102.969" | |
| }, | |
| { | |
| "playID": "15096", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "73.279", | |
| "pitchY": "3.000", | |
| "pitchX": "-1.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/99_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21227", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/99_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1676", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15097", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.102", | |
| "pitchY": "2.667", | |
| "pitchX": "-2.500", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/100_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21229", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/100_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1776", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15098", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "71.473", | |
| "pitchY": "3.250", | |
| "pitchX": "-0.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/101_JosephPreusser_MatthewGoodheart.mp4", | |
| "video_id": "21231", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/101_JosephPreusser_MatthewGoodheart.mp4", | |
| "pspin": "1663", | |
| "exitvelo": "98.631" | |
| }, | |
| { | |
| "playID": "15109", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "72.010", | |
| "pitchY": "1.000", | |
| "pitchX": "-0.250", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/112_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21253", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/112_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1754", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15110", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "71.821", | |
| "pitchY": "1.667", | |
| "pitchX": "-0.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/113_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21255", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/113_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1689", | |
| "exitvelo": "98.554" | |
| }, | |
| { | |
| "playID": "15111", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "70.344", | |
| "pitchY": "2.000", | |
| "pitchX": "1.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/114_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21257", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/114_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1054", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15112", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "72.928", | |
| "pitchY": "2.417", | |
| "pitchX": "3.250", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/115_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21259", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/115_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1625", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15113", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "73.893", | |
| "pitchY": "0.750", | |
| "pitchX": "-0.583", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/116_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21261", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/116_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "0", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15114", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "73.232", | |
| "pitchY": "2.833", | |
| "pitchX": "-0.833", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/117_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21263", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/117_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1753", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15115", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.560", | |
| "pitchY": "2.250", | |
| "pitchX": "2.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/118_JosephPreusser_AndresSosa.mp4", | |
| "video_id": "21265", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/118_JosephPreusser_AndresSosa.mp4", | |
| "pspin": "1829", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15116", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "72.121", | |
| "pitchY": "4.000", | |
| "pitchX": "2.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/119_JosephPreusser_AlerickSolearie.mp4", | |
| "video_id": "21267", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/119_JosephPreusser_AlerickSolearie.mp4", | |
| "pspin": "1690", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15117", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "69.411", | |
| "pitchY": "3.333", | |
| "pitchX": "1.750", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/120_JosephPreusser_AlerickSolearie.mp4", | |
| "video_id": "21269", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/120_JosephPreusser_AlerickSolearie.mp4", | |
| "pspin": "1231", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15118", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Double", | |
| "pitchvelo": "71.525", | |
| "pitchY": "2.167", | |
| "pitchX": "-0.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/121_JosephPreusser_AlerickSolearie.mp4", | |
| "video_id": "21271", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/121_JosephPreusser_AlerickSolearie.mp4", | |
| "pspin": "1671", | |
| "exitvelo": "77.507" | |
| }, | |
| { | |
| "playID": "15119", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "72.546", | |
| "pitchY": "2.167", | |
| "pitchX": "-0.667", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/122_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21273", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/122_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1668", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15120", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "74.601", | |
| "pitchY": "0.917", | |
| "pitchX": "-2.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/123_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21275", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/123_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1859", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15121", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "69.050", | |
| "pitchY": "0.667", | |
| "pitchX": "-2.250", | |
| "ptype": "Slider", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/124_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21277", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/124_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1715", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15122", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "72.810", | |
| "pitchY": "3.333", | |
| "pitchX": "-0.000", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/125_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21279", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/125_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1191", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15123", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "70.335", | |
| "pitchY": "2.667", | |
| "pitchX": "-0.583", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/126_JosephPreusser_SergioMacias.mp4", | |
| "video_id": "21281", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/126_JosephPreusser_SergioMacias.mp4", | |
| "pspin": "1695", | |
| "exitvelo": "89.248" | |
| }, | |
| { | |
| "playID": "15124", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "71.627", | |
| "pitchY": "1.500", | |
| "pitchX": "1.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/127_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21283", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/127_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1634", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15125", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "69.539", | |
| "pitchY": "2.333", | |
| "pitchX": "-0.667", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/128_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21285", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/128_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1336", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15126", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "69.684", | |
| "pitchY": "1.917", | |
| "pitchX": "1.000", | |
| "ptype": "Changeup", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/129_JosephPreusser_JakeMatheny.mp4", | |
| "video_id": "21287", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/129_JosephPreusser_JakeMatheny.mp4", | |
| "pspin": "1324", | |
| "exitvelo": "96.733" | |
| }, | |
| { | |
| "playID": "15127", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "70.360", | |
| "pitchY": "1.667", | |
| "pitchX": "-0.500", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/130_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21289", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/130_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1746", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15128", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "71.827", | |
| "pitchY": "2.500", | |
| "pitchX": "-1.417", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/131_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21291", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/131_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1694", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15129", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Foul Ball", | |
| "pitchvelo": "72.179", | |
| "pitchY": "2.417", | |
| "pitchX": "-0.917", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/132_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21293", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/132_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1653", | |
| "exitvelo": "86.525" | |
| }, | |
| { | |
| "playID": "15130", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "71.520", | |
| "pitchY": "2.250", | |
| "pitchX": "-1.250", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/133_JosephPreusser_MarioMoralez.mp4", | |
| "video_id": "21295", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/133_JosephPreusser_MarioMoralez.mp4", | |
| "pspin": "1754", | |
| "exitvelo": "80.995" | |
| }, | |
| { | |
| "playID": "15131", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Single", | |
| "pitchvelo": "70.142", | |
| "pitchY": "2.333", | |
| "pitchX": "-0.083", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/134_JosephPreusser_HerbertIser.mp4", | |
| "video_id": "21297", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/134_JosephPreusser_HerbertIser.mp4", | |
| "pspin": "1668", | |
| "exitvelo": "75.751" | |
| }, | |
| { | |
| "playID": "15132", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Called Strike", | |
| "pitchvelo": "72.556", | |
| "pitchY": "1.667", | |
| "pitchX": "-0.583", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/135_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21299", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/135_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1586", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15133", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Ball", | |
| "pitchvelo": "70.459", | |
| "pitchY": "4.083", | |
| "pitchX": "-0.167", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/136_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21301", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/136_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1718", | |
| "exitvelo": "0.000" | |
| }, | |
| { | |
| "playID": "15134", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "68.208", | |
| "pitchY": "2.667", | |
| "pitchX": "-0.500", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/137_JosephPreusser_TyrieceSilas.mp4", | |
| "video_id": "21303", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/137_JosephPreusser_TyrieceSilas.mp4", | |
| "pspin": "1750", | |
| "exitvelo": "92.306" | |
| }, | |
| { | |
| "playID": "15135", | |
| "eventName": "San Jac vs South Suburban CC", | |
| "eventDate": "13/3/2018 17:01:48", | |
| "eventID": "32", | |
| "name": "Joseph Preusser", | |
| "presult": "Contact Out", | |
| "pitchvelo": "70.271", | |
| "pitchY": "1.417", | |
| "pitchX": "-0.667", | |
| "ptype": "Fastball", | |
| "angle1": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCC/138_JosephPreusser_MattWiseman.mp4", | |
| "video_id": "21305", | |
| "angle2": "https://s3.amazonaws.com/prospectwire/2018-03-13/SanJacintoCCvsSouthSuburbanCCAngle2/138_JosephPreusser_MattWiseman.mp4", | |
| "pspin": "1636", | |
| "exitvelo": "92.327" | |
| } | |
| ] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .fa-rotate-45 { | |
| -webkit-transform: rotate(45deg); | |
| -moz-transform: rotate(45deg); | |
| -ms-transform: rotate(45deg); | |
| -o-transform: rotate(45deg); | |
| transform: rotate(45deg); | |
| } | |
| .fa-rotate-315 { | |
| -webkit-transform: rotate(315deg); | |
| -moz-transform: rotate(315deg); | |
| -ms-transform: rotate(315deg); | |
| -o-transform: rotate(315deg); | |
| transform: rotate(315deg); | |
| } | |
| .green{ | |
| color: limegreen; | |
| } | |
| table { | |
| border-collapse: collapse; | |
| } | |
| .table { | |
| width: 100%; | |
| max-width: 100%; | |
| margin-bottom: 1rem; | |
| background-color: transparent; | |
| font-size: 0.92rem; | |
| } | |
| .table thead th { | |
| vertical-align: bottom; | |
| border-bottom: 2px solid #e9ecef; | |
| } | |
| .table tr.active{ | |
| background-color: #c5e8f5; | |
| } | |
| .table td, .table th { | |
| padding: .3rem; | |
| vertical-align: top; | |
| border-top: 1px solid #e9ecef; | |
| text-align: center; | |
| } | |
| .table td, .table th { | |
| padding: .3rem; | |
| vertical-align: top; | |
| border-top: 1px solid #e9ecef; | |
| } | |
| .switch { | |
| position: relative; | |
| display: inline-block; | |
| width: 60px; | |
| height: 34px; | |
| vertical-align: middle; | |
| margin-bottom: 0; | |
| } | |
| .switch input {display:none;} | |
| .slider { | |
| position: absolute; | |
| cursor: pointer; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-color: #ccc; | |
| -webkit-transition: .4s; | |
| transition: .4s; | |
| } | |
| .slider:before { | |
| position: absolute; | |
| content: ""; | |
| height: 26px; | |
| width: 26px; | |
| left: 4px; | |
| bottom: 4px; | |
| background-color: white; | |
| -webkit-transition: .4s; | |
| transition: .4s; | |
| } | |
| input:checked + .slider { | |
| background-color: #2196F3; | |
| } | |
| input:focus + .slider { | |
| box-shadow: 0 0 1px #2196F3; | |
| } | |
| input:checked + .slider:before { | |
| -webkit-transform: translateX(26px); | |
| -ms-transform: translateX(26px); | |
| transform: translateX(26px); | |
| } | |
| /* Rounded sliders */ | |
| .slider.round { | |
| border-radius: 34px; | |
| } | |
| .slider.round:before { | |
| border-radius: 50%; | |
| } | |
| /* module specific styles */ | |
| .pitch-ball.active{ | |
| stroke: #ee83d8; | |
| stroke-width: 8; | |
| } | |
| .pitch-ball.hovered{ | |
| fill: #c6c6c6; | |
| } | |
| div.pitch-tooltip { | |
| position: absolute; | |
| text-align: center; | |
| width: 70px; | |
| height: 28px; | |
| line-height: 28px; | |
| padding: 6px 2px 2px 2px; | |
| font: 12px sans-serif; | |
| background: black; | |
| border: 0px; | |
| -webkit-border-radius: 8px; | |
| -moz-border-radius: 8px; | |
| border-radius: 8px; | |
| pointer-events: none; | |
| color:white; | |
| z-index: 2; | |
| } | |
| #pitch-video-module{ | |
| } | |
| #pitch-chart-module { | |
| position: relative; | |
| } | |
| #pitch-chart-module svg{ | |
| position: relative; | |
| z-index: 1; | |
| } | |
| .pitch-heatmap-wrapper{ | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| z-index: 0; | |
| } | |
| .pitch-heatmap { | |
| position: relative; | |
| width: 100%; | |
| height: 100%; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
