www/js/prod_edit.js

changeset 662
4bb005694ce7
parent 660
0e9a725354ac
child 667
1246550451ca
--- a/www/js/prod_edit.js	Sun Apr 26 10:36:38 2020 +0200
+++ b/www/js/prod_edit.js	Fri May 01 11:56:24 2020 +0200
@@ -1064,25 +1064,25 @@
       case 'Melkzuur':
        $('#wa_acid_name').val(0);
        $('#wa_acid').val(row.m_amount * 1000);
-       $('#wa_acid_perc').val(80);
+       $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc);	// TODO: this ignores changed percentages.
        last_acid = 'Melkzuur';
        break;
       case 'Zoutzuur':
        $('#wa_acid_name').val(1);
        $('#wa_acid').val(row.m_amount * 1000);
-       $('#wa_acid_perc').val(80);
+       $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc);
        last_acid = 'Zoutzuur';
        break;
       case 'Fosforzuur':
        $('#wa_acid_name').val(2);
        $('#wa_acid').val(row.m_amount * 1000);
-       $('#wa_acid_perc').val(80);
+       $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc);
        last_acid = 'Fosforzuur';
        break;
       case 'Zwavelzuur':
        $('#wa_acid_name').val(3);
        $('#wa_acid').val(row.m_amount * 1000);
-       $('#wa_acid_perc').val(80);
+       $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc);
        last_acid = 'Zwavelzuur';
        break;
       case 'NaHCO3':
@@ -2794,22 +2794,13 @@
   return Z - (Calc / 3.5 + Magn / 7);
  }
 
