Source for "ESPN4Factors"

By Cherokee
Has no other scripts.


// ESPN 4 factors boxscore
// version 0.3 
// 2007-10-31
//
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script that adds team 4-factors stats
// to ESPN NBA boxscores
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "ESPN4Factors", and click Uninstall.
//
//
// ==UserScript==
// @name          ESPN4Factors
// @description   Adds team 4-factors stats to ESPN NBA boxscores
// @include       http://*.espn.go.com/nba/boxscore?gameId=*
// ==/UserScript==

/* BEGIN LICENSE BLOCK
Copyright (C) 2007 cherokee_acb

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You can download a copy of the GNU General Public License at
http://diveintomark.org/projects/greasemonkey/COPYING
or get a free printed copy by writing to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
END LICENSE BLOCK */

	doc = window.document;

    var live = 0;

    // Read team names
  	var teamCells = doc.evaluate("//td[@class='team']", doc.body, null,  
                                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	var awayTeam = teamCells.snapshotItem(1).firstChild.textContent;
	var homeTeam = teamCells.snapshotItem(2).firstChild.textContent;
	
	// Get team stats
  	var colheads = doc.evaluate("//td[@colspan='2']", doc.body, null,  
                                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
                                    
    // First, the away team
	var fgcA = colheads.snapshotItem(0).nextSibling;
	if (fgcA.textContent.match(/FGM/)) {
		fgcA = colheads.snapshotItem(1).nextSibling;
        live = 1;
	}
	var fgmA = parseInt(fgcA.textContent.substring(0, fgcA.textContent.indexOf("-")));
	var fgaA = parseInt(fgcA.textContent.substring(fgcA.textContent.indexOf("-")+1));

	var p3cA = fgcA.nextSibling;
	var p3mA = parseInt(p3cA.textContent.substring(0, p3cA.textContent.indexOf("-")));
	var p3aA = parseInt(p3cA.textContent.substring(p3cA.textContent.indexOf("-")+1));

	var ftcA = p3cA.nextSibling;
	var ftmA = parseInt(ftcA.textContent.substring(0, ftcA.textContent.indexOf("-")));
	var ftaA = parseInt(ftcA.textContent.substring(ftcA.textContent.indexOf("-")+1));

	var orcA = ftcA.nextSibling;
	var drcA = orcA.nextSibling;
	var orA = parseInt(orcA.textContent);
	var drA = parseInt(drcA.textContent);
    if (live) {
        drA = drA-orA;
    }

    // Now the home team
	var fgcH = colheads.snapshotItem(2).nextSibling;
	if (live) {
		fgcH = colheads.snapshotItem(4).nextSibling;
	}
	var fgmH = parseInt(fgcH.textContent.substring(0, fgcH.textContent.indexOf("-")));
	var fgaH = parseInt(fgcH.textContent.substring(fgcH.textContent.indexOf("-")+1));

	var p3cH = fgcH.nextSibling;
	var p3mH = parseInt(p3cH.textContent.substring(0, p3cH.textContent.indexOf("-")));
	var p3aH = parseInt(p3cH.textContent.substring(p3cH.textContent.indexOf("-")+1));

	var ftcH = p3cH.nextSibling;
	var ftmH = parseInt(ftcH.textContent.substring(0, ftcH.textContent.indexOf("-")));
	var ftaH = parseInt(ftcH.textContent.substring(ftcH.textContent.indexOf("-")+1));

	var orcH = ftcH.nextSibling;
	var drcH = orcH.nextSibling;
	var orH = parseInt(orcH.textContent);
	var drH = parseInt(drcH.textContent);
    if (live) {
        drH = drH-orH;
    }

    // We use total team turnovers, instead of the sum of player turnovers in the boxscore
  	var toCells = doc.evaluate("//td[@colspan='9']", doc.body, null,  
                                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    if (live) {
        toCells = doc.evaluate("//td[@colspan='8']", doc.body, null,  
                                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    }
	var toA = parseInt(toCells.snapshotItem(0).textContent.substr(19,2));
	var toH = parseInt(toCells.snapshotItem(1).textContent.substr(19,2));

	// Get minutes played
	var clock = doc.evaluate("//div[@class='game-status']", doc.body, null,  
                        XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
	var min = 48;
    if (clock.textContent.match(/Final/)) {
    	if (clock.textContent.match(/OT/)) {
    		if (clock.textContent.charAt(10) == 'O' ) {
    			min = 53;
    		}
    		else {
    			min = 48 + 5*clock.textContent.charAt(10);
    		}
    	}
    }
    else if (clock.textContent.match(/Halftime/)) {
        min = 24;
    }
    else {
        delimIndex = clock.textContent.indexOf(":");
        min = 11-parseInt(clock.textContent.substr(delimIndex-2, 2));
    	var secs = 60-parseInt(clock.textContent.substr(delimIndex+1, 2));
        var quarter = parseInt(clock.textContent.substr(delimIndex+5, 1));
        min += secs/60 + 12*(quarter-1);
    }

    // For possessions, we use the Hollinger formula with a 0.976 correction factor.
    //  Then we average both team estimates, and round to the nearest integer
	var possA = fgaA + 0.44*ftaA - orA + toA;
	var possH = fgaH + 0.44*ftaH - orH + toH;
	var poss = 0.976*(possH + possA)/2;
	poss = poss.toFixed(0);
	var pace = 48*poss/min;

    // Now, we compute efficiency and the four factors
	var effA = 100*(2*fgmA + p3mA + ftmA)/poss;
	var efgA = 100*(fgmA + 0.5*p3mA)/fgaA;
	var ftrA = 100*ftmA/fgaA;
	var orpA = 100*orA/(orA+drH);
	var torA = 100*toA/poss;

	var effH = 100*(2*fgmH + p3mH + ftmH)/poss;
	var efgH = 100*(fgmH + 0.5*p3mH)/fgaH;
	var ftrH = 100*ftmH/fgaH;
	var orpH = 100*orH/(orH+drA);
	var torH = 100*toH/poss;

    // Finally, we create the table, rows and cells where data will be displayed.
    // Format is the same as in the per-quarter score table
	var tdAux;	
	var bold;
	var cellWidth = '50px';

	var factors = doc.createElement("table");
	// factors.setAttribute('align','center');

	var header = doc.createElement("tr");
	header.setAttribute('align', 'center');
	tdAux = doc.createElement("td");
	header.appendChild(tdAux);
	tdAux = doc.createElement("td");
    under = doc.createElement("u");
    if (min == 48) {
        under.textContent = "Pace";
        tdAux.setAttribute('width',cellWidth );
    }
    else {
        under.textContent = "Pace (Poss)";
        tdAux.setAttribute('width',2*cellWidth );
    }
    tdAux.appendChild(under);
	header.appendChild(tdAux);
	tdAux = doc.createElement("td");
    under = doc.createElement("u");
    under.textContent = "Eff";
    tdAux.appendChild(under);
	tdAux.setAttribute('width',cellWidth );
	header.appendChild(tdAux);
	tdAux = doc.createElement("td");
    under = doc.createElement("u");
    under.textContent = "eFG";
    tdAux.appendChild(under);
	tdAux.setAttribute('width',cellWidth );
	header.appendChild(tdAux);
	tdAux = doc.createElement("td");
    under = doc.createElement("u");
    under.textContent = "FT/FG";
    tdAux.appendChild(under);
	tdAux.setAttribute('width',cellWidth );
	header.appendChild(tdAux);
	tdAux = doc.createElement("td");
    under = doc.createElement("u");
    under.textContent = "OREB%";
    tdAux.appendChild(under);
	tdAux.setAttribute('width',cellWidth );
	header.appendChild(tdAux);
	tdAux = doc.createElement("td");
    under = doc.createElement("u");
    under.textContent = "TOr";
    tdAux.appendChild(under);
	tdAux.setAttribute('width',cellWidth );
	header.appendChild(tdAux);


	var aRow = doc.createElement("tr");
	aRow.setAttribute('align', 'center');
	tdAux = doc.createElement("td");
	tdAux.setAttribute('align', 'left');
	tdAux.setAttribute('class','team');
	bold = doc.createElement("b");
	bold.textContent = awayTeam;
	tdAux.appendChild(bold);
	aRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
    if (min == 48) {
        tdAux.textContent = pace.toFixed(1);
    }
    else {
        tdAux.textContent = pace.toFixed(1) + " (" + poss + ")";
    }
	aRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = effA.toFixed(1);
	aRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = efgA.toFixed(1) + "%";
	aRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = ftrA.toFixed(1);
	aRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = orpA.toFixed(1);
	aRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = torA.toFixed(1);
	aRow.appendChild(tdAux);

	var hRow = doc.createElement("tr");
	hRow.setAttribute('align', 'center');
	tdAux = doc.createElement("td");
	tdAux.setAttribute('align', 'left');
	bold = doc.createElement("b");
	bold.textContent = homeTeam;
	tdAux.appendChild(bold);
	hRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	// tdAux.textContent = pace.toFixed(1);
	hRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = effH.toFixed(1);
	hRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = efgH.toFixed(1) + "%";
	hRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = ftrH.toFixed(1);
	hRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = orpH.toFixed(1);
	hRow.appendChild(tdAux);
	tdAux = doc.createElement("td");
	tdAux.textContent = torH.toFixed(1);
	hRow.appendChild(tdAux);

	factors.appendChild(header);
	factors.appendChild(aRow);
	factors.appendChild(hRow);

    // We insert the 4 factors table into a <div> element, and this div just before the boxscore table
	var factorsDiv = doc.createElement("div");
    factorsDiv.setAttribute('align','center');
	factorsDiv.appendChild(factors);

  	var tabberNodes = doc.evaluate("//div[@class='gp-body']", doc.body, null,  
                                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    var tabber = tabberNodes.snapshotItem(0);
    tabber.insertBefore(factorsDiv, tabber.firstChild);

//
// ChangeLog
// 2007-03-07 - 0.1 - First draft
// 2007-03-10 - 0.2 - Added support of live boxscores
// 2007-10-31 - 0.3 - Updated to 2007-08 format