Added hops inventory check. Include all whirlpool steps in ibu calculations. Calculate the ibus in the fermenter including top up water. Use enum constants for the hops. Update the invenory state when replacing a hop.

Tue, 03 May 2022 21:37:12 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 03 May 2022 21:37:12 +0200
changeset 191
7446ee2fb427
parent 190
bb6c06910f0f
child 192
718f71f14b41

Added hops inventory check. Include all whirlpool steps in ibu calculations. Calculate the ibus in the fermenter including top up water. Use enum constants for the hops. Update the invenory state when replacing a hop.

src/EditProduct.cpp file | annotate | diff | comparison | revisions
src/EditProductTab3.cpp file | annotate | diff | comparison | revisions
src/EditProductTab4.cpp file | annotate | diff | comparison | revisions
src/global.h file | annotate | diff | comparison | revisions
ui/EditProduct.ui file | annotate | diff | comparison | revisions
--- a/src/EditProduct.cpp	Tue May 03 20:05:04 2022 +0200
+++ b/src/EditProduct.cpp	Tue May 03 21:37:12 2022 +0200
@@ -1100,11 +1100,11 @@
 	return;
     }
 
-    qDebug() << "calcSupplies() f:" << product->fermentables_ok /*<< "h:" << product->hops_ok << "m:" << product->miscs_ok << "y:" << product->yeasts_ok << "w:" << product->waters_ok*/;
-    if (product->fermentables_ok /*&& product->hops_ok && product->miscs_ok && product->yeasts_ok && product->waters_ok */) {
+    qDebug() << "calcSupplies() f:" << product->fermentables_ok << "h:" << product->hops_ok /*<< "m:" << product->miscs_ok << "y:" << product->yeasts_ok << "w:" << product->waters_ok*/;
+    if (product->fermentables_ok && product->hops_ok /*&& product->miscs_ok && product->yeasts_ok && product->waters_ok */) {
 	ui->ok_pmptIcon->setPixmap(QPixmap(QString::fromUtf8(":/icons/silk/tick.png")));
     } else {
-	ui->ok_pmptIcon->setPixmap(QPixmap(QString::fromUtf8(":/icons/silk/error.png")));
+	ui->ok_pmptIcon->setPixmap(QPixmap(QString::fromUtf8(":/icons/silk/cancel.png")));
     }
 }
 
@@ -1122,6 +1122,7 @@
     refreshMashs();
     refreshWaters();
     calcWater();
+    calcSupplies();
 }
 
 
--- a/src/EditProductTab3.cpp	Tue May 03 20:05:04 2022 +0200
+++ b/src/EditProductTab3.cpp	Tue May 03 21:37:12 2022 +0200
@@ -424,7 +424,6 @@
 	}
 	qDebug() << "  SVG" << svg;
     }
-    calcSupplies();
     if (svg == 0)
 	svg = 77.0;
     ui->est_svgEdit->setValue(svg);
--- a/src/EditProductTab4.cpp	Tue May 03 20:05:04 2022 +0200
+++ b/src/EditProductTab4.cpp	Tue May 03 21:37:12 2022 +0200
@@ -49,7 +49,7 @@
                               tr("IBU"), tr("Amount"), tr("Stock"), tr("Delete"), tr("Edit") });
 
     ui->hopsTable->setColumnCount(12);
-    ui->hopsTable->setColumnWidth(0, 130);     /* Origin	*/
+    ui->hopsTable->setColumnWidth(0, 140);     /* Origin	*/
     ui->hopsTable->setColumnWidth(1, 225);     /* Hop		*/
     ui->hopsTable->setColumnWidth(2,  74);     /* Type		*/
     ui->hopsTable->setColumnWidth(3,  84);     /* Form          */
@@ -116,6 +116,8 @@
             item = new QTableWidgetItem(QString("%1 kg").arg(product->hops.at(i).h_inventory, 4, 'f', 3, '0'));
         }
         item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	if (product->hops.at(i).h_inventory < product->hops.at(i).h_amount)
+	    item->setForeground(QBrush(QColor(Qt::red)));
         ui->hopsTable->setItem(i, 9, item);
 
 	/* Add the Delete row button */
