/********************************************************************
 *                             Calculator                            *
 *                            Jerry Baker                            *
 *                                                                   *
 * Portions of this code were inspired by other people's work, and   *
 * the rest is original code. This code may be freely used by anyone *
 * provided that proper credit is given.                             *
 *                                                                   *
 * Thanks to Chuck Gadd (cgadd@cfxc.com) for inpsiration on the      *
 * KH-CO2 calculator, and for portions of the code.                  *
 ********************************************************************/

/* Make these globals */
var KH1degrees,KH1ppm,KHmeq,CO2_Out,CO2molarity,pH1;

function initPage()
{
  KH1degrees=findObj("KH1degrees");
  KH1ppm=findObj("KH1ppm");
  KHmeq=findObj("meq1");
  CO2_Out=findObj("co2_out");
  CO2molarity=findObj("molarityco2");
  pH1=findObj("pH1");
  pH1.focus();
}
//*****************************************************************************
function focusState(s)
{
  return (s==1) ? "txtbkgdon" : "txtbkgdoff";
}
//*****************************************************************************
function calculate_pH()
{

  if(checkVals(KH1degrees,CO2_Out))
  {
    pH1.value=round((7-(Math.log(CO2_Out.value/(3*KH1degrees.value))/Math.log
                    (10))),2);
  }
  else
  {
    alert("Error!\n\nBoth the CO2 and KH fields must have a number\nbefore "+
          "you can solve for pH!");
    document.forms["inputform"].reset();
  }
  return false;
}
//*****************************************************************************
function calculate_KH()
{

  if(checkVals(CO2_Out,pH1))
  {
    KH1degrees.value=round(CO2_Out.value/(3*Math.pow(10,(7-pH1.value))),1);
    fill_KH_fields(KH1degrees);
  }
  else
  {
    alert("Error!\n\nBoth the CO2 and pH fields must have a number\nbefore "+
          "you can solve for KH!");
    document.forms["inputform"].reset();  }

}
//*****************************************************************************
function calculate_co2()
{

  if(checkVals(pH1,KH1degrees))
  {

    CO2_Out.value=round((3*KH1degrees.value*Math.pow(10,(7-pH1.value))),0);
    calculate_co2molefraction(CO2_Out);
  }
  else
  {
    alert("Error!\n\nBoth the KH and pH fields must have a number\nbefore you "
          +"can solve for CO2!");
    document.forms["inputform"].reset();  }

  return false;
}
//*****************************************************************************
function fill_KH_fields(e)
{
  var DegreesPerPPM=0.055865921787709497206703910614525;

  if(!checkVals(e))
    return;

  if(e==KH1degrees)
  {
    KHmeq.value=round((e.value/2.8),3);
    KH1ppm.value=round((e.value/DegreesPerPPM),1);
  }

  else if(e==KH1ppm)
  {
    KHmeq.value=round((e.value/50.12),3);
    KH1degrees.value=round((e.value*DegreesPerPPM),1);
  }

  else if(e==KHmeq)
  {
    KH1degrees.value=round((e.value*2.8),1);
    KH1ppm.value=round((e.value*52.92),1);
  }
}
//*****************************************************************************
function calculate_co2molefraction(e)
{
  // For those that note that the atomic weight of H2O suggests
  // 55.5555 moles per liter, this constant is taking into account
  // the weight of isotopes of hydrogen and oxygen found on average.
  var moles_per_liter_h2o=55.508435061791989910786843168687913815383385659;
  var mg_per_mole_co2=44009.5;

  if(!checkVals(e))
    return;

  if(e==CO2_Out)
    CO2molarity.value=round((((e.value/mg_per_mole_co2)/(moles_per_liter_h2o+
                            (e.value/mg_per_mole_co2)))*1000),8);
  else if(e==CO2molarity)
    CO2_Out.value=round((((e.value/1000)*mg_per_mole_co2)*(moles_per_liter_h2o))
                        ,0);
}
//*****************************************************************************
/*
function convert_liters(e)
{

var LitersPerGallon = 3.785411784;

if(isNaN(e.value) || !e.value) return;

if (e == LITERSBOX)
e.value = round((findObj(GALLONSBOX).value*LitersPerGallon), 3);
else if (e == GALLONSBOX)
e.value = round((findObj(LITERSBOX).value/LitersPerGallon), 3);
}
 */
