~scottydelicious666/brewtarget/brewtarget

« back to all changes in this revision

Viewing changes to mash.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
 
 * mash.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 <iostream>
20
 
#include <string>
21
 
#include <vector>
22
 
#include "xmlnode.h"
23
 
#include "stringparsing.h"
24
 
#include "mash.h"
25
 
#include "mashstep.h"
26
 
#include "ui_mainWindow.h"
27
 
#include "brewtarget.h"
28
 
#include <QDomElement>
29
 
#include <QDomText>
30
 
 
31
 
bool operator<(Mash &m1, Mash &m2)
32
 
{
33
 
   return m1.name < m2.name;
34
 
}
35
 
 
36
 
bool operator==(Mash &m1, Mash &m2)
37
 
{
38
 
   return m1.name == m2.name;
39
 
}
40
 
 
41
 
/*
42
 
std::string Mash::toXml()
43
 
{
44
 
   unsigned int i, size = mashSteps.size();
45
 
   std::string ret = "<MASH>\n";
46
 
   
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";
61
 
   
62
 
   ret += "</MASH>\n";
63
 
   
64
 
   return ret;
65
 
}
66
 
*/
67
 
 
68
 
void Mash::toXml(QDomDocument& doc, QDomNode& parent)
69
 
{
70
 
   QDomElement mashNode;
71
 
   QDomElement tmpNode;
72
 
   QDomText tmpText;
73
 
   
74
 
   unsigned int i, size;
75
 
   
76
 
   mashNode = doc.createElement("MASH");
77
 
   
78
 
   tmpNode = doc.createElement("NAME");
79
 
   tmpText = doc.createTextNode(name.c_str());
80
 
   tmpNode.appendChild(tmpText);
81
 
   mashNode.appendChild(tmpNode);
82
 
   
83
 
   tmpNode = doc.createElement("VERSION");
84
 
   tmpText = doc.createTextNode(text(version));
85
 
   tmpNode.appendChild(tmpText);
86
 
   mashNode.appendChild(tmpNode);
87
 
   
88
 
   tmpNode = doc.createElement("GRAIN_TEMP");
89
 
   tmpText = doc.createTextNode(text(grainTemp_c));
90
 
   tmpNode.appendChild(tmpText);
91
 
   mashNode.appendChild(tmpNode);
92
 
   
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);
98
 
   
99
 
   tmpNode = doc.createElement("NOTES");
100
 
   tmpText = doc.createTextNode(notes.c_str());
101
 
   tmpNode.appendChild(tmpText);
102
 
   mashNode.appendChild(tmpNode);
103
 
   
104
 
   tmpNode = doc.createElement("TUN_TEMP");
105
 
   tmpText = doc.createTextNode(text(tunTemp_c));
106
 
   tmpNode.appendChild(tmpText);
107
 
   mashNode.appendChild(tmpNode);
108
 
   
109
 
   tmpNode = doc.createElement("SPARGE_TEMP");
110
 
   tmpText = doc.createTextNode(text(spargeTemp_c));
111
 
   tmpNode.appendChild(tmpText);
112
 
   mashNode.appendChild(tmpNode);
113
 
   
114
 
   tmpNode = doc.createElement("PH");
115
 
   tmpText = doc.createTextNode(text(ph));
116
 
   tmpNode.appendChild(tmpText);
117
 
   mashNode.appendChild(tmpNode);
118
 
   
119
 
   tmpNode = doc.createElement("TUN_WEIGHT");
120
 
   tmpText = doc.createTextNode(text(tunWeight_kg));
121
 
   tmpNode.appendChild(tmpText);
122
 
   mashNode.appendChild(tmpNode);
123
 
   
124
 
   tmpNode = doc.createElement("TUN_SPECIFIC_HEAT");
125
 
   tmpText = doc.createTextNode(text(tunSpecificHeat_calGC));
126
 
   tmpNode.appendChild(tmpText);
127
 
   mashNode.appendChild(tmpNode);
128
 
   
129
 
   tmpNode = doc.createElement("EQUIP_ADJUST");
130
 
   tmpText = doc.createTextNode(text(equipAdjust));
131
 
   tmpNode.appendChild(tmpText);
132
 
   mashNode.appendChild(tmpNode);
133
 
   
134
 
   parent.appendChild(mashNode);
135
 
}
136
 
 
137
 
void Mash::setDefaults()
138
 
{
139
 
   name = "";
140
 
   grainTemp_c = 21.0;
141
 
   mashSteps = std::vector<MashStep *>();
142
 
   notes = "";
143
 
   tunTemp_c = 21.0;
144
 
   spargeTemp_c = 74.0;
145
 
   ph = 7.0;
146
 
   tunWeight_kg = 0.0;
147
 
   tunSpecificHeat_calGC = 0.0;
148
 
   equipAdjust = true;
149
 
}
150
 
 
151
 
