Commit 0c2a1f0e authored by Meade's avatar Meade

Added version 3.0.0. New grain calculator, accuracy fixes, graphical updates.

parent e232137f
# Maintainer: Meade And Emily <thedarkula2049@gmail.com>
pkgname=brewstillery
pkgver=2.0.1
pkgver=3.0.0
pkgrel=1
pkgdesc="BrewStillery is a brewer's, vintner's, and distiller's calculator. It has a multitude of great functions, such as calculating ABV, determining carbonation, and total sparge water needed."
url="https://monkeylog.in"
......@@ -9,20 +9,20 @@ license=('AGPL3')
makedepends=('git' 'cargo')
provides=('brewstillery')
conflicts=('brewstillery')
source=('git://github.com/MonkeyLog/BrewStillery')
source=("https://github.com/MonkeyLog/BrewStillery/archive/$pkgver.tar.gz")
md5sums=('SKIP')
build() {
cd BrewStillery
cd $srcdir/BrewStillery-$pkgver
cargo build --release
}
package() {
cd $srcdir/BrewStillery/target/release
cd $srcdir/BrewStillery-$pkgver/target/release
install -Dm755 BrewStillery "$pkgdir/usr/bin/BrewStillery"
cd $srcdir/BrewStillery/Arch
cd $srcdir/BrewStillery-$pkgver/Arch
install -Dm755 BrewStillery.desktop "$pkgdir/usr/share/applications/BrewStillery.desktop"
cd $srcdir/BrewStillery/media
cd $srcdir/BrewStillery-$pkgver/media
install -Dm755 BrewStilleryIcon.svg "$pkgdir/usr/share/BrewStillery/BrewStilleryIcon.svg"
install -Dm755 BrewStilleryLogo.svg "$pkgdir/usr/share/BrewStillery/BrewStilleryLogo.svg"
}
\ No newline at end of file
[root]
name = "BrewStillery"
version = "2.0.0"
version = "3.0.0"
dependencies = [
"gtk 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
......
[package]
name = "BrewStillery"
version = "2.0.1"
version = "3.0.0"
authors = ["Emily And Meade <thedarkula2049@gmail.com>"]
description = "BrewStillery is a brewer's, vintner's, and distiller's calculator. It has a multitude of great functions, such as calculating ABV, determining carbonation, and total sparge water needed."
# documentation to come
......
......@@ -4,22 +4,27 @@ It has a multitude of great functions, such as calculating ABV, determining carb
Written in Rust, using GTK3
## New In 2.0.0
Added the IBU calculator to the beer tab.
## New In 3.0.0
Added the grain calculator to the beer tab.
Reworked the maths in the RealABV calculator, because it was completely inaccurate.
Reworked the graphical layout as well.
## Screenshots:
![General Tab Screenshot](media/screenshots/BrewStilleryGeneralTab.png)
![Beer Tab Screenshot](media/screenshots/BrewStilleryBeerTab.png)
![Beer Top Tab Screenshot](media/screenshots/BrewStilleryBeerTopTab.png)
![Beer Tab IBU Screenshot](media/screenshots/BrewStilleryBeerIBU.png)
![Beer Bottom Tab Screenshot](media/screenshots/BrewStilleryBeerBottomTab.png)
![Champagne Tab Screenshot](media/screenshots/BrewStilleryChampagneTab.png)
![About Tab Screenshot](media/screenshots/BrewStilleryABoutTab.png)
## To Do:
* Grain
* Water Minerals
* Export To Gourmet
## Building:
......@@ -42,3 +47,5 @@ Added the IBU calculator to the beer tab.
* ["Brew By Numbers - Add Up What's In Your Beer"](https://www.homebrewersassociation.org/attachments/0000/2497/Math_in_Mash_SummerZym95.pdf) - Michael L. Hall. PH.D., Zymurgy (Summer) 1995
* ["Kraeusening"](http://www.braukaiser.com/wiki/index.php?title=Kraeusening) - Braukaiser.com, Modified: January 2, 2010
* ["Glenn Tinseth's Hop Page"](http://realbeer.com/hops/) - Glenn Tinseth, 1995-1999
* ["Calculating Gravity, Bitterness, And Color: Techniques"](https://byo.com/bock/item/409-calculating-gravity-bitterness-and-color-techniques) - Glenn Tinseth, 1995-1999
* ["Formulas And C Source Code"](https://web.archive.org/web/20090807084643/http://www.primetab.com:80/formulas) - PrimeTab, Modified: March 25, 2002
\ No newline at end of file
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
......@@ -24,7 +22,7 @@ pub fn champagneCarbonationPrep(ref champagneCarbonationBuilderClone: &gtk::Buil
}
}
pub fn onChampagneActivate(champagneVolume: f32, ref champagneCarbonationBuilderClone: &gtk::Builder) {
fn onChampagneActivate(champagneVolume: f32, ref champagneCarbonationBuilderClone: &gtk::Builder) {
let ref champagneCarbonationSwitch: &gtk::Switch = &champagneCarbonationBuilderClone.get_object("champagneCarbonationSwitch").unwrap();
if champagneCarbonationSwitch.get_active() == true {
......
#![allow(non_snake_case)]
use std::f32::consts::E;
pub fn brixToGravity(brix: f32) -> f32 {
(brix / (258.6 - ((brix / 258.2) * 227.1))) + 1.0
}
pub fn gravityToBrix(gravity: f32) -> f32 {
((258.6 * gravity) - 258.6) / ((0.87955073 * gravity) + 0.12044926)
}
pub fn gravityToPlato(gravity: f32) -> f32 {
135.997 * gravity.powi(3) - 630.272 * gravity.powi(2) + 1111.14 * gravity - 616.868
}
......@@ -13,19 +16,86 @@ pub fn gramsToOunces(grams: f32) -> f32 {
0.03527396_f32 * grams
}
pub fn kilosToPounds(kilos: f32) -> f32 {
2.204623_f32 * kilos
}
pub fn litresToGallons(litres: f32) -> f32 {
0.2641729_f32 * litres
}
pub fn validInput(stringToCheck: &String) -> f32 {
let isANumber = stringToCheck.parse::<f32>().is_ok();
if isANumber == true {
stringToCheck.parse().unwrap()
} else {
0.0
let stringInput = stringToCheck.parse::<f32>();
match stringInput {
Ok(number) => number,
Err(_) => 0.0,
}
}
pub fn realIBU(brix: f32, wortVolume: f32, boilTime: f32, alphaAcid: f32, hopAmount: f32) -> f32 {
(1.65 * 0.000125_f32.powf(brixToGravity(brix) - 1.0)) * ((1.0 - E.powf(-0.04 * boilTime)) / 4.15) * (( (alphaAcid / 100.0) * hopAmount * 7490.0 ) / wortVolume)
}
pub fn guestimateABV(originalGravity: f32) -> f32 {
let finalGravity: f32 = 1.010;
// since finalGravity is unknown, this constant is ideal
let originalExtract = (-668.962) + (1262.45 * originalGravity ) - (776.43 * originalGravity.powi(2)) + (182.94 * originalGravity.powi(3));
let apparentExtract = (-668.962) + (1262.45 * finalGravity ) - (776.43 * finalGravity.powi(2)) + (182.94 * finalGravity.powi(3));
let attenuationCoefficient = (0.22) + (0.001 * originalExtract);
let realExtract = ((attenuationCoefficient * originalExtract) + apparentExtract) / (1.0 + attenuationCoefficient);
// unneeded information, but here if we want it
//
// let realAttenuation = ((originalExtract - realExtract) / originalExtract) * 100.0;
// let realAttenuationRounded = format!("{:.2}", realAttenuation);
// println!("Your Real Attenuation is: {}", realAttenuationRounded);
let estimatedABW = (originalExtract - realExtract) / ( 2.0665 - (0.010665 * originalExtract));
let estimatedABV = estimatedABW * (finalGravity / 0.794);
estimatedABV
}
pub fn grainToABV(volumeInGallons: f32, weightInPounds: f32, grainGravity: f32) -> f32 {
let extractPotential = grainGravity % 1.0 * 1000.0;
let extractionEfficiency = 0.57;
// sane default here of 57%
let specificGravityPoints = (weightInPounds * extractPotential * extractionEfficiency) / volumeInGallons;
if specificGravityPoints == 0.0 {
let originalGravity = 1.0;
// set to the gravity of water
originalGravity
} else {
let originalGravity = specificGravityPoints / 1000.0 + 1.0;
originalGravity
}
}
pub fn grainInfo(grainType: &String) -> f32 {
match grainType.as_ref() {
"2-Row PG" => 1.037,
"2-Row LVB" => 1.8,
"6-Row PG" => 1.035,
"6-Row LVB" => 1.8,
"Black PG" => 1.025,
"Black LVB" => 500.0,
"Caramel PG" => 1.034,
"Caramel 60 LVB" => 60.0,
"Caramel 80 LVB" => 80.0,
"Caramel 120 LVB" => 120.0,
"Chocolate PG" => 1.034,
"Chocolate LVB" => 350.0,
"Corn PG" => 1.037,
"Corn LVB" => 1.3,
"Dextrine PG" => 1.033,
"Dextrine LVB" => 1.5,
"Oat PG" => 1.034,
"Oat LVB" => 1.0,
"Rice PG" => 1.032,
"Rice LVB" => 1.0,
"Rye PG" => 1.036,
"Rye LVB" => 2.0,
"Wheat PG" => 1.036,
"Wheat LVB" => 1.6,
_ => 0.0,
}
}
\ No newline at end of file
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
pub fn grainABVPrep(ref grainABVBuilderClone: &gtk::Builder) {
let grainABVWortInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVWortInput").unwrap();
let grainABVWortInputBuffer = grainABVWortInput.get_text().expect("No input");
let grainABVWortInputBufferFloat = validInput(&grainABVWortInputBuffer);
let grainABVFirstAmountInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVFirstAmountInput").unwrap();
let grainABVFirstAmountInputBuffer = grainABVFirstAmountInput.get_text().expect("No input");
let grainABVFirstAmountInputBufferFloat = validInput(&grainABVFirstAmountInputBuffer);
let grainABVFirstTypeInput: &gtk::ComboBoxText = &grainABVBuilderClone.get_object("grainABVFirstTypeInput").unwrap();
let grainABVFirstTypeInputBuffer = grainABVFirstTypeInput.get_active_id().unwrap();
let grainABVFirstTypeInputBufferFloat = grainInfo(&grainABVFirstTypeInputBuffer);
let grainABVSecondAmountInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVSecondAmountInput").unwrap();
let grainABVSecondAmountInputBuffer = grainABVSecondAmountInput.get_text().expect("No input");
let grainABVSecondAmountInputBufferFloat = validInput(&grainABVSecondAmountInputBuffer);
let grainABVSecondTypeInput: &gtk::ComboBoxText = &grainABVBuilderClone.get_object("grainABVSecondTypeInput").unwrap();
let grainABVSecondTypeInputBuffer = grainABVSecondTypeInput.get_active_id().unwrap();
let grainABVSecondTypeInputBufferFloat = grainInfo(&grainABVSecondTypeInputBuffer);
let grainABVThirdAmountInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVThirdAmountInput").unwrap();
let grainABVThirdAmountInputBuffer = grainABVThirdAmountInput.get_text().expect("No input");
let grainABVThirdAmountInputBufferFloat = validInput(&grainABVThirdAmountInputBuffer);
let grainABVThirdTypeInput: &gtk::ComboBoxText = &grainABVBuilderClone.get_object("grainABVThirdTypeInput").unwrap();
let grainABVThirdTypeInputBuffer = grainABVThirdTypeInput.get_active_id().unwrap();
let grainABVThirdTypeInputBufferFloat = grainInfo(&grainABVThirdTypeInputBuffer);
let grainABVFourthAmountInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVFourthAmountInput").unwrap();
let grainABVFourthAmountInputBuffer = grainABVFourthAmountInput.get_text().expect("No input");
let grainABVFourthAmountInputBufferFloat = validInput(&grainABVFourthAmountInputBuffer);
let grainABVFourthTypeInput: &gtk::ComboBoxText = &grainABVBuilderClone.get_object("grainABVFourthTypeInput").unwrap();
let grainABVFourthTypeInputBuffer = grainABVFourthTypeInput.get_active_id().unwrap();
let grainABVFourthTypeInputBufferFloat = grainInfo(&grainABVFourthTypeInputBuffer);
let grainABVFifthAmountInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVFifthAmountInput").unwrap();
let grainABVFifthAmountInputBuffer = grainABVFifthAmountInput.get_text().expect("No input");
let grainABVFifthAmountInputBufferFloat = validInput(&grainABVFifthAmountInputBuffer);
let grainABVFifthTypeInput: &gtk::ComboBoxText = &grainABVBuilderClone.get_object("grainABVFifthTypeInput").unwrap();
let grainABVFifthTypeInputBuffer = grainABVFifthTypeInput.get_active_id().unwrap();
let grainABVFifthTypeInputBufferFloat = grainInfo(&grainABVFifthTypeInputBuffer);
let grainABVSixthAmountInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVSixthAmountInput").unwrap();
let grainABVSixthAmountInputBuffer = grainABVSixthAmountInput.get_text().expect("No input");
let grainABVSixthAmountInputBufferFloat = validInput(&grainABVSixthAmountInputBuffer);
let grainABVSixthTypeInput: &gtk::ComboBoxText = &grainABVBuilderClone.get_object("grainABVSixthTypeInput").unwrap();
let grainABVSixthTypeInputBuffer = grainABVSixthTypeInput.get_active_id().unwrap();
let grainABVSixthTypeInputBufferFloat = grainInfo(&grainABVSixthTypeInputBuffer);
let grainABVSeventhAmountInput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVSeventhAmountInput").unwrap();
let grainABVSeventhAmountInputBuffer = grainABVSeventhAmountInput.get_text().expect("No input");
let grainABVSeventhAmountInputBufferFloat = validInput(&grainABVSeventhAmountInputBuffer);
let grainABVSeventhTypeInput: &gtk::ComboBoxText = &grainABVBuilderClone.get_object("grainABVSeventhTypeInput").unwrap();
let grainABVSeventhTypeInputBuffer = grainABVSeventhTypeInput.get_active_id().unwrap();
let grainABVSeventhTypeInputBufferFloat = grainInfo(&grainABVSeventhTypeInputBuffer);
let grainABVBrixOutput = String::from("grainABVBrixOutput");
if grainABVWortInputBufferFloat == 0.0 {
let output: gtk::Entry = grainABVBuilderClone.get_object(&grainABVBrixOutput).unwrap();
output.set_text("Enter at least the first two inputs");
} else if grainABVFirstAmountInputBufferFloat == 0.0 {
let output: gtk::Entry = grainABVBuilderClone.get_object(&grainABVBrixOutput).unwrap();
output.set_text("Enter at least one grain amount");
} else {
if grainABVWortInputBufferFloat <= 0.0 {
let output: gtk::Entry = grainABVBuilderClone.get_object(&grainABVBrixOutput).unwrap();
output.set_text("Enter a positive number");
} else if grainABVFirstAmountInputBufferFloat <= 0.0 {
let output: gtk::Entry = grainABVBuilderClone.get_object(&grainABVBrixOutput).unwrap();
output.set_text("Enter a positive number");
} else {
onGrainABVActivate(grainABVWortInputBufferFloat, grainABVFirstAmountInputBufferFloat, grainABVFirstTypeInputBufferFloat, grainABVSecondAmountInputBufferFloat, grainABVSecondTypeInputBufferFloat, grainABVThirdAmountInputBufferFloat, grainABVThirdTypeInputBufferFloat, grainABVFourthAmountInputBufferFloat, grainABVFourthTypeInputBufferFloat, grainABVFifthAmountInputBufferFloat, grainABVFifthTypeInputBufferFloat, grainABVSixthAmountInputBufferFloat, grainABVSixthTypeInputBufferFloat, grainABVSeventhAmountInputBufferFloat, grainABVSeventhTypeInputBufferFloat, &grainABVBuilderClone);
}
}
}
fn onGrainABVActivate(grainABVWortInputBufferFloat: f32, grainABVFirstAmountInputBufferFloat: f32, grainABVFirstTypeInputBufferFloat: f32, grainABVSecondAmountInputBufferFloat: f32, grainABVSecondTypeInputBufferFloat: f32, grainABVThirdAmountInputBufferFloat: f32, grainABVThirdTypeInputBufferFloat: f32, grainABVFourthAmountInputBufferFloat: f32, grainABVFourthTypeInputBufferFloat: f32, grainABVFifthAmountInputBufferFloat: f32, grainABVFifthTypeInputBufferFloat: f32, grainABVSixthAmountInputBufferFloat: f32, grainABVSixthTypeInputBufferFloat: f32, grainABVSeventhAmountInputBufferFloat: f32, grainABVSeventhTypeInputBufferFloat: f32, ref grainABVBuilderClone: &gtk::Builder) {
let ref grainABVSwitch: &gtk::Switch = &grainABVBuilderClone.get_object("grainABVSwitch").unwrap();
if grainABVSwitch.get_active() == true {
let imperialOrMetric = String::from("metric");
grainABVMaths(grainABVWortInputBufferFloat, grainABVFirstAmountInputBufferFloat, grainABVFirstTypeInputBufferFloat, grainABVSecondAmountInputBufferFloat, grainABVSecondTypeInputBufferFloat, grainABVThirdAmountInputBufferFloat, grainABVThirdTypeInputBufferFloat, grainABVFourthAmountInputBufferFloat, grainABVFourthTypeInputBufferFloat, grainABVFifthAmountInputBufferFloat, grainABVFifthTypeInputBufferFloat, grainABVSixthAmountInputBufferFloat, grainABVSixthTypeInputBufferFloat, grainABVSeventhAmountInputBufferFloat, grainABVSeventhTypeInputBufferFloat, imperialOrMetric, &grainABVBuilderClone);
} else if grainABVSwitch.get_active() == false {
let imperialOrMetric = String::from("imperial");
grainABVMaths(grainABVWortInputBufferFloat, grainABVFirstAmountInputBufferFloat, grainABVFirstTypeInputBufferFloat, grainABVSecondAmountInputBufferFloat, grainABVSecondTypeInputBufferFloat, grainABVThirdAmountInputBufferFloat, grainABVThirdTypeInputBufferFloat, grainABVFourthAmountInputBufferFloat, grainABVFourthTypeInputBufferFloat, grainABVFifthAmountInputBufferFloat, grainABVFifthTypeInputBufferFloat, grainABVSixthAmountInputBufferFloat, grainABVSixthTypeInputBufferFloat, grainABVSeventhAmountInputBufferFloat, grainABVSeventhTypeInputBufferFloat, imperialOrMetric, &grainABVBuilderClone);
}
}
fn grainABVMaths(grainABVWortInputBufferFloat: f32, grainABVFirstAmountInputBufferFloat: f32, grainABVFirstTypeInputBuffer: f32, grainABVSecondAmountInputBufferFloat: f32, grainABVSecondTypeInputBuffer: f32, grainABVThirdAmountInputBufferFloat: f32, grainABVThirdTypeInputBuffer: f32, grainABVFourthAmountInputBufferFloat: f32, grainABVFourthTypeInputBuffer: f32, grainABVFifthAmountInputBufferFloat: f32, grainABVFifthTypeInputBuffer: f32, grainABVSixthAmountInputBufferFloat: f32, grainABVSixthTypeInputBuffer: f32, grainABVSeventhAmountInputBufferFloat: f32, grainABVSeventhTypeInputBuffer: f32, imperialOrMetric: String, ref grainABVBuilderClone: &gtk::Builder) {
let ref grainABVBrixOutput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVBrixOutput").unwrap();
let ref grainABVABVOutput: &gtk::Entry = &grainABVBuilderClone.get_object("grainABVABVOutput").unwrap();
if imperialOrMetric == "imperial" {
let totalGrain1 = grainToABV(grainABVWortInputBufferFloat, grainABVFirstAmountInputBufferFloat, grainABVFirstTypeInputBuffer);
let totalGrain2 = grainToABV(grainABVWortInputBufferFloat, grainABVSecondAmountInputBufferFloat, grainABVSecondTypeInputBuffer);
let totalGrain3 = grainToABV(grainABVWortInputBufferFloat, grainABVThirdAmountInputBufferFloat, grainABVThirdTypeInputBuffer);
let totalGrain4 = grainToABV(grainABVWortInputBufferFloat, grainABVFourthAmountInputBufferFloat, grainABVFourthTypeInputBuffer);
let totalGrain5 = grainToABV(grainABVWortInputBufferFloat, grainABVFifthAmountInputBufferFloat, grainABVFifthTypeInputBuffer);
let totalGrain6 = grainToABV(grainABVWortInputBufferFloat, grainABVSixthAmountInputBufferFloat, grainABVSixthTypeInputBuffer);
let totalGrain7 = grainToABV(grainABVWortInputBufferFloat, grainABVSeventhAmountInputBufferFloat, grainABVSeventhTypeInputBuffer);
let estimatedBrix = format!("{:.2}°Bx", gravityToBrix(1.0 + &totalGrain1 % 1.0 + &totalGrain2 % 1.0 + &totalGrain3 % 1.0 + &totalGrain4 % 1.0 + &totalGrain5 % 1.0 + &totalGrain6 % 1.0 + &totalGrain7 % 1.0));
let abv = format!("{:.2}%", guestimateABV(1.0 + &totalGrain1 % 1.0 + &totalGrain2 % 1.0 + &totalGrain3 % 1.0 + &totalGrain4 % 1.0 + &totalGrain5 % 1.0 + &totalGrain6 % 1.0 + &totalGrain7 % 1.0));
grainABVBrixOutput.set_text(&estimatedBrix);
grainABVABVOutput.set_text(&abv);
} else if imperialOrMetric == "metric" {
let totalGrain1 = grainToABV(litresToGallons(grainABVWortInputBufferFloat), kilosToPounds(grainABVFirstAmountInputBufferFloat), grainABVFirstTypeInputBuffer);
let totalGrain2 = grainToABV(litresToGallons(grainABVWortInputBufferFloat), kilosToPounds(grainABVSecondAmountInputBufferFloat), grainABVSecondTypeInputBuffer);
let totalGrain3 = grainToABV(litresToGallons(grainABVWortInputBufferFloat), kilosToPounds(grainABVThirdAmountInputBufferFloat), grainABVThirdTypeInputBuffer);
let totalGrain4 = grainToABV(litresToGallons(grainABVWortInputBufferFloat), kilosToPounds(grainABVFourthAmountInputBufferFloat), grainABVFourthTypeInputBuffer);
let totalGrain5 = grainToABV(litresToGallons(grainABVWortInputBufferFloat), kilosToPounds(grainABVFifthAmountInputBufferFloat), grainABVFifthTypeInputBuffer);
let totalGrain6 = grainToABV(litresToGallons(grainABVWortInputBufferFloat), kilosToPounds(grainABVSixthAmountInputBufferFloat), grainABVSixthTypeInputBuffer);
let totalGrain7 = grainToABV(litresToGallons(grainABVWortInputBufferFloat), kilosToPounds(grainABVSeventhAmountInputBufferFloat), grainABVSeventhTypeInputBuffer);
let estimatedBrix = format!("{:.2}°Bx", gravityToBrix(1.0 + &totalGrain1 % 1.0 + &totalGrain2 % 1.0 + &totalGrain3 % 1.0 + &totalGrain4 % 1.0 + &totalGrain5 % 1.0 + &totalGrain6 % 1.0 + &totalGrain7 % 1.0));
let abv = format!("{:.2}%", guestimateABV(1.0 + &totalGrain1 % 1.0 + &totalGrain2 % 1.0 + &totalGrain3 % 1.0 + &totalGrain4 % 1.0 + &totalGrain5 % 1.0 + &totalGrain6 % 1.0 + &totalGrain7 % 1.0));
grainABVBrixOutput.set_text(&estimatedBrix);
grainABVABVOutput.set_text(&abv);
}
}
\ No newline at end of file
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
......@@ -15,9 +13,9 @@ pub fn guestimatePrep(ref guestimatorBuilderClone: &gtk::Builder) {
let output: gtk::Entry = guestimatorBuilderClone.get_object(&guestimatorOutput).unwrap();
output.set_text("Enter a number");
} else {
if startingBrix < 3.83 {
if startingBrix < 2.57 {
let output: gtk::Entry = guestimatorBuilderClone.get_object(&guestimatorOutput).unwrap();
output.set_text("Enter a number greater than 3.83");
output.set_text("Enter a number greater than 2.57");
} else if startingBrix > 49.48 {
let output: gtk::Entry = guestimatorBuilderClone.get_object(&guestimatorOutput).unwrap();
output.set_text("Enter a number less than 49.48");
......@@ -27,24 +25,8 @@ pub fn guestimatePrep(ref guestimatorBuilderClone: &gtk::Builder) {
}
}
pub fn guestiMaths(startingBrix: f32, guestimatorOutput: String, ref guestimatorBuilderClone: &gtk::Builder) {
let originalGravity = brixToGravity(startingBrix);
let finalGravity: f32 = 1.015;
// since finalGravity is unknown, this constant is ideal
let originalExtract = (-668.962) + (1262.45 * originalGravity ) - (776.43 * originalGravity.powi(2)) + (182.94 * originalGravity.powi(3));
let apparentExtract = (-668.962) + (1262.45 * finalGravity ) - (776.43 * finalGravity.powi(2)) + (182.94 * finalGravity.powi(3));
let attenuationCoefficient = (0.22) + (0.001 * originalExtract);
let realExtract = ((attenuationCoefficient * originalExtract) + apparentExtract) / (1.0 + attenuationCoefficient);
// unneeded information, but here if we want it
//
// let realAttenuation = ((originalExtract - realExtract) / originalExtract) * 100.0;
// let realAttenuationRounded = format!("{:.2}", realAttenuation);
// println!("Your Real Attenuation is: {}", realAttenuationRounded);
let estimatedABW = (originalExtract - realExtract) / ( 2.0665 - (0.010665 * originalExtract));
let estimatedABV = estimatedABW * (finalGravity / 0.794);
let abv = format!("{:.2}%", estimatedABV);
fn guestiMaths(startingBrix: f32, guestimatorOutput: String, ref guestimatorBuilderClone: &gtk::Builder) {
let abv = format!("{:.2}%", guestimateABV(brixToGravity(startingBrix)));
let ref output: &gtk::Entry = &guestimatorBuilderClone.get_object(&guestimatorOutput).unwrap();
output.set_text(&abv.to_string());
}
\ No newline at end of file
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
......@@ -75,19 +73,19 @@ pub fn guestimateIBUPrep(ref IBUBuilderClone: &gtk::Builder) {
let totalIBUOutput = String::from("totalIBUOutput");
if validInput(&totalIBUPreBoilBrixInputBuffer) == 0.0 {
if totalIBUPreBoilBrixInputBufferFloat == 0.0 {
let output: gtk::Entry = IBUBuilderClone.get_object(&totalIBUOutput).unwrap();
output.set_text("Enter at least the first five inputs");
} else if validInput(&totalIBUWortVolumeInputBuffer) == 0.0 {
} else if totalIBUWortVolumeInputBufferFloat == 0.0 {
let output: gtk::Entry = IBUBuilderClone.get_object(&totalIBUOutput).unwrap();
output.set_text("Enter at least the first five inputs");
} else if validInput(&totalIBUBoilTimeInputBuffer) == 0.0 {
} else if totalIBUBoilTimeInputBufferFloat == 0.0 {
let output: gtk::Entry = IBUBuilderClone.get_object(&totalIBUOutput).unwrap();
output.set_text("Enter at least the first five inputs");
} else if validInput(&totalIBUFirstHopAlphaInputBuffer) == 0.0 {
} else if totalIBUFirstHopAlphaInputBufferFloat == 0.0 {
let output: gtk::Entry = IBUBuilderClone.get_object(&totalIBUOutput).unwrap();
output.set_text("Enter at least the first five inputs");
} else if validInput(&totalIBUFirstHopAmountInputBuffer) == 0.0 {
} else if totalIBUFirstHopAmountInputBufferFloat == 0.0 {
let output: gtk::Entry = IBUBuilderClone.get_object(&totalIBUOutput).unwrap();
output.set_text("Enter at least the first five inputs");
} else {
......@@ -112,7 +110,7 @@ pub fn guestimateIBUPrep(ref IBUBuilderClone: &gtk::Builder) {
}
}
pub fn onIBUActivate(totalIBUPreBoilBrixInputBufferFloat: f32, totalIBUWortVolumeInputBufferFloat: f32, totalIBUBoilTimeInputBufferFloat: f32, totalIBUFirstHopAlphaInputBufferFloat: f32, totalIBUFirstHopAmountInputBufferFloat: f32, totalIBUSecondHopAlphaInputBufferFloat: f32, totalIBUSecondHopAmountInputBufferFloat: f32, totalIBUThirdHopAlphaInputBufferFloat: f32, totalIBUThirdHopAmountInputBufferFloat: f32, totalIBUFourthHopAlphaInputBufferFloat: f32, totalIBUFourthHopAmountInputBufferFloat: f32, totalIBUFifthHopAlphaInputBufferFloat: f32, totalIBUFifthHopAmountInputBufferFloat: f32, totalIBUSixthHopAlphaInputBufferFloat: f32, totalIBUSixthHopAmountInputBufferFloat: f32, totalIBUSeventhHopAlphaInputBufferFloat: f32, totalIBUSeventhHopAmountInputBufferFloat: f32, ref IBUBuilderClone: &gtk::Builder) {
fn onIBUActivate(totalIBUPreBoilBrixInputBufferFloat: f32, totalIBUWortVolumeInputBufferFloat: f32, totalIBUBoilTimeInputBufferFloat: f32, totalIBUFirstHopAlphaInputBufferFloat: f32, totalIBUFirstHopAmountInputBufferFloat: f32, totalIBUSecondHopAlphaInputBufferFloat: f32, totalIBUSecondHopAmountInputBufferFloat: f32, totalIBUThirdHopAlphaInputBufferFloat: f32, totalIBUThirdHopAmountInputBufferFloat: f32, totalIBUFourthHopAlphaInputBufferFloat: f32, totalIBUFourthHopAmountInputBufferFloat: f32, totalIBUFifthHopAlphaInputBufferFloat: f32, totalIBUFifthHopAmountInputBufferFloat: f32, totalIBUSixthHopAlphaInputBufferFloat: f32, totalIBUSixthHopAmountInputBufferFloat: f32, totalIBUSeventhHopAlphaInputBufferFloat: f32, totalIBUSeventhHopAmountInputBufferFloat: f32, ref IBUBuilderClone: &gtk::Builder) {
let ref totalIBUSwitch: &gtk::Switch = &IBUBuilderClone.get_object("totalIBUSwitch").unwrap();
if totalIBUSwitch.get_active() == true {
......
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
......@@ -44,7 +42,7 @@ pub fn gyleCarbonationPrep(ref gyleBuilderClone: &gtk::Builder) {
}
}
pub fn onGyleActivate(startingBrix: f32, desiredCO2Level: f32, finalVolume: f32, ref gyleBuilderClone: &gtk::Builder) {
fn onGyleActivate(startingBrix: f32, desiredCO2Level: f32, finalVolume: f32, ref gyleBuilderClone: &gtk::Builder) {
let ref gyleCarbonationSwitch: &gtk::Switch = &gyleBuilderClone.get_object("gyleCarbonationSwitch").unwrap();
if gyleCarbonationSwitch.get_active() == true {
......
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
......@@ -44,7 +42,7 @@ pub fn increaseABVPrep(ref increaseABVBuilderClone: &gtk::Builder) {
}
}
pub fn onIncreaseActivate(startingBrix: f32, desiredABV: f32, desiredWortVolume: f32, ref increaseABVBuilderClone: &gtk::Builder) {
fn onIncreaseActivate(startingBrix: f32, desiredABV: f32, desiredWortVolume: f32, ref increaseABVBuilderClone: &gtk::Builder) {
let ref increaseABVSwitch: &gtk::Switch = &increaseABVBuilderClone.get_object("increaseABVSwitch").unwrap();
if increaseABVSwitch.get_active() == true {
......
......@@ -6,3 +6,4 @@ pub mod gyleCarbonation;
pub mod guestimateIBU;
pub mod champagneCarbonation;
pub mod commonFunctions;
pub mod grainToABV;
\ No newline at end of file
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
......@@ -13,23 +11,23 @@ pub fn realABVPrep(ref realABVBuilderClone: &gtk::Builder) {
let realABVFinalBrixInputBuffer = realABVFinalBrixInput.get_text().expect("No input");
let finalBrix = validInput(&realABVFinalBrixInputBuffer);
let realABVRealAttenuationOutput = String::from("realABVRealAttenuationOutput");
let realABVFinalABVOutput = String::from("realABVFinalABVOutput");
if startingBrix == 0.0 {
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVRealAttenuationOutput).unwrap();
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVFinalABVOutput).unwrap();
output.set_text("Enter a number");
} else if finalBrix == 0.0 {
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVRealAttenuationOutput).unwrap();
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVFinalABVOutput).unwrap();
output.set_text("Enter a number");
} else {
if startingBrix <= 0.0 {
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVRealAttenuationOutput).unwrap();
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVFinalABVOutput).unwrap();
output.set_text("Enter a positive number");
} else if finalBrix <= 0.0 {
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVRealAttenuationOutput).unwrap();
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVFinalABVOutput).unwrap();
output.set_text("Enter a positive number");
} else if startingBrix < finalBrix {
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVRealAttenuationOutput).unwrap();
let output: gtk::Entry = realABVBuilderClone.get_object(&realABVFinalABVOutput).unwrap();
output.set_text("Starting brix must be greater than final brix");
} else {
realABVMaths(startingBrix, finalBrix, &realABVBuilderClone);
......@@ -37,21 +35,12 @@ pub fn realABVPrep(ref realABVBuilderClone: &gtk::Builder) {
}
}
pub fn realABVMaths(startingBrix: f32, finalBrix: f32, ref realABVBuilderClone: &gtk::Builder) {
let ref realABVRealAttenuationOutput: &gtk::Entry = &realABVBuilderClone.get_object("realABVRealAttenuationOutput").unwrap();
fn realABVMaths(startingBrix: f32, finalBrix: f32, ref realABVBuilderClone: &gtk::Builder) {
let ref realABVFinalABVOutput: &gtk::Entry = &realABVBuilderClone.get_object("realABVFinalABVOutput").unwrap();
let originalGravity = (startingBrix / (258.6 - ((startingBrix / 258.2) * 227.1))) + 1.0;
let finalGravity = (finalBrix / (258.6 - ((finalBrix / 258.2) * 227.1))) + 1.0;
let originalExtract = (-668.962) + (1262.45 * originalGravity) - (776.43 * originalGravity.powi(2)) + (182.94 * originalGravity.powi(3));
let apparentExtract = (-668.962) + (1262.45 * finalGravity) - (776.43 * finalGravity.powi(2)) + (182.94 * finalGravity.powi(3));
let attenuationCoefficient = (0.22) + (0.001 * originalExtract);
let realExtract = (attenuationCoefficient * originalExtract + apparentExtract) / (1.0 + attenuationCoefficient);
let realAttenuation = ((originalExtract - realExtract) / originalExtract) * 100.0;
let attenuation = format!("{:.2}%", realAttenuation);
let estimatedABW = (originalExtract - realExtract) / ( 2.0665 - (0.010665 * originalExtract));
let finalABV = estimatedABW * (finalGravity / 0.794);
let abv = format!("{:.2}%", finalABV);
realABVRealAttenuationOutput.set_text(&attenuation);
let finalGravity = 1.001843 - (0.002318474 * startingBrix) - (0.000007775 * startingBrix.powi(2)) - (0.000000034 * startingBrix.powi(3)) + (0.00574 * finalBrix) + (0.00003344 * finalBrix.powi(2)) + (0.000000086 * finalBrix.powi(3));
let refractiveIndex = 1.33302 + (0.001427193 * finalBrix) + (0.000005791157 * finalBrix.powi(2));
let abw = 1017.5596 - (277.4 * finalGravity) + refractiveIndex * ((937.8135 * refractiveIndex) - 1805.1228);
let abv = format!("{:.2}%", abw * (finalGravity / 0.794));
realABVFinalABVOutput.set_text(&abv);
}
\ No newline at end of file
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
use functions::commonFunctions::*;
......@@ -47,7 +45,7 @@ pub fn waterSpargePrep(ref waterSpargeBuilderClone: &gtk::Builder) {
}
}
pub fn onSpargeActivate(preFermentVolume: f32, totalGrain: f32, boilTemp: f32, ref waterSpargeBuilderClone: &gtk::Builder) {
fn onSpargeActivate(preFermentVolume: f32, totalGrain: f32, boilTemp: f32, ref waterSpargeBuilderClone: &gtk::Builder) {
let ref waterSpargeSwitch: &gtk::Switch = &waterSpargeBuilderClone.get_object("waterSpargeSwitch").unwrap();
let boilTime: f32 = boilTemp / 60.0;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
#![allow(non_snake_case)]
use gtk;
use gtk::prelude::*;
......@@ -10,6 +8,7 @@ use functions::waterSparge::*;
use functions::gyleCarbonation::*;
use functions::guestimateIBU::*;
use functions::champagneCarbonation::*;
use functions::grainToABV::*;
pub fn startGTK() {
if gtk::init().is_err() {
......@@ -270,6 +269,61 @@ pub fn startGTK() {
});
// grainABV Section
let grainABVButton: gtk::Button = builder.get_object("grainABVButton").unwrap();
let grainABVButtonClone = builder.clone();
grainABVButton.connect_clicked(move |_| {
grainABVPrep(&grainABVButtonClone);
});
let grainABVWortInput: gtk::Entry = builder.get_object("grainABVWortInput").unwrap();
let grainABVWortInputBuilderClone = builder.clone();
grainABVWortInput.connect_activate(move |_| {
grainABVPrep(&grainABVWortInputBuilderClone);
});
let grainABVFirstAmountInput: gtk::Entry = builder.get_object("grainABVFirstAmountInput").unwrap();
let grainABVFirstAmountInputBuilderClone = builder.clone();
grainABVFirstAmountInput.connect_activate(move |_| {
grainABVPrep(&grainABVFirstAmountInputBuilderClone);
});
let grainABVSecondAmountInput: gtk::Entry = builder.get_object("grainABVSecondAmountInput").unwrap();
let grainABVSecondAmountInputBuilderClone = builder.clone();
grainABVSecondAmountInput.connect_activate(move |_| {
grainABVPrep(&grainABVSecondAmountInputBuilderClone);
});
let grainABVThirdAmountInput: gtk::Entry = builder.get_object("grainABVThirdAmountInput").unwrap();
let grainABVThirdAmountInputBuilderClone = builder.clone();
grainABVThirdAmountInput.connect_activate(move |_| {
grainABVPrep(&grainABVThirdAmountInputBuilderClone);
});
let grainABVFourthAmountInput: gtk::Entry = builder.get_object("grainABVFourthAmountInput").unwrap();
let grainABVFourthAmountInputBuilderClone = builder.clone();
grainABVFourthAmountInput.connect_activate(move |_| {
grainABVPrep(&grainABVFourthAmountInputBuilderClone);
});
let grainABVFifthAmountInput: gtk::Entry = builder.get_object("grainABVFifthAmountInput").unwrap();
let grainABVFifthAmountInputBuilderClone = builder.clone();
grainABVFifthAmountInput.connect_activate(move |_| {
grainABVPrep(&grainABVFifthAmountInputBuilderClone);
});
let grainABVSixthAmountInput: gtk::Entry = builder.get_object("grainABVSixthAmountInput").unwrap();
let grainABVSixthAmountInputBuilderClone = builder.clone();
grainABVSixthAmountInput.connect_activate(move |_| {
grainABVPrep(&grainABVSixthAmountInputBuilderClone);
});
let grainABVSeventhAmountInput: gtk::Entry = builder.get_object("grainABVSeventhAmountInput").unwrap();
let grainABVSeventhAmountInputBuilderClone = builder.clone();
grainABVSeventhAmountInput.connect_activate(move |_| {
grainABVPrep(&grainABVSeventhAmountInputBuilderClone);
});
mainWindow.show_all();
......
#![allow(non_snake_case)]
#![allow(non_snake_case, non_upper_case_globals)]
extern crate gtk;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment