125 } |
125 } |
126 |
126 |
127 |
127 |
128 |
128 |
129 /* |
129 /* |
|
130 * sugars is the total extract weight of sugars. |
|
131 */ |
|
132 function estimate_og($sugars, $batch_size) { |
|
133 $plato = 100 * $sugars / $batch_size; |
|
134 $sg = plato_to_sg($plato); |
|
135 |
|
136 /* Average loops, HansH 5x. Brouwhulp 20x, about 10x is enough so keep 20. */ |
|
137 for ($i = 0; $i < 20; $i++) { |
|
138 if ($sg > 0) |
|
139 $plato = 100 * $sugars / ($batch_size * $sg); |
|
140 $sg = plato_to_sg($plato); |
|
141 } |
|
142 return $sg; |
|
143 } |
|
144 |
|
145 |
|
146 |
|
147 function estimate_fg($percSugar, $percCara, $WGratio, $TotTme, $Temp, $attenuation, $og) { |
|
148 if ($percSugar > 40) |
|
149 $percSugar = 0; |
|
150 if ($percCara > 50) |
|
151 $percCara = 0; |
|
152 if (($WGratio > 0) && ($TotTme > 0)) { |
|
153 $BD = $WGratio; |
|
154 $BD = max(2, min(5.5, $BD)); |
|
155 $Temp = max(60, min(72, $Temp)); |
|
156 } else { |
|
157 $BD = 3.5; |
|
158 $Temp = 67; |
|
159 $TotTme = 75; |
|
160 } |
|
161 if ($attenuation < 30) |
|
162 $attenuation = 77; |
|
163 |
|
164 $AttBeer = 0.00825 * $attenuation + 0.00817 * $BD - 0.00684 * $Temp + 0.00026 * $TotTme - 0.00356 * $percCara + 0.00553 * $percSugar + 0.547; |
|
165 $fg = 1 + (1 - $AttBeer) * ($og - 1); |
|
166 // echo $percSugar.' '.$percCara.' '.$attenuation.' attn '.$AttBeer.' FG '.$fg.PHP_EOL; |
|
167 return $fg; |
|
168 } |
|
169 |
|
170 |
|
171 |
|
172 /* |
130 |
173 |
131 Brouwhulp data.pas |
174 Brouwhulp data.pas |
132 |
175 |
133 Function THop.FlavourContribution : double; //in % * concentration in g/l |
176 Function THop.FlavourContribution : double; //in % * concentration in g/l |
134 var bt, vol : double; |
177 var bt, vol : double; |
587 (FBoilTime.Value / 60); |
630 (FBoilTime.Value / 60); |
588 end; |
631 end; |
589 |
632 |
590 |
633 |
591 |
634 |
592 procedure TRecipe.CalcOG; |
635 |
593 var |
|
594 i, j, k: integer; |
|
595 v, v2, sg, d, tot, tot2, vol, vol1, vol2, sugF, sug, sug2, p, x: double; |
|
596 mass1, mass2 : double; |
|
597 F: TFermentable; |
|
598 begin |
|
599 for j := 1 to 1 do |
|
600 begin |
|
601 sug:= 0; |
|
602 sugf:= 0; |
|
603 sug2:= 0; |
|
604 tot := 0; |
|
605 tot2:= 0; |
|
606 vol:= 0; |
|
607 FEfficiency.Value := GetEfficiency; |
|
608 for i := 0 to NumFermentables - 1 do |
|
609 begin |
|
610 F := TFermentable(Fermentable[i]); |
|
611 if (F.AddedType = atMash) or (F.AddedType = atBoil) then |
|
612 begin |
|
613 d := F.Amount.Value * (F.Yield.Value / 100) * (1 - F.Moisture.Value / 100); |
|
614 if (F.AddedType = atMash) then |
|
615 d := FEfficiency.Value / 100 * d; |
|
616 sugf := sugf + d; |
|
617 tot := tot + F.Amount.Value; |
|
618 end |
|
619 else |
|
620 begin |
|
621 x:= (F.Yield.Value / 100) * (1 - F.Moisture.Value / 100); |
|
622 sug2:= sug2 + F.Amount.Value * x; |
|
623 tot2:= tot2 + F.Amount.Value; |
|
624 tot := tot + F.Amount.Value; |
|
625 vol:= vol + F.Amount.Value / (x * SugarDensity + (1 - x) * 1); |
|
626 end; |
|
627 end; |
|
628 if tot > 0 then |
|
629 for i := 0 to NumFermentables - 1 do |
|
630 begin |
|
631 F := Fermentable[i]; |
|
632 F.Percentage.Value := 100 * F.Amount.Value / tot; |
|
633 end; |
|
634 |
|
635 if (FEquipment <> NIL) and (FBatchSize.Value > 0) then |
|
636 begin |
|
637 vol1:= FBatchSize.Value - FEquipment.TrubChillerLoss.Value; |
|
638 vol2:= vol1 + FEquipment.TopUpWater.Value + vol; |
|
639 sug:= sugf * vol1 / FBatchSize.Value; //kg |
|
640 sug:= sug + sug2; //kg |
|
641 if vol2 > 0 then |
|
642 sug:= sug / vol2; //kg/l |
|
643 p:= 100 * sug; |
|
644 sg:= PlatoToSG(p); |
|
645 for k:= 1 to 30 do |
|
646 begin |
|
647 if sg > 0 then |
|
648 p := 100 * sug / sg; //deg. Plato |
|
649 sg := PlatoToSG(p); |
|
650 end; |
|
651 FEstOG.Value:= sg; |
|
652 end |
|
653 else if FBatchSize.Value <> 0 then |
|
654 begin |
|
655 p := 100 * sugf / FBatchSize.Value; //deg. Plato |
|
656 sg := PlatoToSG(p); |
|
657 for k:= 1 to 20 do |
|
658 begin |
|
659 if sg > 0 then |
|
660 p := 100 * sugf / (FBatchSize.Value * sg); //deg. Plato |
|
661 sg := PlatoToSG(p); |
|
662 end; |
|
663 FEstOG.Value := sg; |
|
664 end |
|
665 else |
|
666 FEstOG.Value := 1.0; |
|
667 end; |
|
668 |
|
669 CalcWaterBalance; |
|
670 end; |
|
671 |
|
672 |
|
673 |
|
674 procedure TRecipe.EstimateFG; |
|
675 var |
|
676 i: integer; |
|
677 percS, percCara, BD, Att, AttBeer, sg: double; |
|
678 Temp, TotTme: double; |
|
679 Y: TYeast; |
|
680 // Eq: TEquipment; |
|
681 begin |
|
682 percS := GetPercSugar; |
|
683 //if PercS > 40 then PercS:= 0; |
|
684 percCara := GetPercCrystalMalt; |
|
685 if percCara > 50 then PercCara:= 0; |
|
686 if (Mash <> nil) and (Mash.MashStep[0] <> nil) then |
|
687 begin |
|
688 BD := Mash.MashStep[0].WaterToGrainRatio; |
|
689 BD:= Max(2, Min(5.5, BD)); |
|
690 Temp := Mash.AverageTemperature; |
|
691 Temp:= Max(60, Min(72, Temp)); |
|
692 TotTme := Mash.TotalMashTime; |
|
693 TotTme:= Max(20, Min(90, TotTme)); |
|
694 end |
|
695 else |
|
696 begin |
|
697 BD := 3.5; |
|
698 Temp := 67; |
|
699 TotTme := 75; |
|
700 end; |
|
701 Y := Yeast[0]; |
|
702 if Y <> nil then |
|
703 begin |
|
704 Att := Y.Attenuation.Value; |
|
705 if Att < 30 then Att:= 77; |
|
706 end |
|
707 else |
|
708 Att := 77; |
|
709 AttBeer := 0.00825 * Att + 0.00817 * BD - 0.00684 * Temp + 0.00026 * |
|
710 TotTme - 0.00356 * PercCara + 0.00553 * PercS + 0.547; |
|
711 |
|
712 { Eq := nil; |
|
713 if FEquipment <> nil then |
|
714 Eq := TEquipment(Equipments.FindByName(FEquipment.Name.Value)); |
|
715 if Eq <> nil then |
|
716 AttBeer2 := Eq.EstimateFG(Att, BD, Temp, TotTme, PercCara, PercS);} |
|
717 |
|
718 FEstFG.Value := 1 + (1 - AttBeer) * (FEstOG.Value - 1); |
|
719 CalcOGFermenter; |
|
720 if FOGFermenter.Value > 1.001 then |
|
721 begin |
|
722 sg:= FOGFermenter.Value; |
|
723 FEstFG2.Value := 1 + (1 - AttBeer) * (sg - 1); |
|
724 FEstABV.Value := ABVol(FEstOG.Value, FEstFG.Value); |
|
725 end |
|
726 else if FOG.Value > 1.001 then |
|
727 begin |
|
728 sg:= FOG.Value; |
|
729 FEstFG2.Value := 1 + (1 - AttBeer) * (sg - 1); |
|
730 FEstABV.Value := ABVol(FEstOG.Value, FEstFG.Value); |
|
731 end |
|
732 else |
|
733 begin |
|
734 FEstFG2.Value := 1 + (1 - AttBeer) * (FEstOG.Value - 1); |
|
735 FEstABV.Value := ABVol(FEstOG.Value, FEstFG.Value); |
|
736 end; |
|
737 end; |
|
738 |
636 |
739 Procedure TRecipe.CalcCalories; |
637 Procedure TRecipe.CalcCalories; |
740 var sug, alc, org, fig : double; |
638 var sug, alc, org, fig : double; |
741 begin |
639 begin |
742 if FOGFermenter.Value > 1.001 then org:= FOGFermenter.Value |
640 if FOGFermenter.Value > 1.001 then org:= FOGFermenter.Value |