Mash::Mash()
152
 
{
153
 
   setDefaults();
154
 
}
155
 
 
156
 
/*
157
 
Mash::Mash(const XmlNode *node)
158
 
{
159
 
   std::vector<XmlNode *> children;
160
 
   std::vector<XmlNode *> tmpVec;
161
 
   std::string tag;
162
 
   std::string leafText;
163
 
   XmlNode* leaf;
164
 
   unsigned int i, childrenSize;
165
 
   bool hasName=false, hasVersion=false, hasGrainTemp=false, hasMashStep=false;
166
 
   
167
 
   setDefaults();
168
 
   
169
 
   if( node->getTag() != "MASH" )
170
 
      throw MashException("initializer not passed a MASH node.");
171
 
   
172
 
   node->getChildren( children );
173
 
   childrenSize = children.size();
174
 
   
175
 
   for( i = 0; i < childrenSize; ++i )
176
 
   {
177
 
      tag = children[i]->getTag();
178
 
      children[i]->getChildren( tmpVec );
179
 
      
180
 
      if( tmpVec.size() == 0 )
181
 
         leaf = &XmlNode();
182
 
      else
183
 
         leaf = tmpVec[0]; // May not really be a leaf.
184
 
      
185
 
      if( leaf->isLeaf() )
186
 
         leafText = leaf->getLeafText();
187
 
 
188
 
      if( tag == "NAME" )
189
 
      {
190
 
         if( ! leaf->isLeaf() )
191
 
            throw MashException("Should have been a leaf but is not.");
192
 
         setName(leaf->getLeafText());
193
 
         hasName = true;
194
 
      }
195
 
      else if( tag == "VERSION" )
196
 
      {
197
 
         if( ! leaf->isLeaf() )
198
 
            throw MashException("Should have been a leaf but is not.");
199
 
         
200
 
         if( parseInt(leaf->getLeafText()) != (int)version )
201
 
            std::cerr << "Warning: XML MASH is not version " << version << std::endl;
202
 
         
203
 
         hasVersion = true;
204
 
      }
205
 
      else if( tag == "GRAIN_TEMP" )
206
 
      {
207
 
         if( ! leaf->isLeaf() )
208
 
            throw MashException("Should have been a leaf but is not.");
209
 
         
210
 
         setGrainTemp_c(parseDouble(leaf->getLeafText()));
211
 
         hasGrainTemp=true;
212
 
      }
213
 
      else if( tag == "MASH_STEPS" )
214
 
      {
215
 
         MashStep *a;
216
 
         unsigned int j;
217
 
         for( j = 0; j < tmpVec.size(); ++j )
218
 
         {
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);
222
 
         }
223
 
         hasMashStep=true;
224
 
      }
225
 
      else if( tag == "NOTES" )
226
 
      {
227
 
         if( ! leaf->isLeaf() )
228
 
            throw MashException("Should have been a leaf but is not.");
229
 
         
230
 
         setNotes(leafText);
231
 
      }
232
 
      else if( tag == "TUN_TEMP" )
233
 
      {
234
 
         if( ! leaf->isLeaf() )
235
 
            throw MashException("Should have been a leaf but is not.");
236
 
         
237
 
         setTunTemp_c(parseDouble(leafText));
238
 
      }
239
 
      else if( tag == "SPARGE_TEMP" )
240
 
      {
241
 
         if( ! leaf->isLeaf() )
242
 
            throw MashException("Should have been a leaf but is not.");
243
 
         
244
 
         setSpargeTemp_c(parseDouble(leafText));
245
 
      }
246
 
      else if( tag == "PH" )
247
 
      {
248
 
         if( ! leaf->isLeaf() )
249
 
            throw MashException("Should have been a leaf but is not.");
250
 
         
251
 
         setPh(parseDouble(leafText));
252
 
      }
253
 
      else if( tag == "TUN_WEIGHT" )
254
 
      {
255
 
         if( ! leaf->isLeaf() )
256
 
            throw MashException("Should have been a leaf but is not.");
257
 
         
258
 
         setTunWeight_kg(parseDouble(leafText));
259
 
      }
260
 
      else if( tag == "TUN_SPECIFIC_HEAT" )
261
 
      {
262
 
         if( ! leaf->isLeaf() )
263
 
            throw MashException("Should have been a leaf but is not.");
264
 
         
265
 
         setTunSpecificHeat_calGC(parseDouble(leafText));
266
 
      }
267
 
      else if( tag == "EQUIP_ADJUST" )
268
 
      {
269
 
         if( ! leaf->isLeaf() )
270
 
            throw MashException("Should have been a leaf but is not.");
271
 
         
272
 
         setEquipAdjust(parseBool(leafText));
273
 
      }
274
 
      else
275
 
         std::cerr << "Warning: non-standard tag: " << tag << std::endl;
276
 
   } // end for()
277
 
   
278
 
   if( !hasName || !hasVersion || !hasGrainTemp || !hasMashStep )
279
 
      throw MashException("missing required field.");
280
 
}// end Mash()
281
 
*/
282
 
 
283
 
