src/EditProductTab11.cpp

Thu, 19 May 2022 20:50:36 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 19 May 2022 20:50:36 +0200
changeset 221
54828816233f
parent 220
7792a410a277
child 222
c5a3beb15eef
permissions
-rw-r--r--

Added bottles priming calculations.

/**
 * EditProduct.cpp is part of bmsapp.
 *
 * Tab 11, package
 *
 * bmsapp is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * bmsapp is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

double EditProduct::ResCO2(double T)
{
    double F = T * 1.8 + 32;
    return round((3.0378 - 0.050062 * F + 0.00026555 * F * F) * 1000000.0) / 1000000.0;
}


double EditProduct::CarbCO2toS(double CO2, double T, double SFactor)
{
    //var sugar = SFactor * (CO2 - ResCO2(CO2, T)) / 0.286;
    double sugar = round((SFactor * (CO2 - ResCO2(T)) * 4.014094) * 1000000.0) / 1000000.0;
    if (sugar < 0)
	sugar = 0;
    return sugar; 	//Round(sugar, 3);
}


double EditProduct::GetPressure(double CO2, double T1, double T2)
{
    double V = CO2 - ResCO2(T1);
    V = CO2; // TODO: temp only total pressure, testing
    if (V < 0)
	return 0;

    double P = -1.09145427669121 + 0.00800006989646477 * T2 + 0.000260276315484684 * T2 * T2 + 0.0215142075945119 * T2 * V +
		0.674996600795854 * V + -0.00471757220150754 * V * V;
    if (P < 0)
	P = 0;
    P = round((P * 1.01325) * 100.0) / 100.0;	// atm to bar
    qDebug() << "  GetPressure(" << CO2 << "," << T1 << "," << T2 << ") V:" << V << "Bar:" << P << "ignored ResCO2:" << ResCO2(T1);
    return P;
}


double EditProduct::CarbCO2ToPressure(double CO2, double T)
{
    return (CO2 - (-0.000005594056 * pow(T, 4) + 0.000144357886 * pow(T, 3) +
		0.000362999168 * T * T - 0.064872987645 * T + 1.641145175049)) /
		(0.00000498031 * pow(T, 4) - 0.00024358267 * pow(T, 3) + 0.00385867329 * T * T - 0.05671206825 * T + 1.53801423376);
}


void EditProduct::calcPack()
{
    int		i, j;
    bool	found1, found2;
    QSqlQuery	query;
    double	TSec, SFactor;

    qDebug() << "calcPack()" << product->package_volume << product->package_abv << "inf" << product->package_infuse_amount << product->package_infuse_abv;

    if (product->package_volume < 1) {
	/*
	 * If there is not enough to package, then don't
	 * do any calculations and clear the rest of the form.
	 */
	product->package_volume = 0;
	ui->pack_finalabvShow->setValue(0);

	return;
    }

    double bvol = product->package_volume - (product->package_abv * product->package_volume) / 100.0;
    double balc = product->package_volume - bvol;
    double mvol = product->package_infuse_amount - (product->package_infuse_abv * product->package_infuse_amount) / 100.0;
    double malc = product->package_infuse_amount - mvol;
    double talc = balc + malc;
    double tvol = bvol + mvol;

    product->final_abv = round(talc / (tvol + talc) * 10000.0) / 100.0;
    ui->pack_finalabvShow->setValue(product->final_abv);

    TSec = product->secondary_temp;
    if (TSec < 1)
	TSec = product->primary_end_temp;
    if (TSec < 1)
	TSec = 18;

    /*
     * For bottles and kegs use the following complicated procedure to
     * find the needed priming sugars.
     *
     * 1. If we need a priming sugar then first see in the fermentables
     *    table if there is one selected. If not, clear sugars and done.
     * 2. Then, we update the data from the fermentables inventory.
     * 3. Set the found sugar in the pulldown menu.
     * 4. Calculate the sugar in gr/L and total amount need.
     * 5. Calculate the ABV in the bottles/kegs.
     * 6. Calculate the pressure build by the refermentation.
     *
     * Note that this is all a leftover from the web based application that
     * did work like this. It's a bit strange but it will allways give
     * the right data and sugar concentrations.
     * Sometimes bugs have good things.
     */
    found1 = false;
    if (product->bottle_amount) {
	for (i = 0; i < product->fermentables.size(); i++) {
	    if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_BOTTLE) {
		found1 = true;
		break;
	    }
	}
       	if (found1) {
	    SFactor = 1 / ((product->fermentables.at(i).f_yield / 100) * (1 - product->fermentables.at(i).f_moisture / 100));
	    qDebug() << "  bottle sugar" << product->fermentables.at(i).f_name << SFactor << TSec;

	    query.prepare("SELECT name,supplier FROM inventory_fermentables WHERE type = '1' OR type = '3' ORDER BY name");      // Sugars or dry extract
	    query.exec();
	    j = 0;
	    found2 = false;
	    while (query.next()) {
		j++;
		if (query.value(0).toString() == product->fermentables.at(i).f_name && query.value(1).toString() == product->fermentables.at(i).f_supplier) {
		    ui->bottle_sugarEdit->setCurrentIndex(j);
		    product->bottle_priming_sugar = j;
		    found2 = true;
		    break;
		}
	    }
	    if (! found2) {
		ui->bottle_sugarEdit->setCurrentIndex(0);	// Make sure not selected
		product->fermentables.removeAt(i);		// Remove false fermentable
		refreshFermentables();
	    } else {
		product->bottle_priming_amount = CarbCO2toS(product->bottle_carbonation, TSec, SFactor);
		ui->bottle_sug_amountShow->setValue(product->bottle_priming_amount);
		double total = round(product->bottle_priming_amount * product->bottle_amount * 100.0) / 100000.0;
		qDebug() << "  total" << total << product->fermentables.at(i).f_amount;
		if (total != product->fermentables.at(i).f_amount) {
		    qDebug() << "  update priming sugar" << total;
		    product->fermentables[i].f_amount = total;
		    refreshFermentables();
		    ui->bottle_sug_weightShow->setValue(total * 1000);
		    is_changed();
		}

		double pabv = product->final_abv + product->bottle_priming_amount * 0.47 / 7.907;
		double pvol = product->bottle_amount - (pabv * product->bottle_amount) / 100;
		talc = product->bottle_amount - pvol;
  		tvol = pvol + product->bottle_priming_water;
		ui->bottle_abvShow->setValue(talc / (tvol + talc) * 100);
		ui->bottle_barShow->setValue(GetPressure(product->bottle_carbonation, TSec, product->bottle_carbonation_temp));
	    }
	}
    }
    if (! found1) {
	qDebug() << "  no bottle priming";
	ui->bottle_sug_amountShow->setValue(0);
	ui->bottle_sug_weightShow->setValue(0);
	ui->bottle_abvShow->setValue(0);
	ui->bottle_barShow->setValue(0);
    }

    // keg_amount keg_carbonation keg_priming_sugar keg_priming_amount keg_priming_water keg_carbonation_temp keg_forced_carb keg_pressure
}


