// density data from "Zuckertechniker-Taschenbuch, Albert Bartens Verlage, Berlin, 1966, 7. Auflage"
var density_tbl = new Array(
            /* 0      5     10     15     20     25     30     35     40     g/100g */
  new Array(1.0002,1.0204,1.0418,1.0632,1.0851,1.1088,1.1323,1.1574,1.1840), /*  0°C, extrapolated, does not make much sense below 4°C */
  new Array(0.9997,1.0196,1.0402,1.0614,1.0835,1.1064,1.1301,1.1547,1.1802), /* 10°C */
  new Array(0.9982,1.0178,1.0381,1.0591,1.0810,1.1035,1.1270,1.1513,1.1764), /* 20°C */
  new Array(0.9957,1.0151,1.0353,1.0561,1.0777,1.1000,1.1232,1.1473,1.1723), /* 30°C */
  new Array(0.9922,1.0116,1.0316,1.0522,1.0737,1.0958,1.1189,1.1428,1.1676), /* 40°C */
  new Array(0.9881,1.0072,1.0271,1.0477,1.0690,1.0910,1.1140,1.1377,1.1624), /* 50°C */
  new Array(0.9832,1.0023,1.0221,1.0424,1.0636,1.0856,1.1085,1.1321,1.1568), /* 60°C */
  new Array(0.9778,0.9968,1.0165,1.0368,1.0579,1.0798,1.1026,1.1262,1.1507), /* 70°C */
  new Array(0.9718,0.9908,1.0104,1.0306,1.0517,1.0735,1.0963,1.1198,1.1443), /* 80°C */
  new Array(0.9653,0.9842,1.0038,1.0240,1.0450,1.0669,1.0896,1.1130,1.1375), /* 90°C */
/*new Array(0.9591,0.9780,0.9975,1.0176,1.0386,1.0606,1.0832,1.1065,1.1309)     99°C, original data, extrapolated 100°C is used instead */
  new Array(0.9584,0.9773,0.9968,1.0169,1.0379,1.0599,1.0825,1.1058,1.1301)  /*100°C, extrapolated */
);

// approximate the density function using ax^3+bx^2+cx+d and 
// interpolate for a given x
function interpolate(x1, y1, x2, y2, x3, y3, x4, y4, x) {
  // lagrange interpolation
  var y =
    y1 * (((x-x2)*(x-x3)*(x-x4)) / ((x1-x2)*(x1-x3)*(x1-x4))) +
    y2 * (((x-x1)*(x-x3)*(x-x4)) / ((x2-x1)*(x2-x3)*(x2-x4))) +
    y3 * (((x-x1)*(x-x2)*(x-x4)) / ((x3-x1)*(x3-x2)*(x3-x4))) +
    y4 * (((x-x1)*(x-x2)*(x-x3)) / ((x4-x1)*(x4-x2)*(x4-x3)));

  return y;
}

// interpolates the density values for a given temperature
function interpolateTemperature(temperature) {
  var result = new Array();
  var lowest = Math.floor(temperature / 10) - 1;
  if (0 > lowest) {
    lowest = 0;
  }
  if (lowest > density_tbl.length - 4) {
    lowest = density_tbl.length - 4;
  }

  var temp1 = lowest;
  var temp2 = lowest + 1;
  var temp3 = lowest + 2;
  var temp4 = lowest + 3;

  for (i=0; i<density_tbl[0].length; i++) {
    result[i] = interpolate(temp1*10, density_tbl[temp1][i], temp2*10, density_tbl[temp2][i], temp3*10, density_tbl[temp3][i], temp4*10, density_tbl[temp4][i], temperature);
  }

  return result;
}

