// solver.com javascript master control
// version 0.6 by Chris of Frontline Systems

// ---------------------------------------------------------
// solverJS 
// a short system to set a cookie when a person visits solver.com.
// it's run if the person doesn't have that particular cookie.
// includes Burak Gursoy's HTTP.Cookies-1.11

function startupSolverJS() {
	startupVisitorCookie() ;
}

function startupVisitorCookie() {
	if ( document.referrer ) { // get HTTP referer
		var dr;
		dr = document.referrer ;
		if(dr.indexOf('solver.com') == -1) { 
			// referral is not from solver.com
			checkVisitorCookie();
		}
	}
}

function timeSieve() {
	var startTime = new Date().getTime();
	var stest = doSieve(16384) ;
//	alert("primes below 256:" + stest );
	var endTime = new Date().getTime();
	var timeElapsed = endTime - startTime ;
	return timeElapsed ;
}

function fillFields() {
	var cookie    = new HTTP.Cookies;
	var fv = cookie.read('firstvisit'); 
	var firstvisitdate = new Date( fv * 1);
	
	var fvd = firstvisitdate.getDate(); // Day of the month (1-31)
    var fvm = firstvisitdate.getMonth() + 1; // Number of month (0-11) + 1
    var fvy = firstvisitdate.getFullYear(); // The four digit year (1970-9999)
	var firstvisitdate = fvm + "/" + fvd + "/" + fvy ;

	document.getElementById('solverid').value = cookie.read('uid'); 
	document.getElementById('firstvisit').value = firstvisitdate ;
	document.getElementById('referrer').value = cookie.read('referer'); 		
	document.getElementById('firstpage').value = cookie.read('landing'); 
}

function timestampCookie() {
	var now = new Date().getTime();
	var cookie    = new HTTP.Cookies;
	cookie.write( 'firstvisit', now, '+3y' );
}

function refstampCookie() {
	var dr = document.referrer ;
	var cookie    = new HTTP.Cookies;
	cookie.write( 'referer', dr, '+3y' );
}

function landingstampCookie() {
	var lr =  location.href ;
	var cookie    = new HTTP.Cookies;
	cookie.write( 'landing', lr, '+3y' );
}

function uidstampCookie() {
	var utime = new Date().getTime();
	var sieveMillis = timeSieve();
	var ustring = utime + "0000" + sieveMillis;
	var unum = ustring ;
	var cookie    = new HTTP.Cookies;
	cookie.write( 'uid', unum, '+3y' );
}

function setupVisitorCookie() {	
	refstampCookie();
	uidstampCookie();
	landingstampCookie();
	timestampCookie();
}

function updateVisitorCookie() {		
// let the original cookie date be the timestamp.
}

function clearVisitorCookie() {
	var cookie    = new HTTP.Cookies;
	cookie.remove( 'firstvisit' );
	cookie.remove( 'uid' );
	cookie.remove( 'referer' );
	cookie.remove( 'landing' );
	alert ("visitor cookies cleared." );
}

function checkVisitorCookie() {
	var cookie    = new HTTP.Cookies;
	var uid = cookie.read('referer'); 
	if (uid) {
		updateVisitorCookie() ;
	} else {
		setupVisitorCookie();
	}
}

function reportOnCookie() {
	var cookie    = new HTTP.Cookies;
	var uid = cookie.read('uid'); 
	var firstvisit = cookie.read('firstvisit'); 
	var firstvisitdate = new Date( firstvisit * 1000);
	var referer = cookie.read('referer'); 
//	alert ("First visit: " + firstvisitdate );
}



// ---------------------------------------------------------
// ---------------------------------------------------------
// INCLUDEs