@@ -188,14 +190,26 @@
 
 void EditProduct::calcIBUs()
 {
-    double hop_flavour = 0, hop_aroma = 0, ibus = 0;
+    double hop_flavour = 0, hop_aroma = 0, ibus = 0, ferm_ibus = 0;
 
+    product->hops_ok = true;
     for (int i = 0; i < product->hops.size(); i++) {
 
-	ibus += Utils::toIBU(product->hops.at(i).h_useat, product->hops.at(i).h_form, product->preboil_sg, product->batch_size, product->hops.at(i).h_amount,
-                           product->hops.at(i).h_time, product->hops.at(i).h_alpha, product->ibu_method, 0, product->hops.at(i).h_time, 0);
+	ibus += Utils::toIBU(product->hops.at(i).h_useat, product->hops.at(i).h_form, product->preboil_sg,
+			   product->batch_size, product->hops.at(i).h_amount,
+                           product->hops.at(i).h_time, product->hops.at(i).h_alpha, product->ibu_method,
+			   product->brew_whirlpool9, product->brew_whirlpool7, product->brew_whirlpool6);
+	ferm_ibus += Utils::toIBU(product->hops.at(i).h_useat, product->hops.at(i).h_form, product->preboil_sg,
+			   product->brew_fermenter_volume + product->brew_fermenter_tcloss, product->hops.at(i).h_amount,
+                           product->hops.at(i).h_time, product->hops.at(i).h_alpha, product->ibu_method,
+			   product->brew_whirlpool9, product->brew_whirlpool7, product->brew_whirlpool6);
+
 	hop_flavour += Utils::hopFlavourContribution(product->hops.at(i).h_time, product->batch_size, product->hops.at(i).h_useat, product->hops.at(i).h_amount);
         hop_aroma += Utils::hopAromaContribution(product->hops.at(i).h_time, product->batch_size, product->hops.at(i).h_useat, product->hops.at(i).h_amount);
+	if ((((product->inventory_reduced <= PROD_STAGE_BREW)    && (product->hops.at(i).h_useat <= HOP_USEAT_WHIRLPOOL)) ||
+             ((product->inventory_reduced <= PROD_STAGE_PACKAGE) && (product->hops.at(i).h_useat == HOP_USEAT_DRY_HOP))) &&
+              (product->hops.at(i).h_inventory < product->hops.at(i).h_amount))
+	    product->hops_ok = false;
     }
 
     hop_flavour = round(hop_flavour * 1000.0 / 5.0) / 10;
@@ -204,12 +218,15 @@
         hop_flavour = 100;
     if (hop_aroma > 100)
         hop_aroma = 100;
-    qDebug() << "ibu" << product->est_ibu << ibus << "flavour" << hop_flavour << "aroma" << hop_aroma << "method" << product->ibu_method;
+    qDebug() << "ibu" << product->est_ibu << ibus << "flavour" << hop_flavour << "aroma" << hop_aroma << "method" << product->ibu_method
+	     << "fermenter" << ferm_ibus << "supplies" << product->hops_ok;
 
     product->est_ibu = ibus;
+    product->brew_fermenter_ibu = ferm_ibus;
     ui->est_ibuEdit->setValue(product->est_ibu);
     ui->est_ibu2Edit->setValue(product->est_ibu);
     ui->est_ibuShow->setValue(product->est_ibu);
+    ui->brew_fermentibuShow->setValue(product->brew_fermenter_ibu);
     ui->hop_tasteShow->setValue(hop_flavour);
     ui->hop_aromaShow->setValue(hop_aroma);
 }
@@ -230,9 +247,9 @@
     newh.h_origin = "";
     newh.h_amount = 0;
     newh.h_cost = 0;
-    newh.h_type = 0;
-    newh.h_form = 0;
-    newh.h_useat = 2;
+    newh.h_type = HOP_TYPE_BITTERING;
+    newh.h_form = HOP_FORMS_PELLET;
+    newh.h_useat = HOP_USEAT_BOIL;
     newh.h_time = 0;
     newh.h_alpha = 0;
     newh.h_beta = 0;
@@ -242,6 +259,7 @@
     newh.h_cohumulone = 0;
     newh.h_myrcene = 0;
     newh.h_total_oil = 0;
+    newh.h_inventory = 0;
 
     product->hops.append(newh);
     emit refreshAll();
@@ -299,10 +317,10 @@
 
     qDebug() << "hop_time_changed()" << product->hops_row << val;
 
