2
* MashWizard.cpp is part of Brewtarget, and is Copyright Philip G. Lee
3
* (rocketman768@gmail.com), 2009.
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.
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.
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/>.
20
#include "MashWizard.h"
23
#include "fermentable.h"
24
#include <QMessageBox>
25
#include "HeatCalculations.h"
26
#include "stringparsing.h"
27
#include "brewtarget.h"
29
MashWizard::MashWizard(QWidget* parent) : QDialog(parent)
34
connect(buttonBox, SIGNAL(accepted()), this, SLOT(wizardry()) );
35
connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()) );
38
void MashWizard::setRecipe(Recipe* rec)
43
void MashWizard::show()
45
if( Brewtarget::useEnglishUnits() )
46
label->setText(tr("Mash thickness (qt/lb)"));
48
label->setText(tr("Mash thickness (L/kg)"));
53
void MashWizard::wizardry()
55
if( recObs == 0 || recObs->getMash() == 0 )
58
Mash* mash = recObs->getMash();
65
double grainMass = 0.0, massWater = 0.0;
66
double grainDensity = HeatCalculations::rhoGrain_KgL;
68
size = mash->getNumMashSteps();
69
thickNum = Unit::qstringToSI(lineEdit_mashThickness->text());
70
if( Brewtarget::useEnglishUnits() )
71
thickness_LKg = thickNum * 2.086;
73
thickness_LKg = thickNum;
75
if( thickness_LKg <= 0.0 )
77
QMessageBox::information(this, tr("Bad thickness"), tr("You must have a positive mash thickness."));
80
// Ensure at least one mash step.
83
QMessageBox::information(this, tr("No steps"), tr("You must have at least one mash step to run the wizard."));
87
mashStep = mash->getMashStep(0);
88
// Ensure first mash step is an infusion.
89
if( mashStep->getType() != "Infusion" )
91
QMessageBox::information(this, tr("First step"), tr("Your first mash step must be an infusion."));
96
for( i = 0; i < recObs->getNumFermentables(); i++ )
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();
106
grainMass = recObs->getGrainsInMash_kg();
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;
118
// tw = MC/MCw * (tf-t1) + tf;
120
// Can't have water above boiling.
123
QMessageBox::information(this, tr("Mash too thick"), tr("Your mash is too thick for desired temp. at first step."));
127
mashStep->setInfuseAmount_l(massWater);
128
mashStep->setInfuseTemp_c(tw);
129
// End of first step.
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 )
138
mashStep = mash->getMashStep(i);
140
if( mashStep->getType() == "Temperature")
142
else if( mashStep->getType() == "Decoction" )
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;
148
tf = mashStep->getStepTemp_c();
149
t1 = mash->getMashStep(i-1)->getStepTemp_c();
151
m_w = 0; // Total mass of water.
152
for(j = 0; j < i; ++j )
153
m_w += mash->getMashStep(j)->getInfuseAmount_l();
155
m_e = (mash->getEquipAdjust()) ? mash->getTunWeight_kg() : 0;
157
c_w = HeatCalculations::Cw_calGC;
158
c_g = HeatCalculations::Cgrain_calGC;
159
c_e = (mash->getEquipAdjust()) ? mash->getTunSpecificHeat_calGC() : 0;
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));
165
QMessageBox::critical(this, tr("Decoction error"), tr("Something went wrong in decoction calculation.") );
166
Brewtarget::log(Brewtarget::ERROR, "Decoction: r=" + doubleToString(r));
170
mashStep->setDecoctionAmount_l( r*(m_w + m_g/grainDensity) );
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.
179
massWater = (MC*(tf-t1))/(HeatCalculations::Cw_calGC * (tw-tf));
181
mashStep->setInfuseAmount_l(massWater);
182
mashStep->setInfuseTemp_c(tw);
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();
191
double spargeWater_l = recObs->getBoilSize_l() - wortInBoil_l;
192
if( spargeWater_l >= 0.0 )
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 )
199
if( mash->getMashStep(j)->getName() == "Batch Sparge" )
201
mashStep = mash->getMashStep(j);
207
mashStep = new MashStep(); // Or just make a new one.
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;
216
tw = (MC/(massWater*HeatCalculations::Cw_calGC))*(tf-t1) + tf;
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);
227
mash->addMashStep(mashStep);
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."));
b'\\ No newline at end of file'