// ---------------------------------------------------------
// sfhover enables non-link hover events in IE6. 
// This is a component of the Suckerfish-style CSS menu system.
// 
sfHover = function() {
	var sfEls = document.getElementById("nav").getElementsByTagName("LI");
	for (var i=0; i<sfEls.length; i++) {
		sfEls[i].onmouseover=function() {
			this.className+=" sfhover";
		}
		sfEls[i].onmouseout=function() {
			this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
		}
	}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
// end sfhover definition
// ---------------------------------------------------------


// ---------------------------------------------------------
// Javascript runtime include code
// 		from http://www.phpied.com/javascript-include/
//
function include_dom(script_filename) {
    var html_doc = document.getElementsByTagName('head').item(0);
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', script_filename);
    html_doc.appendChild(js);
    return false;
}

// Javascript <-> PHP RPC code
// 		from http://www.phpied.com/javascript-include/
//
function include_rpc(script_filename) {
    script_filename += '?' + Math.random(0, 1000) + '=' + Math.random(0, 1000);
    var html_doc = document.getElementsByTagName('head').item(0);
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', script_filename);
    html_doc.appendChild(js);
    return false;
}
// ---------------------------------------------------------


// ---------------------------------------------------------
//	HTTP.Cookies by Burak Gursoy <burak[at]cpan[dot]org>
/*
AUTHOR: Burak Gursoy, <burak@cpan.org>
COPYRIGHT: Copyright 2005-2007 Burak ursoy. All rights reserved.
LICENSE: This library is free software; you can redistribute it 
and/or modify it under the terms of the "Artistic License": 
http://dev.perl.org/licenses/artistic.html.
*/

if (!HTTP) var HTTP = {};

HTTP.Cookies = function () {
   this._reset();
}

// expire time calculation
HTTP.Cookies.Date = function () {
   this._init();
}

HTTP.Cookies.VERSION     = '1.11';
HTTP.Cookies.ERRORLEVEL  = 1;
HTTP.Cookies.Date.FORMAT = {
   's' :  1,
   'm' : 60,
   'h' : 60 * 60,
   'd' : 60 * 60 * 24,
   'M' : 60 * 60 * 24 * 30,
   'y' : 60 * 60 * 24 * 365
};

HTTP.Cookies.prototype._reset = function () {
   this['JAR']     = ''; // data cache
   this['CHANGED'] =  0; // cookies altered?
}

// Get the value of the named cookie. Usage: password = cookie.read('password');
HTTP.Cookies.prototype.read = function (name) {
	if(!name) return this._fatal('read', 'Cookie name is missing');
   if(this.CHANGED) this._reset();
   // first populate the internal cache, then return the named cookie
   var value = '';
   this._parse();
   for ( var cookie in this.JAR ) {
      if ( cookie == name ) {
         value = this.JAR[cookie];
         break;
      }
	}
   return value ? value : '';
}

// Create a new cookie or overwrite existing.
// Usage: cookie.write('password', 'secret', '1m');
HTTP.Cookies.prototype.write = function (name, value, expires, path, domain, secure) {
	if(!name) return this._fatal('write', 'Cookie name is missing');
	if(typeof value == 'undefined') value = ''; // workaround
   if (!expires) expires = '';
   if (expires == '_epoch') {
      expires = new Date(0);
   }
   else if (expires != -1) {
      var cdate = new HTTP.Cookies.Date;
      var Now   = new Date;
      Now.setTime(Now.getTime() + cdate.parse(expires));
      expires = Now.toGMTString();
   }
   var extra = '';
   if(expires) extra += '; expires=' + expires;
   if(path   ) extra += '; path='    + path;
   if(domain ) extra += '; domain='  + domain;
   if(secure ) extra += '; secure='  + secure;
   // name can be non-alphanumeric
   var new_cookie  = escape(name) + '=' + escape(value) + extra;
   document.cookie = new_cookie;
   this.CHANGED    = 1; // reset the object in the next call to read()
}

// Delete the named cookie. Usage: cookie.remove('password');
HTTP.Cookies.prototype.remove = function (name, path, domain, secure) {
	if(!name) return this._fatal('remove', 'Cookie name is missing');
   this.write(name, '', '_epoch', path, domain, secure);
}

// cookie.obliterate()
HTTP.Cookies.prototype.obliterate = function () {
   var names = this.names();
   for ( var i = 0; i < names.length; i++ ) {
		if ( !names[i] ) continue;
      this.remove( names[i] );
	}
}

// var cnames = cookie.names()
HTTP.Cookies.prototype.names = function () {
   this._parse();
   var names = [];
   for ( var cookie in this.JAR ) {
		if ( !cookie ) continue;
      names.push(cookie);
	}
	return names;
}

HTTP.Cookies.prototype._parse = function () {
   if(this.JAR) return;
	this.JAR  = {};
   var NAME  = 0; // field id
   var VALUE = 1; // field id
   var array = document.cookie.split(';');
   for ( var element = 0; element < array.length; element++ ) {
      var pair = array[element].split('=');
      pair[NAME] = pair[NAME].replace(/^\s+/, '');
      pair[NAME] = pair[NAME].replace(/\s+$/, '');
      // populate
      this.JAR[ unescape(pair[NAME]) ] = unescape( pair[VALUE] );
   }
}

HTTP.Cookies.prototype._fatal = function (caller, error) {
   var title = 'HTTP.Cookies fatal error';
   switch(HTTP.Cookies.ERRORLEVEL) {
      case 1:
         alert( title + "\n\n"  + caller + ': ' + error );
         break;
      default:
         break;
   }
}

HTTP.Cookies.Date.prototype._fatal = function (caller, error) {
   var title = "HTTP.Cookies.Date fatal error";
   switch(HTTP.Cookies.ERRORLEVEL) {
      case 1:
         alert( title + "\n\n"  + caller + ': ' + error );
         break;
      default:
         break;
   }
}

// HTTP.Cookies.Date Section begins here

HTTP.Cookies.Date.prototype._init = function () {
   this.FORMAT = HTTP.Cookies.Date.FORMAT;
}

HTTP.Cookies.Date.prototype.parse = function (x) {
   if(!x || x == 'now') return 0;
   var NUMBER = 1;
   var LETTER = 2;
   var date = x.match(/^(.+?)(\w)$/i);

   if ( !date ) {
		return this._fatal(
			       'parse',
			       'expires parameter (' + x + ') is not valid'
			    );
	}

   var is_num = this.is_num(  date[NUMBER] );
   var of     = this.is_date( date[NUMBER], date[LETTER] );
   return (is_num && of) ? of : 0;
}

HTTP.Cookies.Date.prototype.is_date = function (num, x) {
   if (!x || x.length != 1) return 0;
   var ar = [];
   return (ar = x.match(/^(s|m|h|d|w|M|y)$/) ) ? num * 1000 * this.FORMAT[ ar[0] ] : 0;
}

HTTP.Cookies.Date.prototype.is_num = function (x) {
   if (x.length == 0) return;
   var ok = 1;
   for (var i = 0; i < x.length; i++) {
      if ( "0123456789.-+".indexOf( x.charAt(i) ) == -1 ) {
         ok--;
         break;
      }
   }
   return ok;
}

//	End HTTP Cookies 1.11   
// ---------------------------------------------------------


// ---------------------------------------------------------
//	Sieve of Eratosthenes from http://tide4javascript.com/?s=Sieve
	// The Sieve of Eratosthenes is a simple, ancient algorithm for
	// finding all prime numbers up to a specified integer, see Wikipedia
	// This implementation is not so simple, but fast

function doSieve(upperlimit) {
	// watch:i,n,sieve
	var MAXN= upperlimit; // maximum value of N
	var P1 = Math.ceil(MAXN/64);
	var P2 = Math.ceil(MAXN/2);
	var P3 = Math.ceil(Math.ceil(Math.sqrt(MAXN))/2);
	var sieve=new Array();
	
	function get(b){
	  return ((sieve[b>>5]>>(b&31))&1);
	}
	
	function make(){
		 var i, j, k;
		 for (k = 1; k <= P3; k++){
			 if (get(k)==0) {
				for(j=2*k+1,i=2*k*(k+1);i<P2;i+=j) {
				  sieve[i>>5]|=1<<(i&31);
				}
			 }
		 }
	}
	   
	function isprime(p) {
		return p==2 || (p>2 && (p&1)==1 && (get((p-1)>>1)==0));
	}
	
	var i, n;
	make();
	for (n = 0, i = 0; i < MAXN; i++){
		if (isprime(i)) n++;
	}
//	alert('The number of primes below '+MAXN + ' is ' + n)
	return n;
}
//	end Sieve
// ---------------------------------------------------------

// -----------------------------------
// startup

startupSolverJS();


