Source for "Time Remaining in DGS Games"


// Requires Greasemonkey 0.2.5 or later

// ==UserScript==
// @name        Time Remaining in DGS Games
// @namespace   http://www.stanford.edu/~wagnerd
// @description Adds a column to the list of games on the status page indicating time left in each game
// @include     *dragongoserver.net/status.php*
// ==/UserScript==

// First, prepare a header column
trs=document.getElementsByTagName( 'tr' );
for( i = 0; i < trs.length; i++ )
	if( trs[i].childNodes.length > 1 )
		if( trs[i].childNodes[1].textContent == 'ID' )
			break;
if( i == trs.length ) return;
td = document.createElement( 'th' );
td.innerHTML = '<a href="javascript:void(0)"><font color="black">Time Remaining</font></a>';
td.setAttribute( 'valign', 'bottom' );
td.noWrap = true;
trs[i].appendChild( td );
lastChild = trs[++i].childNodes.length;
firstTR = i;

// Allow the user to sort on time by clicking the Time Remaining header
td.getElementsByTagName( 'a' )[0].addEventListener( 'click', function( event )
	{
	for( j = firstTR + 1; trs[j].childNodes.length > 1; j++ )
		for( k = firstTR; k < j; k++ )
			if( +trs[j].childNodes[lastChild].getAttribute( 'hoursleft' ) < +trs[k].childNodes[lastChild].getAttribute( 'hoursleft' ) )
				{
				trs[j].parentNode.insertBefore( trs[j], trs[k] );
				break;
				}
	for( j = 0; trs[j + firstTR].childNodes.length > 1; j++ )
		trs[j + firstTR].bgColor = (j % 2)? '#e0e8ed' : '#ffffff';
	}, false );

// Load up the game pages to see how much time is left
for( ; trs[i].childNodes.length > 1; i++ )
	{
	td = document.createElement( 'td' );
	td.innerHTML = '<b>Loading...</b>';
	trs[i].appendChild( td );
	update = new Function( "event",
			"if( event.status == 200 )" +
			"	{" +
			"	hours = document.countHours( event.responseText, trs[" + i + "].innerHTML.indexOf( 'b.gif' ) > 0 );" +
			"	trs[" + i + "].childNodes[lastChild].setAttribute( 'hoursleft', hours );" +
			"	trs[" + i + "].childNodes[lastChild].innerHTML = document.toText( hours );" +
			"	}" +
			"else trs[" + i + "].childNodes[lastChild].innerHTML = '<font color=\"red\">Failed.</font>';" );
	GM_xmlhttpRequest( { method:'GET', url:trs[i].getElementsByTagName('a')[0].href, onload:update } );
	}

// Returns an integer number of hours from the given game page HTML; also, needs to know what color the player is
document.countHours = function( html, skipFirstOne )
{
main = document.getTD( html, 'Main time:', skipFirstOne );
total = document.getTD( html, 'Time limit:', false );
hours = document.parseTimeSentence( main );

// Great, we have the main time taken care of.  Now, let's deal with Fischer, Canadian, and Japanese...
if( total.indexOf( 'Canadian' ) > 0 )
	{
	if( hours == 0 )
		{
		byoyomi = document.getTD( html, 'Byoyomi:', skipFirstOne );
		hours += document.parseTimeSentence( byoyomi ) / byoyomi.substring( byoyomi.indexOf( '(' ) + 1, byoyomi.indexOf( ')' ) );
		}
	else
		{
		total = total.substring( total.indexOf( '+' ) + 2 );
		time = document.parseTimeSentence( total.substring( 0, total.indexOf( '/' ) ) );
		time /= ( document.parseTimeSentence( total.substring( total.indexOf( '/' ) + 1 ) ) / 24 );
		hours += time;
		}
	}
if( total.indexOf( 'Japanese' ) > 0 )
	{
	if( hours == 0 )
		{
		byoyomi = document.getTD( html, 'Byoyomi:', skipFirstOne );
		hours += document.parseTimeSentence( byoyomi );
		hours += document.parseTimeSentence( total.substring( 0, total.indexOf( '/' ) ) ) * ( byoyomi.substring( byoyomi.indexOf( '(' ) + 1, byoyomi.indexOf( ')' ) ) - 1 );
		}
	else
		{
		total = total.substring( total.indexOf( '+' ) + 2 );
		time = document.parseTimeSentence( total.substring( 0, total.indexOf( '/' ) ) );
		time *= ( document.parseTimeSentence( total.substring( total.indexOf( '/' ) + 1 ) ) / 24 );
		hours += time;
		}
	}
return hours;
}

document.parseTimeSentence = function( text )
{
var i, hours = 0;
for( i = 0; i < text.length && text.charAt(i) <= '9' && text.charAt(i) >= '0' ; i++ ) {}
if( i < text.length )
	hours = 24 * text.substring( 0, i );
if( text.indexOf( 'and' ) > 0 )
	{
	text = text.substring( text.indexOf( 'and' ) );
	for( i = 0; text.charAt( i ) < '0' || text.charAt( i ) > '9'; i++ ) {}
	text = text.substring( i );
	if( text.charAt( 1 ) <= '9' && text.charAt( 1 ) >= '0' )
		hours += +( text.substring( 0, 2 ) );
	else	hours += +( text.substring( 0, 1 ) );
	}
return hours;
}

document.getTD = function( text, title, skipFirstOne )
{
text = text.substring( text.indexOf( title ) );
text = text.substring( text.indexOf( '<td' ) );
text = text.substring( text.indexOf( '>' ) + 1 );
if( skipFirstOne ) text = text.substring( text.indexOf( '<td>' ) + 4 );
text = text.substring( 0, text.indexOf( '<' ) );
return text;
}

// Translate an integer into a string
document.toText = function( hours )
{
ho = hours % 24;
da = ( hours - ho ) / 24;
if( ho ) ho += ( ho > 1 )? ' hours' : ' hour';
else ho = '';
if( da ) da += ( da > 1 )? ' days' : ' day';
else da = '';
return da + ( ( da && ho )? ' and ' : '' ) + ho;
}