Mash::Mash(const QDomNode& mashNode)
284
 
{
285
 
   QDomNode node, child;
286
 
   QDomText textNode;
287
 
   QString property, value;
288
 
 
289
 
   setDefaults();
290
 
 
291
 
   for( node = mashNode.firstChild(); ! node.isNull(); node = node.nextSibling() )
292
 
   {
293
 
      if( ! node.isElement() )
294
 
      {
295
 
         Brewtarget::log(Brewtarget::WARNING, QString("Node at line %1 is not an element.").arg(textNode.lineNumber()) );
296
 
         continue;
297
 
      }
298
 
 
299
 
      child = node.firstChild();
300
 
      if( child.isNull() )
301
 
         continue;
302
 
 
303
 
      property = node.nodeName();
304
 
      if( child.isText() )
305
 
         textNode = child.toText();
306
 
      value = textNode.nodeValue();
307
 
 
308
 
      if( property == "NAME" )
309
 
      {
310
 
         name = value.toStdString();
311
 
      }
312
 
      else if( property == "VERSION" )
313
 
      {
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()) );
316
 
      }
317
 
      else if( property == "GRAIN_TEMP" )
318
 
      {
319
 
         setGrainTemp_c(getDouble(textNode));
320
 
      }
321
 
      else if( property == "MASH_STEPS" )
322
 
      {
323
 
         QDomNode step;
324
 
 
325
 
         for( step = child; ! step.isNull(); step = step.nextSibling() )
326
 
            addMashStep(new MashStep(step));
327
 
      }
328
 
      else if( property == "NOTES" )
329
 
      {
330
 
         setNotes(value.toStdString());
331
 
      }
332
 
      else if( property == "TUN_TEMP" )
333
 
      {
334
 
         setTunTemp_c(getDouble(textNode));
335
 
      }
336
 
      else if( property == "SPARGE_TEMP" )
337
 
      {
338
 
         setSpargeTemp_c(getDouble(textNode));
339
 
      }
340
 
      else if( property == "PH" )
341
 
      {
342
 
         setPh(getDouble(textNode));
343
 
      }
344
 
      else if( property == "TUN_WEIGHT" )
345
 
      {
346
 
         setTunWeight_kg(getDouble(textNode));
347
 
      }
348
 
      else if( property == "TUN_SPECIFIC_HEAT" )
349
 
      {
350
 
         setTunSpecificHeat_calGC(getDouble(textNode));
351
 
      }
352
 
      else if( property == "EQUIP_ADJUST" )
353
 
      {
354
 
         setEquipAdjust(getBool(textNode));
355
 
      }
356
 
      else
357
 
      {
358
 
         Brewtarget::log(Brewtarget::WARNING, QString("Unsupported MASH property: %1. Line %2").arg(property).arg(node.lineNumber()) );
359
 
      }
360
 
   }
361
 
}
362
 
 
363
 
void Mash::setName( const std::string& var )
364
 
{
365
 
   name = std::string(var);
366
 
   hasChanged();
367
 
}
368
 
 
369
 
void Mash::setGrainTemp_c( double var )
370
 
{
371
 
   grainTemp_c = var;
372
 
   hasChanged();
373
 
}
374
 
 
375
 
void Mash::setNotes( const std::string& var )
376
 
{
377
 
   notes = std::string(var);
378
 
   hasChanged();
379
 
}
380
 
 
381
 
void Mash::setTunTemp_c( double var )
382
 
{
383
 
   tunTemp_c = var;
384
 
   hasChanged();
385
 
}
386
 
 
387
 
void Mash::setSpargeTemp_c( double var )
388
 
{
389
 
   spargeTemp_c = var;
390
 
   hasChanged();
391
 
}
392
 
 
393
 
void Mash::setPh( double var )
394
 
{
395
 
   if( var < 0.0 || var > 14.0 )
396
 
      throw MashException("invalid PH: " + doubleToString(var) );
397
 
   else
398
 
   {
399
 
      ph = var;
400
 
      hasChanged();
401
 
   }
402
 
}
403
 
 
404
 