// reads the density values for a given temperature from the data table
// values for non existing temperatures are interpolated
function densityAtBaseTemp(base, plato) {
  var density_base = interpolateTemperature(base);//density_tbl[20 / 10];

  var lowest = Math.floor(plato / 5) - 1;
  if (0 > lowest) {
    lowest = 0;
  } 
  if (lowest > density_base.length - 4) {
    lowest = density_base.length - 4;
  }

  var plato1 = lowest;
  var plato2 = lowest + 1;
  var plato3 = lowest + 2;
  var plato4 = lowest + 3;

  return interpolate(plato1*5, density_base[plato1], plato2*5, density_base[plato2], plato3*5, density_base[plato3], plato4*5, density_base[plato4], plato);
}

function densityAtX(platoMeasure, temperature, calibrationTemp) {
  var dAt20 = densityAtBaseTemp(calibrationTemp, platoMeasure);
  var tmp = interpolateTemperature(temperature);

  // find density interval
  var minimalIndex = 0;
  for (i=0; i<tmp.length; i++) {
    if (dAt20 > tmp[i]) {
      minimalIndex = i;
    }
  }
  var lowest = minimalIndex - 1;
  if (0 > lowest) {
    lowest = 0;
  }
  if (lowest > tmp.length - 4) {
    lowest = tmp.length - 4;
  }

  var plato1 = lowest;
  var plato2 = lowest + 1;
  var plato3 = lowest + 2;
  var plato4 = lowest + 3;

  return interpolate(tmp[plato1], plato1*5, tmp[plato2], plato2*5, tmp[plato3], plato3*5, tmp[plato4], plato4*5, dAt20);
}

// replace "," by "." and force handling as float
function parseFloat(s) {
  return s.replace(/\,/g, ".") * 1.0;
}

// round: 2 digits and replace "." by ","
function Round(v) {
  return ("" + (Math.round(v * 100) / 100)).replace(/\./g, ",");
}

//// transform Plato to SG
//function Plato2SG(p) {
//  return 1.00001 + (3.8661E-3 * p) + (1.3488E-5 * p * p) + (4.3074E-8 * p * p * p);
//}

//// transform SG to Plato
//function SG2Plato(sg) {
//  return -668.962 + (1262.45 * sg) - (776.43 * sg * sg) + (182.94 * sg * sg * sg);
//}

//// calculate SG value based on 60 Farenheit
//function SG60(t) {
//  return 1.00130346 - (1.34722124E-4 * t) + (2.04052596E-6 * t * t) - (2.32820948E-9 * t * t * t);
//}

//// transform Celsius to Farenheit
//function Cel2Far(c) {
//  return c * 1.8 + 32;
//}

function correct_wort(field_wort, field_temp, field_calib_temp, id_result) {
  var wort = parseFloat(field_wort.value);
  var temp = parseFloat(field_temp.value);  
  var calibTemp = parseFloat(field_calib_temp.value);
  var result = densityAtX(wort, temp, calibTemp);

  var destEl = document.getElementById(id_result);
  destEl.innerHTML = Round(result);

//  var wort_sg = Plato2SG(parseFloat(field_wort.value));
//  var temp_far = Cel2Far(parseFloat(field_temp.value));
//  var t_far = Cel2Far(20.0);
//  var result = wort_sg * SG60(temp_far) / SG60(t_far);
//  var destEl = document.getElementById(id_result);
//  destEl.innerHTML = Round(SG2Plato(result));
}

function calc_hop(field_alpha, field_utilization, field_ibu, 
                  field_liq_quantum, id_hop_quantum, id_total_hop) {
  var alpha = parseFloat(field_alpha.value);
  var utilization = parseFloat(field_utilization.value);
  var ibu = parseFloat(field_ibu.value);
  var liq_quantum = parseFloat(field_liq_quantum.value);
  var destEl = document.getElementById(id_hop_quantum);

  destEl.innerHTML = Round((10 * ibu) / (alpha * utilization));

  destEl = document.getElementById(id_total_hop);
  destEl.innerHTML = Round((10 * ibu) / (alpha * utilization) * liq_quantum);
}

