function $(id) {
	var el = arguments.callee[id];
	if(typeof el == 'undefined') el = arguments.callee[id] = document.getElementById(id);
	return el;
} 

function addEvent(el,kind,handler,capture) {
    if(typeof capture == 'undefined') capture = false;
    if(el.addEventListener)
        el.addEventListener(kind,handler,capture)
    else
        el.attachEvent('on'+kind,handler);
}
function removeEvent(el,kind,handler,capture) {
    if(typeof capture == 'undefined') capture = false;
    if(el.removeEventListener)
        el.removeEventListener(kind,handler,capture);
    else
        el.detachEvent('on'+kind,handler);
}
function cancelEvent(e) {
    if(e.preventDefault)
        e.preventDefault();
    else
        e.returnValue = false;
}

function addClass(el,x) {
    if(!el.className.match(new RegExp('\\b' + x + '\\b')))
        el.className = el.className + ' ' + x;
}

function removeClass(el,x) {
    el.className = el.className.replace(new RegExp('\\b' + x + '\\b'),'');
}

function changeClass(el,x) {
    var a,i;
    a = x.split(/ +/);
    for(i=0;i<a.length;i++) {
        switch(a[i].charAt(0)) {
            case '+': addClass(el,a[i].substring(1)); break;
            case '-': removeClass(el,a[i].substring(1)); break;
            default: addClass(el,a[i]); break;
        }
    }
};

Number.prototype.myToFixed = function(n) {
  return this < 0 && Math.round(Math.abs(this) * Math.pow(10,n+1)) < 5
    ? (-this).toFixed(n)
    : this.toFixed(n);
};

function Slider(min,max,track,knob) {
    var Slider_this = this;
	if(typeof knob == 'undefined')
	    for(knob=track.firstChild;knob.nodeType != 1;knob=knob.nextSibling);
	this.min = min;
	this.max = max;
	this.value = min;
	this.enabled = true;
    this.knob = knob;
    this.track = track;
    addEvent(knob,'mousedown',function(evt) {
        if(typeof evt == 'undefined') evt = window.event;
        var knob_yoff = evt.clientY - knob.offsetTop;
        var mm_fun,mu_fun;
        if(Slider_this.enabled) {
            addEvent(document,'mousemove',mm_fun=function(evt) {
                if(typeof evt == 'undefined') evt = window.event;
                var y_range = track.offsetHeight - knob.offsetHeight
                var y = Math.max(0,Math.min(y_range,evt.clientY - knob_yoff));
                knob.style.top = y + 'px';
                Slider_this.value = max - y / y_range * (max-min);
                if(typeof Slider_this.onchange != 'undefined')
                    Slider_this.onchange(evt);
                cancelEvent(evt);
            },false);
            addEvent(document,'mouseup',mu_fun=function(evt) {
                removeEvent(document,'mousemove',mm_fun,false);
                removeEvent(document,'mouseup',mu_fun,false);
            });
        }
        cancelEvent(evt);
    });
}
Slider.prototype.setEnabled = function(x) {
    this.enabled = x;
    changeClass(this.track.parentNode,x ? '-dp_disabled' : '+dp_disabled');
};
Slider.prototype.getEnabled = function() {
    return this.enabled;
}
Slider.prototype.getId = function() { return this.track.id; }
Slider.prototype.getValue = function() { return this.value; }
Slider.prototype.setValue = function(value) {
    value = Math.max(this.min,Math.min(this.max,value));
    var y_range = this.track.clientHeight - this.knob.clientHeight
    var y = Math.floor((this.max-value) / (this.max-this.min) * y_range);
    this.knob.style.top = y + 'px';
    this.value = value;
};

var sliders = {};

var deg='f';
function todeg(x) {
    switch(deg) {
        case 'f': return x * 9 / 5 + 32
        case 'c': return x;
        case 'k': return x + 273.15;
        default: return 0;
    }
}

var t = function(RH,TD) {
    var tA = Math.pow(RH/100,1/8);
    return (TD - (112*tA) + 112) / ((0.9 * tA) + 0.1);
};
var rh = function(T,TD) {
    return 100 * (Math.pow((112-(0.1*T) + TD) / (112 + (0.9 * T)),8));
};
var dp = function(T,RH) {
    var tA = Math.pow(RH/100,1/8);
    return ((112 + (0.9 * T))) * tA + (0.1 * T) - 112;
};

var pitable = new Array(9594);
var emctable = new Array(8686);

var pi = function(t,rh) {
    return pitable[((t<-23 ? -23 : t>65 ? 65 : Math.round(t))+23) * 90 + (rh<6 ? 6 : rh >95 ? 95 : Math.round(rh)) - 6];
};

var mold = function(t,rh) {
    if(t > 45 || t < 2 || rh < 65) return 0;
    return pitable[8010 + (Math.round(t) - 2) * 36 + Math.round(rh) - 65];
};

