# HG changeset patch # User Michiel Broek # Date 1651606632 -7200 # Node ID 7446ee2fb42756e3a4147c60913fdfbb1e82ec6c # Parent bb6c06910f0f5c1057fb1a6f98b18bdbd52d3b73 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. diff -r bb6c06910f0f -r 7446ee2fb427 src/EditProduct.cpp --- 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(); } diff -r bb6c06910f0f -r 7446ee2fb427 src/EditProductTab3.cpp --- 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); diff -r bb6c06910f0f -r 7446ee2fb427 src/EditProductTab4.cpp --- 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(); diff -r bb6c06910f0f -r 7446ee2fb427 src/global.h --- 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; diff -r bb6c06910f0f -r 7446ee2fb427 ui/EditProduct.ui --- 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 @@ - :/icons/silk/error.png + :/icons/silk/cancel.png @@ -2348,9 +2348,9 @@ - 10 + 5 130 - 1101 + 1111 331 @@ -2651,9 +2651,9 @@ - 10 + 5 100 - 1101 + 1111 361