# HG changeset patch # User Michiel Broek # Date 1546263668 -3600 # Node ID 6428dae0605d2770b2ea509e6f7add6d1c4cd136 # Parent 3b9e4dfb0476bd9594d17ba3bb55077b93cb4b2d Backport water treatment to the product editor (inluding the bugs). diff -r 3b9e4dfb0476 -r 6428dae0605d www/includes/db_product.php --- a/www/includes/db_product.php Sun Dec 30 22:01:27 2018 +0100 +++ b/www/includes/db_product.php Mon Dec 31 14:41:08 2018 +0100 @@ -203,12 +203,13 @@ $sql .= "', sparge_temp='" . $_POST['sparge_temp']; $sql .= "', sparge_ph='" . $_POST['sparge_ph']; $sql .= "', sparge_volume='" . $_POST['sparge_volume']; -// $sql .= "', sparge_acid_type='" . $_POST['sparge_acid_type']; -// $sql .= "', sparge_acid_perc='" . $_POST['sparge_acid_perc']; -// $sql .= "', sparge_acid_amount='" . $_POST['sparge_acid_amount']; + $sql .= "', sparge_source='" . $_POST['sparge_source']; + $sql .= "', sparge_acid_type='" . $_POST['sparge_acid_type']; + $sql .= "', sparge_acid_perc='" . $_POST['sparge_acid_perc']; + $sql .= "', sparge_acid_amount='" . $_POST['sparge_acid_amount']; $sql .= "', mash_ph='" . $_POST['mash_ph']; $sql .= "', mash_name='" . $_POST['mash_name']; - $sql .= "', calc_acid='" . $_POST['calc_acid']; + ($_POST['calc_acid'] == 'true') ? $sql .= "', calc_acid='1" : $sql .= "', calc_acid='0"; if (isset($_POST['w1_name'])) { $sql .= "', w1_name='" . mysqli_real_escape_string($connect, $_POST['w1_name']); $sql .= "', w1_amount='" . $_POST['w1_amount']; @@ -297,21 +298,18 @@ $sql .= "' WHERE record='" . $_POST['record'] . "';"; } - -// $result = mysqli_query($connect, $sql); -// if (! $result) { - // syslog(LOG_NOTICE, "db_product: result: ".mysqli_error($connect)); - // echo $result; - // return; -// } else { -// if (isset($_POST['update'])) { -// syslog(LOG_NOTICE, "db_product: updated record ".$_POST['record']); -// } else { -// $lastid = mysqli_insert_id($connect); -// syslog(LOG_NOTICE, "db_product: inserted record ".$lastid); -// } -// } -// echo $result; + $result = mysqli_query($connect, $sql); + if (! $result) { + syslog(LOG_NOTICE, "db_product: result: ".mysqli_error($connect)); + } else { + if (isset($_POST['update'])) { + syslog(LOG_NOTICE, "db_product: updated record ".$_POST['record']); + } else { + $lastid = mysqli_insert_id($connect); + syslog(LOG_NOTICE, "db_product: inserted record ".$lastid); + } + } + echo $result; } else if (isset($_POST['delete'])) { /* @@ -494,7 +492,8 @@ $brew .= '","sparge_temp":' . floatval($row['sparge_temp']); $brew .= ',"sparge_ph":' . floatval($row['sparge_ph']); $brew .= ',"sparge_volume":' . floatval($row['sparge_volume']); - $brew .= ',"sparge_acid_type":"' . $row['sparge_acid_type']; + $brew .= ',"sparge_source":"' . $row['sparge_source']; + $brew .= '","sparge_acid_type":"' . $row['sparge_acid_type']; $brew .= '","sparge_acid_perc":' . floatval($row['sparge_acid_perc']); $brew .= ',"sparge_acid_amount":' . floatval($row['sparge_acid_amount']); $brew .= ',"mash_ph":' . $row['mash_ph']; diff -r 3b9e4dfb0476 -r 6428dae0605d www/js/prod_edit.js --- a/www/js/prod_edit.js Sun Dec 30 22:01:27 2018 +0100 +++ b/www/js/prod_edit.js Mon Dec 31 14:41:08 2018 +0100 @@ -305,6 +305,19 @@ $("#brew_mash_efficiency").val(0); }; + function GetBUGU() { + var gu = (dataRecord.est_og - 1) * 1000; + if (gu > 0) + return dataRecord.est_ibu / gu; + else + return 0.5; + } + + function GetOptClSO4ratio() { + var BUGU = GetBUGU(); + return (-1.2 * BUGU + 1.4); + } + function setWaterAgent(name, amount) { console.log("setWaterAgent(" + name + ", " + amount + ")"); var rows = $('#miscGrid').jqxGrid('getrows'); @@ -313,9 +326,7 @@ var row = rows[i]; if (row.m_name == name) { var id = $("#miscGrid").jqxGrid('getrowid', i); - // console.log("name found, erase "+ id); var commit = $("#miscGrid").jqxGrid('deleterow', id); - // console.log("result: "+commit); } } } else { @@ -329,7 +340,6 @@ break; } } - console.log("set something, found: "+found); if (! found) { var miscs = new $.jqx.dataAdapter(miscInvSource, { loadComplete: function () { @@ -368,7 +378,138 @@ return 0; } - // pH calculations + // mg/l as CaCO3 + function ResidualAlkalinity(total_alkalinity, calcium, magnesium) { + return total_alkalinity - (calcium / 1.4 + magnesium / 1.7); + } + + var Ka1 = 0.0000004445; + var Ka2 = 0.0000000000468; + + function PartCO3(pH) { + var H = Math.pow(10, -pH); + return 100 * Ka1 * Ka2 / (H*H + H * Ka1 + Ka1 * Ka2); + } + + function PartHCO3(pH) { + var H = Math.pow(10, -pH); + return 100 * Ka1 * H / (H*H + H * Ka1 + Ka1 * Ka2); + } + + function Charge(pH) { + return (-2 * PartCO3(pH) - PartHCO3(pH)); + } + + //Z alkalinity is the amount of acid (in mEq/l) needed to bring water to the target pH (Z pH) + function ZAlkalinity(pHZ) { + var C43 = Charge(4.3); + var Cw = Charge(parseFloat($("#wg_ph").jqxNumberInput('decimal'))); + var Cz = Charge(pHZ); + var DeltaCNaught = -C43+Cw; + var CT = parseFloat($("#wg_total_alkalinity").jqxNumberInput('decimal')) / 50 / DeltaCNaught; + var DeltaCZ = -Cz+Cw; + return CT * DeltaCZ; + } + + //Z Residual alkalinity is the amount of acid (in mEq/l) needed to bring the water in the mash to the target pH (Z pH) + function ZRA(pHZ) { + + var Calc = parseFloat($("#wg_calcium").jqxNumberInput('decimal')) / (MMCa / 2); + var Magn = parseFloat($("#wg_magnesium").jqxNumberInput('decimal')) / (MMMg / 2); + var Z = ZAlkalinity(pHZ); + return Z - (Calc / 3.5 + Magn / 7); + } + + function ProtonDeficit(pHZ) { + + var Result = ZRA(pHZ) * parseFloat($("#wg_amount").jqxNumberInput('decimal')); + // proton deficit for the grist + var rows = $('#fermentableGrid').jqxGrid('getrows'); + for (var i = 0; i < rows.length; i++) { + var row = rows[i]; + if (row.f_added == 'Mash' && row.f_graintype != 'No malt') { + // Check if acid is required + var 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 { + // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid. + var ebc = row.f_color; + switch (row.f_graintype) { + case 'Base': + case 'Special': + case 'Kilned': C1 = 0.014 * ebc - 34.192; + break; + case 'Crystal': C1 = -0.0597 * ebc - 32.457; + break; + case 'Roast': C1 = 0.0107 * ebc - 54.768; + break; + case 'Sour': C1 = -149; + break; + } + } + x = C1 * (pHZ - row.f_di_ph); // AcidRequired(ZpH) + Result += x * row.f_amount; + } + } + return Result; + } + + function MashpH() { + var n = 0; + var pH = 5.4; + var deltapH = 0.001; + var deltapd = 0.1; + var pd = ProtonDeficit(pH); + while (((pd < -deltapd) || (pd > deltapd)) && (n < 2000)) { + n++; + if (pd < -deltapd) + pH -= deltapH; + else if (pd > deltapd) + pH += deltapH; + pd = ProtonDeficit(pH); + } + console.log("MashpH() n: "+n+" pH: "+pH); + return pH; + } + + function GetAcidSpecs(AT) { + switch(AT) { + case 'Melkzuur': return { + pK1: 3.08, + pK2: 20, + pK3: 20, + MolWt: 90.08, + AcidSG: 1214, + AcidPrc: 0.88 + }; + case 'Zoutzuur': return { + pK1: -10, + pK2: 20, + pK3: 20, + MolWt: 36.46, + AcidSG: 1142, + AcidPrc: 0.28 + }; + case 'Fosforzuur': return { + pK1: 2.12, + pK2: 7.20, + pK3: 12.44, + MolWt: 98.00, + AcidSG: 1170, + AcidPrc: 0.25 + }; + case 'Zwavelzuur': return { + pK1: -10, + pK2: 1.92, + pK3: 20, + MolWt: 98.07, + AcidSG: 1700, + AcidPrc: 0.93 + }; + } + } + function calcWater() { @@ -378,6 +519,7 @@ var magnesium = 0; var sodium = 0; var total_alkalinity = 0; + var bicarbonate = 0; var chloride = 0; var sulfate = 0; var ph = 0; @@ -393,122 +535,316 @@ var AcidPrc = 0; var protonDeficit = 0; - if (dataRecord.w1_name != "") { - if (dataRecord.w2_name != "") { - liters = dataRecord.w1_amount + dataRecord.w2_amount; - calcium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_calcium, dataRecord.w2_calcium); - magnesium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_magnesium, dataRecord.w2_magnesium); - sodium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sodium, dataRecord.w2_sodium); - chloride = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_chloride, dataRecord.w2_chloride); - sulfate = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sulfate, dataRecord.w2_sulfate); - total_alkalinity = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_total_alkalinity, dataRecord.w2_total_alkalinity); - ph = -Math.log10(((Math.pow(10, -dataRecord.w1_ph) * dataRecord.w1_amount) + (Math.pow(10, -dataRecord.w2_ph) * dataRecord.w2_amount)) / liters); - } else { - liters = dataRecord.w1_amount; - calcium = dataRecord.w1_calcium; - magnesium = dataRecord.w1_magnesium; - sodium = dataRecord.w1_sodium; - chloride = dataRecord.w1_chloride; - sulfate = dataRecord.w1_sulfate; - total_alkalinity = dataRecord.w1_total_alkalinity; - ph = dataRecord.w1_ph; - } + if (dataRecord.w1_name == "") { + return; + } + + // If there is a dillute water source, mix the waters. + if (dataRecord.w2_name != "") { + liters = dataRecord.w1_amount + dataRecord.w2_amount; + calcium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_calcium, dataRecord.w2_calcium); + magnesium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_magnesium, dataRecord.w2_magnesium); + sodium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sodium, dataRecord.w2_sodium); + chloride = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_chloride, dataRecord.w2_chloride); + sulfate = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sulfate, dataRecord.w2_sulfate); + total_alkalinity = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_total_alkalinity, dataRecord.w2_total_alkalinity); + ph = -Math.log10(((Math.pow(10, -dataRecord.w1_ph) * dataRecord.w1_amount) + (Math.pow(10, -dataRecord.w2_ph) * dataRecord.w2_amount)) / liters); + } else { + liters = dataRecord.w1_amount; + calcium = dataRecord.w1_calcium; + magnesium = dataRecord.w1_magnesium; + sodium = dataRecord.w1_sodium; + chloride = dataRecord.w1_chloride; + sulfate = dataRecord.w1_sulfate; + total_alkalinity = dataRecord.w1_total_alkalinity; + ph = dataRecord.w1_ph; } $('#wg_amount').val(liters); + var wg_calcium = calcium; $('#wg_calcium').val(Math.round(calcium * 10) / 10); + var wg_magnesium = magnesium; $('#wg_magnesium').val(Math.round(magnesium * 10) / 10); + var wg_sodium = sodium; $('#wg_sodium').val(Math.round(sodium * 10) / 10); + var wg_total_alkalinity = total_alkalinity; $('#wg_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10); + var wg_chloride = chloride; $('#wg_chloride').val(Math.round(chloride * 10) / 10); + var 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; $('#wg_ph').val(Math.round(ph * 10) / 10); + $('#wb_ph').val(Math.round(MashpH() * 10) / 10); + bicarbonate = total_alkalinity * 1.22; + var 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 / parseFloat($("#wg_amount").jqxNumberInput('decimal')); + calcium += 1000 * RA / liters; // Calculate Mg RA = parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMMg / MMMgSO4; - magnesium += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal')); + magnesium += 1000 * RA / liters; // Calculate Na RA = parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMNa / MMNaCl + parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMNa / MMNaHCO3; - sodium += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal')); + sodium += 1000 * RA / liters; // Calculate SO4 RA = parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 + parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMSO4 / MMMgSO4; - sulfate += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal')); + 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 / parseFloat($("#wg_amount").jqxNumberInput('decimal')); + chloride += 1000 * RA / liters; // Einde noot. - TpH = parseFloat(dataRecord.mash_ph); - if (TpH < 5.0 || TpH > 6.0) { - TpH = 5.4; - dataRecord.mash_ph = 5.4; - $("#mash_ph").val(5.4); - $("#tgt_mash_ph").val(5.4); + if ($("#wa_acid_name").val() == "") { + $("#wa_acid_name").val('Melkzuur'); + last_acid = 'Melkzuur'; + } + if ($("#wa_base_name").val() == "") { + $("#wa_base_name").val('NaHCO3'); + last_base = 'NaHCO3'; } - var acid_amount = parseFloat($("#wa_acid").jqxNumberInput('decimal')); - var acid_perc = parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')); + + var AT = $("#wa_acid_name").val(); + var BT = $("#wa_base_name").val(); + + var result = GetAcidSpecs(AT); + pK1 = result.pK1; + pK2 = result.pK2; + pK3 = result.pK3; + MolWt = result.MolWt; + AcidSG = result.AcidSG; + AcidPrc = result.AcidPrc; - switch ($("#wa_acid_name").val()) { - case 'Melkzuur': pK1 = 3.08; - pK2 = 20; - pK3 = 20; - MolWt = 90.08; - AcidSG = 1214; //@88% - AcidPrc = 0.88; - //frac = CalcFrac(TpH, pK1, pK2, pK3); - acid += acid_amount * acid_perc / 100 * AcidSG / MolWt * frac / liters; //mEq/l - break; + if (dataRecord.calc_acid) { + 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); + setWaterAgent(last_base, 0); + frac = CalcFrac(TpH, pK1, pK2, pK3); + Acid = protonDeficit / frac; + Acid *= MolWt; // mg + Acidmg = Acid; + Acid = Acid / AcidSG; // ml + + if (parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')) == 0) + $("#wa_acid_perc").val(AcidPrc); + Acid = Acid * AcidPrc / (parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')) / 100); // ml + console.log("Final ml: "+Acid); + $("#wa_acid").val(Math.round(Acid * 100) / 100); + setWaterAgent(AT, Math.round(Acid * 100) / 100); - case 'Zoutzuur': pK1 = -10; - pK2 = 20; - pK3 = 20; - MolWt = 36.46; - AcidSG = 1142; //@28% - AcidPrc = 0.28; - //frac = CalcFrac(TpH, pK1, pK2, pK3); - Acidmg = acid_amount * acid_perc / 100 * AcidSG / liters; - acid += Acidmg / MolWt * frac; //mEq/l - chloride += Acidmg / 1000 * MMCl / (MMCl + 1); - break; + bicarbonate = bicarbonate - protonDeficit * frac / liters; + total_alkalinity = bicarbonate * 50 / 61; + } else if (protonDeficit < 0) { //Add base + $("#wa_acid").val(0); + setWaterAgent(last_acid, 0); + r1d = Math.pow(10, (TpH - 6.38)); + r2d = Math.pow(10, (TpH - 10.38)); + f1d = 1 / (1 + r1d + r1d * r2d); + f2d = f1d * r1d; + f3d = f2d * r2d; + switch (BT) { + case 'NaHCO3': base = -protonDeficit / (f1d - f3d); //mmol totaal + base = base * MMNaHCO3/1000; //gram + $("#wa_base").val(Math.round(base * 100) / 100); + setWaterAgent(BT, Math.round(base * 100) / 100); + if (liters > 0) { + // 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 'Na2CO3': base = -protonDeficit / (2 * f1d + f2d); //mmol totaal + base = base * MMNa2CO3/1000; //gram + $("#wa_base").val(Math.round(base * 100) / 100); + setWaterAgent(BT, Math.round(base * 100) / 100); + if (liters > 0) { + 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 'CaCO3': base = -protonDeficit * (f1d - f3d); //mmol totaal + base = base * MMCaCO3/1000; //gram + //but only 1/3 is effective, so add 3 times as much + base = 3 * base; + $("#wa_base").val(Math.round(base * 100) / 100); + setWaterAgent(BT, Math.round(base * 100) / 100); + if (liters > 0) { + //Bicarbonate + RA = parseFloat($("#wa_base").jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3; + RA = 1000 * RA / 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; + calcium = wg_calcium + RA; + RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); + } + break; + case 'Ca(OH)2': base = -protonDeficit / 19.3; // g + $("#wa_base").val(Math.round(base * 100) / 100); + setWaterAgent(BT, Math.round(base * 100) / 100); + if (liters > 0) { + // Bicarbonate + RA = -protonDeficit / liters; + 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; + calcium = wg_calcium + RA; + RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); + } + break; + } + } + ph = TpH; + $('#wb_ph').val(Math.round(ph * 10) / 10); + } else { // Manual + console.log("calc_acid no"); + // First add base salts + if (parseFloat($("#wa_base").jqxNumberInput('decimal')) > 0) { + if (liters > 0) { + switch (BT) { + case 'NaHCO3': // 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 'Na2CO3': 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 'CaCO3': // 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; + } + } + } - case 'Fosforzuur': pK1 = 2.12; - pK2 = 7.20; - pK3 = 12.44; - MolWt = 98.00; - AcidSG = 1170; //@25% - AcidPrc = 0.25; - //frac = CalcFrac(TpH, pK1, pK2, pK3); - Acidmg = acid_amount * acid_perc / 100 * AcidSG / liters; - acid += Acidmg / MolWt * frac; //mEq/l - 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; - case 'Zwavelzuur': pK1 = -10; - pK2 = 1.92; - pK3 = 20; - MolWt = 98.07; - AcidSG = 1700; //@93% - AcidPrc = 0.93; - //frac = CalcFrac(TpH, pK1, pK2, pK3); - Acidmg = acid_amount * acid_perc / 100 * AcidSG / liters; - acid += Acidmg / MolWt * frac; //mEq/l - sulfate += Acidmg / 1000 * MMSO4 / (MMSO4 + 2); - break; + deltapH = 0.001; + deltapd = 0.1; + pd = ProtonDeficit(pHa); + n = 0; + while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 2000)) { + n++; + if (pd < (protonDeficit-deltapd)) + pHa -= deltapH; + else if (pd > (protonDeficit+deltapd)) + pHa += deltapH; + frac = CalcFrac(pHa, pK1, pK2, 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(Math.round(ph * 10) / 10); + } } - //protonDeficit = ProtonDeficit(TpH); - //console.log("frac: "+frac+" acid: "+acid+" protonDeficit: "+protonDeficit); - //total_alkalinity -= 50 / 61 * protonDeficit * frac / liters; + + if ((AT == 'Zwavelzuur') && (liters > 0)) { + RA = parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 + + parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 + + Acidmg / 1000 * MMSO4 / (MMSO4 + 2); + RA = 1000 * RA / liters; + sulfate = wg_sulfate + RA; // Not add to sulfate?? + } else if ((AT == 'Zoutzuur') && (liters > 0)) { + RA = parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCl / MMCaCl2 + + parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMCl / MMNaCl + + Acidmg / 1000 * MMCl / (MMCL + 1); + RA = 1000 * RA / liters; + chloride = wg_chloride + RA; + } + + // 2:1 Sulfate to Chroride IPA's, Pale Ales. + // 1:1 Sulfate to Chloride Balanced + // 1:2 Sulfate to Chloride Malty + $('#tgt_bu').val(Math.round(GetBUGU() * 100) / 100); + $('#tgt_cl_so4').val(Math.round(GetOptClSO4ratio() * 10) / 10); // Show real value too + if (sulfate > 0) + RA = chloride / sulfate; + else + RA = 10; + var piCLSO4_low = 0.8 * GetOptClSO4ratio(); + var piCLSO4_high = 1.2 * GetOptClSO4ratio(); + console.log("low: "+piCLSO4_low+" val: "+RA+" high: "+piCLSO4_high); $('#wb_calcium').val(Math.round(calcium * 10) / 10); $('#wb_magnesium').val(Math.round(magnesium * 10) / 10); @@ -544,6 +880,105 @@ } else { setRangeIndicator("sulfate", "high"); } + if (ph < 5.2) { + setRangeIndicator("ph", "low"); + } else if (ph > 5.6) { + setRangeIndicator("ph", "high"); + } else { + setRangeIndicator("ph", "normal"); + } + calcSparge(); + } + + function calcSparge() { + + // Code from BrewBuddy/Brouwhulp, who got it from http://www.brewery.org/brewery/library/Acidi0,00fWaterAJD0497.html + 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 == 'Bron 2') { + if (dataRecord.w2_ph > 0.0) { + Source_pH = dataRecord.w2_ph; + Source_alkalinity = dataRecord.w2_total_alkalinity; + } else { + dataRecord.sparge_source = 'Bron 1'; + $("#sparge_source").val('Bron 1'); + } + } else if (dataRecord.sparge_source == 'Gemengd') { + if (dataRecord.w2_ph > 0.0) { + Source_pH = parseFloat($("#wg_ph").jqxNumberInput('decimal')); + Source_alkalinity = parseFloat($("#wg_total_alkalinity").jqxNumberInput('decimal')); + } else { + dataRecord.sparge_source = 'Bron 1'; + $("#sparge_source").val('Bron 1'); + } + } + + console.log("calcSparge() target pH: "+TargetpH+" Source: "+Source_pH+" alkalinity: "+Source_alkalinity); + + // 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.33); + d = 1 + r1 + r1*r2; + f1 = 1/d; + f2 = r1/d; + 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.33); + d43 = 1 + r143 + r143*r243; + f143 = 1/d43; + f243 = r143 / d43; + f343 = r143 * r243 / d43; + + //Step 3. Convert the sample alkalinity to milliequivalents/L + alkalinity = Source_alkalinity / 50; + //Step 4. Solve + alkalinity = alkalinity / ((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.33); + dg = 1 + r1g + r1g*r2g; + f1g = 1/dg; + f2g = r1g / dg; + f3g = r1g * r2g / dg; + + //Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) + Acid = alkalinity * ((f1g-f1)+(f3-f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH); //mEq/l + + if ($("#sparge_acid_type").val() == "") { + $("#sparge_acid_type").val('Melkzuur'); + dataRecord.sparge_acid_type = 'Melkzuur'; + } + AT = dataRecord.sparge_acid_type; + var 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); + + //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 = Math.round(Acid * 100) / 100; + dataRecord.sparge_acid_amount = Acid / 1000; + $("#sparge_acid_amount").val(Acid); } function calcInit () { @@ -552,6 +987,14 @@ calcSGendMash(); calcMashEfficiency(); + $("#calc_acid").on('checked', function (event) { + dataRecord.calc_acid = true; + calcWater(); + }); + $("#calc_acid").on('unchecked', function (event) { + dataRecord.calc_acid = false; + calcWater(); + }); $("#w1_name").jqxDropDownList('selectItem', dataRecord.w1_name); $("#w2_name").jqxDropDownList('selectItem', dataRecord.w2_name); // Fix tap water if zero using mash infuse amount. @@ -664,9 +1107,30 @@ }); $('#mash_ph').on('change', function (event) { dataRecord.mash_ph = parseFloat(event.args.value); - $("#tgt_mash_ph").val(parseFloat(event.args.value)); calcWater(); }); + + $('#sparge_ph').on('change', function (event) { + dataRecord.sparge_ph = parseFloat(event.args.value); + calcSparge(); + }); + $('#sparge_volume').on('change', function (event) { + dataRecord.sparge_volume = parseFloat(event.args.value); + calcSparge(); + }); + $('#sparge_source').on('change', function (event) { + dataRecord.sparge_source= event.args.item.value; + calcSparge(); + }); + $('#sparge_acid_type').on('change', function (event) { + dataRecord.sparge_acid_type = event.args.item.value; + console.log("new sparge_acid_type: "+dataRecord.sparge_acid_type); + calcSparge(); + }); + $('#sparge_acid_perc').on('change', function (event) { + dataRecord.sparge_acid_perc = parseFloat(event.args.value); + calcSparge(); + }); }; $("#styleSelect").jqxDropDownList({ @@ -858,6 +1322,7 @@ $("#st_abv_max").jqxTooltip({ content: 'Het maximum alcohol volume % voor deze bierstijl.'}); $("#st_carb_min").jqxTooltip({ content: 'Het minimum koolzuur volume voor deze bierstijl.'}); $("#st_carb_max").jqxTooltip({ content: 'Het maximum koolzuur volume voor deze bierstijl.'}); + $("#mash_ph").jqxTooltip({ content: 'Maisch pH tussen 5.2 en 5.6. Gebruik 5.2 voor lichte en 5.5 voor donkere bieren.'}); $("#wa_cacl2").jqxTooltip({ content: 'Voor het maken van een ander waterprofiel. Voegt calcium en chloride toe. Voor het verbeteren van zoetere bieren.'}); $("#wa_caso4").jqxTooltip({ content: 'Gips. Voor het maken van een ander waterprofiel. Voegt calcium en sulfaat toe. Voor het verbeteren van bittere bieren.'}); $("#wa_mgso4").jqxTooltip({ content: 'Epsom zout. Voor het maken van een ander waterprofiel. Voegt magnesium en sulfaat toe. Gebruik spaarzaam!'}); @@ -1005,6 +1470,7 @@ { name: 'sparge_temp', type: 'float' }, { name: 'sparge_ph', type: 'float' }, { name: 'sparge_volume', type: 'float' }, + { name: 'sparge_source', type: 'string' }, { name: 'sparge_acid_type', type: 'string' }, { name: 'sparge_acid_perc', type: 'float' }, { name: 'sparge_acid_amount', type: 'float' }, @@ -1152,13 +1618,13 @@ $("#est_carb").val(dataRecord.est_carb); $("#mash_name").val(dataRecord.mash_name); $("#mash_ph").val(dataRecord.mash_ph); - $("#tgt_mash_ph").val(dataRecord.mash_ph); $("#sparge_temp").val(dataRecord.sparge_temp); $("#sparge_ph").val(dataRecord.sparge_ph); $("#sparge_volume").val(dataRecord.sparge_volume); + $("#sparge_source").val(dataRecord.sparge_source); $("#sparge_acid_type").val(dataRecord.sparge_acid_type); $("#sparge_acid_perc").val(dataRecord.sparge_acid_perc); - $("#sparge_acid_amount").val(dataRecord.sparge_acid_amount); + $("#sparge_acid_amount").val(dataRecord.sparge_acid_amount * 1000); $("#calc_acid").val(dataRecord.calc_acid); $("#w1_name").val(dataRecord.w1_name); $("#w1_amount").val(dataRecord.w1_amount); @@ -2310,6 +2776,7 @@ var srcIBU = [ "Tinseth", "Rager", "Daniels" ]; // Only these are supported at this time. var srcBase = [ "NaHCO3", "Na2CO3", "CaCO3", "Ca(OH)2" ]; var srcAcid = [ "Melkzuur", "Zoutzuur", "Fosforzuur", "Zwavelzuur" ]; + var srcSource = [ "Bron 1", "Bron 2", "Gemengd" ]; var srcMaterial= [ "RVS", "Aluminium", "Kunststof", "Koper" ]; var srcAeration= [ 'None', 'Air', 'Oxygen' ]; var srcCooling= [ '-', 'Emersion chiller', 'Counterflow chiller', 'Au bain marie', 'Natural' ]; @@ -2438,8 +2905,6 @@ $("#mash_name").jqxInput({ theme: theme, width: 320, height: 23 }); $("#mash_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 4, max: 8, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 }); - $("#tgt_mash_ph").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, readOnly: true }); - $("#sparge_temp").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 70, max: 98, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.5 }); $("#est_mash_sg").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 70, height: 23, decimalDigits: 3 }); @@ -2582,21 +3047,29 @@ $("#pr_total_alkalinity").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true }); $("#pr_chloride").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true }); $("#pr_sulfate").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true }); - $("#wa_cacl2").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); - $("#wa_caso4").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); - $("#wa_mgso4").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); - $("#wa_nacl").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); + + $("#tgt_bu").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 2, readOnly: true }); + $("#tgt_cl_so4").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true }); + + $("#wa_cacl2").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, max: 1000, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); + $("#wa_caso4").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, max: 1000, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); + $("#wa_mgso4").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, max: 1000, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); + $("#wa_nacl").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, max: 1000, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' }); $("#calc_acid").jqxCheckBox({ theme: theme, width: 120, height: 23 }); - $("#wa_base_name").jqxDropDownList({ theme: theme, source: srcBase, width: 125, height: 23, dropDownHeight: 128 }); + $("#wa_base_name").jqxDropDownList({ theme: theme, source: srcBase, width: 100, height: 23, dropDownHeight: 128 }); $("#wa_base").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 2, spinButtons: true, spinButtonsStep: 0.05, symbol: ' gr', symbolPosition: 'right' }); - $("#wa_acid_name").jqxDropDownList({ theme: theme, source: srcAcid, width: 125, height: 23, dropDownHeight: 128 }) + $("#wa_acid_name").jqxDropDownList({ theme: theme, source: srcAcid, width: 100, height: 23, dropDownHeight: 128 }) $("#wa_acid").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 2, spinButtons: true, spinButtonsStep: 0.05, symbol: ' ml', symbolPosition: 'right' }); $("#wa_acid_perc").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 80, height: 23, min: 0, max: 100, decimalDigits: 0, spinButtons: true, symbol: '%', symbolPosition: 'right' }); + $("#sparge_temp").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 70, max: 98, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.5 }); $("#sparge_volume").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 }); - $("#sparge_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 }); - $("#sparge_acid_amount").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 5, readOnly: true }); + $("#sparge_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 4.5, max: 6.5, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 }); + $("#sparge_source").jqxDropDownList({ theme: theme, source: srcSource, width: 100, height: 23, dropDownHeight: 95 }); + $("#sparge_acid_amount").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 2, readOnly: true, symbol: ' ml', symbolPosition: 'right' }); + $("#sparge_acid_type").jqxDropDownList({ theme: theme, source: srcAcid, width: 100, height: 23, dropDownHeight: 128 }); + $("#sparge_acid_perc").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, spinButtons: true, decimalDigits: 0, symbol: '%', symbolPosition: 'right' }); $('#jqxTabs').jqxTabs({ theme: theme, @@ -2721,9 +3194,10 @@ sparge_temp: parseFloat($("#sparge_temp").jqxNumberInput('decimal')), sparge_ph: parseFloat($("#sparge_ph").jqxNumberInput('decimal')), sparge_volume: parseFloat($("#sparge_volume").jqxNumberInput('decimal')), - // sparge_acid_type: $("#sparge_acid_type").val(), - // sparge_acid_perc: parseFloat($("#sparge_acid_perc").jqxNumberInput('decimal')), - // sparge_acid_amount: parseFloat($("#sparge_acid_amount").jqxNumberInput('decimal')), + sparge_source: $("#sparge_source").val(), + sparge_acid_type: $("#sparge_acid_type").val(), + sparge_acid_perc: parseFloat($("#sparge_acid_perc").jqxNumberInput('decimal')), + sparge_acid_amount: dataRecord.sparge_acid_amount, calc_acid: $("#calc_acid").val(), w1_name: $("#w1_name").val(), w1_amount: parseFloat($("#w1_amount").jqxNumberInput('decimal')), diff -r 3b9e4dfb0476 -r 6428dae0605d www/js/rec_edit.js --- a/www/js/rec_edit.js Sun Dec 30 22:01:27 2018 +0100 +++ b/www/js/rec_edit.js Mon Dec 31 14:41:08 2018 +0100 @@ -2633,7 +2633,7 @@ $("#sparge_temp").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 70, max: 98, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.5 }); $("#sparge_volume").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 }); - $("#sparge_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 }); + $("#sparge_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 4.5, max: 6.5, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 }); $("#sparge_source").jqxDropDownList({ theme: theme, source: srcSource, width: 100, height: 23, dropDownHeight: 95 }); $("#sparge_acid_amount").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 2, readOnly: true, symbol: ' ml', symbolPosition: 'right' }); $("#sparge_acid_type").jqxDropDownList({ theme: theme, source: srcAcid, width: 100, height: 23, dropDownHeight: 128 }); diff -r 3b9e4dfb0476 -r 6428dae0605d www/prod_edit.php --- a/www/prod_edit.php Sun Dec 30 22:01:27 2018 +0100 +++ b/www/prod_edit.php Mon Dec 31 14:41:08 2018 +0100 @@ -270,11 +270,7 @@ - - - - - + @@ -289,11 +285,9 @@
Maischchema:Maish pH:
Spoelwater temp:
Stappen:
- + - - - + @@ -384,38 +378,49 @@ - - - + + + - + + + + + + + + + - - + + - - - + - + + + + + +
Bitterheidsindex:
Richtgetal Cl/SO4:
Doel maisch pH:
Calciumchloride (CaCl2):
Automatisch pH aanpassen:
Maish pH:
Spoelwater volume:
Gips (CaSO4):
pH Automatisch:
Spoelwater temp:
Epsom zout (MgSO4):
Ontzuren met:
Spoelwater bron:
Epsom zout (MgSO4):
Keukenzout (NaCl):
Aanzuren met:
Spoelwater pH:
Keukenzout (NaCl):
Aanzuren met:
Aanzuren hoeveelheid:Percentage:
Hoeveelheid: