Sat, 10 Apr 2021 14:46:06 +0200
Changed dry-yeast calculation.
--- a/www/getyeastsources.php Fri Apr 09 14:45:18 2021 +0200 +++ b/www/getyeastsources.php Sat Apr 10 14:46:06 2021 +0200 @@ -31,7 +31,11 @@ 'harvest_time' => $row['harvest_time'], 'pitch_temperature' => $row['pitch_temperature'], 'pofpos' => $row['pofpos'], - 'zymocide' => $row['zymocide'] + 'zymocide' => $row['zymocide'], + 'gr_hl_lo' => $row['gr_hl_lo'], + 'sg_lo' => $row['sg_lo'], + 'gr_hl_hi' => $row['gr_hl_hi'], + 'sg_hi' => $row['sg_hi'] ); } header("Content-type: application/json");
--- a/www/includes/db_product.php Fri Apr 09 14:45:18 2021 +0200 +++ b/www/includes/db_product.php Sat Apr 10 14:46:06 2021 +0200 @@ -452,6 +452,10 @@ $yeast .= ',"y_pitch_temperature":' . $item['y_pitch_temperature']; $yeast .= ',"y_pofpos":' . $item['y_pofpos']; $yeast .= ',"y_zymocide":' . $item['y_zymocide']; + $yeast .= ',"y_gr_hl_lo":' . $item['y_gr_hl_lo']; + $yeast .= ',"y_sg_lo":' . $item['y_sg_lo']; + $yeast .= ',"y_gr_hl_hi":' . $item['y_gr_hl_hi']; + $yeast .= ',"y_sg_hi":' . $item['y_sg_hi']; $yeast .= ',"y_cost":' . $item['y_cost'] . '}'; //syslog(LOG_NOTICE, $yeast); $yeasts .= $yeast; @@ -958,7 +962,7 @@ $yeasts[$i]['y_avail'] = 0; // Ingredient not in db if (! isset($yeasts[$i]['y_tolerance'])) $yeasts[$i]['y_tolerance'] = 0; - $sql2 = "SELECT inventory,tolerance,sta1,bacteria,harvest_top,harvest_time,pitch_temperature,pofpos,zymocide "; + $sql2 = "SELECT inventory,tolerance,sta1,bacteria,harvest_top,harvest_time,pitch_temperature,pofpos,zymocide,gr_hl_lo,sg_lo,gr_hl_hi,sg_hi "; $sql2 .= "FROM inventory_yeasts "; $sql2 .= "WHERE name='".str_replace($rescapers, $rreplacements, $yeasts[$i]['y_name'])."' AND"; $sql2 .= " form='".str_replace($rescapers, $rreplacements, $yeasts[$i]['y_form'])."' AND"; @@ -985,6 +989,14 @@ $yeasts[$i]['y_pofpos'] = intval($obj->pofpos); if (! isset($yeasts[$i]['y_zymocide'])) $yeasts[$i]['y_zymocide'] = intval($obj->zymocide); + if (! isset($yeasts[$i]['y_gr_hl_lo'])) + $yeasts[$i]['y_gr_hl_lo'] = intval($obj->gr_hl_lo); + if (! isset($yeasts[$i]['y_sg_lo'])) + $yeasts[$i]['y_sg_lo'] = floatval($obj->sg_lo); + if (! isset($yeasts[$i]['y_gr_hl_hi'])) + $yeasts[$i]['y_gr_hl_hi'] = intval($obj->gr_hl_hi); + if (! isset($yeasts[$i]['y_sg_hi'])) + $yeasts[$i]['y_sg_hi'] = floatval($obj->sg_hi); } else { if (! isset($yeasts[$i]['y_sta1'])) $yeasts[$i]['y_sta1'] = 0;
--- a/www/includes/db_recipes.php Fri Apr 09 14:45:18 2021 +0200 +++ b/www/includes/db_recipes.php Sat Apr 10 14:46:06 2021 +0200 @@ -292,6 +292,10 @@ $yeast .= ',"y_pitch_temperature":' . $item['y_pitch_temperature']; $yeast .= ',"y_pofpos":' . $item['y_pofpos']; $yeast .= ',"y_zymocide":' . $item['y_zymocide']; + $yeast .= ',"y_gr_hl_lo":' . $item['y_gr_hl_lo']; + $yeast .= ',"y_sg_lo":' . $item['y_sg_lo']; + $yeast .= ',"y_gr_hl_hi":' . $item['y_gr_hl_hi']; + $yeast .= ',"y_sg_hi":' . $item['y_sg_hi']; $yeast .= ',"y_cost":' . $item['y_cost'] . '}'; //syslog(LOG_NOTICE, $yeast); $yeasts .= $yeast;
--- a/www/js/global.js Fri Apr 09 14:45:18 2021 +0200 +++ b/www/js/global.js Sat Apr 10 14:46:06 2021 +0200 @@ -678,7 +678,11 @@ { name: 'harvest_time', type: 'int' }, { name: 'pitch_temperature', type: 'float' }, { name: 'pofpos', type: 'int' }, - { name: 'zymocide', type: 'int' } + { name: 'zymocide', type: 'int' }, + { name: 'gr_hl_lo', type: 'int' }, + { name: 'sg_lo', type: 'float' }, + { name: 'gr_hl_hi', type: 'int' }, + { name: 'sg_hi', type: 'float' } ], url: 'getyeastsources.php' },
--- a/www/js/prod_edit.js Fri Apr 09 14:45:18 2021 +0200 +++ b/www/js/prod_edit.js Sat Apr 10 14:46:06 2021 +0200 @@ -1353,6 +1353,10 @@ { name: 'y_pitch_temperature', type: 'float' }, { name: 'y_pofpos', type: 'int' }, { name: 'y_zymocide', type: 'int' }, + { name: 'y_gr_hl_lo', type: 'int' }, + { name: 'y_sg_lo', type: 'float' }, + { name: 'y_gr_hl_hi', type: 'int' }, + { name: 'y_sg_hi', type: 'float' }, { name: 'y_avail', type: 'int' } ], addrow: function(rowid, rowdata, position, commit) { commit(true); }, @@ -1418,6 +1422,10 @@ row['y_pitch_temperature'] = datarecord.pitch_temperature; row['y_pofpos'] = datarecord.pofpos; row['y_zymocide'] = datarecord.zymocide; + row['y_gr_hl_lo'] = datarecord.gr_hl_lo; + row['y_sg_lo'] = datarecord.sg_lo; + row['y_gr_hl_hi'] = datarecord.gr_hl_hi; + row['y_sg_hi'] = datarecord.sg_hi; $('#yeastGrid').jqxGrid('addrow', null, row); } calcViability(); @@ -1628,6 +1636,7 @@ whirlpoolHops(); calcIBUs(); calcMiscs(); + calcViability(); showStarter(); calcYeast(); calcInit(); @@ -1814,7 +1823,7 @@ max = 100; } } else if (row.y_form == 1) { // dry yeast - vpm = 0.997; + vpm = 0.998; max = 100; } else if (row.y_form == 6) { // Dried kveik vpm = 0.92; @@ -2617,6 +2626,7 @@ // Calculate needed cells. var plato, volume, rows, rowscount, row, i, needed, use_cells, sg = dataRecord.brew_fermenter_sg; + if (sg <= 1.0001 && dataRecord.fg > 1.000) sg = dataRecord.fg; else if (sg <= 1.0001) @@ -2641,30 +2651,55 @@ if (rowscount == 0) return; // no yeast in recipe + $('.primary_dry').hide(); + $('.primary_liquid').hide(); + var maybe_starter = 0; var pitchrate = 0.75; // Yeast pitch rate default for (i = 0; i < rowscount; i++) { row = $('#yeastGrid').jqxGrid('getrowdata', i); if (row.y_use == 0) { // primary - // pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/ - // and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ - if (row.y_type == 0) { // lager yeast - pitchrate = 1.5; - if (dataRecord.est_og > 1.060) - pitchrate = 2.0; - } else if (row.y_type == 6) { // Kveik - pitchrate = 0.075; + if (row.y_form == 1) { + // Dry yeast + $('.primary_dry').show(); + console.log('dry yeast: ' + row.y_gr_hl_lo + '@' + row.y_sg_lo + ' ' + row.y_gr_hl_hi + '@' + row.y_sg_hi); + // Build the formule with the yeast parameters. + // Based on https://www.lallemandbrewing.com/en/canada/brewers-corner/brewing-tools/pitching-rate-calculator/ + var og = row.y_sg_lo; + var f1 = row.y_gr_hl_lo / 100; + var f2 = Round(f1 / 5, 6); + // After a lot of try and error, study, the best thing to increase the pitch amount is actually + // use this simple formula by Lallemand. This is about the same as sugar weight increment in the wort. + var multiplier = (sg <= og) ? f1 : (f1 + f2 * (sg - og) / 0.008); + console.log('sg: ' + sg + ' og: ' + og + ' f1: ' + f1 + ' f2: ' + f2 + ' multiplier: ' + multiplier); + // dataRecord.starter_viability + var yeast_grams = Round(volume * multiplier * (100 / dataRecord.starter_viability), 2); + $('#yeast_grams').val(yeast_grams); + var yeast_gr_hl = Round(yeast_grams / (volume * 0.01), 2); + $('#yeast_gr_hl').val(yeast_gr_hl); + console.log('need ' + yeast_grams + ' grams, gr/hl: ' + yeast_gr_hl); +// obj.initgram = Round(obj.volume * multiplier_yeast_needed * (100 / obj.yeastviability), 2); + } else { - pitchrate = 0.75; - if (dataRecord.est_og > 1.060) - pitchrate = 1.0; - } - if (dataRecord.yeast_pitchrate < 0.01) { - dataRecord.yeast_pitchrate = pitchrate; - $('#yeast_pitchrate').val(pitchrate); - } - - if (row.y_form != 1) { // Not dry yeast + // Liquid yeast + $('.primary_liquid').show(); + // pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/ + // and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ + if (row.y_type == 0) { // lager yeast + pitchrate = 1.5; + if (dataRecord.est_og > 1.060) + pitchrate = 2.0; + } else if (row.y_type == 6) { // Kveik + pitchrate = 0.075; + } else { + pitchrate = 0.75; + if (dataRecord.est_og > 1.060) + pitchrate = 1.0; + } + if (dataRecord.yeast_pitchrate < 0.01) { + dataRecord.yeast_pitchrate = pitchrate; + $('#yeast_pitchrate').val(pitchrate); + } maybe_starter = 1; } } @@ -5392,6 +5427,8 @@ // Tab 6, Yeasts $('#est_fg2').jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' }); $('#est_abv2').jqxTooltip({ content: 'Verwacht alcohol volume %. Dit wordt automatisch berekend.' }); + $('#yeast_grams').jqxTooltip({ content: 'De gewenste totale hoeveelheid droge gist voor dit bier.' }); + $('#yeast_gr_hl').jqxTooltip({ content: 'De werkelijke hoeveelheid gist per hectoliter.' }); $('#yeast_cells').jqxTooltip({ content: 'Het aantal miljard beschikbare gistcellen zonder eventuele starter.' }); $('#need_cells').jqxTooltip({ content: 'Het aantal miljard nodige cellen is afhankelijk van het begin SG, biertype en volume.' }); $('#plato_cells').jqxTooltip({ content: 'De berekende pitchrate in miljard cellen per ml per graad Plato.' }); @@ -5402,6 +5439,8 @@ $('#est_fg2').jqxNumberInput({ width: 70 }); $('#est_abv2').jqxNumberInput(Show2dec); $('#est_abv2').jqxNumberInput({ width: 70, symbol: '%', symbolPosition: 'right' }); + $('#yeast_grams').jqxNumberInput(Show1dec); + $('#yeast_gr_hl').jqxNumberInput(Show1dec); $('#yeast_cells,#need_cells').jqxNumberInput(Show1dec); $('#yeast_prod_date').jqxDateTimeInput(Dateopts); $('#yeast_prod_date').on('close', function(event) { @@ -5468,6 +5507,10 @@ y_pitch_temperature: yeastData.y_pitch_temperature, y_pofpos: yeastData.y_pofpos, y_zymocide: yeastData.y_zymocide, + y_gr_hl_lo: yeastData.y_gr_hl_lo, + y_sg_lo: yeastData.y_sg_lo, + y_gr_hl_hi: yeastData.y_gr_hl_hi, + y_sg_hi: yeastData.y_sg_hi, y_avail: yeastData.y_avail }; $('#yeastGrid').jqxGrid('updaterow', rowID, row); @@ -5521,6 +5564,10 @@ yeastData.y_pitch_temperature = datarecord.pitch_temperature; yeastData.y_pofpos = datarecord.pofpos; yeastData.y_zymocide = datarecord.zymocide; + yeastData.y_gr_hl_lo = datarecord.gr_hl_lo; + yeastData.y_sg_lo = datarecord.sg_lo; + yeastData.y_gr_hl_hi = datarecord.gr_hl_hi; + yeastData.y_sg_hi = datarecord.sg_hi; if (yeastData.y_form == 0) { $('#wy_pmpt_amount').html('Pak(ken):'); } else if (yeastData.y_form == 1 || yeastData.y_form == 6) {
--- a/www/prod_edit.php Fri Apr 09 14:45:18 2021 +0200 +++ b/www/prod_edit.php Sat Apr 10 14:46:06 2021 +0200 @@ -322,28 +322,36 @@ <td style="vertical-align: top; float: right; padding: 3px;">Gist conditie %:</td> <td style="padding: 3px;"><div id="starter_viability"></div></td> </tr> - <tr> + <tr class="primary_dry"> + <td style="vertical-align: top; float: right; padding: 3px;">Gist nodig gram:</td> + <td style="padding: 3px;"><div id="yeast_grams"></div></td> + </tr> + <tr class="primary_dry"> + <td style="vertical-align: top; float: right; padding: 3px;">Ent hoeveelheid gr/hl:</td> + <td style="padding: 3px;"><div id="yeast_gr_hl"></div></td> + </tr> + <tr class="primary_liquid"> <td style="vertical-align: top; float: right; padding: 3px;">Gistcellen miljard:</td> <td style="padding: 3px;"><div id="yeast_cells"></div></td> </tr> - <tr> + <tr class="primary_liquid"> <td style="vertical-align: top; float: right; padding: 3px;">Pitch rate:</td> <td style="padding: 3px;"><div style="float: left;" id="yeast_pitchrate"></div><input type="button" id="but_pickpitchrate" value="?" style="margin-left: 10px" /></td> </tr> - <tr> + <tr class="primary_liquid"> <td style="vertical-align: top; float: right; padding: 3px;">Cellen nodig miljard:</td> <td style="padding: 3px;"><div id="need_cells"></div></td> </tr> - <tr> + <tr class="primary_liquid"> <td style="vertical-align: top; float: right; padding: 3px;">Pitch cellen/ml °P:</td> <td style="padding: 3px;"><div id="plato_cells"></div></td> <td style="vertical-align: top; float: right; padding: 3px;">Starter type:</td> <td style="padding: 3px;"><div id="starter_type"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Starter SG:</td> + <td style="vertical-align: top; float: right; padding: 3px;">Starter SG:</td> <td style="padding: 3px;"><div id="starter_sg"></div></td> <td style="vertical-align: top; padding: 3px;"><input type="button" id="starter_try" value="Probeer" /></td> </tr> - <tr><td colspan="7"> </td></tr> + <tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> <tr><td align="center" colspan="7"><div id="yeastGrid"></div></td></tr> </table> </div>