function getBrowserMetrics() {
	return ( 'res_' + window.screen.width + 'x' + window.screen.height +
		'.bpp_' + window.screen.colorDepth +
		'.java_' + navigator.javaEnabled() );
}

function isValidName(name) {
	var name_pattern = new RegExp("^\\w{3,26}$");
	return (name.search(name_pattern) > -1)
}

function toScoreHtml(score_nbr, replace_zero_char) {
	var score_nbr_style = '<span style="color:#336633;padding:0 2px">';
	if (score_nbr > 0) {
		if (score_nbr==999)
			score_nbr = 'F';
		else
			score_nbr = '+' + score_nbr;
		score_nbr_style = '<span style="color:#993333;padding:0 2px">';
	} else if (score_nbr == 0 && replace_zero_char != undefined) {
		score_nbr = replace_zero_char;
	}
	
	return score_nbr_style + score_nbr + '</span>';
}

function toAbsScoreByName(course_name, score_rtp) {
	var course_id = COURSE_NAME_ID[course_name];
	return toAbsScore(course_id, score_rtp);
}

function toAbsScore(course_id, score_rtp) {
	var par = COURSE_ID_PAR['course_id_' + course_id];
	return par + (score_rtp - 0);
}

function toLeaderScoreHtml(score_rtp, leader_score_rtp) {
	if (score_rtp == 999 || leader_score_rtp == 999)
		return toScoreHtml(999);
	
	return toScoreHtml( score_rtp - leader_score_rtp, '-');
}

/*************************************************************************************************
 *  GENERAL JAVASCRIPT FUNCTIONS                                                                 *
 *                                                                                               *
 *  The remaining functions could be usable in any JavaScript application.                       *
 *************************************************************************************************/

function isIE() {
	var is_ie = false;
	/*@cc_on
	  @if (@_jscript)
	    // IE
	    is_ie = true;
	  @else*/
	    // Firefox
	/*@end
	  @*/
	return is_ie;
}

function isFF() {
	return !isIE();
}

var is_ie_6 = false;
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { //test for MSIE x.x;
	var ieversion=new Number(RegExp.$1) // capture x.x portion and store as a number
	if (ieversion>=8)
		is_ie_6 = false;
	else if (ieversion>=7)
		is_ie_6 = false;
	else if (ieversion>=6)
		is_ie_6 = true;
	else if (ieversion>=5)
		is_ie_6 = false;
}

function isIE6() {
	return is_ie_6;
}

function isIE6under() {
	if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { //test for MSIE x.x;
		var ieversion=new Number(RegExp.$1) // capture x.x portion and store as a number
		if (ieversion<=6)
			return true;
	}
	return false;
}

var CLIMB_1_DIR = 1;
var CLIMB_2_DIR = 2;

function getHttpsBaseUrl(climb_dirs, returnHttpInstead) {

	if (!climb_dirs)
		climb_dirs = 0;

	var httpsLocation = location.toString();
	if (httpsLocation.indexOf('http://') == 0 && !returnHttpInstead)
		httpsLocation = 'https://' + httpsLocation.substring(7, httpsLocation.length);

	if (httpsLocation.indexOf('https://') == 0 && returnHttpInstead)
		httpsLocation = 'http://' + httpsLocation.substring(8, httpsLocation.length);	
	
	// Remove any filename, for example: index.html
	for (var i=0; i<climb_dirs+1; i++) {
		var lastIndexOf = httpsLocation.lastIndexOf("/");
		if (lastIndexOf != -1) {
			httpsLocation = httpsLocation.substring(0, lastIndexOf+1);
		}
	}

	return httpsLocation;
}

function getHttpBaseUrl(climb_dirs, returnHttpInstead) {
	return getHttpsBaseUrl(climb_dirs, true);
}

function loadExtJs(url) {
	var jselmt=document.createElement('script');
	jselmt.setAttribute('type','text/javascript');
	jselmt.setAttribute('src', url);
	document.getElementsByTagName('head')[0].appendChild(jselmt);
}

