Permalink
Browse files

adding some files

  • Loading branch information...
1 parent fadafa6 commit aee868b022af5ae40619c4596eca42143ca0a2f0 @indiemaps committed Jul 23, 2009
Showing with 618 additions and 0 deletions.
  1. +24 −0 LICENSE
  2. BIN base.png
  3. BIN blank.png
  4. BIN blueDot.png
  5. +299 −0 index.html
  6. +214 −0 jquery.url.js
  7. +81 −0 js-hit-locations-map.css
  8. BIN pinkDot.png
View
@@ -0,0 +1,24 @@
+Copyright (c) 2009, Zachary Forest Johnson
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the <organization> nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY Zachary Forest Johnson ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL Zachary Forest Johnson BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
@@ -0,0 +1,299 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+ <meta name="author" content="Zachary Forest Johnson" />
+
+ <title>MLB hit locations on a Google Map</title>
+
+ <!-- YUI -->
+ <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?2.7.0/build/paginator/assets/skins/sam/paginator.css&2.7.0/build/datatable/assets/skins/sam/datatable.css">
+ <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.7.0/build/yahoo-dom-event/yahoo-dom-event.js&2.7.0/build/datasource/datasource-min.js&2.7.0/build/element/element-min.js&2.7.0/build/paginator/paginator-min.js&2.7.0/build/datatable/datatable-min.js"></script>
+
+ <!-- Mapstraction -->
+ <script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA7QUChpcnvnmXxsjC7s1fCxQGj0PqsCtxKvarsoS-iqLdqZSKfxTd7Xf-2rEc_PC9o8IsJde80Wnj4g" type="text/javascript"></script>
+ <script type="text/javascript" src="http://www.mapstraction.com/mapstraction-js/mapstraction.js"></script>
+
+ <!-- jQuery -->
+ <script src="http://code.jquery.com/jquery-latest.js"></script>
+
+ <!-- jQuery URL parser -->
+ <script type="text/javascript" src="jquery.url.js"></script>
+
+ <!-- css -->
+ <link rel="stylesheet" type="text/css" href="js-hit-locations-map.css">
+
+ </head>
+
+ <body>
+
+ <div id="wrap">
+
+ <h1 id="game">Loading game info...</h1>
+ <h2 id="venue">Loading stadium info...</h2>
+
+ <div id="left">
+ <!-- HTML Map element - the size must be specified here, or in the CSS -->
+ <div id="mapstraction"></div>
+
+ <h3 id="hitsLoading">Loading hits...</h3>
+
+ <p id="legend">
+ <img class="legendChip_small" src="blueDot.png" width="6" height="6" /> = hit, <img class="legendChip_small" src="pinkDot.png" width="6" height="6" /> = out, <img class="legendChip_big" src="blueDot.png" width="15" height="15" /> = home run, <img class="legendChip_big" src="pinkDot.png" width="15" height="15" /> = double play ball
+ </p>
+
+ </div>
+
+ <div id="right" class="yui-skin-sam">
+ <h3 id="ballsInPlay"></h3>
+ <div id="hitsTable"></div>
+ </div>
+
+ <p>The above mashup loads hit location data from <a href="http://gd2.mlb.com/components/game/mlb/">MLB Gameday</a> data via <a href="http://developer.yahoo.com/yql/">YQL</a> and <a href="http://jquery.com/">jQuery</a>. Data are transformed from an arbitrary pixel coordinate system to latitude-longitude points using methods I describe <a href="">here</a>. Data are presented on <a href="http://maps.google.com/">Google Maps</a> satellite tiles, using <a href="http://mapstraction.com/">Mapstraction</a> as a wrapper. The accompanying <a href="http://developer.yahoo.com/yui/">YUI</a> table shows the same data and allows selection of balls-in-play.</p>
+
+ <p>
+ By default (without a game specified as a url parameter), this page shows the 2009 all star game. To see another game, simply add a <code>gid</code> parameter to the URL. The <code>gid</code> parameter is composed as follows:
+ <ul>
+ <li><code>gid_{year}_{month}_{day}_{away_team}mlb_{home_team}mlb_{game_number}</code></li>
+ </ul>
+ So, the default <code>gid</code>, the 2009 all star game, is <a href="file:///Users/zacharyjohnson/workspaces/pitchalyzer/js-hit-locations-map/index.html?gid=gid_2009_07_14_aasmlb_nasmlb_1"><code>gid_2009_07_14_aasmlb_nasmlb_1</code></a>. A few other example games:
+ <ul>
+ <li><a href="file:///Users/zacharyjohnson/workspaces/pitchalyzer/js-hit-locations-map/index.html?gid=gid_2009_07_10_sdnmlb_sfnmlb_1"><code>gid_2009_07_10_sdnmlb_sfnmlb_1</code></a>: Padres at Giants, July 10, 2009 (2009's only no-hitter)</li>
+ <li><a href="file:///Users/zacharyjohnson/workspaces/pitchalyzer/js-hit-locations-map/index.html?gid=gid_2009_05_22_phimlb_nyamlb_1"><code>gid_2009_05_22_phimlb_nyamlb_1</code></a>: Phillies at Yankees, May 22, 2009 (includes 2009's <a href="http://www.hittrackeronline.com/">longest homer</a>, 477 ft. by Raul Ibanez)</li>
+ <li><a href="file:///Users/zacharyjohnson/workspaces/pitchalyzer/js-hit-locations-map/index.html?gid=gid_2009_05_03_oakmlb_seamlb_1"><code>gid_2009_05_03_oakmlb_seamlb_1</code></a>: Athletics at Mariners, May 3, 2009 (the longest game this season)</li>
+ </ul>
+ Created by Zachary Forest Johnson of <a href="http://indiemaps.com/blog">indiemaps.com</a>. Just <em>view source</em> to see what's going on. Code is <a href="http://www.opensource.org/licenses/bsd-license.php">BSD</a> licensed and available <a href="http://github.com/indiemaps/js-hit-locations-map/tree/master">on github</a>.
+ </p>
+
+ </div> <!-- wrap -->
+
+ <script type="text/javascript">
+
+ var stadium;
+ var game;
+ var hits;
+ var hitMarkers = new Array();
+
+ var latConv;
+ var lngConv;
+
+ var mapstraction;
+
+ var myColumnDefs = [
+ {key:"inning", label:"Inning", sortable:true, width:50 },
+ {key:"event", label:"Event", sortable:true, width:50 },
+ {key:"des", label:"Description", width:350}
+ ];
+
+ var myConfigs = {
+ selectionMode:"single",
+ height:"488px"
+ };
+
+ $( document ).ready( function() {
+
+ $( 'p#legend' ).hide();
+
+ var gid = jQuery.url.param("gid");
+ if ( ! gid ) {
+ gid = "gid_2009_07_14_aasmlb_nasmlb_1";
+ }
+
+
+ mapstraction = new Mapstraction('mapstraction','google');
+ mapstraction.setMapType( Mapstraction.SATELLITE );
+
+ getGame( gid );
+
+ } );
+
+
+ function getGame( gid ) {
+ var year = gid.substring( 4, 8 );
+ var month = gid.substring( 9, 11 );
+ var day = gid.substring( 12, 14 );
+
+
+ var gameQueryURL = "http://query.yahooapis.com/v1/public/yql?q=" +
+ "select%20*%20from%20games%20where%20year%3D%22" +
+ year +
+ "%22%20and%20month%3D%22" +
+ month +
+ "%22%20and%20day%3D%22" +
+ day +
+ "%22%20and%20gid%3D%22" +
+ gid +
+ "%22&format=json&env=http%3A%2F%2Fgithub.com%2Findiemaps%2Fjs-hit-locations-map%2Fraw%2Fmaster%2Fyql%2Fmlb.gd2.env&callback=?";
+ $.getJSON( gameQueryURL,
+ function( gameData ) {
+
+ game = gameData.query.results.game;
+
+ // add teams to game h1
+
+
+ $('#game').html( game.teams.away.name_brief + " at " + game.teams.home.name_brief + " <span id='date'>" + game.date + "<\/span>" );
+
+ getStadium( game.stadium_id, gid );
+
+ } );
+ }
+
+ function getStadium( sid, gid ) {
+ var stadiumQueryURL = "http://query.yahooapis.com/v1/public/yql?q=" +
+ "select%20*%20from%20stadiums%20where%20id%3D%22" +
+ game.stadium_id +
+ "%22&format=json&env=http%3A%2F%2Fgithub.com%2Findiemaps%2Fjs-hit-locations-map%2Fraw%2Fmaster%2Fyql%2Fmlb.gd2.env&callback=?";
+
+ $.getJSON( stadiumQueryURL,
+ function( stadiumData ) {
+
+ stadium = stadiumData.query.results.stadium;
+
+ /*
+ stadium.geo.home_plate.latitude = 38.909647;
+ stadium.geo.home_plate.longitude = -77.043439;
+ */
+
+ $('#venue').text( stadium.name );
+
+ var homePlate_latLong = new LatLonPoint( parseFloat( stadium.geo.home_plate.latitude ), parseFloat( stadium.geo.home_plate.longitude ) );
+
+ // m per degree
+ latConv = homePlate_latLong.distance( new LatLonPoint( homePlate_latLong.lat + .001, homePlate_latLong.lng ) ) * 1000000;
+ lngConv = homePlate_latLong.distance( new LatLonPoint( homePlate_latLong.lat, homePlate_latLong.lng + .001 ) ) * 1000000;
+
+
+ var fieldCenter_feet = { x : 0, y : 250 };
+ var fieldCenter_feet_rotated = rotatePoint( fieldCenter_feet.x, fieldCenter_feet.y, stadium.geo.orientation.degrees );
+
+ var stadiumCenter = new LatLonPoint( homePlate_latLong.lat + feetToMeters( fieldCenter_feet_rotated.y ) / latConv,
+ homePlate_latLong.lng + feetToMeters( fieldCenter_feet_rotated.x ) / lngConv );
+
+ // display the map centered on a latitude and longitude (Google zoom levels)
+ mapstraction.setCenterAndZoom( stadiumCenter, 18 );
+
+ placeBases();
+
+ getHits( gid );
+
+ } );
+ }
+
+ function getHits( gid ) {
+ // select * from atbats where gid="gid_2009_07_11_lanmlb_milmlb_1" and hit_x<>"NaN"
+ // http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20atbats%20where%20gid%3D%22gid_2009_07_11_lanmlb_milmlb_1%22%20and%20hit_x%3C%3E%22NaN%22&format=xml&env=http%3A%2F%2Fgithub.com%2Findiemaps%2Fjs-hit-locations-map%2Fraw%2Fmaster%2Fyql%2Fmlb.gd2.env
+
+ var hitsQueryURL = "http://query.yahooapis.com/v1/public/yql?q=" +
+ "select%20*%20from%20atbats%20where%20gid%3D%22" +
+ gid +
+ "%22%20and%20hit_x%3C%3E%22NaN%22&format=json&env=http%3A%2F%2Fgithub.com%2Findiemaps%2Fjs-hit-locations-map%2Fraw%2Fmaster%2Fyql%2Fmlb.gd2.env&callback=?";
+
+ $.getJSON( hitsQueryURL,
+ function( hitsData ) {
+ hits = hitsData.query.results.atbat;
+
+ $.each( hits, function( index, item ) { addHitToMap( item ); } );
+ $('#hitsLoading').text( "" );
+ $('#ballsInPlay').text( "Balls in play" );
+ $( 'p#legend' ).show();
+
+ mapstraction.addSmallControls();
+
+ var myDataSource = new YAHOO.util.LocalDataSource( hits );
+ var myDataTable = new YAHOO.widget.ScrollingDataTable( "hitsTable",myColumnDefs,myDataSource,myConfigs );
+
+ myDataTable.subscribe( "rowMouseoverEvent", myDataTable.onEventHighlightRow );
+ myDataTable.subscribe("rowMouseoutEvent", myDataTable.onEventUnhighlightRow);
+ myDataTable.subscribe( "rowClickEvent",
+ function( oArgs ) {
+ myDataTable.onEventSelectRow( oArgs.event );
+ var selID = myDataTable.getSelectedRows()[0].substring( 7, 9999 );
+ hitMarkers[ parseInt( selID ) ].openBubble();
+ } );
+
+ }
+ );
+
+ }
+
+ function addHitToMap( hit ) {
+ var hitLocation_feet = { x : ( parseFloat( hit.hit_x ) - parseFloat( stadium.gameday.year2009.home_plate.x ) ) * parseFloat( stadium.gameday.year2009.pixels_per_foot ),
+ y : ( -parseFloat( hit.hit_y ) + parseFloat( stadium.gameday.year2009.home_plate.y ) ) * parseFloat( stadium.gameday.year2009.pixels_per_foot ) };
+
+ var hitLocation_feet_rotated = rotatePoint( hitLocation_feet.x, hitLocation_feet.y, parseFloat( stadium.geo.orientation.degrees ) );
+
+
+ var hitLocation_latLong = new LatLonPoint( parseFloat( stadium.geo.home_plate.latitude ) + feetToMeters( hitLocation_feet_rotated.y ) / latConv,
+ parseFloat( stadium.geo.home_plate.longitude ) + feetToMeters( hitLocation_feet_rotated.x ) / lngConv );
+
+ hit.latitude = hitLocation_latLong.lat;
+ hit.longitude = hitLocation_latLong.lng;
+
+ var hitMarker = new Marker( hitLocation_latLong );
+
+ var size = ( hit.event=="Home Run" || hit.event=="Grounded Into DP" ) ? 15 : 6;
+ var icon = hit.hit_type=="O" ? "pinkDot.png" : "blueDot.png";
+
+ hitMarker.setIcon( icon, [ size, size ] );
+ hitMarker.setShadowIcon( "blank.png", [ 10, 10 ] );
+ hitMarker.setLabel( hit.event );
+ hitMarker.setInfoBubble( hit.des );
+
+ mapstraction.addMarker( hitMarker );
+
+ hitMarkers.push( hitMarker );
+
+ }
+
+ function placeBases() {
+ var homePlateMarker = new Marker( new LatLonPoint( parseFloat( stadium.geo.home_plate.latitude ), parseFloat( stadium.geo.home_plate.longitude ) ) );
+ homePlateMarker.setIcon( "base.png", [ 7, 7 ] );
+ homePlateMarker.setShadowIcon( "blank.png", [ 10, 10 ] );
+
+ mapstraction.addMarker( homePlateMarker );
+
+ var bases_meters_rotated = new Array();
+
+
+ // second base
+ var secondBase_meters = { x : 0, y : feetToMeters( 127.28125 ) };
+
+ bases_meters_rotated.push( rotatePoint( secondBase_meters.x, secondBase_meters.y, parseFloat( stadium.geo.orientation.degrees ) ) );
+
+ // first & third base
+ var firstBase_meters = { x : 0, y : 27.4 };
+
+ bases_meters_rotated.push( rotatePoint( firstBase_meters.x, firstBase_meters.y, -45 + parseFloat( stadium.geo.orientation.degrees ) ) );
+ bases_meters_rotated.push( rotatePoint( firstBase_meters.x, firstBase_meters.y, 45 + parseFloat( stadium.geo.orientation.degrees ) ) );
+
+
+ for ( var i = 0; i < bases_meters_rotated.length; i++ ) {
+
+ var base = bases_meters_rotated[ i ];
+
+ var baseLocation = new LatLonPoint( parseFloat( stadium.geo.home_plate.latitude ) + base.y / latConv,
+ parseFloat( stadium.geo.home_plate.longitude ) + base.x / lngConv );
+
+ var marker = new Marker( baseLocation );
+ marker.setIcon( "base.png", [ 7, 7 ] );
+ marker.setShadowIcon( "blank.png", [ 10, 10 ] );
+
+ mapstraction.addMarker( marker );
+ }
+ }
+
+ function rotatePoint( x, y, rotation_degrees )
+ {
+ var rotation_radians = rotation_degrees / 180 * Math.PI;
+ return { x : x * Math.cos( rotation_radians ) - y * Math.sin( rotation_radians ),
+ y : x * Math.sin( rotation_radians ) + y * Math.cos( rotation_radians ) };
+ }
+
+ function feetToMeters( feet ) { return feet / 3.2808399; }
+
+ </script>
+
+ </body>
+</html>
Oops, something went wrong.

0 comments on commit aee868b

Please sign in to comment.