/*
 * Triggered by writing to ui->pack_abvShow
 */
void EditProduct::pack_abv_changed(double val)
{
    calcPack();
}


void EditProduct::pack_date_changed(QDate val)
{
    qDebug() << "pack_date_changed" << val;
}


void EditProduct::pack_date_button()
{
}


void EditProduct::pack_date_ack()
{
}


void EditProduct::pack_volume_changed(double val)
{
    product->package_volume = val;
    calcPack();
    is_changed();
}


void EditProduct::pack_ph_changed(double val)
{
    if (product->package_ph == 0) {
        product->package_ph = 4.0;
        const QSignalBlocker blocker1(ui->pack_phEdit);
        ui->pack_phEdit->setValue(4.0);
    } else {
    	product->package_ph = val;
    }
    is_changed();
}


void EditProduct::pack_infusion_vol_changed(double val)
{
    product->package_infuse_amount = val;
    calcPack();
    is_changed();
}


void EditProduct::pack_infusion_abv_changed(double val)
{
    product->package_infuse_abv = val;
    calcPack();
    is_changed();
}


void EditProduct::pack_infusion_txt_changed(QString val)
{
    product->package_infuse_notes = val;
    is_changed();
}


void EditProduct::bottle_volume_changed(double val)
{
    product->bottle_amount = val;
    calcPack();
    is_changed();
}


void EditProduct::bottle_co2_changed(double val)
{
    product->bottle_carbonation = val;
    calcPack();
    is_changed();
}


void EditProduct::bottle_sugar_changed(int val)
{
}


void EditProduct::bottle_water_changed(double val)
{
    product->bottle_priming_water = val;
    calcPack();
    is_changed();
}


void EditProduct::bottle_temp_changed(double val)
{
    product->bottle_carbonation_temp = val;
    calcPack();
    is_changed();
}


void EditProduct::kegs_volume_changed(double val)
{
}


void EditProduct::kegs_co2_changed(double val)
{
}


void EditProduct::kegs_sugar_changed(int val)
{
}


void EditProduct::kegs_water_changed(double val)
{
}


void EditProduct::kegs_forced_changed(bool val)
{
}


void EditProduct::kegs_temp_changed(double val)
{
}

mercurial