function calc_hop_alt(field_alpha_rec, field_weight_rec, field_alpha_alt, id_weight_alt) {
  var alphaAlt = parseFloat(field_alpha_rec.value) * parseFloat(field_weight_rec.value) / parseFloat(field_alpha_alt.value);

  destEl = document.getElementById(id_weight_alt);
  destEl.innerHTML = Round(alphaAlt);
}


function calc_volume(field_diameter, field_height, id_result) {
  var height = parseFloat(field_height.value);
  var radius = parseFloat(field_diameter.value) / 2.0;
  var destEl = document.getElementById(id_result);
  destEl.innerHTML = Round(Math.PI * radius * radius * height / 1000.0);
}

function calc_alcohol(field_wort, field_rem_wort, id_result) {
  var wort = parseFloat(field_wort.value);
  var remaining_wort = parseFloat(field_rem_wort.value);

  var fermSuggar = 0.81 * (wort - remaining_wort);
  var alcWeight = fermSuggar * 0.5;
  var alcVol = alcWeight / 0.795;
 
  var destEl = document.getElementById(id_result);
  destEl.innerHTML = Round(alcVol);  
}

function calc_alcohol_old(field_wort, field_rem_wort, id_result) {
  var wort = parseFloat(field_wort.value);
  var remaining_wort = parseFloat(field_rem_wort.value);

  var density  = 261.1 / (261.56 - remaining_wort);
  var dprocalc = 81.92 * (wort - remaining_wort) / (206.65 -1.0665 * wort)
  var wprocalc = density = dprocalc / 0.794;
 
  var destEl = document.getElementById(id_result);
  destEl.innerHTML = Round(wprocalc);  
}

function calc_pressure(field_co2, field_temp, id_result) {
  var co2 = parseFloat(field_co2.value) / 10.0;
  var temp = parseFloat(field_temp.value);

  var p = (co2 / Math.pow(Math.E, -10.73797 + (2617.25 / (temp + 273.15)))) - 1.013;
  var destEl = document.getElementById(id_result);
  destEl.innerHTML = Round(p);  	
}

function calc_pressure_inv(field_pressure, field_temp, id_result) {
  var temp = parseFloat(field_temp.value);
  var presure = parseFloat(field_pressure.value);

  var co2 = (pressure + 1.013) * Math.pow(Math.E, -10.73797 + (2617.25 / (temp + 273.15)));
  var destEl = document.getElementById(id_result);
  destEl.innerHTML = Round(co2);
}

function calc_mix(field_given_vol, field_given_temp, field_sup_temp, 
                  field_dest_temp, id_result) {
  var given_vol = parseFloat(field_given_vol.value);
  var given_temp = parseFloat(field_given_temp.value);
  var sup_temp = parseFloat(field_sup_temp.value);
  var dest_temp = parseFloat(field_dest_temp.value);

  var x = (-given_vol + (given_vol * given_temp) / dest_temp) / (1 - (sup_temp / dest_temp));
  var destEl = document.getElementById(id_result);
  destEl.innerHTML = Round(x);  	  
}

function calc_fermratio(field_wort, field_rest, id_res_real, id_res_apparent) {
  var wort = parseFloat(field_wort.value);
  var rest = parseFloat(field_rest.value);

  var destEl1 = document.getElementById(id_res_real);
  var destEl2 = document.getElementById(id_res_apparent);
  destEl1.innerHTML = Round(81 * (1 - (rest / wort)));
  destEl2.innerHTML = Round(100 * (1 - (rest / wort)));
}

function calc_carbozuck(field_temperature, field_carbwish, field_whichSuggar, field_wort, field_rest, 
	id_res_wort, id_res_suggar) {
  var temperature = parseFloat(field_temperature.value);
  var carbwish = parseFloat(field_carbwish.value);
  var wort = parseFloat(field_wort.value);
  var rest = parseFloat(field_rest.value);

  var co2_0pressure = 10.13 * Math.pow(Math.E, -10.73797 + (2617.25 / (temperature + 273.15)));
  var co2_difference = carbwish - co2_0pressure;

  // calc wort (g/l)
  var wortsuggar = wort * 8.1 * (1 - (rest / wort))

  // calc suggar (1g suggar -> ca. 0.5g CO2)
  var puresuggar = co2_difference;
  if (field_whichSuggar[2].checked) {
    puresuggar = puresuggar / 0.44;
  } else if (field_whichSuggar[1].checked) {
    puresuggar = puresuggar / 0.51;
  } else {
    puresuggar = puresuggar / 0.50;
  }

  var destEl = document.getElementById(id_res_wort);
  destEl.innerHTML = Round(1000 * puresuggar / wortsuggar);  	  
  destEl = document.getElementById(id_res_suggar);
  destEl.innerHTML = Round(puresuggar);
}