- function ProtonDeficit(pHZ) {
-
-  var rows, i, C1, ebc, x, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal'));
-  // proton deficit for the grist
-  if ((rows = $('#fermentableGrid').jqxGrid('getrows'))) {
-   for (i = 0; i < rows.length; i++) {
-    row = rows[i];
-    if (row.f_added == 0 && row.f_graintype != 6) { // Added == Mash && graintype != No Malt
-     // Check if acid is required
-     C1 = 0;
-     if ((row.f_di_ph != 5.7) && ((row.f_acid_to_ph_57 < - 0.1) || (row.f_acid_to_ph_57 > 0.1))) {
-      C1 = row.f_acid_to_ph_57 / (row.f_di_ph - 5.7);
-     } else {
+ function BufferCapacity(di_ph, acid_to_ph_57, ebc, graintype) {
+  C1 = 0;
+  if ((di_ph != 5.7) && ((acid_to_ph_57 < - 0.1) || (acid_to_ph_57 > 0.1))) {
+      C1 = acid_to_ph_57 / (di_ph - 5.7);
+  } else {
       // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid.
-      ebc = row.f_color;
-      switch (row.f_graintype) {
+      switch (graintype) {
        case 0:                                 // Base, Special, Kilned
        case 3:
        case 5: C1 = 0.014 * ebc - 34.192;
@@ -2821,7 +2812,19 @@
        case 4: C1 = -149;                      // Sour malt
                break;
       }
-     }
+  }
+  return C1;
+ }
+
+ function ProtonDeficit(pHZ) {
+
+  var rows, i, C1, x, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal'));
+  // proton deficit for the grist
+  if ((rows = $('#fermentableGrid').jqxGrid('getrows'))) {
+   for (i = 0; i < rows.length; i++) {
+    row = rows[i];
+    if (row.f_added == 0 && row.f_graintype != 6) { // Added == Mash && graintype != No Malt
+     C1 = BufferCapacity(row.f_di_ph, row.f_acid_to_ph_57, row.f_color, row.f_graintype);
      x = C1 * (pHZ - row.f_di_ph);   // AcidRequired(ZpH)
      Result += x * row.f_amount;
     }
@@ -2845,24 +2848,11 @@
     pH += deltapH;
    pd = ProtonDeficit(pH);
   }
-  pH = Round(pH, 2);
+  pH = Round(pH, 6);
   //console.log('MashpH() n: ' + n + ' pH: ' + pH);
   return pH;
  }
 
- function GetAcidSpecs(AT) {
-  switch (AT) {
-   case 0: // Melkzuur
-    return { pK1: 3.86, pK2: 20, pK3: 20, MolWt: 90.08, AcidSG: 1214, AcidPrc: 0.88 };
-   case 1: // Zoutzuur
-    return { pK1: -7, pK2: 20, pK3: 20, MolWt: 36.46, AcidSG: 1142, AcidPrc: 0.28 };
-   case 2: // Fosforzuur
-    return { pK1: 2.12, pK2: 7.20, pK3: 12.44, MolWt: 98.00, AcidSG: 1170, AcidPrc: 0.25 };
-   case 3: // Zwavelzuur
-    return { pK1: -1, pK2: 1.92, pK3: 20, MolWt: 98.07, AcidSG: 1700, AcidPrc: 0.93 };
-  }
- }
-
  function calcWater() {
 
   /* Can be called during loading and building the screens */
@@ -2876,7 +2866,6 @@
   magnesium = 0,
   sodium = 0,
   total_alkalinity = 0,
-  bicarbonate = 0,
   chloride = 0,
   sulfate = 0,
   ph = 0,
@@ -2884,11 +2873,10 @@
   frac = 0,
   TpH = 0,
   protonDeficit = 0,
-  AT, BT, result, pK1, pK2, pK3, MolWt, AcidSG, AcidPrc,
+  AT, BT,
   r1d, r2d, f1d, f2d, f3d,
   deltapH, deltapd, pd, n,
-  Res,
-  wg_calcium, wg_sodium, wg_total_alkalinity, wg_chloride, wg_sulfate, wg_bicarbonate;
+  Res;
 
   if (dataRecord.w1_name == '') {
    return;
@@ -2914,96 +2902,85 @@
    total_alkalinity = dataRecord.w1_total_alkalinity;
    ph = dataRecord.w1_ph;
   }
+  var bicarbonate = total_alkalinity * 1.22;
+
+  /* Save mixed water ions for later */
+  var wg_calcium = calcium;
+  var wg_sodium = sodium;
+  var wg_total_alkalinity = total_alkalinity;
+  var wg_chloride = chloride;
+  var wg_sulfate = sulfate;
+  var wg_bicarbonate = bicarbonate;
+
   $('#wg_amount').val(liters);
-  wg_calcium = calcium;
-  $('#wg_calcium').val(Math.round(calcium * 10) / 10);
-  //var wg_magnesium = magnesium;
-  $('#wg_magnesium').val(Math.round(magnesium * 10) / 10);
-  wg_sodium = sodium;
-  $('#wg_sodium').val(Math.round(sodium * 10) / 10);
-  wg_total_alkalinity = total_alkalinity;
-  $('#wg_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10);
-  wg_chloride = chloride;
-  $('#wg_chloride').val(Math.round(chloride * 10) / 10);
-  wg_sulfate = sulfate;
-  $('#wg_sulfate').val(Math.round(sulfate * 10) / 10);
-  // Note: brouwhulp has the malts included here in the result.
-  //var wg_ph = ph;
-  var mash_ph = Round(MashpH(), 1);
-  $('#wg_ph').val(Round(ph, 1));
-  $('#wb_ph').val(mash_ph);
-  $('#est_mash_ph').val(mash_ph);
-  bicarbonate = total_alkalinity * 1.22;
-  wg_bicarbonate = bicarbonate;
-
-  // Noot: de volgende berekeningen geven bijna gelijke resultaten in Brun'water.
-  // Calculate Ca
-  RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
-       parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4;
-  calcium += 1000 * RA / liters;
-
-  // Calculate Mg
-  RA = parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4;
-  magnesium += 1000 * RA / liters;
-
-  // Calculate Na
-  RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl +
-       parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3;
-  sodium += 1000 * RA / liters;
-
-  // Calculate SO4
-  RA = parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 +
-       parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4;
-  sulfate += 1000 * RA / liters;
-
-  // Calculate Cl
-  RA = 2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 +
-           parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl;
-  chloride += 1000 * RA / liters;
-  // Einde noot.
-
-  if (parseInt($('#wa_acid_name').val()) < 0 || parseInt($('#wa_acid_name').val()) > 3) {
+  $('#wg_calcium').val(Round(calcium, 1));
+  $('#wg_magnesium').val(Round(magnesium, 1));
+  $('#wg_sodium').val(Round(sodium, 1));
+  $('#wg_total_alkalinity').val(Round(total_alkalinity, 1));
+  $('#wg_chloride').val(Round(chloride, 1));
+  $('#wg_sulfate').val(Round(sulfate, 1));
+  $('#wg_ph').val(Round(ph, 2));
+
+  var mash_ph = Round(MashpH(), 3);
+  console.log('Distilled water mash pH: ' + mash_ph);
+
+  /* Calculate Salt additions */
+  if (liters > 0) {
+   calcium += (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 +
+    parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000) / liters;
+   magnesium += (parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000) / liters;
+   sodium += (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 +
+    parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters;
+   sulfate += (parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 +
+    parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / liters;
+   chloride += (2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 +
+    parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000) / liters;
+  }
+
+  if (dataRecord.wa_acid_name < 0 || dataRecord,wa_acid_name >= AcidTypeData.length) {
    $('#wa_acid_name').val(0);
    dataRecord.wa_acid_name = 0;
+   dataRecord.wa_acid_perc = AcidTypeData[0].AcidPrc;
+   $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc);
   }
   if (last_acid == '')
-   last_acid = AcidTypeData[$('#wa_acid_name').val()].nl;
-
-  if (parseInt($('#wa_base_name').val()) < 0 || parseInt($('#wa_base_name').val()) > 3) {
+   last_acid = AcidTypeData[dataRecord.wa_acid_name].nl;
+
+  if (parseFloat(dataRecord.wa_acid_perc) == 0) {
+   dataRecord.wa_acid_perc = AcidTypeData[AT].AcidPrc;
+   $('#wa_acid_perc').val(AcidTypeData[AT].AcidPrc);
+  }
+
+  if (dataRecord.wa_base_name < 0 || dataRecord.wa_base_name > 3) {
    $('#wa_base_name').val(0);
    dataRecord.wa_base_name = 0;
   }
   if (last_base == '')
-   last_base = BaseTypeData[$('#wa_base_name').val()].nl;
+   last_base = BaseTypeData[dataRecord.wa_base_name].nl;
 
   AT = dataRecord.wa_acid_name;
   BT = dataRecord.wa_base_name;
 
-  result = GetAcidSpecs(AT);
-  pK1 = result.pK1;
-  pK2 = result.pK2;
-  pK3 = result.pK3;
-  MolWt = result.MolWt;
-  AcidSG = result.AcidSG;
-  AcidPrc = result.AcidPrc;
+  /* Note that the next calculations do not correct the pH change by the added salts.
+     This pH change is at most 0.1 pH and is a minor difference in Acid amount. */
 
   if (dataRecord.calc_acid) {
+   /* Auto calculate pH */
+   $('.c_mashph').show();
    TpH = parseFloat(dataRecord.mash_ph);
    protonDeficit = ProtonDeficit(TpH);
    //console.log('calc_acid tgt: ' + TpH + ' protonDeficit: ' + protonDeficit);
    if (protonDeficit > 0) { // Add acid
     $('#wa_base').val(0);
+    dataRecord.wa_base = 0;
     setWaterAgent(last_base, 0);
-    frac = CalcFrac(TpH, pK1, pK2, pK3);
+    frac = CalcFrac(TpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
     Acid = protonDeficit / frac;
-    Acid *= MolWt; // mg
+    Acid *= AcidTypeData[AT].MolWt; // mg
     Acidmg = Acid;
-    Acid = Acid / AcidSG; // ml
-
-    if (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) == 0)
-     $('#wa_acid_perc').val(AcidPrc);
-    Acid = Round(Acid * AcidPrc / (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) / 100), 2); // ml
-    //console.log('Final ml: ' + Acid);
+    Acid = Acid / AcidTypeData[AT].AcidSG; // ml
+    Acid = Round(Acid / (parseFloat(dataRecord.wa_acid_perc) / 100), 2); // ml
+    console.log('Mash auto Acid final ml: ' + Acid);
     $('#wa_acid').val(Acid);
     setWaterAgent(AcidTypeData[AT].nl, Acid);
 
@@ -3011,9 +2988,10 @@
     total_alkalinity = bicarbonate * 50 / 61;
    } else if (protonDeficit < 0) { //Add base
     $('#wa_acid').val(0);
+    dataRecord.wa_acid = 0;
     setWaterAgent(last_acid, 0);
-    r1d = Math.pow(10, (TpH - 6.38));
-    r2d = Math.pow(10, (TpH - 10.38));
+    r1d = Math.pow(10, (TpH - 6.35));
+    r2d = Math.pow(10, (TpH - 10.33));
     f1d = 1 / (1 + r1d + r1d * r2d);
     f2d = f1d * r1d;
     f3d = f2d * r2d;
@@ -3025,13 +3003,11 @@
       setWaterAgent('NaHCO3', Round(RA, 2));
       if (liters > 0) {
        // Na
-       RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl +
-            parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3;
-       RA = 1000 * RA / liters;
+       RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 +
+             parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters;
        sodium = wg_sodium + RA;
        // HCO3
-       RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3;
-       RA = 1000 * RA / liters;
+       RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000) / liters;
        bicarbonate = wg_bicarbonate + RA;
        total_alkalinity = bicarbonate * 50 / 61;
        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
@@ -3043,13 +3019,11 @@
       $('#wa_base').val(Round(RA, 2));
       setWaterAgent('Na2CO3', Round(RA, 2));
       if (liters > 0) {
-       RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl +
-            parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3;
-       RA = 1000 * RA / liters;
+       RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000+
+             parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3 * 1000) / liters;
        sodium = wg_sodium + RA;
        // HCO3
-       RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3;
-       RA = 1000 * RA / liters;
+       RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3 * 1000) / liters;
        bicarbonate = wg_bicarbonate + RA;
        total_alkalinity = bicarbonate * 50 / 61;
        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
@@ -3064,15 +3038,13 @@
       setWaterAgent('CaCO3', Round(RA, 2));
       if (liters > 0) {
        //Bicarbonate
-       RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3;
-       RA = 1000 * RA / liters;
+       RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3 * 1000) / liters;
        bicarbonate = wg_bicarbonate + RA;
        total_alkalinity = bicarbonate * 50 / 61;
        //Ca precipitates out as Ca10(PO4)6(OH)2
-       RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
-            parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 +
-            parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaCO3;
-       RA = 1000 * RA / liters;
+       RA = (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 +
+             parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 +
+             parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaCO3 * 1000) / liters;
        calcium = wg_calcium + RA;
        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
       }
@@ -3087,10 +3059,9 @@
        total_alkalinity = wg_total_alkalinity + RA;
        bicarbonate = total_alkalinity * 61 / 50;
        // Calcium
-       RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
-            parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 +
-            parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaOH2;
-       RA = 1000 * RA / liters;
+       RA = (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 +
+             parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 +
+             parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaOH2 * 1000) / liters;
        calcium = wg_calcium + RA;
        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
       }
@@ -3098,98 +3069,86 @@
     }
    }
    ph = TpH;
-   $('#wb_ph').val(Round(ph, 1));
-   $('#est_mash_ph').val(Round(ph, 1));
-  } else { // Manual
+   $('#wb_ph').val(Round(ph, 2));
+   $('#est_mash_ph').val(Round(ph, 2));
+  } else {
+   /* Manual calculate pH */
+   $('.c_mashph').hide();
    console.log('calc_acid no');
-   // First add base salts
-   if (parseFloat($('#wa_base').jqxNumberInput('decimal')) > 0) {
-    if (liters > 0) {
-     switch (BT) {
-      case 0:  // Sodiumbicarbonate, Na
-       RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl +
-            parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3;
-       RA = 1000 * RA / liters;
-       sodium = wg_sodium + RA;
-       // HCO3
-       RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3;
-       RA = 1000 * RA / liters;
-       bicarbonate = wg_bicarbonate + RA;
-       total_alkalinity = bicarbonate * 50 / 61;
-       RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
-       break;
-      case 1: // Sodiumcarbonate
-       RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl +
-            parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3;
-       RA = 1000 * RA / liters;
-       sodium = wg_sodium + RA;
-       // HCO3
-       RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3;
-       RA = 1000 * RA / liters;
-       bicarbonate = wg_bicarbonate + RA;
-       total_alkalinity = bicarbonate * 50 / 61;
-       RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
-       break;
-      case 2: // Calciumcarbonate: Bicarbonate
-       RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3;
-       RA = 1000 * RA / liters;
-       bicarbonate = wg_bicarbonate + RA;
-       total_alkalinity = bicarbonate * 50 / 61;
-       RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
-       // Ca
-       RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
-            parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 +
-            parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaCO3;
-       RA = 1000 * RA / liters;
-       calcium = wg_calcium + RA;
-       break;
-     }
+   if (parseFloat($('#wa_base').jqxNumberInput('decimal')) > 0 && liters > 0) {
+    /* First add the base salts */
+    switch (BT) {
+     case 0:  // Sodiumbicarbonate, Na
+      RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 +
+            parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters;
+      sodium = wg_sodium + RA;
+      // HCO3
+      RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000) / liters;
+      bicarbonate = wg_bicarbonate + RA;
+      total_alkalinity = bicarbonate * 50 / 61;
+      RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
+      break;
+     case 1: // Sodiumcarbonate
+      RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 +
+            parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3 * 1000) / liters;
+      sodium = wg_sodium + RA;
+      // HCO3
+      RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3 * 1000) / liters;
+      bicarbonate = wg_bicarbonate + RA;
+      total_alkalinity = bicarbonate * 50 / 61;
+      RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
+      break;
+     case 2: // Calciumcarbonate: Bicarbonate
+      RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 * 1000 / MMCaCO3) / liters;
+      bicarbonate = wg_bicarbonate + RA;
+      total_alkalinity = bicarbonate * 50 / 61;
+      RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
+      // Ca
+      RA = (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa * 1000 / MMCaCl2 +
+            parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa * 1000 / MMCaSO4 +
+            parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa * 1000/ MMCaCO3) / liters;
+      calcium = wg_calcium + RA;
+      break;
     }
    }
 
-   TpH = parseFloat(dataRecord.mash_ph);
-   pHa = MashpH(); // This one is in demi water, should be in adjusted water???
-   // Then calculate the new pH with added acids
-   if (parseFloat($('#wa_acid').jqxNumberInput('decimal')) > 0) {
-    console.log('TpH: ' + TpH + ' water: ' + pHa);
-    Acid = parseFloat($('#wa_acid').jqxNumberInput('decimal'));
-    if (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) == 0)
-     $('#wa_acid_perc').val(AcidPrc);
-    Acid = Acid / AcidPrc * (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) / 100); // ml
-    Acid *= AcidSG; // ml
-    Acid /= MolWt;  // mg
-    Acidmg = Acid;
-
-    //find the pH where the protondeficit = protondeficit by the acid
-    frac = CalcFrac(pHa, pK1, pK2, pK3);
-    protonDeficit = Acid * frac;
-
-    deltapH = 0.001;
-    deltapd = 0.1;
-    console.log('in calcWater() manual');
-    pd = ProtonDeficit(pHa);
-    n = 0;
-    while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 2000)) {
+   pHa = Round(ph, 3); // Adjusted water pH
+   // Then calculate the new pH with added acids and malts
+   console.log('Mash pH: ' + pHa);
+   Acid  = AcidTypeData[AT].AcidSG * (parseFloat(dataRecord.wa_acid_perc) / 100); // ml
+   Acid *= parseFloat($('#wa_acid').jqxNumberInput('decimal'));
+   Acid /= AcidTypeData[AT].MolWt;  // mg
+   Acidmg = Acid;
+
+   //find the pH where the protondeficit = protondeficit by the acid
+   frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
+   protonDeficit = Round(Acid * frac, 3);
+   //console.log('protonDeficit Acid: ' + protonDeficit + ' frac: ' + frac + ' pH: ' + pHa);
+
+   deltapH = 0.001;
+   deltapd = 0.1;
+   pd = Round(ProtonDeficit(pHa), 6);
+   n = 0;
+   while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 4000)) {
      n++;
      if (pd < (protonDeficit - deltapd))
       pHa -= deltapH;
      else if (pd > (protonDeficit + deltapd))
       pHa += deltapH;
-     frac = CalcFrac(pHa, pK1, pK2, pK3);
+     frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
      protonDeficit = Acid * frac;
      pd = ProtonDeficit(pHa);
-    }
-    console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa);
-    RA = wg_bicarbonate - protonDeficit * frac / liters;
-    bicarbonate = RA;
-    total_alkalinity = RA * 50 / 61;
-    ph = pHa;
-    $('#wb_ph').val(Round(ph, 1));
-    $('#est_mash_ph').val(Round(ph, 1));
    }