-    if (product->hops.at(product->hops_row).h_useat == 2 || product->hops.at(product->hops_row).h_useat == 4) {       // Boil or whirlpool
+    if (product->hops.at(product->hops_row).h_useat == HOP_USEAT_BOIL || product->hops.at(product->hops_row).h_useat == HOP_USEAT_WHIRLPOOL) {
         item = new QTableWidgetItem(QString("%1 min.").arg(val, 1, 'f', 0, '0'));
 	product->hops[product->hops_row].h_time = val;
-    } else if (product->hops.at(product->hops_row).h_useat == 5) {                                   // Dry-hop
+    } else if (product->hops.at(product->hops_row).h_useat == HOP_USEAT_DRY_HOP) {
         item = new QTableWidgetItem(QString("%1 days.").arg(val, 1, 'f', 0, '0'));
 	product->hops[product->hops_row].h_time = val * 1440;
     } else {
@@ -314,7 +332,8 @@
 
     double ibu = Utils::toIBU(product->hops.at(product->hops_row).h_useat, product->hops.at(product->hops_row).h_form, product->preboil_sg,
                               product->batch_size, product->hops.at(product->hops_row).h_amount, product->hops.at(product->hops_row).h_time,
- 			      product->hops.at(product->hops_row).h_alpha, product->ibu_method, 0, product->hops.at(product->hops_row).h_time, 0);
+ 			      product->hops.at(product->hops_row).h_alpha, product->ibu_method,
+			      product->brew_whirlpool9, product->brew_whirlpool7, product->brew_whirlpool6);
 
     ibuEdit->setValue(ibu);
     item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0'));
@@ -341,7 +360,7 @@
     /*
      * Search the hop pointed by the index and instock flag.
      */
-    QString sql = "SELECT name,origin,alpha,beta,humulene,caryophyllene,cohumulone,myrcene,hsi,total_oil,type,form,cost FROM inventory_hops ";
+    QString sql = "SELECT name,origin,alpha,beta,humulene,caryophyllene,cohumulone,myrcene,hsi,total_oil,type,form,cost,inventory FROM inventory_hops ";
     if (instock)
         sql.append("WHERE inventory > 0 ");
     sql.append("ORDER BY origin,name");
@@ -351,7 +370,6 @@
     for (int i = 0; i < (val - 1); i++) {
         query.next();
     }
-    qDebug() << "found" << query.value(1).toString() << query.value(0).toString();
 
     /*
      * Replace the hop record contents
@@ -369,6 +387,7 @@
     product->hops[product->hops_row].h_type = query.value(10).toInt();
     product->hops[product->hops_row].h_form = query.value(11).toInt();
     product->hops[product->hops_row].h_cost = query.value(12).toDouble();
+    product->hops[product->hops_row].h_inventory = query.value(13).toDouble();
 
     /*
      * Update the visible fields
@@ -378,7 +397,8 @@
 
     double ibu = Utils::toIBU(product->hops.at(product->hops_row).h_useat, product->hops.at(product->hops_row).h_form, product->preboil_sg,
 		              product->batch_size, product->hops.at(product->hops_row).h_amount, product->hops.at(product->hops_row).h_time,
-			      product->hops.at(product->hops_row).h_alpha, product->ibu_method, 0, product->hops.at(product->hops_row).h_time, 0);
+			      product->hops.at(product->hops_row).h_alpha, product->ibu_method,
+			      product->brew_whirlpool9, product->brew_whirlpool7, product->brew_whirlpool6);
     ibuEdit->setValue(ibu);
 
     ui->hopsTable->setItem(product->hops_row, 0, new QTableWidgetItem(product->hops.at(product->hops_row).h_origin));
@@ -400,6 +420,16 @@
     item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
     ui->hopsTable->setItem(product->hops_row, 7, item);
 
+    if (product->hops.at(product->hops_row).h_inventory < 1.0) {
+	item = new QTableWidgetItem(QString("%1 gr").arg(product->hops.at(product->hops_row).h_inventory * 1000.0, 2, 'f', 1, '0'));
+    } else {
+	item = new QTableWidgetItem(QString("%1 kg").arg(product->hops.at(product->hops_row).h_inventory, 4, 'f', 3, '0'));
+    }
+    item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+    if (product->hops.at(product->hops_row).h_inventory < product->hops.at(product->hops_row).h_amount)
+	item->setForeground(QBrush(QColor(Qt::red)));
+    ui->hopsTable->setItem(product->hops_row, 9, item);
+
     calcIBUs();
     is_changed();
 }
@@ -438,11 +468,11 @@
     item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
     ui->hopsTable->setItem(product->hops_row, 5, item);
 
-    if (val == 2 || val == 4) {	// Boil or whirlpool
+    if (val == HOP_USEAT_BOIL || val == HOP_USEAT_WHIRLPOOL) {
 	htimeLabel->setText(tr("Time in minutes:"));
         htimeEdit->setValue(product->hops.at(product->hops_row).h_time);
 	htimeEdit->setReadOnly(false);
-    } else if (val == 5) {	// Dry-hop
+    } else if (val == HOP_USEAT_DRY_HOP) {
         htimeLabel->setText(tr("Time in days:"));
 	htimeEdit->setValue(product->hops.at(product->hops_row).h_time / 1440);
 	htimeEdit->setReadOnly(false);
@@ -554,10 +584,10 @@
     htimeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
     htimeEdit->setAccelerated(true);
     htimeEdit->setMaximum(10000.0);
-    if (product->hops.at(product->hops_row).h_useat == 2 || product->hops.at(product->hops_row).h_useat == 4) {	// Boil or whirlpool
+    if (product->hops.at(product->hops_row).h_useat == HOP_USEAT_BOIL || product->hops.at(product->hops_row).h_useat == HOP_USEAT_WHIRLPOOL) {
 	htimeEdit->setValue(product->hops.at(product->hops_row).h_time);
 	htimeEdit->setReadOnly(false);
-    } else if (product->hops.at(product->hops_row).h_useat == 5){	// Dry-hop
+    } else if (product->hops.at(product->hops_row).h_useat == HOP_USEAT_DRY_HOP) {
 	htimeEdit->setValue(product->hops.at(product->hops_row).h_time / 1440);
 	htimeEdit->setReadOnly(false);
     } else {
@@ -588,7 +618,8 @@
     ibuEdit->setDecimals(1);
     double ibu = Utils::toIBU(product->hops.at(product->hops_row).h_useat, product->hops.at(product->hops_row).h_form, product->preboil_sg,
                               product->batch_size, product->hops.at(product->hops_row).h_amount, product->hops.at(product->hops_row).h_time,
-                              product->hops.at(product->hops_row).h_alpha, product->ibu_method, 0, product->hops.at(product->hops_row).h_time, 0);
+                              product->hops.at(product->hops_row).h_alpha, product->ibu_method,
+			      product->brew_whirlpool9, product->brew_whirlpool7, product->brew_whirlpool6);
     ibuEdit->setValue(ibu);
 
     hop_instock_changed(true);
@@ -608,9 +639,9 @@
         product->hops[product->hops_row] = backup;
     } else {
 	/* Clear time if hop is not used for boil, whirlpool or dry-hop. */
-	if (! (product->hops.at(product->hops_row).h_useat == 2 ||
-	       product->hops.at(product->hops_row).h_useat == 4 ||
-	       product->hops.at(product->hops_row).h_useat == 5)) {
+	if (! (product->hops.at(product->hops_row).h_useat == HOP_USEAT_BOIL ||
+	       product->hops.at(product->hops_row).h_useat == HOP_USEAT_WHIRLPOOL ||
+	       product->hops.at(product->hops_row).h_useat == HOP_USEAT_DRY_HOP)) {
 	    if (product->hops.at(product->hops_row).h_time) {
 		product->hops[product->hops_row].h_time = 0;
 		is_changed();
--- a/src/global.h	Tue May 03 20:05:04 2022 +0200
+++ b/src/global.h	Tue May 03 21:37:12 2022 +0200
@@ -610,8 +610,34 @@
 };
 
 extern const QStringList fermentable_added;
+
+enum HopTypes {
+	HOP_TYPE_BITTERING,
+	HOP_TYPE_AROMA,
+	HOP_TYPE_BOTH
+};
+
 extern const QStringList hop_types;
+
+enum HopForms {
+	HOP_FORMS_PELLET,
+	HOP_FORMS_PLUG,
+	HOP_FORMS_LEAF,
+	HOP_FORMS_LEAF_WET,
+	HOP_FORMS_CRYO
+};
+
 extern const QStringList hop_forms;
+
+enum HopUseat {
+	HOP_USEAT_MASH,
+	HOP_USEAT_FWH,
+	HOP_USEAT_BOIL,
+	HOP_USEAT_AROMA,
+	HOP_USEAT_WHIRLPOOL,
+	HOP_USEAT_DRY_HOP
+};
+
 extern const QStringList hop_useat;
 extern const QStringList misc_types;
 extern const QStringList misc_uses;
--- a/ui/EditProduct.ui	Tue May 03 20:05:04 2022 +0200
+++ b/ui/EditProduct.ui	Tue May 03 21:37:12 2022 +0200
@@ -1251,7 +1251,7 @@
          <string/>
         </property>
         <property name="pixmap">
-         <pixmap resource="../../../../../../home/mbroek/MyProjects/bmsapp/resources/icons.qrc">:/icons/silk/error.png</pixmap>
+         <pixmap resource="../../../../../../home/mbroek/MyProjects/bmsapp/resources/icons.qrc">:/icons/silk/cancel.png</pixmap>
         </property>
        </widget>
       </widget>
@@ -2348,9 +2348,9 @@
        <widget class="QTableWidget" name="fermentablesTable">
         <property name="geometry">
          <rect>
-          <x>10</x>
+          <x>5</x>
           <y>130</y>
-          <width>1101</width>
+          <width>1111</width>
           <height>331</height>
          </rect>
         </property>
@@ -2651,9 +2651,9 @@
        <widget class="QTableWidget" name="hopsTable">
         <property name="geometry">
          <rect>
-          <x>10</x>
+          <x>5</x>
           <y>100</y>
-          <width>1101</width>
+          <width>1111</width>
           <height>361</height>
          </rect>
         </property>

mercurial