function isEmpty(str) {
	return (str == null || str == '');
}

function objIsEmpty(obj) {
	for (var mbr in obj)
		return false;
	return true;
}

function listMbrs(obj, delim) {
	var mbrs = '';
	
	for (mbr in obj)
		mbrs += mbr + (delim ? delim : '\n');
	
	return mbrs;
}

var nn6 = document.getElementById&&!document.all;
var isdrag = false;
var x;
var tx;
var x_chg;
var y;
var ty;
var y_chg;
var dobj;

function movemouse(e) {
	if (isdrag) {
		x_chg = nn6 ? tx + e.clientX - x : tx + event.clientX - x;
		y_chg = nn6 ? ty + e.clientY - y : ty + event.clientY - y;
		dobj.style.left = x_chg + "px";
		dobj.style.top = y_chg + "px";
		return false;
	}
}

function selectmouse(e) {
	var fobj = nn6 ? e.target : event.srcElement;
	var topelement = nn6 ? "HTML" : "BODY";

	while (fobj != undefined && fobj.tagName != topelement && fobj.className != "mover") {
		fobj = nn6 ? fobj.parentNode : fobj.parentElement;
	}

	if (fobj != undefined && fobj.className=="mover") {
		tx = parseInt(fobj.style.left+0);
		ty = parseInt(fobj.style.top+0);
		x = nn6 ? e.clientX : event.clientX;
		y = nn6 ? e.clientY : event.clientY;
		if ( (x-tx) < fobj.offsetWidth - 20 &&
				(y-ty) < fobj.offsetHeight - 378 ) {
			isdrag = true;
			dobj = fobj;
			document.onmousemove=movemouse;
		}
		return false;
	}
}

function releasemouse(e) {
	if (isdrag)
		isdrag = false;
}

document.onmousedown=selectmouse;
document.onmouseup=releasemouse;

function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}
	return [curleft,curtop];
}

var days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
var months = ['Jan','Fed','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var INCLUDE_AT_WORD = 1;
function secsToFullTime(secs, inc_at) {
	var inc_at = (inc_at==INCLUDE_AT_WORD);
	var start_time = new Date();
	start_time.setTime(secs * 1000);
	var started = '-';
	if (start_time.getTime() > 0) {
		var hours = start_time.getHours();
		var ampm = 'a';
		if (hours >= 12) {hours -= 12; ampm='p'}
		if (hours == 0) {hours = 12}
		var daymonth = days[start_time.getDay()] + "&nbsp;" +
			(start_time.getMonth() + 1) + "/" +
			start_time.getDate() + "/" +
			(start_time.getFullYear() + "").substring(2,4) + "&nbsp;";
		started = daymonth + (inc_at ? 'at&nbsp;' : '') + hours + ":" + 
			(start_time.getMinutes()).toString().replace(/^(\d)$/,"0$1") + ampm;
	}
	return started;
}

function msToDayDate(ms) {
	var date = new Date();
	date.setTime(ms);
	
	return ( days[date.getUTCDay()] + '&nbsp;' +
			(date.getUTCMonth() + 1) + '/' +
			date.getUTCDate() + '/' +
			(date.getUTCFullYear() + '').substring(2,4) );
}

function secsToHourMin(secs) {
	var start_time = new Date();
	start_time.setTime(secs * 1000);
	var hours = start_time.getHours();
	var ampm = 'a';
	if (hours > 12) {hours -= 12; ampm = 'p'}
	if (hours == 0) {hours = 12}
	return hours + ":" + (start_time.getMinutes()).toString().replace(/^(\d)$/,"0$1") + ampm;
}

function secsToDaysHoursFromNow(secs) {
	var ms1 = (new Date()).getTime();
	var d2 = new Date();
	d2.setTime(secs * 1000);
	var ms2 = d2.getTime();
	var sd = Math.ceil((ms2 - ms1) / 1000);
	return periodSecsToDaysHours(sd);
}

function periodSecsToDaysHours(secs) {
	var h = Math.ceil(secs / 60 / 60);
	var d = Math.floor(h / 24);
	var hr = h % 24;
	return (d ? d + ' days ' : '') + (hr ? hr + ' hours' : '');
}

function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
	document.cookie = name+"="+value+expires+"; path=/a";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}