//*****************************************************************************
function calculateSubstrate(e)
{
  if(!checkVals(findObj("tankLengthinch"),findObj("tankWidthinch"),findObj("desiredDepthinch")))
    return;
  var densityFlourite=31;
  var densityOnyx=densityFlourite;
  var densitySand=19.24;
  var densityEcoComplete=25;
  var densityAragonite=17;
  var CalcOutput=findObj("calculateOutput").childNodes[0];
  var substrateVolume=findObj("tankLengthinch").value*findObj("tankWidthinch")
                              .value*findObj("desiredDepthinch").value;

  switch(e.value)
  {
    case "Flourite":
      var amountNeeded=substrateVolume/densityFlourite;
      CalcOutput.nodeValue="You need about "+Math.ceil(amountNeeded/15.4)+
        " bags of Flourite.";
      break;

    case "Onyx Sand":
      var amountNeeded=substrateVolume/densityOnyx;
      CalcOutput.nodeValue="You need about "+Math.ceil(amountNeeded/15.4)+
        " bags of Onyx Sand.";
      break;

    case "Sand":
      var amountNeeded=substrateVolume/densitySand;
      CalcOutput.nodeValue="You need about "+Math.ceil(amountNeeded)+
        " pounds ("+round(amountNeeded/2.201,2)+" kg) of sand.";
      break;

    case "Eco-Complete":
      var amountNeeded=substrateVolume/densityEcoComplete;
      CalcOutput.nodeValue="You need about "+Math.ceil(amountNeeded/20)+
        " bags of Eco-Complete.";
      break;

    case "Aragonite":
      var amountNeeded=substrateVolume/densityAragonite;
      CalcOutput.nodeValue="You need about "+Math.ceil(amountNeeded)+
        " pounds ("+round(amountNeeded/2.201,2)+" kg) of aragonite.";
      break;

  }
}
//*****************************************************************************
function convertUnits(t,s,c)
{
  if(!isNaN(s.value) && s.value)
    c==1 ? t.value=round(s.value*2.54,2):t.value=round(s.value/2.54,2);
}

//*****************************************************************************
// Below are the "backend" functions. They are used to do some grunt work and
// are mostly called from other functions rather than performing tasks visible
// to the user.
//*****************************************************************************

function round(v,p)
{
  return (Math.round(v*Math.pow(10,p))/Math.pow(10,p)).toFixed(p);
}
//*****************************************************************************
// Allows us to get a reference to document objects pretty much universally
// cross-platform/browser.
//*****************************************************************************
function findObj(n,d)
{
  var p,i,x;

  if(!d)
    d=document;

  if((p=n.indexOf("?"))>0 && parent.frames.length)
  {
    d=parent.frames[n.substring(p+1)].document;
    n=n.substring(0,p);
  }

  if(!(x=d[n]) && d.all)
    x=d.all[n];

  for(i=0;!x && i<d.forms.length;i++)
    x=d.forms[i][n];

  for(i=0;!x && d.layers && i<d.layers.length;i++)
    x=findObj(n,d.layers[i].document);

  if(!x && d.getElementById)
    x=d.getElementById(n);

  if(!x && d.getElementsByName)
    x=d.getElementsByName(n)[0]; // Gets first element with name

  return x;
}
//*****************************************************************************
function checkVals() {
  for(i=0;i<arguments.length;i++) {
    if(!arguments[i].value || isNaN(arguments[i].value))
      return false;
  }
  return true;
}
