Slide right team (me on the far left)
I first got into softball in spring of 2023. Not getting my necessary dose of social interaction from my remote job I signed up to play for the Nexus League of Huntsville. I found so much more than just some exercise on the weekend, I found a family. We were a true cinderella story, a bunch of misfit players that have never played the sport. We practiced hard and played harder. By the end of the season, we found ourselves winning our entire division and qualifying for the NAGAAA world series in Minneapolis, MN.
While I was mostly there for fun, I eventually became the coach for the team. Some of the players asked to get their stats, since I keep them in a google sheet, I created a dashboard for them to see their stats and to assist in finding out where they can improve.
Here is my Plater Stats web app.
– It uses a google sheet with 9 columns:
With these columns I can create a dashboard for basic stats from the book keepers book and display them in a quantitative way.
Deployed Test Web App:
https://script.google.com/macros/s/AKfycbyBNVhmC0O17JguhYOqqZUrDKEhkVKe5wTgGyllPeSzSX_-Hy8_Dufy1t0zZl0NVN6Uow/exec
GitHub: https://github.com/jcorky/Player-Stats-Web-App
Code.gs
function doGet() {
return HtmlService.createTemplateFromFile('Index').evaluate();
}
function getPlayerData(playerSheetName) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(playerSheetName);
var data = sheet.getRange(2, 1, sheet.getLastRow()-1, sheet.getLastColumn()).getValues();
return aggregateData(data); // returns the aggregated data for the player
}
function aggregateData(data) {
var aggregatedData = [];
for (var i = 0; i < data.length; i++) {
var gameNumber = i + 1;
var rowData = data[i];
var timesAtBat = rowData[0];
var hits = rowData[1];
var battingAverage = rowData[2];
var onBase = rowData[3];
var onBaseAverage = rowData[4];
var rbis = rowData[5];
var runsScored = rowData[6];
var strikeouts = rowData[7];
var walks = rowData[8];
aggregatedData.push([gameNumber, timesAtBat, hits, battingAverage, onBase, onBaseAverage, rbis, runsScored, strikeouts, walks]);
}
return aggregatedData;
}
Index.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
function drawChart(playerData) {
var data = new google.visualization.DataTable();
data.addColumn('number', 'Game');
data.addColumn('number', 'Times at Bat');
data.addColumn('number', 'Hits');
data.addColumn('number', 'Batting Average');
data.addColumn('number', 'On Base');
data.addColumn('number', 'On Base Average');
data.addColumn('number', 'RBI\'s');
data.addColumn('number', 'Runs Scored');
data.addColumn('number', 'Strikeouts');
data.addColumn('number', 'Walks');
data.addRows(playerData);
var options = {
title: 'Player Performance',
hAxis: {title: 'Game', viewWindowMode: 'pretty'},
vAxis: {title: 'Stats', viewWindowMode: 'pretty'},
seriesType: 'bars'
};
var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
chart.draw(data, options);
drawLineCharts(data);
}
function drawLineCharts(data) {
for (var i = 1; i < data.getNumberOfColumns(); i++) {
var lineChartData = new google.visualization.DataTable();
lineChartData.addColumn('number', 'Game');
lineChartData.addColumn('number', data.getColumnLabel(i));
lineChartData.addRows(data.getNumberOfRows());
for (var j = 0; j < data.getNumberOfRows(); j++) {
lineChartData.setValue(j, 0, data.getValue(j, 0));
lineChartData.setValue(j, 1, data.getValue(j, i));
}
var lineChartOptions = {
title: data.getColumnLabel(i),
hAxis: {title: 'Game', viewWindowMode: 'pretty'},
vAxis: {title: data.getColumnLabel(i), viewWindowMode: 'pretty'},
series: {
0: {
type: 'line',
color: 'blue'
}
}
};
var lineChart = new google.visualization.LineChart(document.getElementById('line_chart_div_' + i));
lineChart.draw(lineChartData, lineChartOptions);
}
}
function updateChart() {
var player = document.getElementById("playerSelect").value;
google.script.run.withSuccessHandler(drawChart).getPlayerData(player);
}
function refreshData() {
updateChart();
}
// Load the initial data for the first player on page load
google.charts.setOnLoadCallback(function() {
updateChart();
});
</script>
</head>
<body>
<a href="https://lh3.googleusercontent.com/pw/AIL4fc_QvOlvyXaRMNfDR5KQ7CiUfxlV1JlXV2rKPn3P8MwJanQzuiR1DcPBFenQiEA6djTaoVWg5gbII1liuYRi4rmP7OGIt4wf6ABDheTp07m-D5Sp6g=w2400?source=screenshot.guru"> <img src="https://lh3.googleusercontent.com/pw/AIL4fc_QvOlvyXaRMNfDR5KQ7CiUfxlV1JlXV2rKPn3P8MwJanQzuiR1DcPBFenQiEA6djTaoVWg5gbII1liuYRi4rmP7OGIt4wf6ABDheTp07m-D5Sp6g=w600-h315-p-k" /> </a><br>
<div>
<span style="font-family:arial,helvetica,sans-serif;">Welcome!</span></div>
<div>
</div>
<div>
<span style="font-family:arial,helvetica,sans-serif;">This is the player statistic tracker for Slide Right. It was created for keeping track of Hits, RBI's, Batting Averages, etc.. </span></div>
<div>
</div>
<div>
<span style="font-family:arial,helvetica,sans-serif;">Just choose a player from the drop down to see their stats. The stats will typicaly be updated by tuesday of the following week. </span></div>
<div>
</div>
<div>
<span style="font-size:10px;"><span style="font-family:arial,helvetica,sans-serif;"><span style="background-color: rgba(80, 151, 255, 0.18); color: rgb(4, 12, 40);">©</span> Johnathan Cork</span></span></div>
<select id="playerSelect" onchange="updateChart()">
<? var ss = SpreadsheetApp.getActiveSpreadsheet(); ?>
<? var sheets = ss.getSheets(); ?>
<? for (var i = 0; i < sheets.length; i++) { ?>
<option value="<?= sheets[i].getName(); ?>"><?= sheets[i].getName(); ?></option>
<? } ?>
</select>
<button onclick="refreshData()">Refresh Data</button>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
<!-- Add containers for each line chart -->
<? for (var i = 1; i < 10; i++) { ?>
<div id="line_chart_div_<?= i ?>" style="width: 900px; height: 500px;"></div>
<? } ?>
</body>
</html>