function getThisWeekStart() {
	return getMonWeekStart(new Date());
}

function getMonWeekStart(date_obj) {
	date_obj.setMilliseconds(0);
	date_obj.setSeconds(0);
	date_obj.setMinutes(0);
	// adjust week for going Monday - Sunday instead of Sunday - Saturday
	var day_idx = date_obj.getDay() > 0 ? date_obj.getDay() - 1 : 6;
	date_obj.setHours(-(day_idx*24));
	return date_obj;
}

function toOrdinal(x) {
	var n = x % 100;
	var suff = ["th", "st", "nd", "rd", "th"]; // suff for suffix
	var ord= n<21?(n<4 ? suff[n]:suff[0]): (n%10>4 ? suff[0] : suff[n%10]);
	return x + ord;
}

var NO_ZERO_CENTS=1;
var USE_CENTS=1;
function toUsdString(x, zero_cents, use_cents) {
	x = x - 0;
	if ( x >= 1 || x <= -1 || !use_cents) {
		var str = '$' + x.toFixed(2);
		if (zero_cents == NO_ZERO_CENTS)
			str = str.replace('.00','');
		return str;
	} else {
		return ((x * 100) + '&cent;');
	}
}

function secsToDaysHours(x) {
	var x = parseInt(x);
	var days = Math.floor(x/86400);
	var rem_secs = x % 86400;
	var hours = Math.floor(rem_secs/3600);
	return (days + ' days' + (hours > 0 ? ', ' + hours + 'hours' : ''));
}

function clone(obj){
    if(obj == null || typeof(obj) != 'object')
        return obj;
    var temp = new obj.constructor();
    for(var key in obj)
        temp[key] = clone(obj[key]);
    return temp;
}

function coalesce() {
	for (var i=0; i<arguments.length; i++) {
		if (arguments[i] != undefined && arguments[i] != null)
			return arguments[i];
	}
	return null;
}

function Map() {
	this.mbrs = {};
	
	this.size = 0;
	
	this.get = function(key) {
		return this.mbrs['_' + key];
	}
	
	this.put = function(key, value) {
		var return_value = this.get(key);
		
		this.mbrs['_' + key] = value;
		
		if (return_value == undefined)
			this.size++;
		else
			return return_value;
	}
	
	this.getMapIterator = function() {
		return new MapIterator(this);
	}
}

function MapIterator(map) {
	this.map = map;

	this.ordered_keys = [];
	
	for (var key in this.map.mbrs)
		this.ordered_keys.push(key);
	
	this.idx = -1;
	
	this.next = function () {
		this.idx++;
		if (this.idx >= this.ordered_keys.length)
			return null;
		else
			return this.map.mbrs[this.ordered_keys[this.idx]];
	}
}

function safeGetter(obj, property_path, fall_back) {
	if (fall_back == undefined)
		fall_back = null;
	
	if (property_path[0] != undefined && obj != undefined && obj[property_path[0]] != undefined) {
		if (property_path.length == 1) {
			return obj[property_path[0]];
		} else {
			obj = obj[property_path[0]];
			property_path.shift();
			return safeGetter(obj, property_path, fall_back);
		}
	} else {
		return fall_back;
	}
}

if (window.slp)
	slp(5);

/*  DomManipulator Class
 *  Class providing convenience functions for maniupulating (showing, hiding, modifying contents, moving)
 *  DOM elements within the root element passed into the constructor.
 */