+   //console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa);
+   RA = wg_bicarbonate - protonDeficit * frac / liters;
+   bicarbonate = RA;
+   total_alkalinity = RA * 50 / 61;
+   ph = pHa;
+   $('#wb_ph').val(Round(ph, 2));
+   $('#est_mash_ph').val(Round(ph, 2));
   }
 
-  if ((AT == 3) && (liters > 0)) {        // Sulfuctic / Zwavelzuur
+  if ((AT == 3) && (liters > 0)) {        // Sulfuric / Zwavelzuur
    RA = parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 +
         parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 +
         Acidmg / 1000 * MMSO4 / (MMSO4 + 2);
@@ -3304,13 +3263,10 @@
 
  function calcSparge() {
 
-  var TargetpH, Source_pH, Source_alkalinity, r1, r2, d, f1, f3, r143, r243, d43, f143, f343,
-  alkalinity, Ct, r1g, r2g, dg, f1g, f3g, Acid, AT, result, pK1, pK2, pK3, MolWt, AcidSG, AcidPrc, fract;
-
-  // Code from BrewBuddy/Brouwhulp, who got it from http://www.brewery.org/brewery/library/Acidi0,00fWaterAJD0497.html
-  TargetpH = dataRecord.sparge_ph;
-  Source_pH = dataRecord.w1_ph;
-  Source_alkalinity = dataRecord.w1_total_alkalinity;
+  /* Based on the work of ajDeLange. */
+  var TargetpH = dataRecord.sparge_ph;
+  var Source_pH = dataRecord.w1_ph;
+  var Source_alkalinity = dataRecord.w1_total_alkalinity;
   // Select watersource or fallback to the first source.
   if (dataRecord.sparge_source == 1) {    // Source 2
    if (dataRecord.w2_ph > 0.0) {
@@ -3322,73 +3278,62 @@
    }
   } else if (dataRecord.sparge_source == 2) {     // Mixed
    if (dataRecord.w2_ph > 0.0) {
-    Source_pH = parseFloat($('#wg_ph').jqxNumberInput('decimal'));
-    Source_alkalinity = parseFloat($('#wg_total_alkalinity').jqxNumberInput('decimal'));
+    Source_pH = parseFloat(dataRecord.wg_ph);
+    Source_alkalinity = parseFloat(dataRecord.wg_total_alkalinity);
    } else {
     dataRecord.sparge_source = 0;
     $('#sparge_source').val(0);
    }
   }
 
-  // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH
-  r1 = Math.pow(10, Source_pH - 6.38);
-  r2 = Math.pow(10, Source_pH - 10.373);
-  d = 1 + r1 + r1 * r2;
-  f1 = 1 / d;
-  f3 = r1 * r2 / d;
+  // Step 1: Compute the mole fractions of carbonic (f1) and carbonate(f3) at the source water pH
+  var r1 = Math.pow(10, Source_pH - 6.35);
+  var r2 = Math.pow(10, Source_pH - 10.33);
+  var d = 1 + r1 + r1 * r2;
+  var f1 = 1 / d;
+  var f3 = r1 * r2 / d;
 
   //Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity)
-  r143 = Math.pow(10, 4.3 - 6.38);
-  r243 = Math.pow(10, 4.3 - 10.373);
-  d43 = 1 + r143 + r143 * r243;
-  f143 = 1 / d43;
-  f343 = r143 * r243 / d43;
-
-  //Step 3. Convert the water alkalinity to milliequivalents/L
-  alkalinity = Source_alkalinity / 50;
+  var r143 = Math.pow(10, 4.3 - 6.35);
+  var r243 = Math.pow(10, 4.3 - 10.33);
+  var d43 = 1 + r143 + r143 * r243;
+  var f143 = 1 / d43;
+  var f343 = r143 * r243 / d43;
 
   //Step 4. Solve
-  Ct = (alkalinity - 1000 * (Math.pow(10, -4.3) - Math.pow(10, -Source_pH))) / ((f143 - f1) + (f3 - f343));
+  var Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343));
 
   //Step 5. Compute mole fractions at desired pH
-  r1g = Math.pow(10, TargetpH - 6.38);
-  r2g = Math.pow(10, TargetpH - 10.373);
-  dg = 1 + r1g + r1g * r2g;
-  f1g = 1 / dg;
-  f3g = r1g * r2g / dg;
+  var r1g = Math.pow(10, TargetpH - 6.35);
+  var r2g = Math.pow(10, TargetpH - 10.33);
+  var dg = 1 + r1g + r1g * r2g;
+  var f1g = 1 / dg;
+  var f3g = r1g * r2g / dg;
 
   //Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L)
-  Acid = Ct * ((f1g - f1) + (f3 - f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH);  //mEq/l
+  var Acid = Ct * ((f1g - f1) + (f3 - f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH);  //mEq/l
   Acid += 0.01;   // Add acid that would be required for distilled water.
-  if (dataRecord.sparge_acid_type < 0 || dataRecord.sparge_acid_type > 3) {
+
+  //Step 8. Get the acid data.
+  var AT = dataRecord.sparge_acid_type;
+  if (AT < 0 || AT >= AcidTypeData.length) {
+   AT = 0;
    dataRecord.sparge_acid_type = 0;
    $('#sparge_acid_type').val(0);
+   dataRecord.sparge_acid_perc = AcidTypeData[0].AcidPrc;
+   $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc);
   }
-
-  //Step 8. Get the acid data.
-  AT = dataRecord.sparge_acid_type;
-  result = GetAcidSpecs(AT);
-  pK1 = result.pK1;
-  pK2 = result.pK2;
-  pK3 = result.pK3;
-  MolWt = result.MolWt;
-  AcidSG = result.AcidSG;
-  AcidPrc = result.AcidPrc;
-  fract = CalcFrac(TargetpH, pK1, pK2, pK3);
+  var fract = CalcFrac(TargetpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
 
   //Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid.
   Acid /= fract;
 
   //Step 10. Multiply by molecular weight of the acid
-  Acid *= MolWt; //mg
-
-  Acid = Acid / AcidSG; //ml ; 88% lactic solution
-  f1 = dataRecord.sparge_acid_perc;
-  if (f1 <= 0.1)
-   f1 = AcidPrc;
-  Acid = Acid * AcidPrc / (f1 / 100);
-
-  Acid *= dataRecord.sparge_volume; //ml lactic acid total
+  Acid *= AcidTypeData[AT].MolWt; //mg
+
+  //Step 11. Divide by Specific Gravity and Percentage to get the final ml.
+  Acid = Acid / AcidTypeData[AT].AcidSG / (dataRecord.sparge_acid_perc / 100); //ml
+  Acid *= dataRecord.sparge_volume; //ml acid total
   Acid = Round(Acid, 2);
   dataRecord.sparge_acid_amount = Acid / 1000;
   $('#sparge_acid_amount').val(Acid);
@@ -3923,20 +3868,25 @@
   $('#wa_acid_name').on('select', function(event) {
    if (event.args) {
     var index = event.args.index;
-    console.log('wa_acid_name ' + index);
+    console.log('wa_acid_name ' + index + ' last_acid: ' + last_acid);
     setWaterAgent(last_acid, 0);
     last_acid = AcidTypeData[index].nl;
+    dataRecord.wa_acid_name = index;
+    dataRecord.wa_acid_perc = AcidTypeData[index].AcidPrc;
+    $('#wa_acid_perc').val(dataRecord.wa_acid_perc);
+    calcWater();
     setWaterAgent(last_acid, parseFloat($('#wa_acid').jqxNumberInput('decimal')));
-    dataRecord.wa_acid_name = index;
-    calcWater();
    }
   });
   $('#wa_acid').on('change', function(event) {
-   var name = AcidTypeData[$('#wa_acid_name').val()].nl;
+   var name = AcidTypeData[dataRecord.wa_acid_name].nl;
    setWaterAgent(name, parseFloat(event.args.value));
    calcWater();
   });
-  $('#wa_acid_perc').on('change', function(event) { calcWater(); });
+  $('#wa_acid_perc').on('change', function(event) {
+   dataRecord.wa_acid_perc = parseFloat(event.args.value);
+   calcWater();
+  });
 
   $('#color_method').on('select', function(event) {
    dataRecord.color_method = event.args.index;
@@ -4034,6 +3984,8 @@
    if (event.args) {
     dataRecord.sparge_acid_type = event.args.index;
     console.log('new sparge_acid_type: ' + dataRecord.sparge_acid_type);
+    dataRecord.sparge_acid_perc = AcidTypeData[event.args.index].AcidPrc;
+    $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc);
     calcSparge();
    }
   });
@@ -5626,7 +5578,8 @@
    calcWater();
   }
  });
