Changed dry-yeast calculation.

Sat, 10 Apr 2021 14:46:06 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 10 Apr 2021 14:46:06 +0200
changeset 726
872a3635e4ef
parent 725
30346e5b9e12
child 727
08f91a68e757

Changed dry-yeast calculation.

www/getyeastsources.php file | annotate | diff | comparison | revisions
www/includes/db_product.php file | annotate | diff | comparison | revisions
www/includes/db_recipes.php file | annotate | diff | comparison | revisions
www/js/global.js file | annotate | diff | comparison | revisions
www/js/prod_edit.js file | annotate | diff | comparison | revisions
www/prod_edit.php file | annotate | diff | comparison | revisions
--- 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 &deg;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">&nbsp;</td></tr>
+       <tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
        <tr><td align="center" colspan="7"><div id="yeastGrid"></div></td></tr>
       </table>
      </div>

mercurial