void Mash::setTunWeight_kg( double var )
405
 
{
406
 
   if( var < 0.0 )
407
 
      throw MashException("invalid weight: " + doubleToString(var) );
408
 
   else
409
 
   {
410
 
      tunWeight_kg = var;
411
 
      hasChanged();
412
 
   }
413
 
}
414
 
 
415
 
void Mash::setTunSpecificHeat_calGC( double var )
416
 
{
417
 
   if( var < 0.0 )
418
 
      throw MashException("invalid specific heat: " + doubleToString(var) );
419
 
   else
420
 
   {
421
 
      tunSpecificHeat_calGC = var;
422
 
      hasChanged();
423
 
   }
424
 
}
425
 
 
426
 
void Mash::setEquipAdjust( bool var )
427
 
{
428
 
   equipAdjust = var;
429
 
   hasChanged();
430
 
}
431
 
 
432
 
void Mash::addMashStep(MashStep* step)
433
 
{
434
 
   if( step == 0 )
435
 
      return;
436
 
   
437
 
   mashSteps.push_back(step);
438
 
   addObserved(step);
439
 
   hasChanged();
440
 
}
441
 
 
442
 
void Mash::removeMashStep(MashStep* step)
443
 
{
444
 
   if( step == 0 )
445
 
      return;
446
 
 
447
 
   std::vector<MashStep*>::iterator it;
448
 
   for( it = mashSteps.begin(); it != mashSteps.end(); it++ )
449
 
   {
450
 
      if(*it == step )
451
 
      {
452
 
         mashSteps.erase(it);
453
 
         removeObserved(*it);
454
 
         hasChanged();
455
 
         return;
456
 
      }
457
 
   }
458
 
}
459
 
 
460
 
//============================="GET" METHODS====================================
461
 
std::string Mash::getName() const
462
 
{
463
 
   return name;
464
 
}
465
 
 
466
 
double Mash::getGrainTemp_c() const
467
 
{
468
 
   return grainTemp_c;
469
 
}
470
 
 
471
 
unsigned int Mash::getNumMashSteps() const
472
 
{
473
 
   return mashSteps.size();
474
 
}
475
 
 
476
 
MashStep* Mash::getMashStep( unsigned int i )
477
 
{
478
 
   if( i >= mashSteps.size() )
479
 
      throw MashException("getMashStep(): index too large: " + intToString(i));
480
 
   else
481
 
      return mashSteps[i];
482
 
}
483
 
 
484
 
std::string Mash::getNotes() const
485
 
{
486
 
   return notes;
487
 
}
488
 
 
489
 
double Mash::getTunTemp_c() const
490
 
{
491
 
   return tunTemp_c;
492
 
}
493
 
 
494
 
double Mash::getSpargeTemp_c() const
495
 
{
496
 
   return spargeTemp_c;
497
 
}
498
 
 
499
 
double Mash::getPh() const
500
 
{
501
 
   return ph;;
502
 
}
503
 
 
504
 
double Mash::getTunWeight_kg() const
505
 
{
506
 
   return tunWeight_kg;
507
 
}
508
 
 
509
 
double Mash::getTunSpecificHeat_calGC() const
510
 
{
511
 
   return tunSpecificHeat_calGC;
512
 
}
513
 
 
514
 
bool Mash::getEquipAdjust() const
515
 
{
516
 
   return equipAdjust;
517
 
}
518
 
 
519
 
// === other methods ===
520
 
double Mash::totalMashWater_l() const
521
 
{
522
 
   unsigned int i, size;
523
 
   double waterAdded_l = 0.0;
524
 
   MashStep* step;
525
 
   
526
 
   size = mashSteps.size();
527
 
   for( i = 0; i < size; ++i )
528
 
   {
529
 
      step = mashSteps[i];
530
 
      
531
 
      if( step->getType() == "Infusion" )
532
 
         waterAdded_l += step->getInfuseAmount_l();
533
 
   }
534
 
   
535
 
   return waterAdded_l;
536
 
}
537
 
 
538
 
void Mash::notify(Observable *notifier, QVariant info)
539
 
{
540
 
   unsigned int i, size;
541
 
   size = mashSteps.size();
542
 
   
543
 
   for( i = 0; i < size; ++i )
544
 
   {
545
 
      if( mashSteps[i] == notifier )
546
 
      {
547
 
         hasChanged(QVariant(i)); // Mash notifies its observers of which mashStep changed.
548
 
         return;
549
 
      }
550
 
   }
551
 
}
 
 
b'\\ No newline at end of file'