ii-daily-status

ii-daily-status.user.js
// ==UserScript==
// @name           ii-daily-status
// @namespace      http://users.pepperfish.net/vivek/
// @description    Tracks data from the newday menu, for later use.
// @include        http://improbableisland.com/*
// @include        http://www.improbableisland.com/*
// @version        2
// ==/UserScript==
 
var content  = null;
var text     = null;
var xpaths   = [ "//td[@class='content']"     , 
                 "//div[@class='maincolumn']" ,
                 "//body"                     ];
var examples = ( "//table"                     +
                 "/tbody/tr"                   + 
                 "/td[@class='charhead']"      );
var charinfo = examples + "/parent::*/parent::*/parent::*/parent::*[1]";
var example  = {};
 
function find_sample_cells ()
{
    var found = document.evaluate( examples, document, null,
                                   XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                   null );
    var limit = found.snapshotLength - 1;
 
    for( var i = 0; i <= limit; i++ )
    {
        var th = found.snapshotItem( i );
 
        // GM_log( 'checking ' + th.textContent );
 
        if( !th.textContent.match( /Personal/ ) && (i < limit) )
            continue;
 
        var tr   = th.parentNode.parentNode.parentNode;
        var type = tr.nodeType;
        var next;
 
        example[ 'section' ] = th;
        example[ 'item'    ] = [];
 
        for( next = tr.nextSibling; next; next = next.nextSibling )
            if( next.nodeType == type )
                break;
 
        // GM_log( 'sibling target is ' + next.textContent );
 
        var items = document.evaluate( 'tbody/tr', next, null, 
                                       XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                       null );
 
        var data = items.snapshotItem(0);
 
        for( var cell = data.firstChild; cell; cell = cell.nextSibling )
        {
            if( cell.nodeName != 'TD' )
                continue;
 
            // GM_log('added item ' + cell.textContent );
            example[ 'item' ].push( cell );
        }
 
        break;
    }
}
 
function set_cell_text( td, text )
{
    var done = false;
    var kids = document.evaluate( 'descendant::*', td, null,
                                  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                  null );
 
    if( kids.snapshotLength > 0 )
    {
        var node = kids.snapshotItem( kids.snapshotLength - 1 );
 
        if( node.textContent.match( /\S/ ) )
        {
            node.textContent = text;
            done = true;
        }
    }
 
    if( !done )
        td.textContent = text;
}
 
function append_info (tbody, label, heading, value)
{
    var tr = document.createElement( 'tr' );
 
    if( heading )
    {
        var th = example.section.cloneNode( true );
        th.textContent = label;
        tr.appendChild( th );
    }
    else
    {
        var lcell = example.item[0].cloneNode( true );
        var rcell = example.item[1].cloneNode( true );
 
        set_cell_text( lcell, label );
        set_cell_text( rcell, value ? value : '-' );
 
        tr.appendChild( lcell );
        tr.appendChild( rcell );
    }
 
    tbody.appendChild( tr );
}
 
function get_content ()
{
    //GM_log( 'get_content:0' );
 
    if( content )
        return content;
 
    //GM_log( 'get_content:1' );
 
    for( var i = 0; i < xpaths.length; i++ )
    {
        var found = document.evaluate( xpaths[i], document, null,
                                       XPathResult.ANY_UNORDERED_NODE_TYPE,
                                       null );
 
        //GM_log( 'get_content:1:' + i + ' : ' +
        //        (found ? found.singleNodeValue : 'null') );
 
        if( found && found.singleNodeValue ) 
        {
            content = found.singleNodeValue;
            text    = content ? content.textContent : null;
            break;
        }
    }
 
    return content;
}
 
var uri = document.documentURI;
 
