~scottydelicious666/brewtarget/brewtarget

« back to all changes in this revision

Viewing changes to MashWizard.cpp

  • Committer: Philip Greggory Lee
  • Date: 2009-08-23 16:53:43 UTC
  • Revision ID: git-v1:f8d1a25135bd92f06c46c562293800e4faa42c61
Made a src/ and ui/ directory and moved everything.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * MashWizard.cpp is part of Brewtarget, and is Copyright Philip G. Lee
3
 
 * (rocketman768@gmail.com), 2009.
4
 
 *
5
 
 * Brewtarget is free software: you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation, either version 3 of the License, or
8
 
 * (at your option) any later version.
9
 
 
10
 
 * Brewtarget is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
#include "unit.h"
20
 
#include "MashWizard.h"
21
 
#include "mash.h"
22
 
#include "mashstep.h"
23
 
#include "fermentable.h"
24
 
#include <QMessageBox>
25
 
#include "HeatCalculations.h"
26
 
#include "stringparsing.h"
27
 
#include "brewtarget.h"
28
 
 
29
 
MashWizard::MashWizard(QWidget* parent) : QDialog(parent)
30
 
{
31
 
   setupUi(this);
32
 
   recObs = 0;
33
 
   
34
 
   connect(buttonBox, SIGNAL(accepted()), this, SLOT(wizardry()) );
35
 
   connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()) );
36
 
}
37
 
 
38
 
void MashWizard::setRecipe(Recipe* rec)
39
 
{
40
 
   recObs = rec;
41
 
}
42
 
 
43
 
void MashWizard::show()
44
 
{
45
 
   if( Brewtarget::useEnglishUnits() )
46
 
      label->setText(tr("Mash thickness (qt/lb)"));
47
 
   else
48
 
      label->setText(tr("Mash thickness (L/kg)"));
49
 
   
50
 
   setVisible(true);
51
 
}
52
 
 
53
 
void MashWizard::wizardry()
54
 