var emc = function(t,rh) {
    return emctable[(Math.max(-20,Math.min(65,Math.round(t)))+20) * 101 + Math.round(rh)]
};

function slider_change(e) {
    var s;
    $(this.getId() + 'val').innerHTML =
        this.getId() == 'dp_rh' 
            ? this.getValue().toFixed(0) 
            : todeg(this.getValue()).myToFixed(0);
    for(k in sliders) {
        s = sliders[k];
        if(!s.getEnabled()) {
            switch(s.getId()) {
                case 'dp_dp':
                    s.setValue(dp(Math.round(sliders.t.getValue()),Math.round(sliders.rh.getValue())))
                    $('dp_' + k + 'val').innerHTML = todeg(s.getValue()).myToFixed(0);
                    break;
                case 'dp_t':
                    s.setValue(t(Math.round(sliders.rh.getValue()),Math.round(sliders.dp.getValue())))
                    $('dp_' + k + 'val').innerHTML = todeg(s.getValue()).myToFixed(0);
                    break;
                case 'dp_rh':
                    s.setValue(rh(Math.round(sliders.t.getValue()),Math.round(sliders.dp.getValue())))
                    $('dp_' + k + 'val').innerHTML = s.getValue().toFixed(0);
                    break;
            }
        }
    }
    var x;
    if(typeof pitable[0] != 'undefined') {
        $('dp_pival').innerHTML = x = pi(sliders.t.getValue(),sliders.rh.getValue());
        changeClass($('dp_pival'),x < 45 ? '-dp_vgood +dp_vrisk' : x > 75 ? '-dp_vrisk +dp_vgood' : '-dp_vrisk -dp_vgood');
        $('dp_chem').innerHTML = x < 45 ? 'RISK' : x >= 75 ? 'GOOD' : 'OK'
        changeClass($('dp_chem'),x < 45 ? '-dp_rgood +dp_rrisk' : x >= 75 ? '-dp_rrisk +dp_rgood' : '-dp_rrisk -dp_rgood');
        x = mold(sliders.t.getValue(),sliders.rh.getValue());
        $('dp_moldval').innerHTML = x == 0 ? 'No Risk' : x;
        changeClass($('dp_moldval'),x == 0 ? '-dp_vrisk +dp_vgood' : '-dp_vgood +dp_vrisk');
        $('dp_mold').innerHTML = x == 0 ? 'GOOD' : 'RISK';
        changeClass($('dp_mold'),x == 0 ? '-dp_rrisk +dp_rgood' : '-dp_rgood +dp_rrisk');
    }
    if(typeof emctable[0] != 'undefined') {
        $('dp_emcval').innerHTML = x = emc(sliders.t.getValue(),sliders.rh.getValue());
        changeClass($('dp_emcval'),x < 5 || x > 12.5 ? '+dp_vrisk' : '-dp_vrisk');
        $('dp_mech').innerHTML = x < 5 || x > 12.5 ? 'RISK' : 'OK';
        changeClass($('dp_mech'),x < 5 || x > 12.5 ? '+dp_rrisk' : '-dp_rrisk');
        $('dp_emcval2').innerHTML = x = emc(sliders.t.getValue(),sliders.rh.getValue());
        changeClass($('dp_emcval2'),x < 7.0 ? '-dp_vrisk +dp_vgood' : x > 10.5 ? '-dp_vgood +dp_vrisk' : '-dp_vrisk -dp_vgood');
        $('dp_corr').innerHTML = x < 7.0 ? 'GOOD' : x > 10.5 ? 'RISK' : 'OK'
        changeClass($('dp_corr'),x < 7.0 ? '-dp_rrisk +dp_rgood' : x > 10.5 ? '-dp_rgood +dp_rrisk' : '-dp_rrisk -dp_rgood');
    }
}

function switchdeg(x) {
    deg = x.value;
    $('dp_tval').innerHTML = todeg(sliders.t.getValue()).myToFixed(0);
    $('dp_dpval').innerHTML = todeg(sliders.dp.getValue()).myToFixed(0);
}

var pi_readystatechange = function() {
    var xmlHttp = arguments.callee.xmlHttp;
    var i,s;
    switch(xmlHttp.readyState) {
        case 4:
            s = xmlHttp.responseText;
            if(xmlHttp.status == 200 && s.length == pitable.length * 4) {
                for(i=0;i<pitable.length;i++) {
                    pitable[i] = parseInt(s.substring(i*4,i*4+4),16);
                }
            } else {
                alert(xmlHttp.status == 200 ? s.length : xmlHttp.status);
            }
    }
};