if( (uri.match( /module=staminafood/ ) && uri.match( /op=buy/             )) ||
    (uri.match( /module=meatsystem/  ) && uri.match( /op=(?:cook|devour)/ )) ||
    (uri.match( /\/inventory\.php/   ) && uri.match( /items_useitem=/     )) )
{
    //GM_log( 'food' );
    if( get_content() )
    {
        //GM_log( 'checking food' );
        var appetite =
            [ [ /You still .*?haven\'t eaten in days/i, 'very hungry' ] ,
              [ /You feel a little less hungry/i      , 'hungry'      ] ,
              [ /You .*room for more/i                , 'peckish'     ] ,
              [ /You\'re stuffed!/i                   , 'stuffed'     ] ,
              [ /You\'re far too full/i               , 'stuffed'     ] ,
              [ /You.*?feel (.*)$/i                   , null          ] ];
 
        for( var i = 0; i < appetite.length; i++ )
        {
            var matched;
 
            if( matched = text.match( appetite[i][0] ) )
            {
                var hunger = appetite[i][1] ? appetite[i][1] : matched[1];
                localStorage.setItem('ii/hunger', hunger );
                break;
            }
        }
    }
}
else if( uri.match( /\/newday\.php/ ) )
{
    if( get_content() )
    {
	    if( text.match( /It is a new day!/i ) )
        {
		    var matched;
 
            // health
		    if( matched = text.match( /You are feeling .*?(energetic|well-nourished|healthy|(?:very |kinda |a little )?weak).*?[.!]/i ) )
                localStorage.setItem( 'ii/strength', matched[1] );
	  	    else if ( matched = text.match( /You are.*?dying/i ) )
			    localStorage.setItem( 'ii/strength', 'dying' );
            else
                localStorage.removeItem( 'ii/strength' );
 
            // weight
		    if( matched = text.match( /You are looking .*?(trim|well-fed|round|chunky|fat)/i ) )
                localStorage.setItem( 'ii/weight', matched[1] )
            else if( matched = text.match(/orphans/i) )
                localStorage.setItem( 'ii/weight', 'obese' );
            else
                localStorage.removeItem( 'ii/weight' );
 
            // age
            if( matched = text.match( /day number (.*?)\./ ) )
		        localStorage.setItem( "ii/days" , matched[1] );
            else
                localStorage.removeItem( 'ii/days' );
 
            // WCG
		    if( matched = text.match( /You have ([0-9]) days of enhanced/ ) )
                localStorage.setItem( "ii/wcg", matched[1] );
            else
                localStorage.removeItem( 'ii/wcg' );
        }
    }
}
else if( ( uri.match( /\/forest\.php/ ) &&
           uri.match( /op=(?:search|talk|quester|fight)/ ) ) ||
         uri.match( /module=quester/ ) )
{
    //GM_log( 'checking quest' );
 
    if( get_content() )
    {
        var quest = null;
 
        //GM_log( 'checking quest content' );
 
        if( quest = 
            ( text.match(/You have defeated the (.*?)!!!\./) ||
              text.match(/After a bit of digging, you find the (.*?)! It did take a little longer than you thought, however\./)          ||
              text.match(/He's giving you the (.*?) you needed for Dan! How lucky you are!/)                                             ||
              text.match(/It's the (.*?)! You think how incredibly lucky you are as you pick it up and make your way back to the path\./) ) )
        {
            // GM_log( 'quest FOUND' );
            localStorage.setItem( 'ii/quest/target', quest[1] );
            localStorage.setItem( 'ii/quest/done'  , '1'      );
        }
        else if( quest = 
                 ( text.match(/(?:You need to seek out and kill the |So first, you'll need to go and kill the )(.*?), (?:which you'll find in the jungle immediately around|which, from what we can gather, is hanging out in the jungles around|down in the jungles of) (.*?)\./) ||
                   text.match(/You need to go and find the (.*?), (?:in the jungle around|down in the jungles of) (.*?)\./) ) )
        {
            // GM_log( 'quest ASSIGNED' );
            var step = localStorage.getItem( 'ii/quest/step' ) || '0';
            localStorage.setItem( 'ii/quest/target'  , quest[1] );
            localStorage.setItem( 'ii/quest/location', quest[2] );
            localStorage.setItem( 'ii/quest/done'    , '0'      );
            localStorage.setItem( 'ii/quest/step'    , (step * 1) + 1 );
            localStorage.setItem( 'ii/quest/final'   , '0'      );
        }
        else if( quest = text.match( /It is known as the (.*?),(?:.|\n)*last one in the jungles around (.*?)\./ ) )
        {
            // GM_log( 'quest DENOUEMONT' );
            var step = localStorage.getItem( 'ii/quest/step' ) || '0';
            localStorage.setItem( 'ii/quest/target'  , quest[1] );
            localStorage.setItem( 'ii/quest/location', quest[2] );
            localStorage.setItem( 'ii/quest/done'    , '0'      );
            localStorage.setItem( 'ii/quest/step'    , (step * 1) + 1 );
            localStorage.setItem( 'ii/quest/final'   , '1'      );
        }
        else if( text.match( /You have completed this quest!/ ) ||
                 ( uri.match( /module=quester/ ) && 
                   uri.match( /op=abandon/     ) ) )
        {
            // GM_log( 'quest COMPLETE' );
            localStorage.removeItem( 'ii/quest/target'   );
            localStorage.removeItem( 'ii/quest/location' );
            localStorage.removeItem( 'ii/quest/done'     );
            localStorage.removeItem( 'ii/quest/step'     );
            localStorage.removeItem( 'ii/quest/final'    );
        }
    }
}
else
{
    var robot = false;
    var sieve = ( "//div[@class='navbox']/div[@class='navhead']"    + "|" + 
                  "//td[@class='navigation']/div[@class='navhead']" + "|" + 
                  "//td[@class='nav']/span[@class='navhead']"             );
    var where = document.evaluate( sieve, document, null,
                                   XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                   null );
 
    for( var i = 0; i < where.snapshotLength; i++ )
    {
        var text = where.snapshotItem( i ).textContent;
 
        if( text.match( /Robot Talents/ ) ) { robot = true; break; }
    }
 
    if( robot )
    {
        localStorage.removeItem( 'ii/strength' );
        localStorage.removeItem( 'ii/weight'   );
        localStorage.removeItem( 'ii/hunger'   );
    }
}
 
 
find_sample_cells();
 
var chartable = document.evaluate( charinfo, document, null,
                                   XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                   null );
 
if( chartable.snapshotLength > 0 )
{
    var target = null;
    var robot  = localStorage.getItem( 'ii/robot' ) ? true : false;
    var table  = chartable.snapshotItem( 0 );
    var items  = [ [ 'Health'  , 'ii/strength', false ] ,
                   [ 'Weight'  , 'ii/weight'  , false ] ,
                   [ 'Hunger'  , 'ii/hunger'  , false ] ,
                   [ 'Age'     , 'ii/days'    , true  ] ,
                   [ 'WCG Days', 'ii/wcg'     , true  ] ];
    var statt = document.createElement( 'table' );
    var statb = document.createElement( 'tbody' );
 
    statt.appendChild( statb );
    table.appendChild( statt );
    statt.setAttribute( 'class', 'charinfo' );
 
    append_info( statt, 'Status', true, null );
 
    for( var j = 0; j < items.length; j++ )
    {
        var value = localStorage.getItem( items[j][1] );
        if( items[j][2] || value )
            append_info( statt, items[j][0], false, value );
    }
 
    if( target = localStorage.getItem('ii/quest/target') )
    {
        var here = localStorage.getItem( 'ii/quest/location' ) || '???';
        var step = localStorage.getItem( 'ii/quest/step'     ) || '1'
        var last = ((localStorage.getItem( 'ii/quest/final' ) || '0') == 1);
        var done = ((localStorage.getItem( 'ii/quest/done'  ) || '0') == 1);
        var nofn = ' [' + (last ? (step + '/' + step) : (step + '/?')) + ']';
        var head = 'Quest ' + nofn;
 
        append_info( statt, head     , true , null   );
        append_info( statt, 'Seek:'  , false, target );
        append_info( statt, 'Here:'  , false, here   );
        append_info( statt, 'Status:', false, done ? 'FOUND' : 'searching');
    }
    else
    {
        append_info( statt, 'No Quest', true, null );
    }
}

Version 2.0