function DomManipulator(root_elmt, caller_root) {
	this.root_elmt = root_elmt;
	
	this.caller_root = (caller_root ? caller_root : '');
	
	this.showTableElmt = function(table_elmt) {
		try { table_elmt.style.display = 'table'; }
		catch (e) { table_elmt.style.display = 'block'; }
	}
	
	this.showTableById = function(table_elmt_id) { // originally showTable(table_elmt_id)
		this.showTableElmt(this.getElementById(table_elmt_id));
	}
	
	this.showRowElmt = function(row_elmt) {
		if (isIE())
			row_elmt.style.display = 'block';
		else
			try { row_elmt.style.display = 'table-row'; }
			catch (e) { row_elmt.style.display = 'block'; }
	}
	
	this.showRowById = function(row_elmt_id) { // orginally showRow(row_elmt_id)
		this.showRowElmt(this.getElementById(row_elmt_id));
	}
	
	this.showCellElmt = function(cell_elmt) {
		try { cell_elmt.style.display = 'table-cell'; }
		catch (e) { cell_elmt.style.display = 'block'; }
	}
	
	this.showCellById = function(cell_elmt_id) { // originally showCell(cell_elmt_id)
		this.showCellElmt(this.getElementById(cell_elmt_id));
	}

	this.showElmt = function(elmt) {
		elmt.style.display = 'block';
	}
	
	this.hideElmt = function(elmt) {
		elmt.style.display = 'none';
	}

	this.showById = function(elmt_id) { // originally show(elmt_id)
		this.showElmt(this.getElementById(elmt_id));
	}
	
	this.hideById = function(elmt_id) { // originally hide(elmt_id)
		this.hideElmt(this.getElementById(elmt_id));
	}

	this.putById = function (inner_html, elmt_id) { //originally put(inner_html, elmt_id)
		this.getElementById(elmt_id).innerHTML = inner_html;
	}
	
	this.moveOffScreenById = function (elmt_id) { // originally moveOffScreen(elmt_id)
		with(this.getElementById(elmt_id)) {
			style.top = '-4000px';
			style.right = '0px';
		}
	}
	
	this.getElementById = function (elmt_id) {
		return this.root_elmt.getElementById(elmt_id);
	}
	
	this.$ = this.getElementById;
	
	this.out = function (html, elmt_bindings, id_suffix) {
		this.root_elmt.write(html);
		
		if (elmt_bindings)
			for (var elmt_id in elmt_bindings) {
				elmt_bindings[elmt_id] = this.$(elmt_id + (id_suffix ? id_suffix : ''));
			}
		
		return elmt_bindings;
	}
	
}

/*  DDOC [Dommanipulator for DOCument]
 *  This is a Static instantiation of the DomManipulator Class using document as the root element.
 *  It will be used In the vast majority of cases where DomManipulator convenience functions are desirable.
 *  Separate instantiation of another DomManipulator object should only be necessary when manipulating
 *  elements within an iframe.
 */
 
var DDOC = new DomManipulator(document);

/*  The following nine functions provide backwards compatibility for code writen before the DomManipulator
 *  class and DDOC object were built.
 */

function showTable(table_elmt_id) { DDOC.showTableById(table_elmt_id); }
function showRow(row_elmt_id) { DDOC.showRowById(row_elmt_id); }
function showCell(cell_elmt_id) { DDOC.showCellById(cell_elmt_id); }
function show(elmt_id) { DDOC.showById(elmt_id); }
function showElmt(elmt) { DDOC.showElmt(elmt); }
function hide(elmt_id) { DDOC.hideById(elmt_id); }
function hideElmt(elmt) { DDOC.hideElmt(elmt); }
function put(inner_html, elmt_id) { DDOC.putById(inner_html, elmt_id); }
function moveOffScreen(elmt_id) { DDOC.moveOffScreenById(elmt_id); }

function $(id) { return DDOC.$(id); }

/* End DomManipulator stuff */