var emc_readystatechange = function() {
    var xmlHttp = arguments.callee.xmlHttp;
    var i,s;
    switch(xmlHttp.readyState) {
        case 4: 
            s = xmlHttp.responseText;
            if(xmlHttp.status == 200 &&  s.length == emctable.length * 4) {
                for(i=0;i<emctable.length;i++)
                    emctable[i] = parseInt(s.substring(i*4,i*4+4),16)/10;
            } else {
                alert(xmlHttp.status == 200 ? s.length : xmlHttp.status);
            }
    }
};

function dp_init() {
    var xmlHttp;

    xmlHttp = window.XMLHttpRequest 
                ? new XMLHttpRequest() 
                : new ActiveXObject("Microsoft.XMLHTTP");
    xmlHttp.onreadystatechange = pi_readystatechange;
    pi_readystatechange.xmlHttp = xmlHttp;
    xmlHttp.open('GET','dp_hex.asp?f=pi.dat',true);
    xmlHttp.send(null);

    xmlHttp = window.XMLHttpRequest 
                ? new XMLHttpRequest() 
                : new ActiveXObject("Microsoft.XMLHTTP");
    xmlHttp.onreadystatechange = emc_readystatechange;
    emc_readystatechange.xmlHttp = xmlHttp;
    xmlHttp.open('GET','dp_hex.asp?f=emc.dat',true);
    xmlHttp.send(null);
    
	sliders.t = new Slider(-20,65,$('dp_t'));
	sliders.t.onchange = slider_change;
	sliders.t.setValue(20);
	sliders.rh = new Slider(0,100,$('dp_rh'));
	sliders.rh.onchange = slider_change;
	sliders.rh.setValue(50);
	sliders.dp = new Slider(-65,65,$('dp_dp'));
	sliders.dp.onchange = slider_change;
	sliders.dp.setValue(9);
	sliders.dp.setEnabled(false);
}

function setSolve(id) {
    var k;
    for(k in sliders) sliders[k].setEnabled(k!=id);
}

function map(f,a) {
  var b = new Array(a.length);
  var i;
  for(i=0;i<a.length;i++)
    b[i] = f(a[i]);
  return b;
}

function compose(f,g) { return function(x) { return f(g(x)); }; }
function toString(x) { return x.toString(); }

function createRow(a) {
  var i;
  var tr = document.createElement("TR");
  for(i=0;i<a.length;i++)
    tr.appendChild(a[i]);
  return tr;
}

function createTextCell(s) {
  var td = document.createElement("TD");
  var t = document.createTextNode(s);
  td.appendChild(t);
  return td;
}

function memocell(v,suffix,bad) {
  var el = document.createElement("TD");
  var text = document.createTextNode(v + suffix);
  el.className = bad(v) ? "dp_vrisk" : "";
  el.style.fontWeight = bad(v) ? "bold" : "normal";
  el.appendChild(text);
  return el;
}

function memosave(table) {
  var tbody = table.getElementsByTagName("TBODY")[0];
  var x;
  tbody.appendChild(createRow([
    createTextCell(todeg(sliders.t.getValue().toFixed(0)) + '\xB0' + deg.toUpperCase()),
    createTextCell(sliders.rh.getValue().toFixed(0) + "%"),
    createTextCell(todeg(sliders.dp.getValue()).myToFixed(0) + '\xB0' + deg.toUpperCase()),
    memocell(pi(sliders.t.getValue(),sliders.rh.getValue()),"",function(x){return x < 45;}),
    (x=mold(sliders.t.getValue(),sliders.rh.getValue())) ? memocell(x,"",function(x){return x != 0;}) : createTextCell("No Risk"),
    memocell(emc(sliders.t.getValue(),sliders.rh.getValue()),"%",function(x){return x < 5 || x > 12.5;})
    ]));
}
function memoclear(table) {
  var i;
  var tbody = table.getElementsByTagName("TBODY")[0];
  var els = tbody.getElementsByTagName("TR");
  while(els.length > 1) tbody.removeChild(els[1]);
}

function memoexport(table) {
  var tbody = table.getElementsByTagName("TBODY")[0];
  var i,j,buf;
  var trs,tds,td;
  buf = "T,RH,DP,PI,Mold,EMC\n";
  trs = tbody.getElementsByTagName("TR");
  for(i=1;i<trs.length;i++) {
    tds = trs[i].getElementsByTagName("TD");
    for(j=0;j<tds.length;j++) {
      td = tds[j];
      if(j) buf += ","
      buf += td.textContent ? td.textContent : td.innerText;
    }
    buf += "\n";
  }
  var f = document.createElement("FORM");
  f.setAttribute("action","dp_export.asp");
  f.setAttribute("method","post");
  i = document.createElement("INPUT");
  i.setAttribute("type","hidden");
  i.setAttribute("name","data");
  i.setAttribute("value",buf);
  f.appendChild(i);
  document.body.appendChild(f);
  f.submit();
  document.body.removeChild(f);
}
