////////////////////////////////////////////////////////////////////////////
// Name:			thermo.js
// Description:		Include all common functions using in the weather
//					calculator.
// Created Date:	10 July 2003
// Author:			Yuttana Buasen 
//					Thai Meteorological Department
// Comment:			Most of functions in these file are adopted from
//					http://www.srh.noaa.gov
////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------
// Temperature
//-------------------------------------------------
function convertFtoC(Fahr)
{
	var Cels;
	Cels = .55556 * (Fahr - 32);
	return Cels;
}

function convertKtoC(Kel)
{
	var Cels;
	Cels = Kel - 273.15;
	return Cels;
}

function convertKtoF(Kelvin)
{
	var Fahr;
	Fahr = (1.8 * (Kelvin -273.15) + 32);
	return Fahr;
}

function convertCtoF(Cels)
{
	var Fahr;
	Fahr = 1.8 * Cels + 32;
	return Fahr;
}

function convertCtoK(Cels)
{
	var Kelvin;
	Kelvin = Cels + 273.15;
	return Kelvin;
}

function convertCtoR(Cels)
{
	var Rankin;
	Rankin = (1.8 * Cels + 32) + 459.69;
	return Rankin;
}

function convertKtoR(Kel)
{
	var Fahr, Cels, Rank;
	Cels = parseFloat(convertKtoC(Kel));
	Fahr = parseFloat(convertCtoF(Cels));
	Rank = Fahr + 459.69;
	return Rank;
}

function convertFtoK(Fahr)
{
	var Kelvin;
	Kelvin = (.5556 * (Fahr - 32)) + 273.15;
	return Kelvin;
}

function convertFtoR(Fahr)
{
	var Rankin;
	Rankin = Fahr + 459.69;
	return Rankin;
}

function convertRtoK(Rankin)
{
	var Kelvin;
	Kelvin = (.55556 * ((Rankin - 459.69) - 32)) + 273.15;
	return Kelvin;
}

function convertRtoF(Rankin)
{
	var Fahr;
	Fahr = Rankin - 459.69;
	return Fahr;
}

function convertRtoC(Rankin)
{
	var Cels;
	Cels = .55556 * ((Rankin - 459.69) - 32);
	return Cels;
}

//-------------------------------------------------
// Pressure
//-------------------------------------------------
function convertinHGtomb(inHG)
{
	var mb;
	mb = 33.8639*inHG;
	return mb;
}

function convertinHGtommHG(inHG)
{
	var mmHG;
	mmHG = 25.4*inHG;
	return mmHG;
}

function convertmmHGtomb(mmHG)
{
	var mb;
	mb = 1.333224*mmHG;
	return mb;
}

function convertmbtoinHG(mb)
{
	var inHG;
	inHG = 0.0295300*mb;
	return inHG;
}

function convertmbtommHG(mb)
{
	var mmHG;
	mmHG = 0.750062*mb;
	return mmHG;
}

function convertmbtolbsinch(mb)
{
	var lbsinch;
	lbsinch = 0.0145038*mb;
	return lbsinch;
}

function converthPAtokPA(inHG)
{
	var kPA;
	kPA = document.Convert.hPA.value/10;
	return kPA;
}

function convertinHGtolbsin(inHG)
{
	var lbsin;
	lbsin = 0.491130*inHG;
	return lbsin;
}

function convertmmHGtoinHG(mmHG)
{
	var inHG;
	inHG = 0.03937008*mmHG;
	return inHG;
}

function convertmmHGtolbsin(mmHG)
{
	var lbsin;
	lbsin = 0.0193368*mmHG;
	return lbsin;
}

function convertmbtolbsin(mb)
{
	var lbsin;
	lbsin = 0.0145038*mb;
	return lbsin;
}

function convertmbtokPA(mb)
{
	var kPA;
	kPA = mb/10;
	return kPA;
}

function convertkPAtoinHG(kPA)
{
	var inHG;
	inHG = 0.295300*kPA;
	return inHG;
}

function convertlbsintoinHG(lbsin)
{
	var inHG;
	inHG = 2.03602*lbsin;
	return inHG;
}

function convertlbsintommHG(lbsin)
{
	var mmHG;
	mmHG = 51.7149*lbsin;
	return mmHG;
}

function convertlbsintomb(lbsin)
{
	var mb;
	mb = 68.9476*lbsin;
	return mb;
}

