2
* mash.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/>.
23
#include "stringparsing.h"
26
#include "ui_mainWindow.h"
27
#include "brewtarget.h"
28
#include <QDomElement>
31
bool operator<(Mash &m1, Mash &m2)
33
return m1.name < m2.name;
36
bool operator==(Mash &m1, Mash &m2)
38
return m1.name == m2.name;
42
std::string Mash::toXml()
44
unsigned int i, size = mashSteps.size();
45
std::string ret = "<MASH>\n";
47
ret += "<NAME>"+name+"</NAME>\n";
48
ret += "<VERSION>"+intToString(version)+"</VERSION>\n";
49
ret += "<GRAIN_TEMP>"+doubleToString(grainTemp_c)+"</GRAIN_TEMP>\n";
50
ret += "<MASH_STEPS>\n";
51
for( i = 0; i < size; ++i )
52
ret += mashSteps[i]->toXml();
53
ret += "</MASH_STEPS>\n";
54
ret += "<NOTES>"+notes+"</NOTES>\n";
55
ret += "<TUN_TEMP>"+doubleToString(tunTemp_c)+"</TUN_TEMP>\n";
56
ret += "<SPARGE_TEMP>"+doubleToString(spargeTemp_c)+"</SPARGE_TEMP>\n";
57
ret += "<PH>"+doubleToString(ph)+"</PH>\n";
58
ret += "<TUN_WEIGHT>"+doubleToString(tunWeight_kg)+"</TUN_WEIGHT>\n";
59
ret += "<TUN_SPECIFIC_HEAT>"+doubleToString(tunSpecificHeat_calGC)+"</TUN_SPECIFIC_HEAT>\n";
60
ret += "<EQUIP_ADJUST>"+boolToString(equipAdjust)+"</EQUIP_ADJUST>\n";
68
void Mash::toXml(QDomDocument& doc, QDomNode& parent)
76
mashNode = doc.createElement("MASH");
78
tmpNode = doc.createElement("NAME");
79
tmpText = doc.createTextNode(name.c_str());
80
tmpNode.appendChild(tmpText);
81
mashNode.appendChild(tmpNode);
83
tmpNode = doc.createElement("VERSION");
84
tmpText = doc.createTextNode(text(version));
85
tmpNode.appendChild(tmpText);
86
mashNode.appendChild(tmpNode);
88
tmpNode = doc.createElement("GRAIN_TEMP");
89
tmpText = doc.createTextNode(text(grainTemp_c));
90
tmpNode.appendChild(tmpText);
91
mashNode.appendChild(tmpNode);
93
tmpNode = doc.createElement("MASH_STEPS");
94
size = mashSteps.size();
95
for( i = 0; i < size; ++i )
96
mashSteps[i]->toXml(doc, tmpNode);
97
mashNode.appendChild(tmpNode);
99
tmpNode = doc.createElement("NOTES");
100
tmpText = doc.createTextNode(notes.c_str());
101
tmpNode.appendChild(tmpText);
102
mashNode.appendChild(tmpNode);
104
tmpNode = doc.createElement("TUN_TEMP");
105
tmpText = doc.createTextNode(text(tunTemp_c));
106
tmpNode.appendChild(tmpText);
107
mashNode.appendChild(tmpNode);
109
tmpNode = doc.createElement("SPARGE_TEMP");
110
tmpText = doc.createTextNode(text(spargeTemp_c));
111
tmpNode.appendChild(tmpText);
112
mashNode.appendChild(tmpNode);
114
tmpNode = doc.createElement("PH");
115
tmpText = doc.createTextNode(text(ph));
116
tmpNode.appendChild(tmpText);
117
mashNode.appendChild(tmpNode);
119
tmpNode = doc.createElement("TUN_WEIGHT");
120
tmpText = doc.createTextNode(text(tunWeight_kg));
121
tmpNode.appendChild(tmpText);
122
mashNode.appendChild(tmpNode);
124
tmpNode = doc.createElement("TUN_SPECIFIC_HEAT");
125
tmpText = doc.createTextNode(text(tunSpecificHeat_calGC));
126
tmpNode.appendChild(tmpText);
127
mashNode.appendChild(tmpNode);
129
tmpNode = doc.createElement("EQUIP_ADJUST");
130
tmpText = doc.createTextNode(text(equipAdjust));
131
tmpNode.appendChild(tmpText);
132
mashNode.appendChild(tmpNode);
134
parent.appendChild(mashNode);
137
void Mash::setDefaults()
141
mashSteps = std::vector<MashStep *>();
147
tunSpecificHeat_calGC = 0.0;
157
Mash::Mash(const XmlNode *node)
159
std::vector<XmlNode *> children;
160
std::vector<XmlNode *> tmpVec;
162
std::string leafText;
164
unsigned int i, childrenSize;
165
bool hasName=false, hasVersion=false, hasGrainTemp=false, hasMashStep=false;
169
if( node->getTag() != "MASH" )
170
throw MashException("initializer not passed a MASH node.");
172
node->getChildren( children );
173
childrenSize = children.size();
175
for( i = 0; i < childrenSize; ++i )
177
tag = children[i]->getTag();
178
children[i]->getChildren( tmpVec );
180
if( tmpVec.size() == 0 )
183
leaf = tmpVec[0]; // May not really be a leaf.
186
leafText = leaf->getLeafText();
190
if( ! leaf->isLeaf() )
191
throw MashException("Should have been a leaf but is not.");
192
setName(leaf->getLeafText());
195
else if( tag == "VERSION" )
197
if( ! leaf->isLeaf() )
198
throw MashException("Should have been a leaf but is not.");
200
if( parseInt(leaf->getLeafText()) != (int)version )
201
std::cerr << "Warning: XML MASH is not version " << version << std::endl;
205
else if( tag == "GRAIN_TEMP" )
207
if( ! leaf->isLeaf() )
208
throw MashException("Should have been a leaf but is not.");
210
setGrainTemp_c(parseDouble(leaf->getLeafText()));
213
else if( tag == "MASH_STEPS" )
217
for( j = 0; j < tmpVec.size(); ++j )
219
a = new MashStep(tmpVec[j]);
220
// TODO: need to check to make sure tmpVec[j] is a Mash node.
221
mashSteps.push_back(a);
225
else if( tag == "NOTES" )
227
if( ! leaf->isLeaf() )
228
throw MashException("Should have been a leaf but is not.");
232
else if( tag == "TUN_TEMP" )
234
if( ! leaf->isLeaf() )
235
throw MashException("Should have been a leaf but is not.");
237
setTunTemp_c(parseDouble(leafText));
239
else if( tag == "SPARGE_TEMP" )
241
if( ! leaf->isLeaf() )
242
throw MashException("Should have been a leaf but is not.");
244
setSpargeTemp_c(parseDouble(leafText));
246
else if( tag == "PH" )
248
if( ! leaf->isLeaf() )
249
throw MashException("Should have been a leaf but is not.");
251
setPh(parseDouble(leafText));
253
else if( tag == "TUN_WEIGHT" )
255
if( ! leaf->isLeaf() )
256
throw MashException("Should have been a leaf but is not.");
258
setTunWeight_kg(parseDouble(leafText));
260
else if( tag == "TUN_SPECIFIC_HEAT" )
262
if( ! leaf->isLeaf() )
263
throw MashException("Should have been a leaf but is not.");
265
setTunSpecificHeat_calGC(parseDouble(leafText));
267
else if( tag == "EQUIP_ADJUST" )
269
if( ! leaf->isLeaf() )
270
throw MashException("Should have been a leaf but is not.");
272
setEquipAdjust(parseBool(leafText));
275
std::cerr << "Warning: non-standard tag: " << tag << std::endl;
278
if( !hasName || !hasVersion || !hasGrainTemp || !hasMashStep )
279
throw MashException("missing required field.");
283
Mash::Mash(const QDomNode& mashNode)
285
QDomNode node, child;
287
QString property, value;
291
for( node = mashNode.firstChild(); ! node.isNull(); node = node.nextSibling() )
293
if( ! node.isElement() )
295
Brewtarget::log(Brewtarget::WARNING, QString("Node at line %1 is not an element.").arg(textNode.lineNumber()) );
299
child = node.firstChild();
303
property = node.nodeName();
305
textNode = child.toText();
306
value = textNode.nodeValue();
308
if( property == "NAME" )
310
name = value.toStdString();
312
else if( property == "VERSION" )
314
if( version != getInt(textNode) )
315
Brewtarget::log(Brewtarget::ERROR, QString("YEAST says it is not version %1. Line %2").arg(version).arg(textNode.lineNumber()) );
317
else if( property == "GRAIN_TEMP" )
319
setGrainTemp_c(getDouble(textNode));
321
else if( property == "MASH_STEPS" )
325
for( step = child; ! step.isNull(); step = step.nextSibling() )
326
addMashStep(new MashStep(step));
328
else if( property == "NOTES" )
330
setNotes(value.toStdString());
332
else if( property == "TUN_TEMP" )
334
setTunTemp_c(getDouble(textNode));
336
else if( property == "SPARGE_TEMP" )
338
setSpargeTemp_c(getDouble(textNode));
340
else if( property == "PH" )
342
setPh(getDouble(textNode));
344
else if( property == "TUN_WEIGHT" )
346
setTunWeight_kg(getDouble(textNode));
348
else if( property == "TUN_SPECIFIC_HEAT" )
350
setTunSpecificHeat_calGC(getDouble(textNode));
352
else if( property == "EQUIP_ADJUST" )
354
setEquipAdjust(getBool(textNode));
358
Brewtarget::log(Brewtarget::WARNING, QString("Unsupported MASH property: %1. Line %2").arg(property).arg(node.lineNumber()) );
363
void Mash::setName( const std::string& var )
365
name = std::string(var);
369
void Mash::setGrainTemp_c( double var )
375
void Mash::setNotes( const std::string& var )
377
notes = std::string(var);
381
void Mash::setTunTemp_c( double var )
387
void Mash::setSpargeTemp_c( double var )
393
void Mash::setPh( double var )
395
if( var < 0.0 || var > 14.0 )
396
throw MashException("invalid PH: " + doubleToString(var) );
404
void Mash::setTunWeight_kg( double var )
407
throw MashException("invalid weight: " + doubleToString(var) );
415
void Mash::setTunSpecificHeat_calGC( double var )
418
throw MashException("invalid specific heat: " + doubleToString(var) );
421
tunSpecificHeat_calGC = var;
426
void Mash::setEquipAdjust( bool var )
432
void Mash::addMashStep(MashStep* step)
437
mashSteps.push_back(step);
442
void Mash::removeMashStep(MashStep* step)
447
std::vector<MashStep*>::iterator it;
448
for( it = mashSteps.begin(); it != mashSteps.end(); it++ )
460
//============================="GET" METHODS====================================
461
std::string Mash::getName() const
466
double Mash::getGrainTemp_c() const
471
unsigned int Mash::getNumMashSteps() const
473
return mashSteps.size();
476
MashStep* Mash::getMashStep( unsigned int i )
478
if( i >= mashSteps.size() )
479
throw MashException("getMashStep(): index too large: " + intToString(i));
484
std::string Mash::getNotes() const
489
double Mash::getTunTemp_c() const
494
double Mash::getSpargeTemp_c() const
499
double Mash::getPh() const
504
double Mash::getTunWeight_kg() const
509
double Mash::getTunSpecificHeat_calGC() const
511
return tunSpecificHeat_calGC;
514
bool Mash::getEquipAdjust() const
519
// === other methods ===
520
double Mash::totalMashWater_l() const
522
unsigned int i, size;
523
double waterAdded_l = 0.0;
526
size = mashSteps.size();
527
for( i = 0; i < size; ++i )
531
if( step->getType() == "Infusion" )
532
waterAdded_l += step->getInfuseAmount_l();
538
void Mash::notify(Observable *notifier, QVariant info)
540
unsigned int i, size;
541
size = mashSteps.size();
543
for( i = 0; i < size; ++i )
545
if( mashSteps[i] == notifier )
547
hasChanged(QVariant(i)); // Mash notifies its observers of which mashStep changed.
b'\\ No newline at end of file'