- $('#w1_amount,#w1_calcium,#w1_magnesium,#w1_sodium,#w1_total_alkalinity,#w1_chloride,#w1_sulfate,#w1_ph').jqxNumberInput(Show1wat);
+ $('#w1_amount,#w1_calcium,#w1_magnesium,#w1_sodium,#w1_total_alkalinity,#w1_chloride,#w1_sulfate').jqxNumberInput(Show1wat);
+ $('#w1_ph').jqxNumberInput(Show2wat);
  // Water source 2
  $('#w2_name').jqxDropDownList({
   placeHolder: 'Kies meng water:',
@@ -5668,16 +5621,19 @@
   inputMode: 'simple', spinMode: 'simple', theme: theme, width: 94, height: 23, min: 0, max: 0, decimalDigits: 1,
   spinButtons: true, spinButtonsStep: 0.1, readOnly: true
  });
- $('#w2_calcium,#w2_magnesium,#w2_sodium,#w2_total_alkalinity,#w2_chloride,#w2_sulfate,#w2_ph').jqxNumberInput(Show1wat);
+ $('#w2_calcium,#w2_magnesium,#w2_sodium,#w2_total_alkalinity,#w2_chloride,#w2_sulfate').jqxNumberInput(Show1wat);
+ $('#w2_ph').jqxNumberInput(Show2wat);
  // Water mixed
