diff -r 296caca18161 -r 3d61397fe9cd www/js/prod_edit.js --- a/www/js/prod_edit.js Fri Feb 08 11:30:22 2019 +0100 +++ b/www/js/prod_edit.js Sat Feb 09 15:43:13 2019 +0100 @@ -48,13 +48,15 @@ var to_100 = false; // Fermentables adjust to 100% var preboil_sg = 0; + var aboil_sg = 0; var est_mash_sg = 0; var sugarsm = 0; // Sugars after mash - var sugarsf = 0; // Sugars after boil + var sugarsf = 0; // Sugars after boil in kettle var psugar = 0; // Percentage real sugars var pcara = 0; // Percentage cara/crystal malts var svg = 77; // Default attenuation var mashkg = 0; // Malt in mash weight + var hop_flavour = 0; var hop_aroma = 0; var mash_infuse = 0; @@ -97,17 +99,38 @@ theme: theme }); + /* + * All calculations that depend on changes in the fermentables, + * volumes and equipments. + */ function calcFermentables() { + console.log("calcFermentables()"); - sugarsf = 0; - sugarsm = 0; + sugarsf = 0; // fermentable sugars mash + boil + sugarsm = 0; // fermentable sugars in mash psugar = 0; pcara = 0; mashkg = 0; - var colorw = 0; // Colors working + var vol = 0; // Volume sugars after boil + var addedS = 0; // Added sugars after boil + var addedmass = 0; // Added mass after boil + var mvol = 0; // mash volume + var colort = 0; // Colors srm * vol totals var my_100 = false; - var rows = $('#fermentableGrid').jqxGrid('getrows'); + if ((rows = $('#mashGrid').jqxGrid('getrows'))) { + for (var i = 0; i < rows.length; i++) { + var row = rows[i]; + if (row.step_type == 0) // Infusion + mvol += parseFloat(row.step_infuse_amount); + } + } + + if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) { + return; // grid not yet loaded. + } + + var s = 0; for (var i = 0; i < rows.length; i++) { var row = rows[i]; if (row.f_adjust_to_total_100) @@ -118,12 +141,23 @@ pcara += row.f_percentage; var d = row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100); if (row.f_added == 0) { // Mash + if (mvol > 0) { // Only if mash already known. + mvol += row.f_amount * row.f_moisture / 100; + s += d; + } d = parseFloat(dataRecord.efficiency) / 100 * d; sugarsm += d; mashkg += row.f_amount; } - sugarsf += d; - colorw += row.f_amount * ebc_to_srm(row.f_color) / parseFloat(dataRecord.batch_size) * 8.34436; + if (row.f_added == 0 || row.f_added == 1) // Mash or Boil + sugarsf += d; + if (row.f_added == 2 || row.f_added == 3) { + var x = (row.f_yield / 100) * (1 - row.f_moisture / 100); + addedS += row.f_amount * x; + addedmass += row.f_amount; + vol += (x * sugardensity + (1 - x) * 1) * row.f_amount; + } + colort += row.f_amount * ebc_to_srm(row.f_color); } to_100 = my_100; if (to_100) { @@ -131,93 +165,126 @@ } else { $("#wf_amount").jqxNumberInput({ width: 110, readOnly: false, spinButtons: true }); } - var est_og = estimate_sg(sugarsf, parseFloat(dataRecord.batch_size)); - dataRecord.est_og = est_og; - $('#est_og').val(est_og); - $('#est_og2').val(est_og); - $('#est_og3').val(est_og); + + if (mvol > 0) { + var v = s / sugardensity + mvol; + s = 1000 * s / (v * 10); //deg. Plato + est_mash_sg = Math.round(plato_to_sg(s) * 1000) / 1000; + //console.log("est_mash_sg "+est_mash_sg); + $('#est_mash_sg').val(est_mash_sg); + } + + // Estimate total recipe OG. + dataRecord.est_og = estimate_sg(sugarsf + addedS, parseFloat(dataRecord.batch_size)); + $('#est_og').val(dataRecord.est_og); + $('#est_og2').val(dataRecord.est_og); + + // Estimate SG in kettle after boil + aboil_sg = estimate_sg(sugarsf, parseFloat(dataRecord.batch_size)); + $('#est_og3').val(aboil_sg); + + // Estimate SG in kettle before boil preboil_sg = estimate_sg(sugarsm, parseFloat(dataRecord.boil_size)); $('#est_pre_sg').val(preboil_sg); - var color = kw_to_ebc(dataRecord.color_method, colorw); + + // Recalculate volumes. + var aboil_volume = parseFloat(dataRecord.batch_size); + if (dataRecord.brew_aboil_volume > 0) + aboil_volume = dataRecord.brew_aboil_volume / 1.04; // volume @ 20 degrees + dataRecord.brew_fermenter_volume = aboil_volume - dataRecord.brew_fermenter_tcloss + dataRecord.brew_fermenter_extrawater; + $("#brew_fermenter_volume").val(dataRecord.brew_fermenter_volume); + + // Calculate SG in fermenter + var ogx = dataRecord.brew_aboil_sg; + if (ogx < 1.002) + ogx = aboil_sg; + var top = dataRecord.brew_fermenter_extrawater; + + if (dataRecord.brew_fermenter_volume > 0) { + var sug = sg_to_plato(ogx) * dataRecord.brew_fermenter_volume * ogx / 100; //kg of sugar in + sug += addedS; //kg + console.log("Contents ferm_vol:"+dataRecord.brew_fermenter_volume+" top:"+top+" vol:"+vol+" addedS:"+addedS+" addedmass:"+addedmass); + + if ((dataRecord.brew_fermenter_volume * ogx + addedmass) > 0) { + var pt = 100 * sug / (dataRecord.brew_fermenter_volume * ogx + addedmass + top); + dataRecord.brew_fermenter_sg = Math.round(plato_to_sg(pt) * 1000) / 1000; + $("#brew_fermenter_sg").val(dataRecord.brew_fermenter_sg); + // color + var cw = colort / (aboil_volume + top) * 8.34436; + dataRecord.brew_fermenter_color = kw_to_ebc(dataRecord.color_method, cw); + $("#brew_fermenter_color").val(dataRecord.brew_fermenter_color); + var scolor = ebc_to_color(dataRecord.brew_fermenter_color); + $("#bcolorf").show(); + document.getElementById("bcolorf").style.background= scolor; + console.log("OG in fermenter:"+dataRecord.brew_fermenter_sg+" color:"+dataRecord.brew_fermenter_color); + } + } else { + // Negative volume + dataRecord.brew_fermenter_sg = dataRecord.brew_fermenter_color = 0; + $("#brew_fermenter_sg").val(0); + $("#brew_fermenter_color").val(0); + $("#bcolorf").hide(); + } + + // Color of the wort + var cw = colort / parseFloat(dataRecord.batch_size) * 8.34436; + var color = kw_to_ebc(dataRecord.color_method, cw); dataRecord.est_color = color; $('#est_color').val(color); $('#est_color2').val(color); var scolor = ebc_to_color(color); document.getElementById("bcolor").style.background= scolor; document.getElementById("bcolor2").style.background= scolor; + + // Progress bars pmalts = mashkg / dataRecord.eq_mash_max * 100; -// console.log("mash kg: "+mashkg+" max: "+dataRecord.eq_mash_max+" perc: "+pmalts); + //console.log("mash kg: "+mashkg+" max: "+dataRecord.eq_mash_max+" perc: "+pmalts); $("#perc_malts").jqxProgressBar('val', pmalts); $("#perc_sugars").jqxProgressBar('val', psugar); $("#perc_cara").jqxProgressBar('val', pcara); calcStage(); }; + /* + * Change OG of recipe but keep the water volumes. + */ function calcFermentablesFromOG(OG) { console.log("calcFermentablesFromOG("+OG+")"); - var i, j, sug, d, tot, totmass; - var vol, vol1, vol2, sug2; - var mass1, mass2, efficiency; + var efficiency = parseFloat($("#efficiency").jqxNumberInput('decimal')); + var sug = sg_to_plato(OG) * parseFloat($("#batch_size").jqxNumberInput('decimal')) * OG / 100; //total amount of sugars in kg + var tot = 0; + var rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount; - for (j = 1; j < 15; j++) { - vol = 0; - sug2 = 0; - efficiency = parseFloat(dataRecord.efficiency); - var rows = $('#fermentableGrid').jqxGrid('getrows'); - for (i = 0; i < rows.length; i++) { - var row = rows[i]; - if ((row.f_added == 2) || (row.f_added == 3) || (row.f_added == 4)) { // Fermentation, Lagering or Bottle - var x = (row.f_yield / 100) * (1 - row.f_moisture / 100); - vol += row.f_amount / (x * sugardensity + (1 - x) * 1); - sug2 += row.f_amount * x; - } + for (var i = 0; i < rowscount; i++) { + var row = $("#fermentableGrid").jqxGrid('getrowdata', i); + var d = row.f_percentage / 100 * (row.f_yield / 100) * (1 - row.f_moisture / 100); + if (row.f_added == 0) // Mash + d = efficiency / 100 * d; + tot += d; + } + var totmass = 0; + if (tot) + totmass = sug / tot; + + if (totmass) { + for (i = 0; i < rowscount; i++) { + var row = $("#fermentableGrid").jqxGrid('getrowdata', i); + var amount = row.f_percentage / 100 * totmass; + $("#fermentableGrid").jqxGrid('setcellvalue', i, "f_amount", amount); } - sug = sg_to_plato(OG) * OG / 100; // kg/l - vol1 = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss; - vol2 = vol1 + dataRecord.eq_top_up_water + vol; - sug = sug * vol2; // kg in het gistvat - sug = sug - sug2; // kg voor toevoeging in gistvat - if (vol1 > 0) - sug = sug * dataRecord.batch_size / vol1; //kg in kookketel - sug = sug + sug2; - // sug = sg_to_plato(OG) * parseFloat($("#batch_size").jqxNumberInput('decimal')) * OG / 100; //total amount of sugars in kg - - tot = 0; - d = 0; - for (i = 0; i < rows.length; i++) { - var row = rows[i]; - d = row.f_percentage / 100 * (row.f_yield / 100) * (1 - row.f_moisture / 100); - if (row.f_added == 0) // Mash - d = efficiency / 100 * d; - tot += d; - } - if (tot) - totmass = sug / tot; - else - totmass = 0; - - if (totmass) { - console.log("pass:"+j+" totmass:"+totmass); - for (i = 0; i < rows.length; i++) { - var row = rows[i]; - row.f_amount = row.f_percentage / 100 * totmass; - $("#fermentableGrid").jqxGrid('setcellvalue', i, "f_amount", row.f_percentage / 100 * totmass); - } - } - }; - //CalcWaterBalance; + } }; function calcFG() { - var fg = estimate_fg(psugar, pcara, 0, 0, 0, svg, parseFloat(parseFloat($("#est_og").jqxNumberInput('decimal')))); + var fg = estimate_fg(psugar, pcara, 0, 0, 0, svg, dataRecord.est_og); dataRecord.est_fg = fg; $('#est_fg').val(fg); $('#est_fg2').val(fg); } function calcABV() { - var abv = abvol(parseFloat($("#est_og").jqxNumberInput('decimal')), parseFloat($("#est_fg").jqxNumberInput('decimal'))); + var abv = abvol(dataRecord.est_og, dataRecord.est_fg); $("#est_abv").val(abv); $("#est_abv2").val(abv); }; @@ -292,36 +359,6 @@ } } - function calcSGendMash() { - est_mash_sg = 0; - var mvol = 0; // Mash volume - var s = 0; - var gs = 0; // Grain absorbtion - var rows = $('#mashGrid').jqxGrid('getrows'); - for (var i = 0; i < rows.length; i++) { - var row = rows[i]; - if (row.step_type == 0) // Infusion - mvol += parseFloat(row.step_infuse_amount); - } - if (mvol > 0) { - var rows = $('#fermentableGrid').jqxGrid('getrows'); - for (var i = 0; i < rows.length; i++) { - var row = rows[i]; - if (row.f_added == 0) { // Mash - var d = row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100); - mvol += row.f_amount * row.f_moisture / 100; -// TODO: where do I need this gs += my_grain_absorbtion * row.f_amount; - s += d; - } - } - var v = s / sugardensity + mvol; - s = 1000 * s / (v * 10); //deg. Plato - est_mash_sg = plato_to_sg(s); - } - console.log("calcSGendMash(): " + est_mash_sg); - $('#est_mash_sg').val(est_mash_sg); - }; - function calcMashEfficiency() { // console.log("calcMashEfficiency()"); var c = sg_to_plato(est_mash_sg); @@ -399,7 +436,7 @@ } function setWaterAgent(name, amount) { - console.log("setWaterAgent(" + name + ", " + amount + ")"); + //console.log("setWaterAgent(" + name + ", " + amount + ")"); var rows = $('#miscGrid').jqxGrid('getrows'); if (amount == 0) { for (var i = 0; i < rows.length; i++) { @@ -1236,7 +1273,6 @@ function calcInit () { console.log("calcInit()"); - calcSGendMash(); calcMashEfficiency(); calcEfficiencyBeforeBoil(); calcEfficiencyAfterBoil(); @@ -1388,7 +1424,6 @@ $('#est_og').on('change', function (event) { console.log("est_og change:"+event.args.value); $('#est_og2').val(event.args.value); - $('#est_og3').val(event.args.value); calcFermentablesFromOG(event.args.value); // Adjust fermentables amounts calcFermentables(); // Update the recipe details calcSVG(); @@ -1468,6 +1503,15 @@ calcCarbonation(); }); + $("#brew_fermenter_extrawater").on('change', function (event) { + dataRecord.brew_fermenter_extrawater = parseFloat(event.args.value); + calcFermentables(); + }); + $("#brew_fermenter_tcloss").on('change', function (event) { + dataRecord.brew_fermenter_tcloss = parseFloat(event.args.value); + calcFermentables(); + }); + $("#BLog").jqxButton({ disabled: (dataRecord.log_brew) ? false:true }); $("#FLog").jqxButton({ disabled: (dataRecord.log_fermentation) ? false:true }); }; @@ -1641,11 +1685,13 @@ { name: 'brew_whirlpool2', type: 'float' }, { name: 'brew_fermenter_volume', type: 'float' }, { name: 'brew_fermenter_extrawater', type: 'float' }, + { name: 'brew_fermenter_tcloss', type: 'float' }, { name: 'brew_aeration_time', type: 'float' }, { name: 'brew_aeration_speed', type: 'float' }, { name: 'brew_aeration_type', type: 'int' }, { name: 'brew_fermenter_sg', type: 'float' }, { name: 'brew_fermenter_ibu', type: 'float' }, + { name: 'brew_fermenter_color', type: 'float' }, { name: 'brew_date_end', type: 'string' }, { name: 'og', type: 'float' }, { name: 'fg', type: 'float' }, @@ -1811,6 +1857,9 @@ $("#brew_fermenter_sg").val(dataRecord.brew_fermenter_sg); $("#brew_fermenter_sg2").val(dataRecord.brew_fermenter_sg); $("#brew_fermenter_ibu").val(dataRecord.brew_fermenter_ibu); + $("#brew_fermenter_color").val(dataRecord.brew_fermenter_color); + $("#brew_fermenter_extrawater").val(dataRecord.brew_fermenter_extrawater); + $("#brew_fermenter_tcloss").val(dataRecord.brew_fermenter_tcloss); $("#brew_aboil_ph").val(dataRecord.brew_aboil_ph); $("#brew_aboil_sg").val(dataRecord.brew_aboil_sg); @@ -1821,10 +1870,6 @@ $("#brew_cooling_method").val(dataRecord.brew_cooling_method); $("#brew_cooling_time").val(dataRecord.brew_cooling_time); // Niks - // Header Naar gistvat - $("#brew_fermenter_extrawater").val(dataRecord.brew_fermenter_extrawater); - $("#brew_fermenter_extrasugar").val(dataRecord.brew_fermenter_extrasugar); - $("#brew_fermenter_color").val(dataRecord.brew_fermenter_color); $("#brew_date_end").val(dataRecord.brew_date_end); $("#og").val(dataRecord.og); $("#fg").val(dataRecord.fg); @@ -1890,7 +1935,7 @@ $("#efficiency").val(dataRecord.efficiency); $("#est_og").val(dataRecord.est_og); $("#est_og2").val(dataRecord.est_og); - $("#est_og3").val(dataRecord.est_og); + $("#est_og3").val(0); $("#est_fg").val(dataRecord.est_fg); $("#est_fg2").val(dataRecord.est_fg); $("#est_color").val(dataRecord.est_color); @@ -2873,17 +2918,6 @@ }; // initialize the input fields. -// var srcType = [ "All Grain", "Partial Mash", "Extract" ]; - var srcColor = [ "Morey", "Mosher", "Daniels" ]; - 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 srcSugar = [ "Kristalsuiker", "Glucose/dextrose", "Honing", "Moutextract", "Melasse" ]; - var srcMaterial= [ "RVS", "Aluminium", "Kunststof", "Koper" ]; - var srcAeration= [ 'None', 'Air', 'Oxygen' ]; - var srcCooling= [ '-', 'Emersion chiller', 'Counterflow chiller', 'Au bain marie', 'Natural' ]; - // '-', 'Dompelkoeler', 'Tegenstroomkoeler', 'Au bain marie', 'Laten afkoelen' // Tab 1, Algemeen $("#name").jqxTooltip({ content: 'De naam voor dit product.' }); $("#name").jqxInput({ theme: theme, width: 640, height: 23 }); @@ -3241,6 +3275,13 @@ autoDropDownHeight: true, dropDownVerticalAlignment: 'top' }); + $("#wf_added").on('select', function (event) { + if (event.args) { + var index = event.args.index; + $("#fermentableGrid").jqxGrid('setcellvalue', fermentableRow, 'f_added', index); + calcFermentables(); + } + }); // Tab 4, Hops $("#est_ibu2").jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' }); @@ -3957,19 +3998,19 @@ $("#est_pre_sg").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 70, height: 23, decimalDigits: 3 }); $("#brew_aboil_sg").jqxTooltip({ content: 'Het gemeten SG in de kookketel na het koken.' }); $("#brew_aboil_sg").jqxNumberInput( SGopts ); - $("#brew_aboil_sg").on('valueChanged', function (event) { dataRecord.brew_aboil_sg = event.args.value; calcEfficiencyAfterBoil() }); + $("#brew_aboil_sg").on('valueChanged', function (event) { dataRecord.brew_aboil_sg = event.args.value; calcEfficiencyAfterBoil(); calcFermentables(); }); $("#est_og3").jqxTooltip({ content: 'Het gewenste SG in de kookketel na het koken.' }); $("#est_og3").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 70, height: 23, decimalDigits: 3, readOnly: true }); $("#brew_mash_efficiency").jqxTooltip({ content: 'Het behaalde maisch rendement.' }); $("#brew_mash_efficiency").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 90, height: 23, decimalDigits: 1 }); - $("#brew_preboil_volume").jqxTooltip({ content: 'Het volume van het wort voor het koken.' }); + $("#brew_preboil_volume").jqxTooltip({ content: 'Het gemeten volume van het wort voor het koken.' }); $("#brew_preboil_volume").jqxNumberInput( Spin1dec ); $("#brew_preboil_volume").on('valueChanged', function (event) { dataRecord.brew_preboil_volume = event.args.value; calcEfficiencyBeforeBoil() }); $("#est_pre_vol").jqxTooltip({ content: 'Het berekende volume van het wort voor het koken.' }); $("#est_pre_vol").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 70, height: 23, decimalDigits: 1 }); - $("#brew_aboil_volume").jqxTooltip({ content: 'Het volume van het wort na het koken.' }); + $("#brew_aboil_volume").jqxTooltip({ content: 'Het gemeten volume van het wort na het koken.' }); $("#brew_aboil_volume").jqxNumberInput( Spin1dec ); - $("#brew_aboil_volume").on('valueChanged', function (event) { dataRecord.brew_aboil_volume = event.args.value; calcEfficiencyAfterBoil() }); + $("#brew_aboil_volume").on('valueChanged', function (event) { dataRecord.brew_aboil_volume = event.args.value; calcEfficiencyAfterBoil(); calcFermentables(); }); $("#est_a_vol").jqxTooltip({ content: 'Het gewenste volume na het koken.' }); $("#est_a_vol").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 70, height: 23, decimalDigits: 1 }); $("#brew_preboil_efficiency").jqxTooltip({ content: 'Het berekende rendement voor het koken.' }); @@ -4012,10 +4053,10 @@ $("#brew_aeration_time").jqxNumberInput({ max: 1440 }); $("#brew_aeration_speed").jqxNumberInput( PosInt ); $("#brew_aeration_speed").jqxNumberInput({ max: 1440 }); - $("#brew_fermenter_volume").jqxNumberInput( Spin1dec ); + $("#brew_fermenter_volume").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 90, height: 23, decimalDigits: 1 }); $("#brew_fermenter_extrawater").jqxNumberInput( Spin1dec ); $("#brew_fermenter_sg").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 90, height: 23, decimalDigits: 3 }); - $("#brew_fermenter_extrasugar").jqxNumberInput( Spin1dec ); + $("#brew_fermenter_tcloss").jqxNumberInput( Spin1dec ); $("#brew_fermenter_ibu").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 90, height: 23, decimalDigits: 0 }); $("#brew_fermenter_color").jqxNumberInput({ inputMode: 'simple', readOnly: true, theme: theme, width: 90, height: 23, decimalDigits: 0 }); $("#BLog").jqxButton({ template: "info", width: '150px', theme: theme }); @@ -4239,11 +4280,13 @@ brew_whirlpool2: parseFloat($("#brew_whirlpool2").jqxNumberInput('decimal')), brew_fermenter_volume: parseFloat($("#brew_fermenter_volume").jqxNumberInput('decimal')), brew_fermenter_extrawater: parseFloat($("#brew_fermenter_extrawater").jqxNumberInput('decimal')), + brew_fermenter_tcloss: parseFloat($("#brew_fermenter_tcloss").jqxNumberInput('decimal')), brew_aeration_time: parseFloat($("#brew_aeration_time").jqxNumberInput('decimal')), brew_aeration_speed: parseFloat($("#brew_aeration_speed").jqxNumberInput('decimal')), brew_aeration_type: $("#brew_aeration_type").val(), brew_fermenter_sg: parseFloat($("#brew_fermenter_sg").jqxNumberInput('decimal')), brew_fermenter_ibu: parseFloat($("#brew_fermenter_ibu").jqxNumberInput('decimal')), + brew_fermenter_color: parseFloat($("#brew_fermenter_color").jqxNumberInput('decimal')), brew_date_end: $("#brew_date_end").val(), og: dataRecord.og, fg: parseFloat($("#fg").jqxNumberInput('decimal')),