function esubw(Cwetbulb)
{
	var Ew;
	
	// Noaa
	//Ew = 6.112 * Math.exp((17.67 * Cwetbulb) / (Cwetbulb + 243.5));
	
	// TMD
	Cwetbulb = convertCtoK(Cwetbulb);
	
	x1 = 11.344 * (1 - Cwetbulb / 373.16);
	x2 = -3.49149 * (373.16 / Cwetbulb - 1);
    Ew = -7.90298 * (373.16 / Cwetbulb - 1) 
    	+ 5.02808 * log10(373.16 / Cwetbulb) 
    	- 1.3816 * 0.0000007 * (Math.pow(10,x1) - 1)
    	+ 8.1328 * 0.001 * (Math.pow(10,x2) - 1) 
    	+ log10(1013.246);
    	
    Ew = Math.pow(10,Ew);
    
	return Ew;
}

function VaporPressureEwAssMann(Ew, MBpressure, Ctemp, Cwetbulb)
{
	// Assmann Psychrometer has A = 6.60x10-4
	return VaporPressureEw(Ew, MBpressure, Ctemp, Cwetbulb, 0.000660);
}

function VaporPressureEwStevenson(Ew, MBpressure, Ctemp, Cwetbulb)
{
	// Stevenson Screen Psychrometer has A = 7.99x10-4
	return VaporPressureEw(Ew, MBpressure, Ctemp, Cwetbulb, 0.000799);
}

function VaporPressureEw(Ew, MBpressure, Ctemp, Cwetbulb, A)
{
	var E;
	
	// For unventilated screen type instruments, typically A=7.99x10-4
	// For aspirated instruments with a ventilation rate of about 3 m/s, 
	//  typically A=6.60x10-4
															  
	// Noaa website (http://www.srh.noaa.gov) uses A=0.000660. For our case,
	//  it should be A=0.000799 because we use unventilated screen type.
	
	if (A==undefined)
	{
		// Set default to unventilated screen type
		A = 0.000799;
	}
	
	E = Ew - MBpressure * (Ctemp - Cwetbulb) * A * (1 + (0.00115 * Cwetbulb));
	
	return E;
}

function VaporPressure(Ctemp)
{
	var E;
	E = 6.11 * Math.pow(10, (7.5 * Ctemp / (237.7 + Ctemp)));
	return E;
}

function Dewpoint (E)
{
	var Dewpoint;
	Dewpoint = (243.5 * Math.log(E/6.112))/(17.67 - Math.log(E/6.112));
	return Dewpoint;
}

function esubs(Ctemp)
{
	var Es;
	
	// Noaa
	//Es = 6.112 * Math.exp(17.67 * Ctemp / (Ctemp + 243.5));
	
	
	// TMD
	Ctemp = convertCtoK(Ctemp);
	
	x1 = 11.344 * (1 - Ctemp / 373.16);
    x2 = -3.49149 * (373.16 / Ctemp - 1);
    Es = -7.90298 * (373.16 / Ctemp - 1) 
    	+ 5.02808 * log10(373.16 / Ctemp) 
    	- 1.3816 * 0.0000007 * (Math.pow(10,x1) - 1)
    	+ 8.1328 * 0.001 * (Math.pow(10,x2) - 1) 
    	+ log10(1013.246);
    	
    Es = Math.pow(10,Es);
    
	return Es;
}

function RH(E,Es)
{
	var RH;
	RH = 100 * E/Es;
	return RH;
}

function invertedRH(Es,rh)
{
	var E;
	E = Es * (rh/100);
	return E;
}

function esubx(temp)
{
	var Ex;
	
	// Noaa
	//Ex = 6.112 * Math.exp((17.67 * temp) / (temp + 243.5));
	
	temp = convertCtoK(temp);
	
	x1 = 11.344 * (1 - temp / 373.16);
    x2 = -3.49149 * (373.16 / temp - 1);
    Ex = -7.90298 * (373.16 / temp - 1) 
    	+ 5.02808 * log10(373.16 / temp) 
    	- 1.3816 * 0.0000007 * (Math.pow(10,x1) - 1)
    	+ 8.1328 * 0.001 * (Math.pow(10,x2) - 1) 
    	+ log10(1013.246);
    	
    Ex = Math.pow(10,Ex);
    
	return Ex;
}

function altpress(mb)
{
	var altpress, pstd;
	pstd = 1013.25;
	altpress =  (1 - Math.pow((mb/pstd), 0.190284)) * 145366.45;
	return altpress;
}

function calcwetbulb(Edifference,Twguess,Ctemp,MBpressure,E,previoussign,incr)
{
	outerloop:
	while (Math.abs(Edifference) > 0.05)
	{
		Ewguess = 6.112 * Math.exp((17.67 * Twguess) / (Twguess + 243.5));
		Eguess = Ewguess - MBpressure * (Ctemp - Twguess) * 0.00066 * (1 + (0.00115 * Twguess));
		Edifference = E - Eguess;
		
		if (Edifference == 0)
		{
			break outerloop;
		} 
		else 
		{
			if (Edifference < 0)
			{
				cursign = -1;
				if (cursign != previoussign)
				{
					previoussign = cursign;
					incr = incr/10;
				} 
				else 
				{
					incr = incr;
				}
			} 
			else 
			{
				cursign = 1;
				if (cursign != previoussign)
				{
					previoussign = cursign;
					incr = incr/10;
				} 
				else 
				{
					incr = incr;
				}
			}
		}

		if (Math.abs(Edifference) <= 0.05)
		{
		  break outerloop;
		} 
		else 
		{
		 Twguess = Twguess + incr * previoussign;
		} 
		
	}
	wetbulb = Twguess;
	return wetbulb;
}			

//-------------------------------------------------
// Distance
//-------------------------------------------------
function convertfeettometer(feet)
{
	var meter;
	meter = 0.3048 * feet;
	return meter;
}

//-------------------------------------------------
// Speed
//-------------------------------------------------
function convertktstomph(knots)
{
	var mph;
	mph = 1.15155*knots;
	return mph;
}

function convertktstomps(knots)
{
	var ws1;
	ws1 = 0.514791*knots;
	return ws1;
}

function convetkphtomph(kph)
{
	var mph;
	mph = 0.621371*kph;
	return mph;
}

function convertkphtomps(kph)
{
	var ws1;
	ws1 = 0.277778*kph;
	return ws1;
}

function convertmphtoknots(mph)
{
	knots = 0.868391 * mph;
	return knots;
}

function convertmphtomps(mph)
{
	mps = 0.44704 * mph;
	return mps;
}

function convertmphtoftps(mph)
{
	ftps = 1.46667 * mph;
	return ftps;
}

function convertmphtokmph(mph)
{
	kmph = 1.609344 * mph;
	return kmph;
}

function convertknotstomph(knots)
{
	mph = 1.15155 * knots;
	return mph;
}

function convertknotstomps(knots)
{
	mps = 0.514791 * knots;
	return mps;
}

function convertknotstoftps(knots)
{
	ftps = 1.68895 * knots;
	return ftps;
}

function convertknotstokmph(knots)
{
	kmph = 1.85325 * knots;
	return kmph;
}

function convertmpstomph(mps)
{
	mph = 2.23694*mps;
	return mph;
}

function convertmpstoknots(mps)
{
	knots = 1.94254 * mps;
	return knots;
}

function convertmpstoftps(mps)
{
	ftps = 3.28084 * mps;
	return ftps;
}

function convertmpstokmph(mps)
{
	kmph = 3.6 * mps;
	return kmph
}

function convertftpstomph(ftps)
{
	mph = 0.681818*ftps;
	return mph;
}

function convertftpstoknots(ftps)
{
	knots =  0.592085 * ftps;
	return knots;
}

function convertftpstomps(ftps)
{
	mps =  0.3048 * ftps;
	return mps;
}

function convertftpstokmph(ftps)
{
	kmph = 1.09728 * ftps;
	return kmph;
}

function convertkmphtomph(kmph)
{
	mph = 0.621371*kmph;
	return mph;
}

function convertkmphtoknots(kmph)
{
	knots = 0.539593 * kmph;
	return knots;
}

function convertkmphtomps(kmph)
{
	mps = 0.277778 * kmph;
	return mps;
}

function convertkmphtoftps(kmph)
{
	ftps = 0.911344 * kmph;
	return ftps;
}

//-------------------------------------------------
// Virtual Temperature
//-------------------------------------------------
function virtualTemperature(Kel, INpressure, Cdewpoint)
{
	var Tempv, dewpoint, E;
	dewpoint = parseFloat(convertKtoC(Kel));
	E = parseFloat(VaporPressure(Cdewpoint));
	mbpressure = parseFloat(convertinHGtomb(INpressure));
	Tempv = Kel / ( 1 - (E / mbpressure ) * ( 1 - 0.622));
	return Tempv;
}