{
55
 
   if( recObs == 0 || recObs->getMash() == 0 )
56
 
      return;
57
 
 
58
 
   Mash* mash = recObs->getMash();
59
 
   MashStep* mashStep;
60
 
   int i, j, size;
61
 
   double thickness_LKg;
62
 
   double thickNum;
63
 
   double MC, MCw;
64
 
   double tw, tf, t1;
65
 
   double grainMass = 0.0, massWater = 0.0;
66
 
   double grainDensity = HeatCalculations::rhoGrain_KgL;
67
 
   
68
 
   size = mash->getNumMashSteps();
69
 
   thickNum = Unit::qstringToSI(lineEdit_mashThickness->text());
70
 
   if( Brewtarget::useEnglishUnits() )
71
 
      thickness_LKg = thickNum * 2.086;
72
 
   else
73
 
      thickness_LKg = thickNum;
74
 
 
75
 
   if( thickness_LKg <= 0.0 )
76
 
   {
77
 
      QMessageBox::information(this, tr("Bad thickness"), tr("You must have a positive mash thickness."));
78
 
      return;
79
 
   }
80
 
   // Ensure at least one mash step.
81
 
   if( size == 0 )
82
 
   {
83
 
      QMessageBox::information(this, tr("No steps"), tr("You must have at least one mash step to run the wizard."));
84
 
      return;
85
 
   }
86
 
 
87
 
   mashStep = mash->getMashStep(0);
88
 
   // Ensure first mash step is an infusion.
89
 
   if( mashStep->getType() != "Infusion" )
90
 
   {
91
 
      QMessageBox::information(this, tr("First step"), tr("Your first mash step must be an infusion."));
92
 
      return;
93
 
   }
94
 
 
95
 
   /*
96
 
   for( i = 0; i < recObs->getNumFermentables(); i++ )
97
 
   {
98
 
      Fermentable* ferm = recObs->getFermentable(i);
99
 
      // NOTE: we are assuming it's in the mash because it's recommended.
100
 
      // We are also assuming it's a grain.
101
 
      if( ferm->getRecommendMash() )
102
 
         grainMass += ferm->getAmount_kg();
103
 
   }
104
 
   */
105
 
   
106
 
   grainMass = recObs->getGrainsInMash_kg();
107
 
 
108
 
   // Do first step
109
 
   tf = mashStep->getStepTemp_c();
110
 
   t1 = mash->getGrainTemp_c();
111
 
   massWater = thickness_LKg * grainMass;
112
 
   MCw = HeatCalculations::Cw_calGC * massWater;
113
 
   MC = HeatCalculations::Cgrain_calGC * grainMass;
114
 
   // I am specifically ignoring BeerXML's request to only do this if mash->getEquipAdjust() is set.
115
 
   //if( mash->getEquipAdjust() )
116
 
      tw = MC/MCw * (tf-t1) + (mash->getTunSpecificHeat_calGC()*mash->getTunWeight_kg())/MCw * (tf-mash->getTunTemp_c()) + tf;
117
 
   //else
118
 
   //   tw = MC/MCw * (tf-t1) + tf;
119
 
 
120
 
   // Can't have water above boiling.
121
 
   if( tw > 100 )
122
 
   {
123
 
      QMessageBox::information(this, tr("Mash too thick"), tr("Your mash is too thick for desired temp. at first step."));
124
 
      return;
125
 
   }
126
 
 
127
 
   mashStep->setInfuseAmount_l(massWater);
128
 
   mashStep->setInfuseTemp_c(tw);
129
 
   // End of first step.
130
 
 
131
 
   // Do rest of steps.
132
 
   // Add mass*specific heat constant of equipment to MC.
133
 
   // I am specifically ignoring BeerXML's request to only do this if mash->getEquipAdjust() is set.
134
 
   //if( mash->getEquipAdjust() )
135
 
      MC += mash->getTunSpecificHeat_calGC()*mash->getTunWeight_kg();
136
 
   for( i = 1; i < size; ++i )
137
 
   {
138
 
      mashStep = mash->getMashStep(i);
139
 
 
140
 
      if( mashStep->getType() == "Temperature")
141
 
         continue;
142
 
      else if( mashStep->getType() == "Decoction" )
143
 
      {
144
 
         QMessageBox::warning(this, tr("Decoction"), tr("Haven't tested decoction calculations yet.\nUse at own risk."));
145
 
         double m_w, m_g, m_e, r;
146
 
         double c_w, c_g, c_e;
147
 
 
148
 
         tf = mashStep->getStepTemp_c();
149
 
         t1 = mash->getMashStep(i-1)->getStepTemp_c();
150
 
 
151
 
         m_w = 0; // Total mass of water.
152
 
         for(j = 0; j < i; ++j )
153
 
            m_w += mash->getMashStep(j)->getInfuseAmount_l();
154
 
         m_g = grainMass;
155
 
         m_e = (mash->getEquipAdjust()) ? mash->getTunWeight_kg() : 0;
156
 
 
157
 
         c_w = HeatCalculations::Cw_calGC;
158
 
         c_g = HeatCalculations::Cgrain_calGC;
159
 
         c_e = (mash->getEquipAdjust()) ? mash->getTunSpecificHeat_calGC() : 0;
160
 
 
161
 
         // r is the ratio of water and grain to take out for decoction.
162
 
         r = ((m_w*c_w + m_g*c_g + m_e*c_e)*(tf-t1)) / ((m_w*c_w + m_g*c_g)*(100-tf) + (m_w*c_w + m_g*c_g)*(tf-t1));
163
 
         if( r < 0 || r > 1 )
164
 
         {
165
 
            QMessageBox::critical(this, tr("Decoction error"), tr("Something went wrong in decoction calculation.") );
166
 
            Brewtarget::log(Brewtarget::ERROR, "Decoction: r=" + doubleToString(r));
167
 
            return;
168
 
         }
169
 
 
170
 
         mashStep->setDecoctionAmount_l( r*(m_w + m_g/grainDensity) );
171
 
      }
172
 
      else
173
 
      {
174
 
         tf = mashStep->getStepTemp_c();
175
 
         t1 = mash->getMashStep(i-1)->getStepTemp_c();
176
 
         tw = 100; // Assume adding boiling water to minimize final volume.
177
 
         MC += massWater * HeatCalculations::Cw_calGC; // Add MC product of last addition.
178
 
 
179
 
         massWater = (MC*(tf-t1))/(HeatCalculations::Cw_calGC * (tw-tf));
180
 
 
181
 
         mashStep->setInfuseAmount_l(massWater);
182
 
         mashStep->setInfuseTemp_c(tw);
183
 
      }
184
 
   }
185
 
   
186
 
   // Now, do a sparge step to get the total volume of the mash up to the boil size.
187
 
   double wortInBoil_l = recObs->estimateWortFromMash_l();
188
 
   if( recObs->getEquipment() != 0 )
189
 
      wortInBoil_l -= recObs->getEquipment()->getLauterDeadspace_l();
190
 
   
191
 
   double spargeWater_l = recObs->getBoilSize_l() - wortInBoil_l;
192
 
   if( spargeWater_l >= 0.0 )
193
 
   {
194
 
      // If the recipe already has a mash step named "Batch Sparge",
195
 
      // find it and use it instead of making a new one.
196
 
      bool foundSparge = false;
197
 
      for( int j = 0; j < mash->getNumMashSteps(); ++j )
198
 
      {
199
 
         if( mash->getMashStep(j)->getName() == "Batch Sparge" )
200
 
         {
201
 
            mashStep = mash->getMashStep(j);
202
 
            foundSparge = true;
203
 
            break;
204
 
         }
205
 
      }
206
 
      if( ! foundSparge )
207
 
         mashStep = new MashStep(); // Or just make a new one.
208
 
      
209
 
      tf = 74; // 74C is recommended in John Palmer's How to Brew
210
 
      t1 = mash->getMashStep(size-1)->getStepTemp_c() - 10.0; // You will lose about 10C from last step.
211
 
      MC = recObs->getGrainsInMash_kg() * HeatCalculations::Cgrain_calGC
212
 
           + HeatCalculations::absorption_LKg * recObs->getGrainsInMash_kg() * HeatCalculations::Cw_calGC
213
 
           + mash->getTunWeight_kg() * mash->getTunSpecificHeat_calGC();
214
 
      massWater = spargeWater_l;
215
 
      
216
 
      tw = (MC/(massWater*HeatCalculations::Cw_calGC))*(tf-t1) + tf;
217
 
      
218
 
      mashStep->setName("Batch Sparge");
219
 
      mashStep->setType("Infusion");
220
 
      mashStep->setInfuseAmount_l(spargeWater_l);
221
 
      mashStep->setInfuseTemp_c(tw);
222
 
      mashStep->setEndTemp_c(tw);
223
 
      mashStep->setStepTemp_c(tf);
224
 
      mashStep->setStepTime_min(15);
225
 
      
226
 
      if( ! foundSparge )
227
 
         mash->addMashStep(mashStep);
228
 
   }
229
 
   else
230
 
   {
231
 
      QMessageBox::information(this, tr("Too much wort"),
232
 
      tr("You have too much wort from the mash for your boil size. I suggest increasing the boil size by increasing the boil time, or reducing your mash thickness."));
233
 
   }
234
 
}
 
 
b'\\ No newline at end of file'