# HG changeset patch # User Michiel Broek # Date 1537542641 -7200 # Node ID ad28e09e3abd3e2d64538b4bd77c40b9125fcd70 # Parent 83ccc36df6755c40c9cf16c4093f6f29fb8891ca Added Tinseth IBU calculation. diff -r 83ccc36df675 -r ad28e09e3abd www/import/from_brouwhulp.php --- a/www/import/from_brouwhulp.php Thu Sep 20 17:50:30 2018 +0200 +++ b/www/import/from_brouwhulp.php Fri Sep 21 17:10:41 2018 +0200 @@ -601,6 +601,8 @@ $hops .= ',"h_useat":"' . mysqli_real_escape_string($db, $hop->USE) . '"'; if ($hop->TIME) $hops .= ',"h_time":' . floatval($hop->TIME); + else + $hops .= ',"h_time":0'; $hops .= ',"h_alpha":' . floatval($hop->ALPHA); $hops .= ',"h_beta":' . floatval($hop->BETA); $hops .= ',"h_hsi":' . floatval($hop->HSI); diff -r 83ccc36df675 -r ad28e09e3abd www/js/global.js --- a/www/js/global.js Thu Sep 20 17:50:30 2018 +0200 +++ b/www/js/global.js Fri Sep 21 17:10:41 2018 +0200 @@ -90,3 +90,74 @@ $("#jqxWidget").css('visibility', 'visible'); }); + + +/* + * Berekeningen uit https://www.hobbybrouwen.nl/forum/index.php/topic,6079.msg69464.html#msg69464 + */ +function toIBU_Tinseth(Use, Form, SG, Volume, Amount, Boiltime, Alpha) { + var gravity = parseFloat(SG); + var liters = parseFloat(Volume); + var alpha = parseFloat(Alpha)/100; + var mass = parseFloat(Amount) * 1000; + var time = parseFloat(Boiltime); + var fmoment = 1.0; + var pfactor = 1.0; + + if ((Use == "Dry Hop") || (Use == "Dry hop")) { + fmoment = 0.0; + } else if (Use == "Whirlpool") { + fmoment = 0.0; + } else if (Use == "Mash") { + fmoment = 0.7; // Brouwhulp + } else if ((Use == "First Wort") || (Use == "First wort")) { + fmoment = 1.1; // Brouwhulp, Louis, Ozzie + } else if (Use == "Aroma") { + fmoment = 0.0; + } + + if (Form == "Pellet") { + pfactor = 1.1; + } + + // TODO: sg = (postBoilGravity - 1.0) * batchSize / boilSize; + + /* + * http://realbeer.com/hops/research.html + * + * decimal AA rating * grams hops * 1000 + * mg/l of added alpha acids = ------------------------------------- + * volume of finished beer in liters + * + * Bigness factor = 1.65 * 0.000125^(wort gravity - 1) + * + * 1 - e^(-0.04 * time in mins) + * Boil Time factor = ---------------------------- + * 4.15 + * + * decimal alpha acid utilization = Bigness factor * Boil Time factor + * + * IBUs = decimal alpha acid utilization * mg/l of added alpha acids + */ + var AddedAlphaAcids = (alpha * mass * 1000) / liters; + var Bigness_factor = 1.65 * Math.pow( 0.000125, gravity - 1); + var BoilTime_factor = ((1 - Math.exp(-0.04 * time)) / 4.15); // Glen Tinseth + var utiisation = Bigness_factor * BoilTime_factor; + + console.log(" AddedAlphaAcids:"+AddedAlphaAcids+" Bigness_factor:"+Bigness_factor+" BoilTime_factor:"+BoilTime_factor+" utilisation:"+utiisation); + console.log(" fmoment:"+fmoment+" pfactor:"+pfactor); + + var ibu = (Math.round(utiisation * AddedAlphaAcids * fmoment * pfactor * 10) / 10.0); + return ibu; +} + + + +function toIBU(Use, Form, SG, Volume, Amount, Boiltime, Alpha, Method) { + + console.log("toIBU_Tinseth("+Use+"," + Form + "," + SG + "," + Volume + "," + Amount + "," + Boiltime + "," + Alpha + "," + Method + ")"); + return toIBU_Tinseth(Use, Form, SG, Volume, Amount, Boiltime, Alpha); +} + + + diff -r 83ccc36df675 -r ad28e09e3abd www/js/recipes.js --- a/www/js/recipes.js Thu Sep 20 17:50:30 2018 +0200 +++ b/www/js/recipes.js Fri Sep 21 17:10:41 2018 +0200 @@ -314,6 +314,7 @@ var hopSource = { localdata: data.hops, datatype: "local", + cache: false, datafields: [ { name: 'h_name', type: 'string' }, { name: 'h_origin', type: 'string' }, @@ -430,9 +431,9 @@ }, columns: [ { text: 'Hop', editable: false, datafield: 'h_name' }, - { text: 'Type', editable: false, width: 100, datafield: 'h_type' }, + { text: 'Type', editable: false, width: 90, align: 'center', cellsalign: 'center', datafield: 'h_type' }, + { text: 'Vorm', editable: false, width: 90, align: 'center', cellsalign: 'center', datafield: 'h_form' }, { text: 'Alpha', datafield: 'h_alpha', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' }, - { text: 'Beta', datafield: 'h_beta', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' }, { text: 'Gewicht', datafield: 'h_amount', width: 110, align: 'right', cellsalign: 'right', cellsformat: 'f3', columntype: 'numberinput', validation: function (cell, value) { @@ -442,13 +443,28 @@ return true; } }, - { text: 'Tijd', datafield: 'h_time', width: 110, align: 'right', cellsalign: 'right', cellsformat: 'f0', + { text: 'Gebruik', width: 110, align: 'center', cellsalign: 'center', datafield: 'h_useat' }, + { text: 'Tijd', datafield: 'h_time', width: 70, align: 'right', cellsalign: 'right', cellsformat: 'f0', columntype: 'numberinput', validation: function (cell, value) { if (value < 0 || value > 100000000000 ) { return { result: false, message: "De tijd moet 0-~ zijn" }; } return true; + } // TODO: Only enable editing if Boil, else use fixed values. + }, + { text: 'IBU', editable: false, datafield: 'ibu', width: 80, align: 'right', + cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) { + var ibu = toIBU(rowdata.h_useat, + rowdata.h_form, + parseFloat($("#est_og").jqxNumberInput('decimal')), + parseFloat($("#batch_size").jqxNumberInput('decimal')), + parseFloat(rowdata.h_amount), + parseFloat(rowdata.h_time), + parseFloat(rowdata.h_alpha), + $("#ibu_method").val() + ); + return "
" + dataAdapter.formatNumber(ibu, "f1") + "
"; } } ] @@ -788,7 +804,7 @@ mash_ph: parseFloat($("#mash_ph").jqxNumberInput('decimal')), mash_sparge_temp: parseFloat($("#mash_sparge_temp").jqxNumberInput('decimal')), fermentables: fermentablerow, - hops: hopwor, + hops: hoprow, waters: waterrow }; $('#jqxgrid').jqxGrid('updaterow', rowID, row);