- $('#wg_amount,#wg_calcium,#wg_magnesium,#wg_sodium,#wg_total_alkalinity,#wg_chloride,#wg_sulfate,#wg_ph').jqxNumberInput(Show1wat);
+ $('#wg_amount,#wg_calcium,#wg_magnesium,#wg_sodium,#wg_total_alkalinity,#wg_chloride,#wg_sulfate').jqxNumberInput(Show1wat);
+ $('#wg_ph').jqxNumberInput(Show2wat);
  // Water treated
  $('#wb_calcium').jqxTooltip({ content: 'De ideale hoeveelheid Calcium is tussen 40 en 150.'});
  $('#wb_magnesium').jqxTooltip({ content: 'De ideale hoeveelheid Magnesium is tusse 10 en 30.'});
  $('#wb_sodium').jqxTooltip({ content: 'De ideale hoeveelheid Natrium is lager dan 150.'});
  $('#wb_chloride').jqxTooltip({ content: 'De ideale hoeveelheid Chloride is tussen 50 en 100.'});
  $('#wb_sulfate').jqxTooltip({ content: 'De ideale hoeveelheid Sulfaat is tussen 50 en 350.'});
- $('#wb_calcium,#wb_magnesium,#wb_sodium,#wb_total_alkalinity,#wb_chloride,#wb_sulfate,#wb_ph').jqxNumberInput(Show1wat);
+ $('#wb_calcium,#wb_magnesium,#wb_sodium,#wb_total_alkalinity,#wb_chloride,#wb_sulfate').jqxNumberInput(Show1wat);
+ $('#wb_ph').jqxNumberInput(Show2wat);
  // Water target profile
  $('#pr_name').jqxDropDownList({
   placeHolder: 'Kies doel profiel:',
@@ -5790,7 +5746,7 @@
  $('#brew_sparge_volume').jqxTooltip({ content: 'Het spoelwater voorraad volume, in te stellen in de Water tab.' });
  $('#brew_date_start,#brew_date_end').jqxDateTimeInput(DateTimeopts);
  $('#brew_date_start,#brew_date_end').on('close', function(event) { calcStage(); });
- $('#est_mash_ph').jqxNumberInput(Show1wat);
+ $('#est_mash_ph').jqxNumberInput(Show2wat);
  $('#brew_mash_ph,#brew_preboil_ph,#brew_aboil_ph').jqxNumberInput(SpinpH);
  $('#brew_mash_sg').on('valueChanged', function() { calcMashEfficiency(); });
  $('#brew_preboil_sg').on('valueChanged', function(event) {

mercurial