function densityAltitude(INpressure, Tempv)
{
	var DensityAlt, dummy, Rank;
	Rank = parseFloat(convertKtoR(Tempv));
	dummy = (17.326 * INpressure) / Rank;
	DensityAlt = 145366 * (1 - (Math.pow(dummy, 0.235)));
	return DensityAlt;
}

//-------------------------------------------------
// Heat Index
//-------------------------------------------------
function heatIndex(F, rh)
{
	var Hindex;
	
	Hindex = -42.379 + 2.04901523*F + 10.14333127*rh 
		- 0.22475541*F*rh - 6.83783*Math.pow(10,-3)*F*F
		- 5.481717*Math.pow(10,-2)*rh*rh
		+ 1.22874*Math.pow(10,-3)*F*F*rh 
		+ 8.5282*Math.pow(10,-4)*F*rh*rh 
		- 1.99*Math.pow(10,-6)*F*F*rh*rh;
	return Hindex;
}

//-------------------------------------------------
// Wind Chill
//-------------------------------------------------
function windChill(F, mph)
{
	var wChill;
	
	wChill = 35.74 + .6215*F - 35.75*Math.pow(mph, 0.16) + 0.4275*F*Math.pow(mph, 0.16);
	return wChill;
}

function WPM2 (C, mps)
{
	var Watts;

	Watts = (12.1452 + 11.6222*Math.sqrt(mps) - 1.16222*mps)*(33 - C);
	return Watts;
}

//-------------------------------------------------
// Mix Ratio
//-------------------------------------------------
function MixRatio(VaporPress, MBpressure)
{
	var MixRatio;
	MixRatio = 621.97 * VaporPress/(MBpressure - VaporPress);
	return MixRatio;
}

//-------------------------------------------------
// Mathametic
//-------------------------------------------------
function roundOff(value)
{
	value = Math.round(100*value)/100;
	return value;
}

function roundOff2(value)
{
	value = Math.round(1000*value)/1000;
	return value;
}

function roundOff1(value)
{
	value = Math.round(value);
	return value;
}

function roundOff10(value)
{
	value = Math.round(10*value)/10;
	return value;
}

function roundOff100(value)
{
	value = Math.round(100*value)/100;
	return value;
}

function log10(number)
{
	return Math.log(number)/Math.log(10);
}

// Tools
function GetCookie(name) 
{
	var start = document.cookie.indexOf(name+"=");
	
	var len = start+name.length+1;
	if ((!start) && (name != document.cookie.substring(0,name.length))) return "";
	if (start == -1) return "";
	var end = document.cookie.indexOf(";",len);
	if (end == -1) end = document.cookie.length;
	return unescape(document.cookie.substring(len,end));
}

function SetCookie(name,value,expires,path,domain,secure) 
{
	document.cookie = name + "=" +escape(value) +
		( (expires) ? ";expires=" + expires.toGMTString() : "") +
		( (path) ? ";path=" + path : "") + 
		( (domain) ? ";domain=" + domain : "") +
		( (secure) ? ";secure" : "");
}

function GetUserDataObject()
{
	if (null==document.all["hdnUserData"])
	{
		var objUserData = document.createElement("<SPAN>");
		objUserData.id	= "hdnUserData";
		objUserData.name= "hdnUserData";
		objUserData.style.behavior = "url(#default#userData)";
		objUserData.style.display = "none";
		document.body.appendChild(objUserData);
	}
	return document.body.all["hdnUserData"];
}   

function GetUserData(sStoreName, sAttributeName)
{
	try
	{
		var objUserData = GetUserDataObject();
		objUserData.load(sStoreName);
		return objUserData.getAttribute(sAttributeName);
	}
	catch (err)
	{
		return null;
	}
}

function SetUserData(sStoreName, sAttributeName, sAttributeValue)
{
	try
	{
		// set the expiration date to one year after 
		// the information is persisted.
		var oTimeNow = new Date();
		oTimeNow.setFullYear(oTimeNow.getFullYear() + 1);		
		var sExpirationDate = oTimeNow.toUTCString();
		
		var objUserData = GetUserDataObject();		
		objUserData.expires	= sExpirationDate;
		objUserData.setAttribute(sAttributeName, sAttributeValue);		
		objUserData.save(sStoreName);	
		return true;
	}
	catch (err)
	{
		alert('set err: ' + err.description);
		return false;
	}
}   