//function calc_carbozuck(field_carbtemp, field_carbwish, field_carbspst, field_carbspen, id_carbozuck, id_carbospeis) {
//  var temp = parseFloat(field_carbtemp.value);
//  var carbwish = parseFloat(field_carbwish.value);
//  var co2 = 10.13 * Math.pow(Math.E, -10.73797 + (2617.25 / (temp + 273.15)));
//  var speis = parseFloat(field_carbspst.value)-parseFloat(field_carbspen.value);
//  var benzuck = 2 * (carbwish - co2);
//  var benspeis = benzuck / speis * 100;

//  var destEl = document.getElementById(id_carbozuck);
//  destEl.innerHTML = Round (benzuck);
//  var destSp = document.getElementById(id_carbospeis);
//  destSp.innerHTML = Round (benspeis);
//}

function calc_alkalinity(field_ca, field_mg, field_ac, field_dest_ra, field_water, id_alkalinity, id_alkalinity_cbh, id_alkalinity_cah, id_alkalinity_mgh, id_alkalinity_acid) {
  var ca = parseFloat(field_ca.value);
  var mg = parseFloat(field_mg.value);
  var ac = parseFloat(field_ac.value);
  var water_vol = parseFloat(field_water.value);
  var dest_ra = parseFloat(field_dest_ra.value);

  // convert to °dH
  var ca_dh = (ca / 40.8) / 0.1783;
  var mg_dh = (mg / 24.3) / 0.1783;
  var ac_dh = ac * 2.8;

  var alkalinity = ac_dh - ((ca_dh + 0.5*mg_dh) / 3.5);

  var acid2add = ((alkalinity - dest_ra) * water_vol) / 30;

  var destEl = document.getElementById(id_alkalinity_cbh);
  destEl.innerHTML = Round(ac_dh);
  destEl = document.getElementById(id_alkalinity_cah);
  destEl.innerHTML = Round(ca_dh);
  destEl = document.getElementById(id_alkalinity_mgh);
  destEl.innerHTML = Round(mg_dh);
  destEl = document.getElementById(id_alkalinity);
  destEl.innerHTML = Round(alkalinity);
  destEl = document.getElementById(id_alkalinity_acid);
  destEl.innerHTML = Round(acid2add);
}

function convertMass2Mix(field_wort, field_volume, field_mass, field_tempFactor, id_mixed, id_yield) {
  var wort = parseFloat(field_wort.value);
  var volume = parseFloat(field_volume.value);
  var mass = parseFloat(field_mass.value);
  var tempFactor = 1.0;
  if (field_tempFactor[0].checked) {
    tempFactor = 0.96;
  }
  var mixed = densityAtBaseTemp(20, wort) * wort;

  destEl = document.getElementById(id_mixed);
  destEl.innerHTML = Round(mixed);
  destEl = document.getElementById(id_yield);
  destEl.innerHTML = Round(tempFactor * mixed * volume / mass);
}

function calcWortVolume(field_vol, field_wort, field_temp1, field_temp2, id_destvol) {
  var vol1 = parseFloat(field_vol.value);
  var wort = parseFloat(field_wort.value);
  var sourceTemp = parseFloat(field_temp1.value);
  var destTemp = parseFloat(field_temp2.value);

  

  var destEl = document.getElementById(id_destvol);
  destEl.innerHTML = Round(2);
}

